diff options
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/attrs.c | 7 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 20 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 2 | ||||
-rw-r--r-- | proto/bgp/config.Y | 4 | ||||
-rw-r--r-- | proto/bgp/packets.c | 29 |
5 files changed, 46 insertions, 16 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index d0ec41f..d839ed0 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -996,7 +996,7 @@ bgp_get_neighbor(rte *r) eattr *e = ea_find(r->attrs->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH)); u32 as; - if (e && as_path_get_last(e->u.ptr, &as)) + if (e && as_path_get_first(e->u.ptr, &as)) return as; else return ((struct bgp_proto *) r->attrs->proto)->remote_as; @@ -1191,7 +1191,7 @@ bgp_reconstruct_4b_atts(struct bgp_proto *p, rta *a, struct linpool *pool) if (a4) log(L_WARN "%s: AS4_AGGREGATOR attribute received, but AGGREGATOR attribute is missing", p->p.name); - int p2_len = as_path_getlen(p2->u.ptr); + int p2_len = as_path_getlen_int(p2->u.ptr, 2); int p4_len = p4 ? validate_as4_path(p, p4->u.ptr) : -1; if (p4 && (p4_len < 0)) @@ -1247,7 +1247,6 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin int errcode; byte *z, *attr_start; byte seen[256/8]; - eattr *e; ea_list *ea; struct adata *ad; @@ -1471,7 +1470,7 @@ bgp_get_route_info(rte *e, byte *buf, ea_list *attrs) u32 origas; buf += bsprintf(buf, " (%d) [", e->pref); - if (p && as_path_get_first(p->u.ptr, &origas)) + if (p && as_path_get_last(p->u.ptr, &origas)) buf += bsprintf(buf, "AS%u", origas); if (o) buf += bsprintf(buf, "%c", "ie?"[o->u.data]); diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index 0c8ee6d..b38c6b1 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -120,7 +120,9 @@ bgp_startup(struct bgp_proto *p) { BGP_TRACE(D_EVENTS, "Started"); p->start_state = p->cf->capabilities ? BSS_CONNECT : BSS_CONNECT_NOCAP; - bgp_active(p); + + if (!p->cf->passive) + bgp_active(p); } static void @@ -292,7 +294,8 @@ bgp_decision(void *vp) DBG("BGP: Decision start\n"); if ((p->p.proto_state == PS_START) - && (p->outgoing_conn.state == BS_IDLE)) + && (p->outgoing_conn.state == BS_IDLE) + && (!p->cf->passive)) bgp_active(p); if ((p->p.proto_state == PS_STOP) @@ -428,8 +431,15 @@ bgp_hold_timeout(timer *t) { struct bgp_conn *conn = t->data; - DBG("BGP: Hold timeout, closing connection\n"); - bgp_error(conn, 4, 0, NULL, 0); + DBG("BGP: Hold timeout\n"); + + /* If there is something in input queue, we are probably congested + and perhaps just not processed BGP packets in time. */ + + if (sk_rx_ready(conn->sk) > 0) + bgp_start_timer(conn->hold_timer, 10); + else + bgp_error(conn, 4, 0, NULL, 0); } static void @@ -679,7 +689,7 @@ bgp_start_locked(struct object_lock *lock) } DBG("BGP: Got lock\n"); - p->local_id = cf->c.global->router_id; + p->local_id = proto_get_router_id(&cf->c); p->next_hop = cf->multihop ? cf->multihop_via : cf->remote_ip; p->neigh = neigh_find(&p->p, &p->next_hop, NEF_STICKY); diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 9bbdab8..0a82be2 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -9,6 +9,7 @@ #ifndef _BIRD_BGP_H_ #define _BIRD_BGP_H_ +#include <stdint.h> #include "nest/route.h" struct linpool; @@ -32,6 +33,7 @@ struct bgp_config { int rs_client; /* Whether neighbor is RS client of me */ int advertise_ipv4; /* Whether we should add IPv4 capability advertisement to OPEN message */ u32 route_limit; /* Number of routes that may be imported, 0 means disable limit */ + int passive; /* Do not initiate outgoing connection */ unsigned connect_retry_time; unsigned hold_time, initial_hold_time; unsigned keepalive_time; diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y index 872fb27..7360820 100644 --- a/proto/bgp/config.Y +++ b/proto/bgp/config.Y @@ -22,7 +22,7 @@ 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) + CAPABILITIES, LIMIT, PASSIVE) CF_GRAMMAR @@ -34,7 +34,6 @@ bgp_proto_start: proto_start BGP { BGP_CFG->hold_time = 240; BGP_CFG->connect_retry_time = 120; BGP_CFG->initial_hold_time = 240; - BGP_CFG->default_med = 0; BGP_CFG->compare_path_lengths = 1; BGP_CFG->start_delay_time = 5; BGP_CFG->error_amnesia_time = 300; @@ -78,6 +77,7 @@ bgp_proto: | bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; } | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; } | bgp_proto ROUTE LIMIT expr ';' { BGP_CFG->route_limit = $4; } + | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; } ; CF_ADDTO(dynamic_attr, BGP_PATH diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ac697be..d126fe5 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -234,7 +234,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) { struct bgp_proto *p = conn->bgp; struct bgp_bucket *buck; - int size; + int size, second; int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4; byte *w, *tmp, *tstart; ip_addr *ipp, ip, ip_ll; @@ -292,7 +292,9 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP)); ASSERT(nh); - /* We have two addresses here in 'nh'. Really. */ + /* 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]; ip_ll = IPA_NONE; @@ -316,7 +318,7 @@ bgp_create_update(struct bgp_conn *conn, byte *buf) n = neigh_find(&p->p, &ip, 0); if (n && n->iface == p->neigh->iface) { - if (ipa_nonzero(ipp[1])) + if (second && ipa_nonzero(ipp[1])) ip_ll = ipp[1]; else { @@ -569,7 +571,6 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) { struct bgp_conn *other; struct bgp_proto *p = conn->bgp; - struct bgp_config *cf = p->cf; unsigned hold; u16 base_as; u32 id; @@ -601,7 +602,17 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name); if (conn->advertised_as != p->remote_as) - { bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return; } + { + if (conn->peer_as4_support) + { + u32 val = htonl(conn->advertised_as); + bgp_error(conn, 2, 2, (byte *) &val, 4); + } + else + bgp_error(conn, 2, 2, pkt+20, 2); + + return; + } /* Check the other connection */ other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn; @@ -973,11 +984,19 @@ bgp_log_error(struct bgp_proto *p, u8 class, char *msg, unsigned code, unsigned { *t++ = ':'; *t++ = ' '; + + if ((code == 2) && (subcode == 2) && ((len == 2) || (len == 4))) + { + /* Bad peer AS - we would like to print the AS */ + t += bsprintf(t, "%d", (len == 2) ? get_u16(data) : get_u32(data)); + goto done; + } if (len > 16) len = 16; for (i=0; i<len; i++) t += bsprintf(t, "%02x", data[i]); } + done: *t = 0; log(L_REMOTE "%s: %s: %s%s", p->p.name, msg, name, argbuf); } |