From: claudio Date: Mon, 30 Jan 2023 16:51:34 +0000 (+0000) Subject: Alter the way extended communities are matched when part of the value X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=b2402ebb883a47f43803ca92f4436daec6817b86;p=openbsd Alter the way extended communities are matched when part of the value is auto-expanded or masked off. Try to match against both 2- and 4-byte AS encoding and on insertion check if expansion is actually possible and deny communities where both community values are > USHRT_MAX. OK tb@ --- diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index de3ee73929c..74ce8fd008e 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.440 2023/01/24 14:13:11 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.441 2023/01/30 16:51:34 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -4083,11 +4083,11 @@ parseextvalue(int type, char *s, uint32_t *v, uint32_t *flag) } else if (strcmp(s, "neighbor-as") == 0) { *flag = COMMUNITY_NEIGHBOR_AS; *v = 0; - return EXT_COMMUNITY_TRANS_FOUR_AS; + return EXT_COMMUNITY_TRANS_TWO_AS; } else if (strcmp(s, "local-as") == 0) { *flag = COMMUNITY_LOCAL_AS; *v = 0; - return EXT_COMMUNITY_TRANS_FOUR_AS; + return EXT_COMMUNITY_TRANS_TWO_AS; } else if ((p = strchr(s, '.')) == NULL) { /* AS_PLAIN number (4 or 2 byte) */ strtonum(s, 0, USHRT_MAX, &errstr); diff --git a/usr.sbin/bgpd/rde_community.c b/usr.sbin/bgpd/rde_community.c index 8c470480ded..746076d27d4 100644 --- a/usr.sbin/bgpd/rde_community.c +++ b/usr.sbin/bgpd/rde_community.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_community.c,v 1.10 2022/12/28 21:30:16 jmc Exp $ */ +/* $OpenBSD: rde_community.c,v 1.11 2023/01/30 16:51:34 claudio Exp $ */ /* * Copyright (c) 2019 Claudio Jeker @@ -112,6 +112,7 @@ fc2c(struct community *fc, struct rde_peer *peer, struct community *c, c->data3 = type << 8 | subtype; switch (type & EXT_COMMUNITY_VALUE) { case EXT_COMMUNITY_TRANS_TWO_AS: + case EXT_COMMUNITY_TRANS_FOUR_AS: if ((fc->flags >> 8 & 0xff) == COMMUNITY_ANY) break; @@ -121,11 +122,9 @@ fc2c(struct community *fc, struct rde_peer *peer, struct community *c, if (apply_flag(fc->data2, fc->flags >> 16, peer, &c->data2, m ? &m->data2 : NULL)) return -1; - /* check that values fit */ - if (c->data1 > USHRT_MAX) - return -1; + if (m) + m->data3 &= ~(EXT_COMMUNITY_TRANS_FOUR_AS << 8); return 0; - case EXT_COMMUNITY_TRANS_FOUR_AS: case EXT_COMMUNITY_TRANS_IPV4: if ((fc->flags >> 8 & 0xff) == COMMUNITY_ANY) break; @@ -268,7 +267,6 @@ struct rde_peer *peer) sizeof(*fc), fast_match) != NULL); } else { /* slow path */ - if (fc2c(fc, peer, &test, &mask) == -1) return 0; @@ -335,6 +333,24 @@ struct rde_peer *peer) } else { if (fc2c(fc, peer, &set, NULL) == -1) return 0; + if ((uint8_t)set.flags == COMMUNITY_TYPE_EXT) { + int type = (int)set.data3 >> 8; + switch (type & EXT_COMMUNITY_VALUE) { + case EXT_COMMUNITY_TRANS_TWO_AS: + case EXT_COMMUNITY_TRANS_FOUR_AS: + /* check that values fit */ + if (set.data1 > USHRT_MAX && + set.data2 > USHRT_MAX) + return 0; + if (set.data1 > USHRT_MAX) + set.data3 = (set.data3 & 0xff) | + EXT_COMMUNITY_TRANS_FOUR_AS << 8; + else + set.data3 = (set.data3 & 0xff) | + EXT_COMMUNITY_TRANS_TWO_AS << 8; + break; + } + } insert_community(comm, &set); } return 1;