diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-03-10 11:38:34 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-03-10 11:38:34 +0000 |
commit | abad3baed4b13617494132f3b7093177b1632689 (patch) | |
tree | d962ec01cd551fcb8b25c02377ca79126b03b13e /usr.sbin/bgpd | |
parent | fd7b9fc3b134fe231ec808a21c97c2a2d0824660 (diff) |
implement framework to announce capabilities in the open messages we send.
this includes handling "unsupported optional parameter" notifications from the
peer and retrying without capability announcement. claudio ok
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/bgpd.h | 3 | ||||
-rw-r--r-- | usr.sbin/bgpd/parse.y | 7 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.c | 40 | ||||
-rw-r--r-- | usr.sbin/bgpd/session.h | 13 |
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; |