Found while looking for something else. We did not fully implement RFC7607 the AGGREGATOR and AS4_AGGREGATOR could slip through a AS 0. This fixes the issue. While there also change the check in parse.y to only allow AS 0 for templates (the only case where remote-as can be 0 aka uninitalized). Last but not least, order the RFC by numbers.
OK? -- :wq Claudio Index: bgpd.8 =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.8,v retrieving revision 1.60 diff -u -p -r1.60 bgpd.8 --- bgpd.8 4 Dec 2018 14:13:40 -0000 1.60 +++ bgpd.8 5 Aug 2019 17:06:51 -0000 @@ -353,16 +353,6 @@ control socket .Re .Pp .Rs -.%A W. Kumari -.%A R. Bush -.%A H. Schiller -.%A K. Patel -.%D August 2015 -.%R RFC 7607 -.%T Codification of AS 0 Processing -.Re -.Pp -.Rs .%A L. Blunk .%A M. Karir .%A C. Labovitz @@ -378,6 +368,16 @@ control socket .%D May 2012 .%R RFC 6608 .%T Subcodes for BGP Finite State Machine Error +.Re +.Pp +.Rs +.%A W. Kumari +.%A R. Bush +.%A H. Schiller +.%A K. Patel +.%D August 2015 +.%R RFC 7607 +.%T Codification of AS 0 Processing .Re .Pp .Rs Index: parse.y =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v retrieving revision 1.397 diff -u -p -r1.397 parse.y --- parse.y 5 Aug 2019 08:46:55 -0000 1.397 +++ parse.y 6 Aug 2019 09:39:56 -0000 @@ -4211,7 +4211,7 @@ neighbor_consistent(struct peer *p) if (p->conf.enforce_local_as == ENFORCE_AS_UNDEF) p->conf.enforce_local_as = ENFORCE_AS_ON; - if (p->conf.remote_as == 0 && p->conf.enforce_as != ENFORCE_AS_OFF) { + if (p->conf.remote_as == 0 && !p->conf.template) { yyerror("peer AS may not be zero"); return (-1); } Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.481 diff -u -p -r1.481 rde.c --- rde.c 5 Aug 2019 08:46:55 -0000 1.481 +++ rde.c 6 Aug 2019 15:36:04 -0000 @@ -1508,7 +1508,7 @@ rde_attr_parse(u_char *p, u_int16_t len, struct bgpd_addr nexthop; struct rde_aspath *a = &state->aspath; u_char *op = p, *npath; - u_int32_t tmp32; + u_int32_t tmp32, zero = 0; int error; u_int16_t attr_len, nlen; u_int16_t plen = 0; @@ -1682,12 +1682,25 @@ bad_flags: t[0] = t[1] = 0; UPD_READ(&t[2], p, plen, 2); UPD_READ(&t[4], p, plen, 4); + if (memcmp(t, &zero, sizeof(u_int32_t)) == 0) { + /* As per RFC7606 use "attribute discard". */ + log_peer_warnx(&peer->conf, "bad AGGREGATOR, " + "AS 0 not allowed, attribute discarded"); + break; + } if (attr_optadd(a, flags, type, t, sizeof(t)) == -1) goto bad_list; break; } /* 4-byte ready server take the default route */ + if (memcmp(p, &zero, sizeof(u_int32_t)) == 0) { + /* As per RFC7606 use "attribute discard" here. */ + log_peer_warnx(&peer->conf, "bad AGGREGATOR, " + "AS 0 not allowed, attribute discarded"); + plen += attr_len; + break; + } goto optattr; case ATTR_COMMUNITIES: if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, @@ -1793,6 +1806,13 @@ bad_flags: if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE, ATTR_PARTIAL)) goto bad_flags; + if (memcmp(p, &zero, sizeof(u_int32_t)) == 0) { + /* As per RFC6793 use "attribute discard" here. */ + log_peer_warnx(&peer->conf, "bad AS4_AGGREGATOR, " + "AS 0 not allowed, attribute discarded"); + plen += attr_len; + break; + } a->flags |= F_ATTR_AS4BYTE_NEW; goto optattr; case ATTR_AS4_PATH: