--- bgpd/session.c.orig 2007-01-12 09:49:37.000000000 +1000 +++ bgpd/session.c 2007-01-12 09:50:12.000000000 +1000 @@ -64,6 +64,7 @@ void session_tcp_established(struct peer *); void session_capa_ann_none(struct peer *); int session_capa_mp_add(struct buf *, u_int16_t, u_int8_t); +int session_capa_as_4bytes_add(struct buf *, u_int32_t) ; /*4BYTE - add the 4byte AS capability to the Open message block */ void session_open(struct peer *); void session_keepalive(struct peer *); void session_update(u_int32_t, void *, size_t); @@ -1168,6 +1169,7 @@ peer->capa.ann.mp_v4 = SAFI_NONE; peer->capa.ann.mp_v4 = SAFI_NONE; peer->capa.ann.refresh = 0; + peer->capa.ann.as_4bytes = 0 ; } int @@ -1188,6 +1190,22 @@ return (errs); } +/*4BYTE - add the 4byte AS capability to the Open message block */ +int +session_capa_as_4bytes_add(struct buf *buf, u_int32_t myas) +{ + u_int8_t capa_code, capa_len; + int errs = 0; + + myas = htonl(myas) ; + capa_code = CAPA_4AS; + 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, &myas, sizeof(myas)); + return (errs); +} + void session_open(struct peer *p) { @@ -1195,10 +1213,15 @@ struct buf *buf; struct mrt *mrt; u_int16_t len; + u_int16_t short_as; int errs = 0; u_int8_t op_type, op_len = 0, optparamlen = 0; u_int8_t capa_code, capa_len; + /***/ + fprintf(stderr,"session_open: called\n"); + /****/ + /* multiprotocol extensions, RFC 2858 */ if (p->capa.ann.mp_v4) op_len += 2 + 4; /* 1 code + 1 len + 4 data */ @@ -1209,6 +1232,11 @@ if (p->capa.ann.refresh) op_len += 2 + 0; /* 1 code + 1 len, no data */ + /*4BYTE 4-byte AS capability - always advertised (65,4,as)*/ + if (p->capa.ann.as_4bytes) + op_len += 2 + 4 ; /* 1 code + 1 len + 4 data */ + + if (op_len > 0) optparamlen = sizeof(op_type) + sizeof(op_len) + op_len; len = MSGSIZE_OPEN_MIN + optparamlen; @@ -1217,7 +1245,21 @@ msg.header.len = htons(len); msg.header.type = OPEN; msg.version = 4; - msg.myas = htons(conf->as); + + /*4BYTE - myas is the low 16 bits if the upper 16 bits of the AS are zero - AS_TRANS otherwise */ + + /****/ + fprintf(stderr,"Open: conf->as = %u.%u\n",((conf->as >> 16) & 65535),(conf->as & 65535)); + /****/ + + if (!((conf->as >> 16) & 65535)) short_as = (u_int16_t) conf->as; + else short_as = AS_TRANS ; + msg.myas = htons(short_as) ; + + /****/ + fprintf(stderr,"Open: myas = %u (net = %u)\n",short_as, msg.myas); + /****/ + if (p->conf.holdtime) msg.holdtime = htons(p->conf.holdtime); else @@ -1238,25 +1280,45 @@ errs += buf_add(buf, &msg.bgpid, sizeof(msg.bgpid)); errs += buf_add(buf, &msg.optparamlen, sizeof(msg.optparamlen)); + /****/ + fprintf(stderr,"Options length: %d)\n",op_len); + /****/ if (optparamlen) { op_type = OPT_PARAM_CAPABILITIES; errs += buf_add(buf, &op_type, sizeof(op_type)); errs += buf_add(buf, &op_len, sizeof(op_len)); + /*4BYTE - 4 byte as capability */ + if (p->capa.ann.as_4bytes) { + errs += session_capa_as_4bytes_add(buf, conf->as); + /****/ + fprintf(stderr,"Options: 4byte AS\n"); + /****/ + } /* multiprotocol extensions, RFC 2858 */ - if (p->capa.ann.mp_v4) + if (p->capa.ann.mp_v4) { errs += session_capa_mp_add(buf, AFI_IPv4, p->capa.ann.mp_v4); - if (p->capa.ann.mp_v6) + /****/ + fprintf(stderr,"Options: multiproto V4\n"); + /****/ + } + if (p->capa.ann.mp_v6) { errs += session_capa_mp_add(buf, AFI_IPv6, p->capa.ann.mp_v6); - + /****/ + fprintf(stderr,"Options: multiproto V6\n"); + /****/ + } /* route refresh, RFC 2918 */ if (p->capa.ann.refresh) { 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)); + /****/ + fprintf(stderr,"Options: refresh\n"); + /****/ } } @@ -1284,6 +1346,10 @@ } p->stats.msg_sent_open++; + + /***/ + fprintf(stderr,"session_open: message queued for delivery\n"); + /****/ } void @@ -1295,6 +1361,9 @@ ssize_t len; int errs = 0; + /***/ + fprintf(stderr,"session_keepalive: called\n"); + /****/ len = MSGSIZE_KEEPALIVE; memset(&msg.marker, 0xff, sizeof(msg.marker)); @@ -1333,6 +1402,10 @@ start_timer_keepalive(peer); peer->stats.msg_sent_keepalive++; + + /***/ + fprintf(stderr,"session_keepalive: message queued for delivery\n"); + /****/ } void @@ -1345,6 +1418,10 @@ ssize_t len; int errs = 0; + /***/ + fprintf(stderr,"session_update: called\n"); + /****/ + if ((p = getpeerbyid(peerid)) == NULL) { log_warnx("no such peer: id=%u", peerid); return; @@ -1392,6 +1469,9 @@ start_timer_keepalive(p); p->stats.msg_sent_update++; + /***/ + fprintf(stderr,"session_update: message queued for delivery\n"); + /****/ } void @@ -1405,6 +1485,10 @@ int errs = 0; u_int8_t null8 = 0; + /***/ + fprintf(stderr,"session_notification: called\n"); + /****/ + if (peer->stats.last_sent_errcode) /* some notifctn already sent */ return; @@ -1455,6 +1539,10 @@ peer->stats.msg_sent_notification++; peer->stats.last_sent_errcode = errcode; peer->stats.last_sent_suberr = subcode; + + /***/ + fprintf(stderr,"session_notification: message queued for delivery\n"); + /****/ } int @@ -1554,28 +1642,47 @@ break; p->rbuf->rptr = p->rbuf->buf + rpos; + switch (msgtype) { case OPEN: + /****/ + fprintf(stderr,"session_dispatch: msg OPEN\n") ; + /****/ bgp_fsm(p, EVNT_RCVD_OPEN); p->stats.msg_rcvd_open++; break; case UPDATE: + /****/ + fprintf(stderr,"session_dispatch: msg UPDATE\n") ; + /****/ bgp_fsm(p, EVNT_RCVD_UPDATE); p->stats.msg_rcvd_update++; break; case NOTIFICATION: + /****/ + fprintf(stderr,"session_dispatch: msg NOTIFY\n") ; + /****/ bgp_fsm(p, EVNT_RCVD_NOTIFICATION); p->stats.msg_rcvd_notification++; break; case KEEPALIVE: + /****/ + fprintf(stderr,"session_dispatch: msg KEEPALIVE\n") ; + /****/ bgp_fsm(p, EVNT_RCVD_KEEPALIVE); p->stats.msg_rcvd_keepalive++; break; case RREFRESH: + /****/ + fprintf(stderr,"session_dispatch: msg RREFRESH\n") ; + /****/ parse_refresh(p); p->stats.msg_rcvd_rrefresh++; break; default: /* cannot happen */ + /****/ + fprintf(stderr,"session_dispatch: msg OUNK\n") ; + /****/ session_notification(p, ERR_HEADER, ERR_HDR_TYPE, &msgtype, 1); log_warnx("received message with " @@ -1717,7 +1824,13 @@ u_int32_t bgpid; u_int8_t optparamlen, plen; u_int8_t op_type, op_len; + int error_code; + /****/ +fprintf(stderr,"parse_open\n") ; +/****/ + + peer->capa.peer.as_4bytes = 0 ; p = peer->rbuf->rptr; p += MSGSIZE_HEADER_MARKER; memcpy(&msglen, p, sizeof(msglen)); @@ -1751,13 +1864,6 @@ peer->conf.ebgp = (peer->conf.remote_as != conf->as); } - if (peer->conf.remote_as != ntohs(as)) { - log_peer_warnx(&peer->conf, "peer sent wrong AS %u", ntohs(as)); - session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0); - change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); - return (-1); - } - memcpy(&oholdtime, p, sizeof(oholdtime)); p += sizeof(oholdtime); @@ -1836,8 +1942,9 @@ switch (op_type) { case OPT_PARAM_CAPABILITIES: /* RFC 3392 */ - if (parse_capabilities(peer, op_val, op_len) == -1) { - session_notification(peer, ERR_OPEN, 0, + if ((error_code = parse_capabilities(peer, op_val, op_len)) < 0) { + error_code = -1 - error_code; + session_notification(peer, ERR_OPEN, error_code, NULL, 0); change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); return (-1); @@ -1864,6 +1971,19 @@ } } + /*4BYTE - delayed check */ + + if ((peer->conf.remote_as != (unsigned int)ntohs(as)) && (!peer->capa.peer.as_4bytes)) { + log_peer_warnx(&peer->conf, "peer sent wrong AS %u", ntohs(as)); + session_notification(peer, ERR_OPEN, ERR_OPEN_AS, NULL, 0); + change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN); + return (-1); + } + + /****/ + fprintf(stderr,"no errors in OPEN\n") ; + /*****/ + return (0); } @@ -1873,6 +1993,10 @@ u_char *p; u_int16_t datalen; + /****/ + fprintf(stderr,"parse_update\n") ; + /****/ + /* * we pass the message verbatim to the rde. * in case of errors the whole session is reset with a @@ -1888,10 +2012,18 @@ datalen -= MSGSIZE_HEADER; if (imsg_compose(ibuf_rde, IMSG_UPDATE, peer->conf.id, 0, -1, p, - datalen) == -1) + datalen) == -1) { + /****/ + fprintf(stderr,"send to imsg_compose -- error (-1)\n") ; + /***/ return (-1); + } + /****/ + fprintf(stderr,"send to imsg message bus\n") ; + /***/ return (0); + } int @@ -2025,6 +2157,7 @@ u_char *capa_val; u_int16_t mp_afi; u_int8_t mp_safi; + u_int32_t remote_as ; len = dlen; while (len > 0) { @@ -2039,6 +2172,9 @@ memcpy(&capa_len, d, sizeof(capa_len)); d += sizeof(capa_len); len -= sizeof(capa_len); + /***/ + fprintf(stderr,"capability code = %u length = %u\n",capa_code,capa_len) ; + /***/ if (capa_len > 0) { if (len < capa_len) { log_peer_warnx(&peer->conf, @@ -2054,6 +2190,24 @@ capa_val = NULL; switch (capa_code) { + case CAPA_4AS: + if (capa_len != 4) { + log_peer_warnx(&peer->conf, + "parse_capabilities: " + "expect len 4, len is %u", capa_len); + return (-1); + } + memcpy(&remote_as, capa_val, sizeof(remote_as)); + remote_as = ntohl(remote_as); + peer->capa.peer.as_4bytes = 1 ; + if (peer->conf.remote_as != remote_as) { + log_peer_warnx(&peer->conf, "peer sent wrong AS %u", ntohs(remote_as)); + return (0 - (ERR_OPEN_AS + 1)); + } + /***/ + fprintf(stderr,"capability 4byteas = %u.%u\n",((remote_as >> 16) & 65535),(remote_as & 65535)) ; + /***/ + break ; case CAPA_MP: /* RFC 2858 */ if (capa_len != 4) { log_peer_warnx(&peer->conf, @@ -2067,10 +2221,14 @@ switch (mp_afi) { case AFI_IPv4: if (mp_safi < 1 || mp_safi > 3) { + /**** log_peer_warnx(&peer->conf, "parse_capabilities: AFI IPv4, " "mp_safi %u illegal", mp_safi); return (-1); + ***/ + fprintf(stderr,"change mp_safi from %u to 1\n",mp_safi) ; + mp_safi = 1 ; } peer->capa.peer.mp_v4 = mp_safi; break;