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/session.c | |
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/session.c')
-rw-r--r-- | usr.sbin/bgpd/session.c | 40 |
1 files changed, 34 insertions, 6 deletions
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); } |