summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bgpd/session.c106
-rw-r--r--usr.sbin/bgpd/session.h4
2 files changed, 84 insertions, 26 deletions
diff --git a/usr.sbin/bgpd/session.c b/usr.sbin/bgpd/session.c
index 9164b24ec14..bcda68724f4 100644
--- a/usr.sbin/bgpd/session.c
+++ b/usr.sbin/bgpd/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.159 2004/04/28 00:38:39 henning Exp $ */
+/* $OpenBSD: session.c,v 1.160 2004/04/28 06:45:37 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -422,6 +422,8 @@ init_peer(struct peer *p)
{
p->sock = p->wbuf.sock = -1;
p->capa.announce = p->conf.capabilities;
+ p->capa.ann_mp = 1;
+ p->capa.ann_refresh = 1;
change_state(p, STATE_IDLE, EVNT_NONE);
p->IdleHoldTimer = time(NULL); /* start ASAP */
@@ -973,14 +975,17 @@ session_open(struct peer *p)
struct capa_mp capa_mp_v4;
if (p->capa.announce) {
- /* multiprotocol extensions, RFC 2858 */
- bzero(&capa_mp_v4, sizeof(capa_mp_v4));
- capa_mp_v4.afi = AFI_IPv4;
- capa_mp_v4.safi = SAFI_UNICAST;
- op_len += 6; /* 1 code + 1 len + 4 data */
-
- /* route refresh, RFC 2918 */
- op_len += 2; /* 1 code + 1 len, no data */
+ if (p->capa.ann_mp) {
+ /* multiprotocol extensions, RFC 2858 */
+ bzero(&capa_mp_v4, sizeof(capa_mp_v4));
+ capa_mp_v4.afi = AFI_IPv4;
+ capa_mp_v4.safi = SAFI_UNICAST;
+ op_len += 6; /* 1 code + 1 len + 4 data */
+ }
+ if (p->capa.ann_refresh) {
+ /* route refresh, RFC 2918 */
+ op_len += 2; /* 1 code + 1 len, no data */
+ }
if (op_len > 0)
optparamlen = sizeof(op_type) + sizeof(op_len) + op_len;
@@ -1018,20 +1023,28 @@ session_open(struct peer *p)
errs += buf_add(buf, &op_type, sizeof(op_type));
errs += buf_add(buf, &op_len, sizeof(op_len));
- /* multiprotocol extensions, RFC 2858 */
- capa_code = CAPA_MP;
- capa_len = 4;
- errs += buf_add(buf, &capa_code, sizeof(capa_code));
- errs += buf_add(buf, &capa_len, sizeof(capa_len));
- errs += buf_add(buf, &capa_mp_v4.afi, sizeof(capa_mp_v4.afi));
- errs += buf_add(buf, &capa_mp_v4.pad, sizeof(capa_mp_v4.pad));
- errs += buf_add(buf, &capa_mp_v4.safi, sizeof(capa_mp_v4.safi));
-
- /* route refresh, RFC 2918 */
- capa_code = CAPA_REFRESH;
- capa_len = 0;
- errs += buf_add(buf, &capa_code, sizeof(capa_code));
- errs += buf_add(buf, &capa_len, sizeof(capa_len));
+
+ if (p->capa.ann_mp) {
+ /* multiprotocol extensions, RFC 2858 */
+ capa_code = CAPA_MP;
+ capa_len = 4;
+ errs += buf_add(buf, &capa_code, sizeof(capa_code));
+ errs += buf_add(buf, &capa_len, sizeof(capa_len));
+ errs += buf_add(buf, &capa_mp_v4.afi,
+ sizeof(capa_mp_v4.afi));
+ errs += buf_add(buf, &capa_mp_v4.pad,
+ sizeof(capa_mp_v4.pad));
+ errs += buf_add(buf, &capa_mp_v4.safi,
+ sizeof(capa_mp_v4.safi));
+ }
+
+ if (p->capa.ann_refresh) {
+ /* route refresh, RFC 2918 */
+ capa_code = CAPA_REFRESH;
+ capa_len = 0;
+ errs += buf_add(buf, &capa_code, sizeof(capa_code));
+ errs += buf_add(buf, &capa_len, sizeof(capa_len));
+ }
}
if (errs == 0) {
@@ -1676,6 +1689,8 @@ parse_notification(struct peer *peer)
u_int8_t errcode;
u_int8_t subcode;
u_int16_t datalen;
+ u_int8_t capa_code;
+ u_int8_t capa_len;
/* just log */
p = peer->rbuf->rptr;
@@ -1695,10 +1710,51 @@ parse_notification(struct peer *peer)
p += sizeof(subcode);
datalen -= sizeof(subcode);
- /* read & parse data section if needed */
-
log_notification(peer, errcode, subcode, p, datalen);
+ if (errcode == ERR_OPEN && subcode == ERR_OPEN_CAPA) {
+ if (datalen == 0) /* zebra likes to send those.. humbug */
+ peer->capa.announce = 0;
+
+ while (datalen > 0) {
+ if (datalen < 2) {
+ log_peer_warnx(&peer->conf,
+ "parse_notification: "
+ "expect len >= 2, len is %u", datalen);
+ return (-1);
+ }
+ memcpy(&capa_code, p, sizeof(capa_code));
+ p += sizeof(capa_code);
+ datalen -= sizeof(capa_code);
+ memcpy(&capa_len, p, sizeof(capa_len));
+ p += sizeof(capa_len);
+ datalen -= sizeof(capa_len);
+ if (datalen < capa_len) {
+ log_peer_warnx(&peer->conf,
+ "parse_notification: capa_len %u exceeds"
+ "remaining msg length", capa_len);
+ return (-1);
+ }
+ p += capa_len;
+ datalen -= capa_len;
+ switch (capa_code) {
+ case CAPA_MP:
+ peer->capa.ann_mp = 0;
+ log_peer_warnx(&peer->conf,
+ "disabling multiprotocol capability");
+ break;
+ case CAPA_REFRESH:
+ peer->capa.ann_refresh = 0;
+ log_peer_warnx(&peer->conf,
+ "disabling route refresh capability");
+ break;
+ default: /* should not happen... */
+ peer->capa.announce = 0;
+ break;
+ }
+ }
+ }
+
if (errcode == ERR_OPEN && subcode == ERR_OPEN_OPT) {
peer->capa.announce = 0;
return (1);
diff --git a/usr.sbin/bgpd/session.h b/usr.sbin/bgpd/session.h
index 0b5eb378a90..99885ad8991 100644
--- a/usr.sbin/bgpd/session.h
+++ b/usr.sbin/bgpd/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.48 2004/04/28 02:57:01 henning Exp $ */
+/* $OpenBSD: session.h,v 1.49 2004/04/28 06:45:37 henning Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -147,6 +147,8 @@ struct peer_stats {
struct peer_capa {
u_int8_t announce;
+ u_int8_t ann_mp;
+ u_int8_t ann_refresh;
u_int8_t mp_v4; /* multiprotocol extensions, RFC 2858 */
u_int8_t mp_v6;
u_int8_t refresh; /* route refresh, RFC 2918 */