diff options
Diffstat (limited to 'proto')
-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 | ||||
-rw-r--r-- | proto/ospf/config.Y | 5 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 2 | ||||
-rw-r--r-- | proto/pipe/pipe.c | 3 | ||||
-rw-r--r-- | proto/rip/config.Y | 2 |
9 files changed, 55 insertions, 19 deletions
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index d0ec41f9..d839ed09 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 0c8ee6da..b38c6b13 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 9bbdab8e..0a82be2b 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 872fb271..7360820f 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 ac697be1..d126fe5f 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); } diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 7b2641b2..f75e8eb5 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -45,12 +45,13 @@ finish_iface_config(struct ospf_iface_patt *ip) CF_DECLS -CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG) +CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, BROADCAST) CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT) CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE) CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC) CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK) -CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, LSADB) +CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY) +CF_KEYWORDS(WAIT, DELAY, LSADB) %type <t> opttext diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index 3e33e453..5a11418f 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -786,6 +786,8 @@ static inline void schedule_link_lsa(struct ospf_iface *ifa) {} void ospf_sh_neigh(struct proto *p, char *iff); void ospf_sh(struct proto *p); void ospf_sh_iface(struct proto *p, char *iff); +void ospf_sh_state(struct proto *p, int verbose); + #define EA_OSPF_METRIC1 EA_CODE(EAP_OSPF, 0) #define EA_OSPF_METRIC2 EA_CODE(EAP_OSPF, 1) diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index 8ff430a9..e57c9efd 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -62,11 +62,14 @@ pipe_send(struct pipe_proto *p, rtable *dest, net *n, rte *new, rte *old, ea_lis a.eattrs = attrs; e = rte_get_temp(&a); e->net = nn; + e->pflags = 0; if (p->mode == PIPE_TRANSPARENT) { /* Copy protocol specific embedded attributes. */ memcpy(&(e->u), &(new->u), sizeof(e->u)); + e->pref = new->pref; + e->pflags = new->pflags; } src = new->attrs->proto; diff --git a/proto/rip/config.Y b/proto/rip/config.Y index 9a11069e..2df0c5c8 100644 --- a/proto/rip/config.Y +++ b/proto/rip/config.Y @@ -24,7 +24,7 @@ CF_DEFINES CF_DECLS -CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT, PASSWORDS, +CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT, MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1, AUTHENTICATION, NONE, PLAINTEXT, MD5, HONOR, NEVER, NEIGHBOR, ALWAYS, |