diff options
-rw-r--r-- | doc/bird.sgml | 19 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 47 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 18 | ||||
-rw-r--r-- | proto/bgp/packets.c | 33 |
4 files changed, 66 insertions, 51 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index ff2c188f..3ab9dee9 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -2040,6 +2040,16 @@ using the following configuration parameters: source address for the BGP session. Default: the address of the local end of the interface our neighbor is connected to. + <tag><label id="bgp-strict-bind">strict bind <m/switch/</tag> + Specify whether BGP listening socket should be bound to a specific local + address (the same as the <cf/source address/) and associated interface, + or to all addresses. Binding to a specific address could be useful in + cases like running multiple BIRD instances on a machine, each using its + IP address. Note that listening sockets bound to a specific address and + to all addresses collide, therefore either all BGP protocols (of the + same address family and using the same local port) should have set + <cf/strict bind/, or none of them. Default: disabled. + <tag><label id="bgp-next-hop-self">next hop self</tag> Avoid calculation of the Next Hop attribute and always advertise our own source address as a next hop. This needs to be used only occasionally to @@ -2112,7 +2122,7 @@ using the following configuration parameters: Note that full (ICMP protection, for example) <rfc id="5082"> support is provided by Linux only. Default: disabled. - <tag><label id="bgp-pass">password <m/string/</tag> + <tag><label id="bgp-password">password <m/string/</tag> Use this password for MD5 authentication of BGP sessions (<rfc id="2385">). When used on BSD systems, see also <cf/setkey/ option below. Default: no authentication. @@ -2270,13 +2280,6 @@ using the following configuration parameters: This option is relevant to IPv4 mode with enabled capability advertisement only. Default: on. - <tag><label id="bgp-route-limit">route limit <m/number/</tag> - The maximal number of routes that may be imported from the protocol. If - the route limit is exceeded, the connection is closed with an error. - Limit is currently implemented as <cf>import limit <m/number/ action - restart</cf>. This option is obsolete and it is replaced by - <ref id="proto-import-limit" name="import limit option">. Default: no limit. - <tag><label id="bgp-disable-after-error">disable after error <m/switch/</tag> When an error is encountered (either locally or by the other side), disable the instance automatically and wait for an administrator to fix diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index c557403b..d5bf2add 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1325,29 +1325,23 @@ bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li static adata null_adata; /* adata of length 0 */ -static inline void -bgp_cluster_list_prepend(ea_list **attrs, struct linpool *pool, u32 id) -{ - eattr *a = bgp_find_attr(*attrs, BA_CLUSTER_LIST); - adata *d = int_set_add(pool, a ? a->u.ptr : NULL, id); - bgp_set_attr_ptr(attrs, pool, BA_CLUSTER_LIST, 0, d); -} - static ea_list * -bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs, struct linpool *pool) +bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs0, struct linpool *pool) { struct proto *SRC = e->attrs->src->proto; struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (void *) SRC : NULL; struct bgp_export_state s = { .proto = p, .channel =c, .pool = pool, .src = src, .route = e }; + ea_list *attrs = attrs0; eattr *a; + adata *ad; /* ORIGIN attribute - mandatory, attach if missing */ - if (! bgp_find_attr(attrs, BA_ORIGIN)) + if (! bgp_find_attr(attrs0, BA_ORIGIN)) bgp_set_attr_u32(&attrs, pool, BA_ORIGIN, 0, src ? ORIGIN_INCOMPLETE : ORIGIN_IGP); - /* AS_PATH attribute */ - a = bgp_find_attr(attrs, BA_AS_PATH); - adata *ad = a ? a->u.ptr : &null_adata; + /* AS_PATH attribute - mandatory */ + a = bgp_find_attr(attrs0, BA_AS_PATH); + ad = a ? a->u.ptr : &null_adata; /* AS_PATH attribute - strip AS_CONFED* segments outside confederation */ if ((!p->cf->confederation || !p->is_interior) && as_path_contains_confed(ad)) @@ -1374,33 +1368,40 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at bgp_set_attr_ptr(&attrs, pool, BA_AS_PATH, 0, ad); /* MULTI_EXIT_DESC attribute - accept only if set in export filter */ - a = bgp_find_attr(attrs, BA_MULTI_EXIT_DISC); + a = bgp_find_attr(attrs0, BA_MULTI_EXIT_DISC); if (a && !(a->type & EAF_FRESH)) bgp_unset_attr(&attrs, pool, BA_MULTI_EXIT_DISC); } /* NEXT_HOP attribute - delegated to AF-specific hook */ - a = bgp_find_attr(attrs, BA_NEXT_HOP); + a = bgp_find_attr(attrs0, BA_NEXT_HOP); bgp_update_next_hop(&s, a, &attrs); /* LOCAL_PREF attribute - required for IBGP, attach if missing */ - if (p->is_interior && ! bgp_find_attr(attrs, BA_LOCAL_PREF)) + if (p->is_interior && ! bgp_find_attr(attrs0, BA_LOCAL_PREF)) bgp_set_attr_u32(&attrs, pool, BA_LOCAL_PREF, 0, p->cf->default_local_pref); /* IBGP route reflection, RFC 4456 */ if (src && src->is_internal && p->is_internal && (src->local_as == p->local_as)) { /* ORIGINATOR_ID attribute - attach if not already set */ - if (! bgp_find_attr(attrs, BA_ORIGINATOR_ID)) + if (! bgp_find_attr(attrs0, BA_ORIGINATOR_ID)) bgp_set_attr_u32(&attrs, pool, BA_ORIGINATOR_ID, 0, src->remote_id); /* CLUSTER_LIST attribute - prepend cluster ID */ + a = bgp_find_attr(attrs0, BA_CLUSTER_LIST); + ad = a ? a->u.ptr : NULL; + + /* Prepend src cluster ID */ if (src->rr_cluster_id) - bgp_cluster_list_prepend(&attrs, pool, src->rr_cluster_id); + ad = int_set_add(pool, ad, src->rr_cluster_id); - /* Handle different src and dst cluster ID - prepend both ones */ + /* Prepend dst cluster ID if src and dst clusters are different */ if (p->rr_cluster_id && (src->rr_cluster_id != p->rr_cluster_id)) - bgp_cluster_list_prepend(&attrs, pool, p->rr_cluster_id); + ad = int_set_add(pool, ad, p->rr_cluster_id); + + /* Should be at least one prepended cluster ID */ + bgp_set_attr_ptr(&attrs, pool, BA_CLUSTER_LIST, 0, ad); } /* AS4_* transition attributes, RFC 6793 4.2.2 */ @@ -1421,6 +1422,12 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at } } + /* + * Presence of mandatory attributes ORIGIN and AS_PATH is ensured by above + * conditions. Presence and validity of quasi-mandatory NEXT_HOP attribute + * should be checked in AF-specific hooks. + */ + /* Apply per-attribute export hooks for validatation and normalization */ return bgp_export_attrs(&s, attrs); } diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index e5d86075..7d7d349a 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -73,7 +73,7 @@ struct bgp_config { u16 local_port; /* Local listening port */ u16 remote_port; /* Neighbor destination port */ int multihop; /* Number of hops if multihop */ - int strict_bind; /* Bind listening socket to local address XXXX */ + int strict_bind; /* Bind listening socket to local address */ int ttl_security; /* Enable TTL security [RFC 5082] */ int compare_path_lengths; /* Use path lengths when selecting best route */ int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */ @@ -509,22 +509,18 @@ void bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to); #define BAF_PARTIAL 0x20 #define BAF_EXT_LEN 0x10 -#define BA_ORIGIN 0x01 /* [RFC1771] */ /* WM */ +#define BA_ORIGIN 0x01 /* RFC 4271 */ /* WM */ #define BA_AS_PATH 0x02 /* WM */ #define BA_NEXT_HOP 0x03 /* WM */ #define BA_MULTI_EXIT_DISC 0x04 /* ON */ #define BA_LOCAL_PREF 0x05 /* WD */ #define BA_ATOMIC_AGGR 0x06 /* WD */ #define BA_AGGREGATOR 0x07 /* OT */ -#define BA_COMMUNITY 0x08 /* [RFC1997] */ /* OT */ -#define BA_ORIGINATOR_ID 0x09 /* [RFC1966] */ /* ON */ -#define BA_CLUSTER_LIST 0x0a /* ON */ -/* We don't support these: */ -#define BA_DPA 0x0b /* ??? */ -#define BA_ADVERTISER 0x0c /* [RFC1863] */ -#define BA_RCID_PATH 0x0d -#define BA_MP_REACH_NLRI 0x0e /* [RFC2283] */ -#define BA_MP_UNREACH_NLRI 0x0f +#define BA_COMMUNITY 0x08 /* RFC 1997 */ /* OT */ +#define BA_ORIGINATOR_ID 0x09 /* RFC 4456 */ /* ON */ +#define BA_CLUSTER_LIST 0x0a /* RFC 4456 */ /* ON */ +#define BA_MP_REACH_NLRI 0x0e /* RFC 4760 */ +#define BA_MP_UNREACH_NLRI 0x0f /* RFC 4760 */ #define BA_EXT_COMMUNITY 0x10 /* RFC 4360 */ #define BA_AS4_PATH 0x11 /* RFC 6793 */ #define BA_AS4_AGGREGATOR 0x12 /* RFC 6793 */ diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index dbc5fe12..385d5a36 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -713,9 +713,13 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len) #define REPORT(msg, args...) \ ({ log(L_REMOTE "%s: " msg, s->proto->p.name, ## args); }) +#define DISCARD(msg, args...) \ + ({ REPORT(msg, ## args); return; }) + #define WITHDRAW(msg, args...) \ ({ REPORT(msg, ## args); s->err_withdraw = 1; return; }) +#define BAD_AFI "Unexpected AF <%u/%u> in UPDATE" #define BAD_NEXT_HOP "Invalid NEXT_HOP attribute" #define NO_NEXT_HOP "Missing NEXT_HOP attribute" @@ -836,21 +840,27 @@ bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to) static uint bgp_encode_next_hop_none(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED) { - // FIXME return 0; } static void bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, rta *a UNUSED) { - // FIXME + /* + * Although we expect no next hop and RFC 7606 7.11 states that attribute + * MP_REACH_NLRI with unexpected next hop length is considered malformed, + * FlowSpec RFC 5575 4 states that next hop shall be ignored on receipt. + */ + return; } static void -bgp_update_next_hop_none(struct bgp_export_state *s UNUSED, eattr *a UNUSED, ea_list **to UNUSED) +bgp_update_next_hop_none(struct bgp_export_state *s, eattr *a, ea_list **to) { - // FIXME + /* NEXT_HOP shall not pass */ + if (a) + bgp_unset_attr(to, s->pool, BA_NEXT_HOP); } @@ -1652,15 +1662,15 @@ bgp_create_end_mark(struct bgp_channel *c, byte *buf) } static inline void -bgp_rx_end_mark(struct bgp_proto *p, u32 afi) +bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi) { + struct bgp_proto *p = s->proto; struct bgp_channel *c = bgp_get_channel(p, afi); BGP_TRACE(D_PACKETS, "Got END-OF-RIB"); - /* XXXX handle unknown AF in MP_*_NLRI */ if (!c) - return; + DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi)); if (c->load_state == BFS_LOADING) c->load_state = BFS_NONE; @@ -1678,9 +1688,8 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis struct bgp_channel *c = bgp_get_channel(s->proto, afi); rta *a = NULL; - /* XXXX handle unknown AF in MP_*_NLRI */ if (!c) - return; + DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi)); s->channel = c; s->add_path = c->add_path_rx; @@ -1791,12 +1800,12 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len) /* Check for End-of-RIB marker */ if (!s.attr_len && !s.ip_unreach_len && !s.ip_reach_len) - { bgp_rx_end_mark(p, BGP_AF_IPV4); goto done; } + { bgp_rx_end_mark(&s, BGP_AF_IPV4); goto done; } /* Check for MP End-of-RIB marker */ if ((s.attr_len < 8) && !s.ip_unreach_len && !s.ip_reach_len && - !s.mp_reach_len && !s.mp_unreach_len && s.mp_unreach_af) /* XXXX See RFC 7606 5.2 */ - { bgp_rx_end_mark(p, s.mp_unreach_af); goto done; } + !s.mp_reach_len && !s.mp_unreach_len && s.mp_unreach_af) + { bgp_rx_end_mark(&s, s.mp_unreach_af); goto done; } if (s.ip_unreach_len) bgp_decode_nlri(&s, BGP_AF_IPV4, s.ip_unreach_nlri, s.ip_unreach_len, NULL, NULL, 0); |