summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/bgpd/bgpd.h3
-rw-r--r--usr.sbin/bgpd/parse.y7
-rw-r--r--usr.sbin/bgpd/session.c40
-rw-r--r--usr.sbin/bgpd/session.h13
4 files changed, 54 insertions, 9 deletions
diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h
index 7f94cb412c3..fd1fc8de1a0 100644
--- a/usr.sbin/bgpd/bgpd.h
+++ b/usr.sbin/bgpd/bgpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bgpd.h,v 1.104 2004/03/02 19:45:04 henning Exp $ */
+/* $OpenBSD: bgpd.h,v 1.105 2004/03/10 11:38:32 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -160,6 +160,7 @@ struct peer_config {
enum announce_type announce_type;
enum enforce_as enforce_as;
char tcp_md5_key[TCP_MD5_KEY_LEN];
+ u_int8_t capabilities;
enum reconf_action reconf_action;
};
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index 702338f294f..b095966ebcf 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.73 2004/03/08 10:48:06 henning Exp $ */
+/* $OpenBSD: parse.y,v 1.74 2004/03/10 11:38:32 henning Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -513,6 +513,9 @@ peeropts : REMOTEAS asnumber {
}
free($4);
}
+ | ANNOUNCE CAPABILITIES yesno {
+ curpeer->conf.capabilities = $3;
+ }
| SET filter_set_opt {
memcpy(&curpeer->conf.attrset, &$2,
sizeof(curpeer->conf.attrset));
@@ -767,6 +770,7 @@ lookup(char *s)
{ "allow", ALLOW},
{ "announce", ANNOUNCE},
{ "any", ANY},
+ { "capabilities", CAPABILITIES},
{ "deny", DENY},
{ "descr", DESCR},
{ "dump", DUMP},
@@ -1193,6 +1197,7 @@ alloc_peer(void)
p->next = NULL;
p->conf.distance = 1;
p->conf.announce_type = ANNOUNCE_UNDEF;
+ p->conf.capabilities = 1;
return (p);
}
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index 8294df159ac..118fd26c5aa 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.127 2004/03/05 21:48:28 henning Exp $ */
+/* $OpenBSD: session.c,v 1.128 2004/03/10 11:38:33 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -365,6 +365,7 @@ void
init_peer(struct peer *p)
{
p->sock = p->wbuf.sock = -1;
+ p->capa.announce = p->conf.capabilities;
change_state(p, STATE_IDLE, EVNT_NONE);
p->IdleHoldTimer = time(NULL); /* start ASAP */
@@ -503,8 +504,13 @@ bgp_fsm(struct peer *peer, enum session_events event)
change_state(peer, STATE_OPENCONFIRM, event);
break;
case EVNT_RCVD_NOTIFICATION:
- parse_notification(peer);
- change_state(peer, STATE_IDLE, event);
+ if (parse_notification(peer)) {
+ change_state(peer, STATE_IDLE, event);
+ /* don't punish, capa negotiation */
+ peer->IdleHoldTimer = time(NULL);
+ peer->IdleHoldTime /= 2;
+ } else
+ change_state(peer, STATE_IDLE, event);
break;
default:
session_notification(peer, ERR_FSM, 0, NULL, 0);
@@ -904,8 +910,17 @@ session_open(struct peer *p)
struct mrt_config *mrt;
u_int16_t len;
int errs = 0, n;
+ u_int8_t op_type, op_len = 0, optparamlen = 0;
+
+ if (p->capa.announce) {
+ /* multiprotocol extensions, RFC 2858 */
+ /* route refresh, RFC 2918 */
+
+ if (op_len > 0)
+ optparamlen = sizeof(op_type) + sizeof(op_len) + op_len;
+ }
- len = MSGSIZE_OPEN_MIN;
+ len = MSGSIZE_OPEN_MIN + optparamlen;
memset(&msg.header.marker, 0xff, sizeof(msg.header.marker));
msg.header.len = htons(len);
@@ -917,7 +932,7 @@ session_open(struct peer *p)
else
msg.holdtime = htons(conf->holdtime);
msg.bgpid = conf->bgpid; /* is already in network byte order */
- msg.optparamlen = 0;
+ msg.optparamlen = optparamlen;
if ((buf = buf_open(len)) == NULL) {
bgp_fsm(p, EVNT_CON_FATAL);
@@ -932,6 +947,15 @@ session_open(struct peer *p)
errs += buf_add(buf, &msg.bgpid, sizeof(msg.bgpid));
errs += buf_add(buf, &msg.optparamlen, sizeof(msg.optparamlen));
+ if (p->capa.announce && optparamlen) {
+ op_type = OPT_PARAM_CAPABILITIES;
+ errs += buf_add(buf, &op_type, sizeof(op_type));
+ errs += buf_add(buf, &op_len, sizeof(op_len));
+
+ /* multiprotocol extensions, RFC 2858 */
+ /* route refresh, RFC 2918 */
+ }
+
if (errs == 0) {
LIST_FOREACH(mrt, &mrt_l, list) {
if (mrt->type != MRT_ALL_OUT)
@@ -1552,9 +1576,13 @@ parse_notification(struct peer *peer)
/* read & parse data section if needed */
- /* log */
log_notification(peer, errcode, subcode, p, datalen);
+ if (errcode == ERR_OPEN && subcode == ERR_OPEN_OPT) {
+ peer->capa.announce = 0;
+ return (1);
+ }
+
return (0);
}
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index 0f36cda28d6..d40cfdec62b 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.34 2004/03/05 21:44:26 henning Exp $ */
+/* $OpenBSD: session.h,v 1.35 2004/03/10 11:38:33 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -94,6 +94,12 @@ enum opt_params {
OPT_PARAM_CAPABILITIES
};
+enum capa_codes {
+ CAPA_NONE,
+ CAPA_MP,
+ CAPA_REFRESH
+};
+
struct msg_header {
u_char marker[16];
u_int16_t len;
@@ -134,10 +140,15 @@ struct peer_auth {
u_int32_t spi_out;
};
+struct peer_capa {
+ u_int8_t announce;
+};
+
struct peer {
struct peer_config conf;
struct peer_stats stats;
struct peer_auth auth;
+ struct peer_capa capa;
u_int32_t remote_bgpid;
u_int16_t holdtime;
enum session_state state;