diff options
Diffstat (limited to 'usr.sbin/bgpd/session.c')
-rw-r--r-- | usr.sbin/bgpd/session.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c index 9f8e7718d22..1f00f61a599 100644 --- a/usr.sbin/bgpd/session.c +++ b/usr.sbin/bgpd/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.272 2007/03/28 11:53:48 claudio Exp $ */ +/* $OpenBSD: session.c,v 1.273 2007/04/23 13:04:24 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org> @@ -32,6 +32,7 @@ #include <err.h> #include <errno.h> #include <fcntl.h> +#include <limits.h> #include <poll.h> #include <pwd.h> #include <signal.h> @@ -82,7 +83,7 @@ int parse_open(struct peer *); int parse_update(struct peer *); int parse_refresh(struct peer *); int parse_notification(struct peer *); -int parse_capabilities(struct peer *, u_char *, u_int16_t); +int parse_capabilities(struct peer *, u_char *, u_int16_t, u_int32_t *); void session_dispatch_imsg(struct imsgbuf *, int, u_int *); void session_up(struct peer *); void session_down(struct peer *); @@ -1247,6 +1248,7 @@ session_capa_ann_none(struct peer *peer) peer->capa.ann.mp_v4 = SAFI_NONE; peer->capa.ann.refresh = 0; peer->capa.ann.restart = 0; + peer->capa.ann.as4byte = 0; } int @@ -1380,6 +1382,15 @@ session_open(struct peer *p) errs += buf_add(opb, &c, 4); } + /* 4-bytes AS numbers, draft-ietf-idr-as4bytes-12 */ + if (p->capa.ann.as4byte) { /* 4 bytes data */ + u_int32_t nas; + + nas = htonl(conf->as); + errs += session_capa_add(p, opb, CAPA_AS4BYTE, 4, &optparamlen); + errs += buf_add(opb, &nas, 4); + } + len = MSGSIZE_OPEN_MIN + optparamlen; if (errs || (buf = session_newmsg(OPEN, len)) == NULL) { buf_free(opb); @@ -1388,7 +1399,10 @@ session_open(struct peer *p) } msg.version = 4; - msg.myas = htons(conf->as); + if (conf->as > USHRT_MAX) + msg.myas = htons(conf->short_as); + else + msg.myas = htons(conf->as); if (p->conf.holdtime) msg.holdtime = htons(p->conf.holdtime); else @@ -1816,9 +1830,9 @@ parse_open(struct peer *peer) { u_char *p, *op_val; u_int8_t version, rversion; - u_int16_t as, msglen; + u_int16_t short_as, msglen; u_int16_t holdtime, oholdtime, myholdtime; - u_int32_t bgpid; + u_int32_t as, bgpid; u_int8_t optparamlen, plen; u_int8_t op_type, op_len; @@ -1846,22 +1860,16 @@ parse_open(struct peer *peer) return (-1); } - memcpy(&as, p, sizeof(as)); - p += sizeof(as); + memcpy(&short_as, p, sizeof(short_as)); + p += sizeof(short_as); + as = peer->short_as = ntohs(short_as); /* if remote-as is zero and it's a cloned neighbor, accept any */ - if (peer->conf.cloned && !peer->conf.remote_as) { - peer->conf.remote_as = ntohs(as); + if (peer->conf.cloned && !peer->conf.remote_as && as != AS_TRANS) { + peer->conf.remote_as = as; peer->conf.ebgp = (peer->conf.remote_as != conf->as); } - if (peer->conf.remote_as != ntohs(as)) { - log_peer_warnx(&peer->conf, "peer sent wrong AS %u", ntohs(as)); - session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0); - change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); - return (-1); - } - memcpy(&oholdtime, p, sizeof(oholdtime)); p += sizeof(oholdtime); @@ -1940,7 +1948,8 @@ parse_open(struct peer *peer) switch (op_type) { case OPT_PARAM_CAPABILITIES: /* RFC 3392 */ - if (parse_capabilities(peer, op_val, op_len) == -1) { + if (parse_capabilities(peer, op_val, op_len, + &as) == -1) { session_notification(peer, ERR_OPEN, 0, NULL, 0); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); @@ -1968,6 +1977,14 @@ parse_open(struct peer *peer) } } + if (peer->conf.remote_as != as) { + log_peer_warnx(&peer->conf, "peer sent wrong AS %s", + log_as(as)); + session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0); + change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); + return (-1); + } + return (0); } @@ -2103,6 +2120,11 @@ parse_notification(struct peer *peer) log_peer_warnx(&peer->conf, "disabling restart capability"); break; + case CAPA_AS4BYTE: + peer->capa.ann.as4byte = 0; + log_peer_warnx(&peer->conf, + "disabling 4-byte AS num capability"); + break; default: /* should not happen... */ log_peer_warnx(&peer->conf, "received " "\"unsupported capability\" notification " @@ -2126,7 +2148,7 @@ parse_notification(struct peer *peer) } int -parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen) +parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen, u_int32_t *as) { u_int16_t len; u_int8_t capa_code; @@ -2134,6 +2156,7 @@ parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen) u_char *capa_val; u_int16_t mp_afi; u_int8_t mp_safi; + u_int32_t remote_as; len = dlen; while (len > 0) { @@ -2203,6 +2226,17 @@ parse_capabilities(struct peer *peer, u_char *d, u_int16_t dlen) peer->capa.peer.restart = 1; /* we don't care about the further restart capas yet */ break; + case CAPA_AS4BYTE: + if (capa_len != 4) { + log_peer_warnx(&peer->conf, + "parse_capabilities: " + "expect len 4, len is %u", capa_len); + return (-1); + } + memcpy(&remote_as, capa_val, sizeof(remote_as)); + *as = ntohl(remote_as); + peer->capa.peer.as4byte = 1; + break; default: break; } @@ -2754,6 +2788,7 @@ session_up(struct peer *p) } sup.remote_bgpid = p->remote_bgpid; + sup.short_as = p->short_as; memcpy(&sup.capa_announced, &p->capa.ann, sizeof(sup.capa_announced)); memcpy(&sup.capa_received, &p->capa.peer, sizeof(sup.capa_received)); p->stats.last_updown = time(NULL); |