This diff adds 'reject as-set yes' as an option to filter out AS paths
with AS_SET segement elements. In bgpctl they show up with {} elements,
e.g. 174 6762 24835 { 36893 }.
This diff uses the soft-error path from RFC7606 and because of this
prefixes that have such an AS_SET segment will be removed via
treat-as-withdraw. These prefixes can be seen in `bgpctl show rib in error`.
By default this is turned off.
--
:wq Claudio
Index: bgpctl/output.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
retrieving revision 1.11
diff -u -p -r1.11 output.c
--- bgpctl/output.c 30 Dec 2020 07:31:19 -0000 1.11
+++ bgpctl/output.c 14 Jan 2021 14:31:45 -0000
@@ -647,8 +647,8 @@ show_attr(u_char *data, size_t len, stru
case ATTR_ASPATH:
case ATTR_AS4_PATH:
/* prefer 4-byte AS here */
- e4 = aspath_verify(data, alen, 1);
- e2 = aspath_verify(data, alen, 0);
+ e4 = aspath_verify(data, alen, 1, 0);
+ e2 = aspath_verify(data, alen, 0, 0);
if (e4 == 0 || e4 == AS_ERR_SOFT) {
path = data;
} else if (e2 == 0 || e2 == AS_ERR_SOFT) {
Index: bgpctl/output_json.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output_json.c,v
retrieving revision 1.5
diff -u -p -r1.5 output_json.c
--- bgpctl/output_json.c 30 Dec 2020 07:31:19 -0000 1.5
+++ bgpctl/output_json.c 14 Jan 2021 14:31:57 -0000
@@ -598,8 +598,8 @@ json_attr(u_char *data, size_t len, stru
case ATTR_ASPATH:
case ATTR_AS4_PATH:
/* prefer 4-byte AS here */
- e4 = aspath_verify(data, alen, 1);
- e2 = aspath_verify(data, alen, 0);
+ e4 = aspath_verify(data, alen, 1, 0);
+ e2 = aspath_verify(data, alen, 0, 0);
if (e4 == 0 || e4 == AS_ERR_SOFT) {
path = data;
} else if (e2 == 0 || e2 == AS_ERR_SOFT) {
Index: bgpd/bgpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v
retrieving revision 1.205
diff -u -p -r1.205 bgpd.conf.5
--- bgpd/bgpd.conf.5 16 May 2020 16:58:11 -0000 1.205
+++ bgpd/bgpd.conf.5 14 Jan 2021 14:30:43 -0000
@@ -330,6 +330,20 @@ This renders the decision process nondet
The default is
.Ic ignore .
.Pp
+.It Xo
+.Ic reject Ic as-set
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
+.Em AS paths
+attributes containing
+.Em AS_SET
+path segements will be rejected and
+all prefixes will be treated as withdraws.
+The default is
+.Ic no .
+.Pp
.It Ic router-id Ar dotted-quad
Set the BGP router ID, which must be non-zero and should be unique
within the AS.
@@ -1086,6 +1100,21 @@ statement defines the maximum hops the n
.Pp
.It Ic passive
Do not attempt to actively open a TCP connection to the neighbor system.
+.Pp
+.It Xo
+.Ic reject Ic as-set
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
+.Em AS paths
+attributes containing
+.Em AS_SET
+path segements will be rejected and
+all prefixes will be treated as withdraws.
+The default is inherited from the global
+.Ic reject Ic as-set
+setting.
.Pp
.It Ic remote-as Ar as-number
Set the AS number of the remote system.
Index: bgpd/bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.409
diff -u -p -r1.409 bgpd.h
--- bgpd/bgpd.h 4 Jan 2021 13:40:32 -0000 1.409
+++ bgpd/bgpd.h 14 Jan 2021 14:05:58 -0000
@@ -65,6 +65,7 @@
#define BGPD_FLAG_DECISION_ROUTEAGE 0x0100
#define BGPD_FLAG_DECISION_TRANS_AS 0x0200
#define BGPD_FLAG_DECISION_MED_ALWAYS 0x0400
+#define BGPD_FLAG_NO_AS_SET 0x0800
#define BGPD_LOG_UPDATES 0x0001
@@ -427,6 +428,7 @@ struct peer_config {
#define PEERFLAG_TRANS_AS 0x01
#define PEERFLAG_LOG_UPDATES 0x02
+#define PEERFLAG_NO_AS_SET 0x04
enum network_type {
NETWORK_DEFAULT, /* from network statements */
@@ -1346,7 +1348,7 @@ int aspath_snprint(char *, size_t, voi
int aspath_asprint(char **, void *, u_int16_t);
size_t aspath_strlen(void *, u_int16_t);
u_int32_t aspath_extract(const void *, int);
-int aspath_verify(void *, u_int16_t, int);
+int aspath_verify(void *, u_int16_t, int, int);
#define AS_ERR_LEN -1
#define AS_ERR_TYPE -2
#define AS_ERR_BAD -3
Index: bgpd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.411
diff -u -p -r1.411 parse.y
--- bgpd/parse.y 29 Dec 2020 15:30:34 -0000 1.411
+++ bgpd/parse.y 14 Jan 2021 14:17:19 -0000
@@ -623,6 +623,12 @@ conf_main : AS as4number {
else
conf->flags &= ~BGPD_FLAG_DECISION_TRANS_AS;
}
+ | REJECT ASSET yesno {
+ if ($3 == 1)
+ conf->flags |= BGPD_FLAG_NO_AS_SET;
+ else
+ conf->flags &= ~BGPD_FLAG_NO_AS_SET;
+ }
| LOG STRING {
if (!strcmp($2, "updates"))
conf->log |= BGPD_LOG_UPDATES;
@@ -1657,6 +1663,12 @@ peeropts : REMOTEAS as4number {
}
free($2);
}
+ | REJECT ASSET yesno {
+ if ($3 == 1)
+ curpeer->conf.flags |= PEERFLAG_NO_AS_SET;
+ else
+ curpeer->conf.flags &= ~PEERFLAG_NO_AS_SET;
+ }
;
restart : /* nada */ { $$ = 0; }
@@ -3815,6 +3827,8 @@ alloc_peer(void)
if (conf->flags & BGPD_FLAG_DECISION_TRANS_AS)
p->conf.flags |= PEERFLAG_TRANS_AS;
+ if (conf->flags & BGPD_FLAG_NO_AS_SET)
+ p->conf.flags |= PEERFLAG_NO_AS_SET;
return (p);
}
Index: bgpd/rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.512
diff -u -p -r1.512 rde.c
--- bgpd/rde.c 13 Jan 2021 11:34:01 -0000 1.512
+++ bgpd/rde.c 14 Jan 2021 14:00:03 -0000
@@ -79,6 +79,7 @@ static void rde_softreconfig_in(struct
static void rde_softreconfig_sync_reeval(struct rib_entry *, void *);
static void rde_softreconfig_sync_fib(struct rib_entry *, void *);
static void rde_softreconfig_sync_done(void *, u_int8_t);
+static int rde_no_as_set(struct rde_peer *);
int rde_update_queue_pending(void);
void rde_update_queue_runner(void);
void rde_update6_queue_runner(u_int8_t);
@@ -1591,7 +1592,8 @@ bad_flags:
case ATTR_ASPATH:
if (!CHECK_FLAGS(flags, ATTR_WELL_KNOWN, 0))
goto bad_flags;
- error = aspath_verify(p, attr_len, rde_as4byte(peer));
+ error = aspath_verify(p, attr_len, rde_as4byte(peer),
+ rde_no_as_set(peer));
if (error == AS_ERR_SOFT) {
/*
* soft errors like unexpected segment types are
@@ -1599,8 +1601,6 @@ bad_flags:
* marked invalid.
*/
a->flags |= F_ATTR_PARSE_ERR;
- log_peer_warnx(&peer->conf, "bad ASPATH, "
- "path invalidated and prefix withdrawn");
} else if (error != 0) {
rde_update_err(peer, ERR_UPDATE, ERR_UPD_ASPATH,
NULL, 0);
@@ -1616,6 +1616,15 @@ bad_flags:
if (npath == NULL)
fatal("aspath_inflate");
}
+ if (error == AS_ERR_SOFT) {
+ char *str;
+
+ aspath_asprint(&str, npath, nlen);
+ log_peer_warnx(&peer->conf, "bad ASPATH %s, "
+ "path invalidated and prefix withdrawn",
+ str ? str : "(bad aspath)");
+ free(str);
+ }
a->flags |= F_ATTR_ASPATH;
a->aspath = aspath_get(npath, nlen);
if (npath != p)
@@ -1842,7 +1851,8 @@ bad_flags:
if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
ATTR_PARTIAL))
goto bad_flags;
- if ((error = aspath_verify(p, attr_len, 1)) != 0) {
+ if ((error = aspath_verify(p, attr_len, 1,
+ rde_no_as_set(peer))) != 0) {
/*
* XXX RFC does not specify how to handle errors.
* XXX Instead of dropping the session because of a
@@ -3583,6 +3593,12 @@ int
rde_as4byte(struct rde_peer *peer)
{
return (peer->capa.as4byte);
+}
+
+static int
+rde_no_as_set(struct rde_peer *peer)
+{
+ return (peer->conf.flags & PEERFLAG_NO_AS_SET);
}
/* End-of-RIB marker, RFC 4724 */
Index: bgpd/util.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
retrieving revision 1.58
diff -u -p -r1.58 util.c
--- bgpd/util.c 5 Jan 2021 10:00:28 -0000 1.58
+++ bgpd/util.c 14 Jan 2021 13:54:48 -0000
@@ -331,7 +331,7 @@ aspath_extract(const void *seg, int pos)
* Verify that the aspath is correctly encoded.
*/
int
-aspath_verify(void *data, u_int16_t len, int as4byte)
+aspath_verify(void *data, u_int16_t len, int as4byte, int noset)
{
u_int8_t *seg = data;
u_int16_t seg_size, as_size = 2;
@@ -364,6 +364,12 @@ aspath_verify(void *data, u_int16_t len,
* bgp session running.
*/
if (seg_type == AS_CONFED_SEQUENCE || seg_type == AS_CONFED_SET)
+ error = AS_ERR_SOFT;
+ /*
+ * If AS_SET filtering (RFC6472) is on, error out on AS_SET
+ * as well.
+ */
+ if (noset && seg_type == AS_SET)
error = AS_ERR_SOFT;
if (seg_type != AS_SET && seg_type != AS_SEQUENCE &&
seg_type != AS_CONFED_SEQUENCE && seg_type != AS_CONFED_SET)