diff options
author | Jun-ichiro itojun Hagino <itojun@itojun.org> | 1999-10-16 15:35:27 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@itojun.org> | 1999-10-16 15:35:27 +0000 |
commit | a4e1535f19627b7eb4a2baa923a6b1ab5e345635 (patch) | |
tree | a85802089281c2bfd0a2657ac820b1a55b5a10c6 /packet-bgp.c | |
parent | 06f434844b66f5339dbbe32f3a82e793795abcfd (diff) |
upport BGP multiprotocol extension (required for IPv6 BGP exchange).
svn path=/trunk/; revision=858
Diffstat (limited to 'packet-bgp.c')
-rw-r--r-- | packet-bgp.c | 223 |
1 files changed, 222 insertions, 1 deletions
diff --git a/packet-bgp.c b/packet-bgp.c index 7be9c1f387..1e85702c60 100644 --- a/packet-bgp.c +++ b/packet-bgp.c @@ -2,7 +2,7 @@ * Routines for BGP packet dissection * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org> * - * $Id: packet-bgp.c,v 1.2 1999/10/16 00:21:07 itojun Exp $ + * $Id: packet-bgp.c,v 1.3 1999/10/16 15:35:27 itojun Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@unicom.net> @@ -38,9 +38,19 @@ # include <netinet/in.h> #endif +#ifdef NEED_SNPRINTF_H +# ifdef HAVE_STDARG_H +# include <stdarg.h> +# else +# include <varargs.h> +# endif +# include "snprintf.h" +#endif + #include <string.h> #include <glib.h> #include "packet.h" +#include "packet-ipv6.h" struct bgp { guint8 bgp_marker[16]; @@ -174,12 +184,51 @@ static const value_string bgpattr_type[] = { /* Subsequent address family identifier, RFC2283 section 7 */ static const value_string bgpattr_nlri_safi[] = { + { 0, "Reserved" }, { 1, "Unicast" }, { 2, "Multicast" }, { 3, "Unicast+Multicast" }, { 0, NULL }, }; +/* RFC1700 address family numbers */ +#define AFNUM_INET 1 +#define AFNUM_INET6 2 +#define AFNUM_NSAP 3 +#define AFNUM_HDLC 4 +#define AFNUM_BBN1822 5 +#define AFNUM_802 6 +#define AFNUM_E163 7 +#define AFNUM_E164 8 +#define AFNUM_F69 9 +#define AFNUM_X121 10 +#define AFNUM_IPX 11 +#define AFNUM_ATALK 12 +#define AFNUM_DECNET 13 +#define AFNUM_BANYAN 14 +#define AFNUM_E164NSAP 15 + +static const value_string afnumber[] = { + { 0, "Reserved" }, + { AFNUM_INET, "IPv4" }, + { AFNUM_INET6, "IPv6" }, + { AFNUM_NSAP, "NSAP" }, + { AFNUM_HDLC, "HDLC" }, + { AFNUM_BBN1822, "BBN 1822" }, + { AFNUM_802, "802" }, + { AFNUM_E163, "E.163" }, + { AFNUM_E164, "E.164" }, + { AFNUM_F69, "F.69" }, + { AFNUM_X121, "X.121" }, + { AFNUM_IPX, "IPX" }, + { AFNUM_ATALK, "Appletalk" }, + { AFNUM_DECNET, "Decnet IV" }, + { AFNUM_BANYAN, "Banyan Vines" }, + { AFNUM_E164NSAP, "E.164 with NSAP subaddress" }, + { 65535, "Reserved" }, + { 0, NULL }, +}; + static int proto_bgp = -1; @@ -187,6 +236,42 @@ static int proto_bgp = -1; #define offsetof(type, member) ((size_t)(&((type *)0)->member)) #endif +static int +decode_prefix4(const u_char *pd, char *buf, int buflen) +{ + guint8 addr[4]; + int plen; + + plen = pd[0]; + if (plen < 0 || 32 < plen) + return -1; + + memset(addr, 0, sizeof(addr)); + memcpy(addr, &pd[1], (plen + 7) / 8); + if (plen % 8) + addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); + snprintf(buf, buflen, "%s/%d", ip_to_str(addr), plen); + return 1 + (plen + 7) / 8; +} + +static int +decode_prefix6(const u_char *pd, char *buf, int buflen) +{ + struct e_in6_addr addr; + int plen; + + plen = pd[0]; + if (plen < 0 || 128 < plen) + return -1; + + memset(&addr, 0, sizeof(addr)); + memcpy(&addr, &pd[1], (plen + 7) / 8); + if (plen % 8) + addr.s6_addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); + snprintf(buf, buflen, "%s/%d", ip6_to_str(&addr), plen); + return 1 + (plen + 7) / 8; +} + static void dissect_bgp_open(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { @@ -253,6 +338,8 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd, while (i < len) { int alen, aoff; char *msg; + guint16 af; + int off, snpa; memcpy(&bgpa, &p[i], sizeof(bgpa)); if (bgpa.bgpa_flags & 0x10) { @@ -394,6 +481,140 @@ dissect_bgp_update(const u_char *pd, int offset, frame_data *fd, ip_to_str(&p[i + aoff + 2])); } break; + case BGPTYPE_MP_REACH_NLRI: + af = ntohs(*(guint16 *)&p[i + aoff]); + proto_tree_add_text(subtree2, p - pd + i + aoff, 2, + "Address family: %s (%u)", + val_to_str(af, afnumber, "Unknown"), af); + proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 1, + "Subsequent address family identifier: %s (%u)", + val_to_str(p[i + aoff + 2], bgpattr_nlri_safi, + p[i + aoff + 2] >= 128 ? "Vendor specific" : "Unknown"), + p[i + aoff + 2]); + ti = proto_tree_add_text(subtree2, p - pd + i + aoff + 3, 1, + "Next hop network address (%d bytes)", + p[i + aoff + 3]); + if (af == AFNUM_INET || af == AFNUM_INET6) { + int j, advance; + const char *s; + + subtree3 = proto_item_add_subtree(ti, ETT_BGP); + + j = 0; + while (j < p[i + aoff + 3]) { + if (af == AFNUM_INET) + advance = 4; + else if (af == AFNUM_INET6) + advance = 16; + else + break; + if (j + advance > p[i + aoff + 3]) + break; + + if (af == AFNUM_INET) + s = ip_to_str(&p[i + aoff + 4 + j]); + else { + s = ip6_to_str((struct e_in6_addr *) + &p[i + aoff + 4 + j]); + } + proto_tree_add_text(subtree3, + p - pd + i + aoff + 4 + j, advance, + "Next hop: %s", s); + j += advance; + } + } + + alen -= (p[i + aoff + 3] + 4); + aoff += (p[i + aoff + 3] + 4); + off = 0; + snpa = p[i + aoff]; + ti = proto_tree_add_text(subtree2, p - pd + i + aoff, 1, + "Subnetwork points of attachment: %u", snpa); + off++; + if (snpa) + subtree3 = proto_item_add_subtree(ti, ETT_BGP); + for (/*nothing*/; snpa > 0; snpa--) { + proto_tree_add_text(subtree3, p - pd + i + aoff + off, 1, + "SNPA length: ", p[i + aoff + off]); + off++; + proto_tree_add_text(subtree3, p - pd + i + aoff + off, + p[i + aoff + off - 1], + "SNPA (%u bytes)", p[i + aoff + off - 1]); + off += p[i + aoff + off - 1]; + } + + alen -= off; + aoff += off; + ti = proto_tree_add_text(subtree2, p - pd + i + aoff, alen, + "Network Layer Reachability Information (%u bytes)", + alen); + if (alen) + subtree3 = proto_item_add_subtree(ti, ETT_BGP); + while (alen > 0) { + int advance; + char buf[256]; + + if (af == AFNUM_INET) { + advance = decode_prefix4(&p[i + aoff], buf, + sizeof(buf)); + } else if (af == AFNUM_INET6) { + advance = decode_prefix6(&p[i + aoff], buf, + sizeof(buf)); + } else + break; + if (advance < 0) + break; + if (alen < advance) + break; + proto_tree_add_text(subtree3, p - pd + i + aoff, advance, + "Network Layer Reachability Information: %s", buf); + + alen -= advance; + aoff += advance; + } + + break; + case BGPTYPE_MP_UNREACH_NLRI: + af = ntohs(*(guint16 *)&p[i + aoff]); + proto_tree_add_text(subtree2, p - pd + i + aoff, 2, + "Address family: %s (%u)", + val_to_str(af, afnumber, "Unknown"), af); + proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 1, + "Subsequent address family identifier: %s (%u)", + val_to_str(p[i + aoff + 2], bgpattr_nlri_safi, + p[i + aoff + 2] >= 128 ? "Vendor specific" : "Unknown"), + p[i + aoff + 2]); + ti = proto_tree_add_text(subtree2, p - pd + i + aoff + 3, + alen - 3, "Withdrawn Routes (%u bytes)", alen - 3); + + alen -= 3; + aoff += 3; + if (alen > 0) + subtree3 = proto_item_add_subtree(ti, ETT_BGP); + while (alen > 0) { + int advance; + char buf[256]; + + if (af == AFNUM_INET) { + advance = decode_prefix4(&p[i + aoff], buf, + sizeof(buf)); + } else if (af == AFNUM_INET6) { + advance = decode_prefix6(&p[i + aoff], buf, + sizeof(buf)); + } else + break; + if (advance < 0) + break; + if (alen < advance) + break; + proto_tree_add_text(subtree3, p - pd + i + aoff, advance, + "Withdrawn route: %s", buf); + + alen -= advance; + aoff += advance; + } + + break; default: proto_tree_add_text(subtree2, p - pd + i + aoff, alen, "Unknown (%d bytes)", alen); |