diff --git a/doc/bird.sgml b/doc/bird.sgml index b475830e..db9a7474 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -646,7 +646,7 @@ incompatible with each other (that is to prevent you from shooting in the foot). but 1.0.0.0/16 ˜ [ 1.0.0.0/8- ] is false. Cisco-style patterns like 10.0.0.0/8 ge 16 le 24 can be expressed - in Bird as 10.0.0.0/8{16,24}, 192.168.0.0/16 le 24 as + in BIRD as 10.0.0.0/8{16,24}, 192.168.0.0/16 le 24 as 192.168.0.0/16{16,24} and 192.168.0.0/16 ge 24 as 192.168.0.0/16{24,32}. @@ -887,12 +887,28 @@ for each neighbor using the following configuration parameters: we should route via our direct neighbor with address next hop self Avoid calculation of the Next Hop attribute - and always advertise our own source address (see below) as a next hop. - This needs to be used only - occasionally to circumvent misconfigurations of other routers. + next hop self Avoid calculation of the Next Hop + attribute and always advertise our own source address (see + below) as a next hop. This needs to be used only occasionally + to circumvent misconfigurations of other routers. Default: disabled. + missing lladdr self|drop|ignoreNext Hop attribute + in BGP-IPv6 sometimes contains just the global IPv6 address, + but sometimes it has to contain both global and link-local + IPv6 addresses. This option specifies what to do if BIRD have + to send both addresses but does not know link-local address. + This situation might happen when routes from other protocols + are exported to BGP, or when improper updates are received + from BGP peers. source address Define local address we should use for next hop calculation. Default: the address of the local end of the interface our neighbor is connected to. @@ -920,7 +936,7 @@ for each neighbor using the following configuration parameters: as a route server client. A route server is used as a replacement for full mesh EBGP routing in Internet exchange points in a similar way to route reflectors used in IBGP routing. - Bird does not implement obsoleted RFC 1863, but uses ad-hoc implementation, + BIRD does not implement obsoleted RFC 1863, but uses ad-hoc implementation, which behaves like plain EBGP but reduces modifications to advertised route attributes to be transparent (for example does not prepend its AS number to AS PATH attribute and keep MED attribute). Default: disabled. diff --git a/nest/config.Y b/nest/config.Y index f2879430..3d6f1548 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -141,7 +141,7 @@ proto_item: | EXPORT imexport { this_proto->out_filter = $2; } | TABLE rtable { this_proto->table = $2; } | ROUTER ID idval { this_proto->router_id = $3; } - | DESCRIPTION dsc { this_proto->dsc = $2; } + | DESCRIPTION TEXT { this_proto->dsc = $2; } ; imexport: diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index b38c6b13..cde02768 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -886,6 +886,10 @@ bgp_check(struct bgp_config *c) if ((c->local_as == c->remote_as) && (c->rs_client)) cf_error("Only external neighbor can be RS client"); + + /* Different default based on rs_client */ + if (c->missing_lladdr == 0) + c->missing_lladdr = c->rs_client ? MLL_DROP : MLL_SELF; } static char *bgp_state_names[] = { "Idle", "Connect", "Active", "OpenSent", "OpenConfirm", "Established", "Close" }; diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index c487aafb..c4d03352 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -23,6 +23,7 @@ struct bgp_config { ip_addr multihop_via; /* Multihop: address to route to */ ip_addr source_addr; /* Source address to use */ int next_hop_self; /* Always set next hop to local IP address */ + int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */ int compare_path_lengths; /* Use path lengths when selecting best route */ int prefer_older; /* Prefer older routes according to RFC 5004 */ u32 default_local_pref; /* Default value for LOCAL_PREF attribute */ @@ -46,6 +47,10 @@ struct bgp_config { char *password; /* Password used for MD5 authentication */ }; +#define MLL_SELF 1 +#define MLL_DROP 2 +#define MLL_IGNORE 3 + struct bgp_conn { struct bgp_proto *bgp; struct birdsock *sk; diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 94011750..35769466 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -22,7 +22,8 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE, BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP, BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY, SOURCE, ADDRESS, PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE, IPV4, - CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER) + CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR, + DROP, IGNORE) CF_GRAMMAR @@ -64,6 +65,9 @@ bgp_proto: | bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; } | bgp_proto MULTIHOP expr VIA ipa ';' { BGP_CFG->multihop = $3; BGP_CFG->multihop_via = $5; } | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; } + | bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; } + | bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; } + | bgp_proto MISSING LLADDR IGNORE ';' { BGP_CFG->missing_lladdr = MLL_IGNORE; } | bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; } | bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; } | bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; } diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index d126fe5f..4176c9fe 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -199,7 +199,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) if (a_size < 0) { - log(L_ERR "%s: Attribute list too long, skipping corresponding route group", p->p.name); + log(L_ERR "%s: Attribute list too long, skipping corresponding routes", p->p.name); bgp_flush_prefixes(p, buck); rem_node(&buck->send_node); bgp_free_bucket(p, buck); @@ -234,9 +234,9 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) { struct bgp_proto *p = conn->bgp; struct bgp_bucket *buck; - int size, second; + int size, second, rem_stored; int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4; - byte *w, *tmp, *tstart; + byte *w, *w_stored, *tmp, *tstart; ip_addr *ipp, ip, ip_ll; ea_list *ea; eattr *nh; @@ -272,28 +272,25 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) } DBG("Processing bucket %p\n", buck); - size = bgp_encode_attrs(p, w, buck->eattrs, 2048); + rem_stored = remains; + w_stored = w; + size = bgp_encode_attrs(p, w, buck->eattrs, 2048); if (size < 0) { - log(L_ERR "%s: Attribute list too long, ignoring corresponding route group", p->p.name); + log(L_ERR "%s: Attribute list too long, skipping corresponding routes", p->p.name); bgp_flush_prefixes(p, buck); rem_node(&buck->send_node); bgp_free_bucket(p, buck); continue; } - w += size; remains -= size; - tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8); - *tmp++ = 0; - *tmp++ = BGP_AF_IPV6; - *tmp++ = 1; + + /* We have two addresses here in NEXT_HOP eattr. Really. + Unless NEXT_HOP was modified by filter */ nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); ASSERT(nh); - - /* We have two addresses here in 'nh'. Really. - Unless NEXT_HOP was modified by filter */ second = (nh->u.ptr->length == NEXT_HOP_LENGTH); ipp = (ip_addr *) nh->u.ptr->data; ip = ipp[0]; @@ -322,12 +319,32 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) ip_ll = ipp[1]; else { - ip = p->source_addr; - ip_ll = p->local_link; + switch (p->cf->missing_lladdr) + { + case MLL_SELF: + ip = p->source_addr; + ip_ll = p->local_link; + break; + case MLL_DROP: + log(L_ERR "%s: Missing link-local next hop address, skipping corresponding routes", p->p.name); + w = w_stored; + remains = rem_stored; + bgp_flush_prefixes(p, buck); + rem_node(&buck->send_node); + bgp_free_bucket(p, buck); + continue; + case MLL_IGNORE: + break; + } } } } + tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8); + *tmp++ = 0; + *tmp++ = BGP_AF_IPV6; + *tmp++ = 1; + if (ipa_nonzero(ip_ll)) { *tmp++ = 32;