diff options
author | Martin Mares <mj@ucw.cz> | 2000-04-25 15:32:17 +0200 |
---|---|---|
committer | Martin Mares <mj@ucw.cz> | 2000-04-25 15:32:17 +0200 |
commit | a47a01083b6ff9196f39136d68ed32ac70b31d15 (patch) | |
tree | 4cc56e60452dcf5245f1fc90944f5a9dd498ab0e /proto/bgp | |
parent | 8b258e4e659cd8bacf0f7e3997d30b43561ac3e6 (diff) | |
download | bird-a47a01083b6ff9196f39136d68ed32ac70b31d15.tar bird-a47a01083b6ff9196f39136d68ed32ac70b31d15.zip |
Real parsing of BGP OPEN options including capability
negotiation.
Diffstat (limited to 'proto/bgp')
-rw-r--r-- | proto/bgp/packets.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index ccaa91c..504af93 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -199,6 +199,44 @@ bgp_tx(sock *sk) ; } +static int +bgp_parse_options(struct bgp_conn *conn, byte *opt, int len) +{ + while (len > 0) + { + if (len < 2 || len < 2 + opt[1]) + { bgp_error(conn, 2, 0, 0, 0); return 0; } +#ifdef LOCAL_DEBUG + { + int i; + DBG("\tOption %02x:", opt[0]); + for(i=0; i<opt[1]; i++) + DBG(" %02x", opt[2+i]); + DBG("\n"); + } +#endif + switch (opt[0]) + { + case 2: + /* Defined in draft-ietf-idr-bgp4-cap-neg-06 */ + /* We can safely ignore all capabilities */ + break; + default: + /* + * BGP specs don't tell us to send which option + * we didn't recognize, but it's common practice + * to do so. Also, capability negotiation with + * Cisco routers doesn't work without that. + */ + bgp_error(conn, 2, 4, opt[0], 1); + return 0; + } + len -= 2 + opt[1]; + opt += 2 + opt[1]; + } + return 0; +} + static void bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) { @@ -226,8 +264,8 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len) if (hold > 0 && hold < 3) { bgp_error(conn, 2, 6, hold, 0); return; } p->remote_id = id; - if (pkt[28]) /* Currently we support no optional parameters */ - { bgp_error(conn, 2, 4, pkt[29], 0); return; } + if (bgp_parse_options(conn, pkt+29, pkt[28])) + return; if (!id || id == 0xffffffff || id == p->local_id) { bgp_error(conn, 2, 3, id, 0); return; } |