diff options
-rw-r--r-- | .gitlab-ci.yml | 104 | ||||
-rw-r--r-- | doc/bird.sgml | 18 | ||||
-rw-r--r-- | filter/config.Y | 9 | ||||
-rw-r--r-- | filter/data.c | 11 | ||||
-rw-r--r-- | filter/data.h | 2 | ||||
-rw-r--r-- | filter/f-inst.c | 114 | ||||
-rw-r--r-- | filter/test.conf | 27 | ||||
-rw-r--r-- | nest/a-set.c | 130 | ||||
-rw-r--r-- | nest/attrs.h | 6 | ||||
-rw-r--r-- | proto/rpki/packets.c | 27 | ||||
-rw-r--r-- | sysdep/bsd/krt-sock.c | 36 |
11 files changed, 420 insertions, 64 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 39202098..2c1f7175 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ variables: LC_ALL: C.UTF-8 GIT_STRATEGY: fetch DOCKER_CMD: docker --config="$HOME/.docker/$CI_JOB_ID/" - IMG_BASE: registry.labs.nic.cz/labs/bird + IMG_BASE: registry.nic.cz/labs/bird TOOLS_DIR: /var/lib/gitlab-runner/bird-tools stages: @@ -16,7 +16,7 @@ stages: stage: image allow_failure: true script: - - $DOCKER_CMD login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.labs.nic.cz + - $DOCKER_CMD login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.nic.cz # Make sure we refresh the base image if it updates (eg. security updates, etc) # If we do just the build, cache is always reused and the freshness of the # base image is never checked. However, pull always asks and updates the @@ -224,123 +224,123 @@ docker_opensuse-15.3-amd64: build-debian-8-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-8-amd64 + image: registry.nic.cz/labs/bird:debian-8-amd64 build-debian-8-i386: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-8-i386 + image: registry.nic.cz/labs/bird:debian-8-i386 build-debian-9-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-9-amd64 + image: registry.nic.cz/labs/bird:debian-9-amd64 build-debian-9-i386: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-9-i386 + image: registry.nic.cz/labs/bird:debian-9-i386 build-debian-10-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-10-amd64 + image: registry.nic.cz/labs/bird:debian-10-amd64 build-debian-10-i386: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-10-i386 + image: registry.nic.cz/labs/bird:debian-10-i386 build-debian-11-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-11-amd64 + image: registry.nic.cz/labs/bird:debian-11-amd64 #build-debian-11-i386: # <<: *build-linux -# image: registry.labs.nic.cz/labs/bird:debian-11-i386 +# image: registry.nic.cz/labs/bird:debian-11-i386 build-debian-testing-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:debian-testing-amd64 + image: registry.nic.cz/labs/bird:debian-testing-amd64 #build-debian-testing-i386: # <<: *build-linux -# image: registry.labs.nic.cz/labs/bird:debian-testing-i386 +# image: registry.nic.cz/labs/bird:debian-testing-i386 build-fedora-25-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-25-amd64 + image: registry.nic.cz/labs/bird:fedora-25-amd64 build-fedora-26-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-26-amd64 + image: registry.nic.cz/labs/bird:fedora-26-amd64 build-fedora-27-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-27-amd64 + image: registry.nic.cz/labs/bird:fedora-27-amd64 build-fedora-28-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-28-amd64 + image: registry.nic.cz/labs/bird:fedora-28-amd64 build-fedora-29-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-29-amd64 + image: registry.nic.cz/labs/bird:fedora-29-amd64 build-fedora-30-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-30-amd64 + image: registry.nic.cz/labs/bird:fedora-30-amd64 build-fedora-31-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-31-amd64 + image: registry.nic.cz/labs/bird:fedora-31-amd64 build-fedora-32-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-32-amd64 + image: registry.nic.cz/labs/bird:fedora-32-amd64 build-fedora-33-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-33-amd64 + image: registry.nic.cz/labs/bird:fedora-33-amd64 build-fedora-34-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:fedora-33-amd64 + image: registry.nic.cz/labs/bird:fedora-33-amd64 build-centos-8-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:centos-8-amd64 + image: registry.nic.cz/labs/bird:centos-8-amd64 build-ubuntu-16_04-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:ubuntu-16.04-amd64 + image: registry.nic.cz/labs/bird:ubuntu-16.04-amd64 build-ubuntu-18_04-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:ubuntu-18.04-amd64 + image: registry.nic.cz/labs/bird:ubuntu-18.04-amd64 build-ubuntu-20_04-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:ubuntu-20.04-amd64 + image: registry.nic.cz/labs/bird:ubuntu-20.04-amd64 build-ubuntu-20_10-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:ubuntu-20.10-amd64 + image: registry.nic.cz/labs/bird:ubuntu-20.10-amd64 #build-ubuntu-21_04-amd64: # <<: *build-linux -# image: registry.labs.nic.cz/labs/bird:ubuntu-21.04-amd64 +# image: registry.nic.cz/labs/bird:ubuntu-21.04-amd64 build-opensuse-15.0-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:opensuse-15.0-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.0-amd64 build-opensuse-15.1-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:opensuse-15.1-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.1-amd64 build-opensuse-15.2-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:opensuse-15.2-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.2-amd64 build-opensuse-15.3-amd64: <<: *build-linux - image: registry.labs.nic.cz/labs/bird:opensuse-15.3-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.3-amd64 build-freebsd-11-amd64: <<: *build-base @@ -390,105 +390,105 @@ build-freebsd-11-i386: #pkg-debian-8-amd64: # <<: *pkg-deb # needs: [build-debian-8-amd64] -# image: registry.labs.nic.cz/labs/bird:debian-8-amd64 +# image: registry.nic.cz/labs/bird:debian-8-amd64 # Dpkg error: PATH is not set #pkg-debian-8-i386: # <<: *pkg-deb # needs: [build-debian-8-i386] -# image: registry.labs.nic.cz/labs/bird:debian-8-i386 +# image: registry.nic.cz/labs/bird:debian-8-i386 # Dpkg error: PATH is not set pkg-debian-9-amd64: <<: *pkg-deb needs: [build-debian-9-amd64] - image: registry.labs.nic.cz/labs/bird:debian-9-amd64 + image: registry.nic.cz/labs/bird:debian-9-amd64 # Dpkg error: PATH is not set pkg-debian-9-i386: <<: *pkg-deb needs: [build-debian-9-i386] - image: registry.labs.nic.cz/labs/bird:debian-9-i386 + image: registry.nic.cz/labs/bird:debian-9-i386 pkg-debian-10-amd64: <<: *pkg-deb needs: [build-debian-10-amd64] - image: registry.labs.nic.cz/labs/bird:debian-10-amd64 + image: registry.nic.cz/labs/bird:debian-10-amd64 pkg-debian-10-i386: <<: *pkg-deb needs: [build-debian-10-i386] - image: registry.labs.nic.cz/labs/bird:debian-10-i386 + image: registry.nic.cz/labs/bird:debian-10-i386 pkg-debian-11-amd64: <<: *pkg-deb needs: [build-debian-11-amd64] - image: registry.labs.nic.cz/labs/bird:debian-11-amd64 + image: registry.nic.cz/labs/bird:debian-11-amd64 pkg-fedora-30-amd64: <<: *pkg-rpm-wa needs: [build-fedora-30-amd64] - image: registry.labs.nic.cz/labs/bird:fedora-30-amd64 + image: registry.nic.cz/labs/bird:fedora-30-amd64 pkg-fedora-31-amd64: <<: *pkg-rpm-wa needs: [build-fedora-31-amd64] - image: registry.labs.nic.cz/labs/bird:fedora-31-amd64 + image: registry.nic.cz/labs/bird:fedora-31-amd64 pkg-fedora-32-amd64: <<: *pkg-rpm-wa needs: [build-fedora-32-amd64] - image: registry.labs.nic.cz/labs/bird:fedora-32-amd64 + image: registry.nic.cz/labs/bird:fedora-32-amd64 pkg-fedora-33-amd64: <<: *pkg-rpm-wa needs: [build-fedora-33-amd64] - image: registry.labs.nic.cz/labs/bird:fedora-33-amd64 + image: registry.nic.cz/labs/bird:fedora-33-amd64 pkg-fedora-34-amd64: <<: *pkg-rpm needs: [build-fedora-34-amd64] - image: registry.labs.nic.cz/labs/bird:fedora-34-amd64 + image: registry.nic.cz/labs/bird:fedora-34-amd64 pkg-centos-8-amd64: <<: *pkg-rpm-wa needs: [build-centos-8-amd64] - image: registry.labs.nic.cz/labs/bird:centos-8-amd64 + image: registry.nic.cz/labs/bird:centos-8-amd64 pkg-ubuntu-18.04-amd64: <<: *pkg-deb needs: [build-ubuntu-18_04-amd64] - image: registry.labs.nic.cz/labs/bird:ubuntu-18.04-amd64 + image: registry.nic.cz/labs/bird:ubuntu-18.04-amd64 pkg-ubuntu-20.04-amd64: <<: *pkg-deb needs: [build-ubuntu-20_04-amd64] - image: registry.labs.nic.cz/labs/bird:ubuntu-20.04-amd64 + image: registry.nic.cz/labs/bird:ubuntu-20.04-amd64 pkg-ubuntu-20.10-amd64: <<: *pkg-deb needs: [build-ubuntu-20_10-amd64] - image: registry.labs.nic.cz/labs/bird:ubuntu-20.10-amd64 + image: registry.nic.cz/labs/bird:ubuntu-20.10-amd64 #pkg-ubuntu-21.04-amd64: # <<: *pkg-deb # needs: [build-ubuntu-21_04-amd64] -# image: registry.labs.nic.cz/labs/bird:ubuntu-21.04-amd64 +# image: registry.nic.cz/labs/bird:ubuntu-21.04-amd64 pkg-opensuse-15.1-amd64: <<: *pkg-rpm-wa needs: [build-opensuse-15.1-amd64] - image: registry.labs.nic.cz/labs/bird:opensuse-15.1-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.1-amd64 pkg-opensuse-15.2-amd64: <<: *pkg-rpm-wa needs: [build-opensuse-15.2-amd64] - image: registry.labs.nic.cz/labs/bird:opensuse-15.2-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.2-amd64 pkg-opensuse-15.3-amd64: <<: *pkg-rpm-wa needs: [build-opensuse-15.3-amd64] - image: registry.labs.nic.cz/labs/bird:opensuse-15.3-amd64 + image: registry.nic.cz/labs/bird:opensuse-15.3-amd64 build-birdlab: diff --git a/doc/bird.sgml b/doc/bird.sgml index cca7d470..99aa140a 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1299,6 +1299,9 @@ in the foot). The same syntax can also be used to construct a pair from two arbitrary integer expressions (for example <cf/(1+2,a)/). + Operators <cf/.asn/ and <cf/.data/ can be used to extract corresponding + components of a pair: <cf>(<m/asn/, <m/data/)</cf>. + <tag><label id="type-quad">quad</tag> This is a dotted quad of numbers used to represent router IDs (and others). Each component can have a value from 0 to 255. Literals of @@ -1389,6 +1392,10 @@ in the foot). pairs, LCs can be constructed using expressions for its parts, (e.g. <cf/(myas, 10+20, 3*10)/, where <cf/myas/ is an integer variable). + Operators <cf/.asn/, <cf/.data1/, and <cf/.data2/ can be used + to extract corresponding components of LCs: + <cf>(<m/asn/, <m/data1/, <m/data2/)</cf>. + <tag><label id="type-set">int|pair|quad|ip|prefix|ec|lc|enum set</tag> Filters recognize four types of sets. Sets are similar to strings: you can pass them around but you can't modify them. Literals of type <cf>int @@ -1532,7 +1539,7 @@ in the foot). Clist is similar to a set, except that unlike other sets, it can be modified. The type is used for community list (a set of pairs) and for cluster list (a set of quads). There exist no literals of this type. - There are three special operators on clists: + There are special operators on clists: <cf><m/C/.len</cf> returns the length of clist <m/C/. @@ -1559,6 +1566,15 @@ in the foot). <cf><m/C/.add(<m/P/);</cf> if <m/C/ is appropriate route attribute (for example <cf/bgp_community/). Similarly for <cf/delete/ and <cf/filter/. + <cf><m/C/.min</cf> returns the minimum element of clist <m/C/. + + <cf><m/C/.max</cf> returns the maximum element of clist <m/C/. + + Operators <cf/.min/, <cf/.max/ can be used together with <cf/filter/ + to extract the community from the specific subset of communities + (e.g. localpref or prepend) without the need to check every possible + value (e.g. <cf/filter(bgp_community, [(23456, 1000..1099)]).min/). + <tag><label id="type-eclist">eclist</tag> Eclist is a data type used for BGP extended community lists. Eclists are very similar to clists, but they are sets of ECs instead of pairs. diff --git a/filter/config.Y b/filter/config.Y index 8034b790..15b77761 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -279,9 +279,11 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, ROA_CHECK, ASN, SRC, DST, IS_V4, IS_V6, LEN, MAXLEN, + DATA, DATA1, DATA2, DEFINED, ADD, DELETE, CONTAINS, RESET, PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH, + MIN, MAX, EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT, STACKS) @@ -790,13 +792,18 @@ term: | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER, $1); } | term '.' LEN { $$ = f_new_inst(FI_LENGTH, $1); } | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN, $1); } - | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN, $1); } + | term '.' ASN { $$ = f_new_inst(FI_ASN, $1); } | term '.' SRC { $$ = f_new_inst(FI_NET_SRC, $1); } | term '.' DST { $$ = f_new_inst(FI_NET_DST, $1); } | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK, $1, $5); } | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST, $1); } | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST, $1); } | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG, $1); } + | term '.' DATA { $$ = f_new_inst(FI_PAIR_DATA, $1); } + | term '.' DATA1 { $$ = f_new_inst(FI_LC_DATA1, $1); } + | term '.' DATA2 { $$ = f_new_inst(FI_LC_DATA2, $1); } + | term '.' MIN { $$ = f_new_inst(FI_MIN, $1); } + | term '.' MAX { $$ = f_new_inst(FI_MAX, $1); } /* Communities */ /* This causes one shift/reduce conflict diff --git a/filter/data.c b/filter/data.c index 7c33d2cb..56c1fb17 100644 --- a/filter/data.c +++ b/filter/data.c @@ -68,6 +68,17 @@ f_type_name(enum f_type t) return "?"; } +enum f_type +f_type_element_type(enum f_type t) +{ + switch(t) { + case T_CLIST: return T_PAIR; + case T_ECLIST: return T_EC; + case T_LCLIST: return T_LC; + default: return T_VOID; + }; +} + const struct f_val f_const_empty_path = { .type = T_PATH, .val.ad = &null_adata, diff --git a/filter/data.h b/filter/data.h index 45246f9f..6d4ca333 100644 --- a/filter/data.h +++ b/filter/data.h @@ -189,6 +189,8 @@ void trie_format(const struct f_trie *t, buffer *buf); const char *f_type_name(enum f_type t); +enum f_type f_type_element_type(enum f_type t); + int val_same(const struct f_val *v1, const struct f_val *v2); int val_compare(const struct f_val *v1, const struct f_val *v2); void val_format(const struct f_val *v, buffer *buf); diff --git a/filter/f-inst.c b/filter/f-inst.c index 0341a2f1..b4795357 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -902,14 +902,31 @@ ((net_addr_roa6 *) v1.val.net)->max_pxlen); } - INST(FI_ROA_ASN, 1, 1) { /* Get ROA ASN */ - ARG(1, T_NET); - if (!net_is_roa(v1.val.net)) - runtime( "ROA expected" ); + INST(FI_ASN, 1, 1) { /* Get ROA ASN or community ASN part */ + ARG_ANY(1); + RESULT_TYPE(T_INT); + switch(v1.type) + { + case T_NET: + if (!net_is_roa(v1.val.net)) + runtime( "ROA expected" ); - RESULT(T_INT, i, (v1.val.net->type == NET_ROA4) ? - ((net_addr_roa4 *) v1.val.net)->asn : - ((net_addr_roa6 *) v1.val.net)->asn); + RESULT_(T_INT, i, (v1.val.net->type == NET_ROA4) ? + ((net_addr_roa4 *) v1.val.net)->asn : + ((net_addr_roa6 *) v1.val.net)->asn); + break; + + case T_PAIR: + RESULT_(T_INT, i, v1.val.i >> 16); + break; + + case T_LC: + RESULT_(T_INT, i, v1.val.lc.asn); + break; + + default: + runtime( "Net, pair or lc expected" ); + } } INST(FI_IP, 1, 1) { /* Convert prefix to ... */ @@ -943,6 +960,89 @@ RESULT(T_INT, i, as_path_get_last_nonaggregated(v1.val.ad)); } + INST(FI_PAIR_DATA, 1, 1) { /* Get data part from the standard community */ + ARG(1, T_PAIR); + RESULT(T_INT, i, v1.val.i & 0xFFFF); + } + + INST(FI_LC_DATA1, 1, 1) { /* Get data1 part from the large community */ + ARG(1, T_LC); + RESULT(T_INT, i, v1.val.lc.ldp1); + } + + INST(FI_LC_DATA2, 1, 1) { /* Get data2 part from the large community */ + ARG(1, T_LC); + RESULT(T_INT, i, v1.val.lc.ldp2); + } + + INST(FI_MIN, 1, 1) { /* Get minimum element from set */ + ARG_ANY(1); + RESULT_TYPE(f_type_element_type(v1.type)); + switch(v1.type) + { + case T_CLIST: + { + u32 val = 0; + int_set_min(v1.val.ad, &val); + RESULT_(T_PAIR, i, val); + } + break; + + case T_ECLIST: + { + u64 val = 0; + ec_set_min(v1.val.ad, &val); + RESULT_(T_EC, ec, val); + } + break; + + case T_LCLIST: + { + lcomm val = { 0, 0, 0 }; + lc_set_min(v1.val.ad, &val); + RESULT_(T_LC, lc, val); + } + break; + + default: + runtime( "Clist or lclist expected" ); + } + } + + INST(FI_MAX, 1, 1) { /* Get maximum element from set */ + ARG_ANY(1); + RESULT_TYPE(f_type_element_type(v1.type)); + switch(v1.type) + { + case T_CLIST: + { + u32 val = 0; + int_set_max(v1.val.ad, &val); + RESULT_(T_PAIR, i, val); + } + break; + + case T_ECLIST: + { + u64 val = 0; + ec_set_max(v1.val.ad, &val); + RESULT_(T_EC, ec, val); + } + break; + + case T_LCLIST: + { + lcomm val = { 0, 0, 0 }; + lc_set_max(v1.val.ad, &val); + RESULT_(T_LC, lc, val); + } + break; + + default: + runtime( "Clist or lclist expected" ); + } + } + INST(FI_RETURN, 1, 1) { NEVER_CONSTANT; /* Acquire the return value */ diff --git a/filter/test.conf b/filter/test.conf index 93e7a770..f373bac5 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -683,6 +683,11 @@ clist l; clist l2; clist r; { + bt_assert((10, 20).asn = 10); + bt_assert((10, 20).data = 20); + bt_assert(p23.asn = 2); + bt_assert(p23.data = 3); + l = - empty -; bt_assert(l !~ [(*,*)]); bt_assert((l ~ [(*,*)]) != (l !~ [(*,*)])); @@ -775,6 +780,12 @@ clist r; r = filter(l, [(3,1), (*,2)]); bt_assert(r = add(add(-empty-, (3,1)), (3,2))); bt_assert(format(r) = "(clist (3,1) (3,2))"); + + # minimim & maximum element + r = add(add(add(add(add(-empty-, (2,1)), (1,3)), (2,2)), (3,1)), (2,3)); + bt_assert(format(r) = "(clist (2,1) (1,3) (2,2) (3,1) (2,3))"); + bt_assert(r.min = (1,3)); + bt_assert(r.max = (3,1)); } bt_test_suite(t_clist, "Testing lists of communities"); @@ -880,6 +891,12 @@ eclist r; r = filter(el, [(rt, 10, 1), (rt, 10, 25..30), (ro, 10, 40)]); bt_assert(r = add(add(--empty--, (rt, 10, 1)), (rt, 10, 30))); bt_assert(format(r) = "(eclist (rt, 10, 1) (rt, 10, 30))"); + + # minimim & maximum element + r = add(add(add(add(add(--empty--, (rt, 2, 1)), (rt, 1, 3)), (rt, 2, 2)), (rt, 3, 1)), (rt, 2, 3)); + bt_assert(format(r) = "(eclist (rt, 2, 1) (rt, 1, 3) (rt, 2, 2) (rt, 3, 1) (rt, 2, 3))"); + bt_assert(r.min = (rt, 1, 3)); + bt_assert(r.max = (rt, 3, 1)); } bt_test_suite(t_eclist, "Testing lists of extended communities"); @@ -939,6 +956,10 @@ lclist r; bt_assert(---empty--- = ---empty---); bt_assert((10, 20, 30) !~ ---empty---); + bt_assert((10, 20, 30).asn = 10); + bt_assert((10, 20, 30).data1 = 20); + bt_assert((10, 20, 30).data2 = 30); + ll = --- empty ---; ll = add(ll, (ten, 20, 30)); ll = add(ll, (1000, 2000, 3000)); @@ -985,6 +1006,12 @@ lclist r; r = filter(ll, [(5..15, *, *), (20, 15..25, *)]); bt_assert(r = add(add(---empty---, (10, 10, 10)), (20, 20, 20))); bt_assert(format(r) = "(lclist (10, 10, 10) (20, 20, 20))"); + + # minimim & maximum element + r = add(add(add(add(add(---empty---, (2, 3, 3)), (1, 2, 3)), (2, 3, 1)), (3, 1, 2)), (2, 1, 3)); + bt_assert(format(r) = "(lclist (2, 3, 3) (1, 2, 3) (2, 3, 1) (3, 1, 2) (2, 1, 3))"); + bt_assert(r.min = (1, 2, 3)); + bt_assert(r.max = (3, 1, 2)); } bt_test_suite(t_lclist, "Testing lists of large communities"); diff --git a/nest/a-set.c b/nest/a-set.c index 1186eb56..71fbac94 100644 --- a/nest/a-set.c +++ b/nest/a-set.c @@ -516,6 +516,48 @@ int_set_sort(struct linpool *pool, const struct adata *src) return dst; } +int +int_set_min(const struct adata *list, u32 *val) +{ + if (!list) + return 0; + + u32 *l = (u32 *) list->data; + int len = int_set_get_size(list); + int i; + + if (len < 1) + return 0; + + *val = *l++; + for (i = 1; i < len; i++, l++) + if (int_set_cmp(val, l) > 0) + *val = *l; + + return 1; +} + +int +int_set_max(const struct adata *list, u32 *val) +{ + if (!list) + return 0; + + u32 *l = (u32 *) list->data; + int len = int_set_get_size(list); + int i; + + if (len < 1) + return 0; + + *val = *l++; + for (i = 1; i < len; i++, l++) + if (int_set_cmp(val, l) < 0) + *val = *l; + + return 1; +} + static int ec_set_cmp(const void *X, const void *Y) @@ -541,6 +583,50 @@ ec_set_sort_x(struct adata *set) qsort(set->data, set->length / 8, 8, ec_set_cmp); } +int +ec_set_min(const struct adata *list, u64 *val) +{ + if (!list) + return 0; + + u32 *l = int_set_get_data(list); + int len = int_set_get_size(list); + int i; + + if (len < 1) + return 0; + + u32 *res = l; l += 2; + for (i = 2; i < len; i += 2, l += 2) + if (ec_set_cmp(res, l) > 0) + res = l; + + *val = ec_generic(res[0], res[1]); + return 1; +} + +int +ec_set_max(const struct adata *list, u64 *val) +{ + if (!list) + return 0; + + u32 *l = int_set_get_data(list); + int len = int_set_get_size(list); + int i; + + if (len < 1) + return 0; + + u32 *res = l; l += 2; + for (i = 2; i < len; i += 2, l += 2) + if (ec_set_cmp(res, l) < 0) + res = l; + + *val = ec_generic(res[0], res[1]); + return 1; +} + static int lc_set_cmp(const void *X, const void *Y) @@ -563,3 +649,47 @@ lc_set_sort(struct linpool *pool, const struct adata *src) qsort(dst->data, dst->length / LCOMM_LENGTH, LCOMM_LENGTH, lc_set_cmp); return dst; } + +int +lc_set_min(const struct adata *list, lcomm *val) +{ + if (!list) + return 0; + + u32 *l = int_set_get_data(list); + int len = int_set_get_size(list); + int i; + + if (len < 1) + return 0; + + u32 *res = l; l += 3; + for (i = 3; i < len; i += 3, l += 3) + if (lc_set_cmp(res, l) > 0) + res = l; + + *val = (lcomm) { res[0], res[1], res[2] }; + return 1; +} + +int +lc_set_max(const struct adata *list, lcomm *val) +{ + if (!list) + return 0; + + u32 *l = int_set_get_data(list); + int len = int_set_get_size(list); + int i; + + if (len < 1) + return 0; + + u32 *res = l; l += 3; + for (i = 3; i < len; i += 3, l += 3) + if (lc_set_cmp(res, l) < 0) + res = l; + + *val = (lcomm) { res[0], res[1], res[2] }; + return 1; +} diff --git a/nest/attrs.h b/nest/attrs.h index 50da817b..ef2b95e6 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -218,6 +218,12 @@ struct adata *ec_set_del_nontrans(struct linpool *pool, const struct adata *set) struct adata *int_set_sort(struct linpool *pool, const struct adata *src); struct adata *ec_set_sort(struct linpool *pool, const struct adata *src); struct adata *lc_set_sort(struct linpool *pool, const struct adata *src); +int int_set_min(const struct adata *list, u32 *val); +int ec_set_min(const struct adata *list, u64 *val); +int lc_set_min(const struct adata *list, lcomm *val); +int int_set_max(const struct adata *list, u32 *val); +int ec_set_max(const struct adata *list, u64 *val); +int lc_set_max(const struct adata *list, lcomm *val); void ec_set_sort_x(struct adata *set); /* Sort in place */ diff --git a/proto/rpki/packets.c b/proto/rpki/packets.c index abe6abfc..d7895a22 100644 --- a/proto/rpki/packets.c +++ b/proto/rpki/packets.c @@ -729,6 +729,33 @@ rpki_handle_prefix_pdu(struct rpki_cache *cache, const struct pdu_header *pdu) net_addr_union addr = {}; rpki_prefix_pdu_2_net_addr(pdu, &addr); + if (type == IPV4_PREFIX) + { + if ((addr.roa4.pxlen > addr.roa4.max_pxlen) || + (addr.roa4.max_pxlen > IP4_MAX_PREFIX_LENGTH)) + { + RPKI_WARN(cache->p, "Received corrupt packet from RPKI cache server: invalid pxlen or max_pxlen"); + byte tmp[pdu->len]; + const struct pdu_header *hton_pdu = rpki_pdu_back_to_network_byte_order((void *) tmp, (const void *) pdu); + rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, hton_pdu, "Corrupted PDU: invalid pxlen or max_pxlen"); + rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL); + return RPKI_ERROR; + } + } + else + { + if ((addr.roa6.pxlen > addr.roa6.max_pxlen) || + (addr.roa6.max_pxlen > IP6_MAX_PREFIX_LENGTH)) + { + RPKI_WARN(cache->p, "Received corrupt packet from RPKI cache server: invalid pxlen or max_pxlen"); + byte tmp[pdu->len]; + const struct pdu_header *hton_pdu = rpki_pdu_back_to_network_byte_order((void *) tmp, (const void *) pdu); + rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, hton_pdu, "Corrupted PDU: invalid pxlen or max_pxlen"); + rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL); + return RPKI_ERROR; + } + } + if (cf->ignore_max_length) { if (type == IPV4_PREFIX) diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 923001bf..fb407739 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -368,6 +368,30 @@ krt_replace_rte(struct krt_proto *p, const net_addr *n UNUSED, rte *new, const r } } +/** + * krt_assume_onlink - check if routes on interface are considered onlink + * @iface: The interface of the next hop + * @ipv6: Switch to only consider IPv6 or IPv4 addresses. + * + * The BSD kernel does not support an onlink flag. If the interface has only + * host addresses configured, all routes should be considered as onlink and + * the function returns 1. + */ +static int +krt_assume_onlink(struct iface *iface, int ipv6) +{ + const u8 type = ipv6 ? NET_IP6 : NET_IP4; + + struct ifa *ifa; + WALK_LIST(ifa, iface->addrs) + { + if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST)) + return 0; + } + + return 1; +} + #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0) static void @@ -525,15 +549,21 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) a.dest = RTD_UNICAST; if (flags & RTF_GATEWAY) { - neighbor *ng; a.nh.gw = igate; /* Clean up embedded interface ID returned in link-local address */ if (ipa_is_link_local(a.nh.gw)) _I0(a.nh.gw) = 0xfe800000; - ng = neigh_find(&p->p, a.nh.gw, a.nh.iface, 0); - if (!ng || (ng->scope == SCOPE_HOST)) + /* The BSD kernel does not support an onlink flag. We heuristically + set the onlink flag, if the iface has only host addresses. */ + if (krt_assume_onlink(a.nh.iface, ipv6)) + a.nh.flags |= RNF_ONLINK; + + neighbor *nbr; + nbr = neigh_find(&p->p, a.nh.gw, a.nh.iface, + (a.nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0); + if (!nbr || (nbr->scope == SCOPE_HOST)) { /* Ignore routes with next-hop 127.0.0.1, host routes with such next-hop appear on OpenBSD for address aliases. */ |