summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml104
-rw-r--r--doc/bird.sgml18
-rw-r--r--filter/config.Y9
-rw-r--r--filter/data.c11
-rw-r--r--filter/data.h2
-rw-r--r--filter/f-inst.c114
-rw-r--r--filter/test.conf27
-rw-r--r--nest/a-set.c130
-rw-r--r--nest/attrs.h6
-rw-r--r--proto/rpki/packets.c27
-rw-r--r--sysdep/bsd/krt-sock.c36
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. */