From abad3baed4b13617494132f3b7093177b1632689 Mon Sep 17 00:00:00 2001 From: Henning Brauer Date: Wed, 10 Mar 2004 11:38:34 +0000 Subject: 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 --- usr.sbin/bgpd/bgpd.h | 3 ++- usr.sbin/bgpd/parse.y | 7 ++++++- usr.sbin/bgpd/session.c | 40 ++++++++++++++++++++++++++++++++++------ usr.sbin/bgpd/session.h | 13 ++++++++++++- 4 files changed, 54 insertions(+), 9 deletions(-) (limited to 'usr.sbin/bgpd') 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 @@ -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 @@ -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 @@ -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 @@ -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; -- cgit v1.2.3