summaryrefslogtreecommitdiff
path: root/usr.sbin/bgpd/session.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2007-04-23 13:04:25 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2007-04-23 13:04:25 +0000
commit08c3c9310d4b3dbbe393bd4048439d572c15a835 (patch)
tree595e0a61227029b9198526b626ac9bce5ac2390e /usr.sbin/bgpd/session.c
parentd1c0f4acb7b6be8baa3fd007c8fde95a78ab1dab (diff)
Make bgpd 4-byte AS compatible. All internal representations of AS numbers
are now 4-byte instead of the old 2-byte numbers. The only exception are communities because they can not be switched. The RDE will inflate and deflate the ASPATH and AGGREGATOR attributes on demand and create the NEW_ASPATH and NEW_AGGREGATOR field whenever needed. Both old and new stile sessions are supported and can be mixed. Currently new stile sessions with the 4-byte AS number capability turned on are only enabled if one of the AS numbers involved is a 4-byte one. This is based on an initial diff by Geoff Huston gih (at) apnic (dot) net Cleanup, testing and bug-fixes by myself (via AS 3.10). Currently mrt table dumps are producing incompatible output this will be fixed afterwards -- this diff is already big enough. "get it in if you think it is ready" henning@
Diffstat (limited to 'usr.sbin/bgpd/session.c')
-rw-r--r--usr.sbin/bgpd/session.c71
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);