* Routines for BGP packet dissection.
* Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
*
- * $Id: packet-bgp.c,v 1.44 2001/07/08 22:59:50 guy Exp $
+ * $Id: packet-bgp.c,v 1.48 2001/11/03 21:25:12 guy Exp $
*
* Supports:
* RFC1771 A Border Gateway Protocol 4 (BGP-4)
#include "packet.h"
#include "packet-bgp.h"
#include "packet-ipv6.h"
+#include "afn.h"
static const value_string bgptypevals[] = {
{ BGP_OPEN, "OPEN Message" },
{ 0, NULL },
};
-static const value_string bgpext_osptf_rtype_metric[] = {
-};
/* MUST be resized if a longer named extended community is added */
#define MAX_SIZE_OF_EXT_COM_NAMES 20
-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 },
-};
-
/* Subsequent address family identifier, RFC2858 */
static const value_string bgpattr_nlri_safi[] = {
{ 0, "Reserved" },
{ 0, NULL },
};
+/* ORF Type, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_type_vals[] = {
+ { 2, "Communities ORF-Type" },
+ { 3, "Extended Communities ORF-Type" },
+ { 0, NULL },
+};
+
+/* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_send_recv_vals[] = {
+ { 1, "Receive" },
+ { 2, "Send" },
+ { 3, "Both" },
+ { 0, NULL },
+};
+
/* Maximal size of an IP address string */
#define MAX_SIZE_OF_IP_ADDR_STRING 16
int plen; /* parameter length */
int ctype; /* capability type */
int clen; /* capability length */
+ int cend; /* capabilities end */
int ostart; /* options start */
int oend; /* options end */
int p; /* tvb offset counter */
proto_item *ti; /* tree item */
proto_tree *subtree; /* subtree for options */
+ proto_tree *subtree1; /* subtree for an option */
proto_tree *subtree2; /* subtree for an option */
proto_tree *subtree3; /* subtree for an option */
+ guint8 orfnum; /* number of ORFs */
+ guint8 orftype; /* ORF Type */
+ guint8 orfsendrecv; /* ORF Send/Receive */
/* snarf OPEN message */
tvb_memcpy(tvb, bgpo.bgpo_marker, offset, BGP_MIN_OPEN_MSG_SIZE);
break;
case BGP_OPTION_CAPABILITY:
/* grab the capability code */
+ cend = p - 1 + plen;
ctype = tvb_get_guint8(tvb, p++);
clen = tvb_get_guint8(tvb, p++);
-
- /* check the capability type */
- switch (ctype) {
- case BGP_CAPABILITY_RESERVED:
- ti = proto_tree_add_text(subtree, tvb, p - 4,
- 2 + plen, "Reserved capability (%u %s)", 2 + plen,
- (plen == 1) ? "byte" : "bytes");
- subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
- proto_tree_add_text(subtree2, tvb, p - 4,
- 1, "Parameter type: Capabilities (2)");
- proto_tree_add_text(subtree2, tvb, p - 3,
- 1, "Parameter length: %u %s", plen,
- (plen == 1) ? "byte" : "bytes");
- proto_tree_add_text(subtree2, tvb, p - 2,
- 1, "Capability code: Reserved (0)");
- proto_tree_add_text(subtree2, tvb, p - 1,
- 1, "Capability length: %u %s", clen,
- (clen == 1) ? "byte" : "bytes");
- if (clen != 0) {
- proto_tree_add_text(subtree2, tvb, p,
- clen, "Capability value: Unknown");
- }
- p += clen;
- break;
- case BGP_CAPABILITY_MULTIPROTOCOL:
- ti = proto_tree_add_text(subtree, tvb, p - 4,
- 2 + plen,
- "Multiprotocol extensions capability (%u %s)",
- 2 + plen, (plen == 1) ? "byte" : "bytes");
- subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
- proto_tree_add_text(subtree2, tvb, p - 4,
- 1, "Parameter type: Capabilities (2)");
- proto_tree_add_text(subtree2, tvb, p - 3,
- 1, "Parameter length: %u %s", plen,
- (plen == 1) ? "byte" : "bytes");
- proto_tree_add_text(subtree2, tvb, p - 2,
- 1, "Capability code: Multiprotocol extensions (%d)",
- ctype);
- if (clen != 4) {
- proto_tree_add_text(subtree2, tvb, p - 1,
- 1, "Capability length: Invalid");
- proto_tree_add_text(subtree2, tvb, p,
- clen, "Capability value: Unknown");
- }
- else {
- proto_tree_add_text(subtree2, tvb, p - 1,
+ ti = proto_tree_add_text(subtree, tvb, p - 4,
+ 2 + plen, "Capabilities Advertisement (%u bytes)",
+ 2 + plen);
+ subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree1, tvb, p - 4,
+ 1, "Parameter type: Capabilities (2)");
+ proto_tree_add_text(subtree1, tvb, p - 3,
+ 1, "Parameter length: %u %s", plen,
+ (plen == 1) ? "byte" : "bytes");
+ p -= 2;
+
+ /* step through all of the capabilities */
+ while (p < cend) {
+ ctype = tvb_get_guint8(tvb, p++);
+ clen = tvb_get_guint8(tvb, p++);
+
+ /* check the capability type */
+ switch (ctype) {
+ case BGP_CAPABILITY_RESERVED:
+ ti = proto_tree_add_text(subtree1, tvb, p - 2,
+ 2 + clen, "Reserved capability (%u %s)", 2 + clen,
+ (clen == 1) ? "byte" : "bytes");
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree2, tvb, p - 2,
+ 1, "Capability code: Reserved (0)");
+ proto_tree_add_text(subtree2, tvb, p - 1,
1, "Capability length: %u %s", clen,
(clen == 1) ? "byte" : "bytes");
- ti = proto_tree_add_text(subtree2, tvb, p,
+ if (clen != 0) {
+ proto_tree_add_text(subtree2, tvb, p,
+ clen, "Capability value: Unknown");
+ }
+ p += clen;
+ break;
+ case BGP_CAPABILITY_MULTIPROTOCOL:
+ ti = proto_tree_add_text(subtree1, tvb, p - 2,
+ 2 + clen,
+ "Multiprotocol extensions capability (%u %s)",
+ 2 + clen, (clen == 1) ? "byte" : "bytes");
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree2, tvb, p - 2,
+ 1, "Capability code: Multiprotocol extensions (%d)",
+ ctype);
+ if (clen != 4) {
+ proto_tree_add_text(subtree2, tvb, p - 1,
+ 1, "Capability length: Invalid");
+ proto_tree_add_text(subtree2, tvb, p,
+ clen, "Capability value: Unknown");
+ }
+ else {
+ proto_tree_add_text(subtree2, tvb, p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ ti = proto_tree_add_text(subtree2, tvb, p,
+ clen, "Capability value");
+ subtree3 = proto_item_add_subtree(ti,
+ ett_bgp_option);
+ /* AFI */
+ i = tvb_get_ntohs(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 2, "Address family identifier: %s (%u)",
+ val_to_str(i, afn_vals, "Unknown"), i);
+ p += 2;
+ /* Reserved */
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "Reserved: 1 byte");
+ p++;
+ /* SAFI */
+ i = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "Subsequent address family identifier: %s (%u)",
+ val_to_str(i, bgpattr_nlri_safi,
+ i >= 128 ? "Vendor specific" : "Unknown"), i);
+ p++;
+ }
+ break;
+ case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
+ case BGP_CAPABILITY_ROUTE_REFRESH:
+ ti = proto_tree_add_text(subtree1, tvb, p - 2,
+ 2 + clen, "Route refresh capability (%u %s)", 2 + clen,
+ (clen == 1) ? "byte" : "bytes");
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree2, tvb, p - 2,
+ 1, "Capability code: Route refresh (%d)", ctype);
+ if (clen != 0) {
+ proto_tree_add_text(subtree2, tvb, p,
+ clen, "Capability value: Invalid");
+ }
+ else {
+ proto_tree_add_text(subtree2, tvb, p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ }
+ p += clen;
+ break;
+ case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
+ ti = proto_tree_add_text(subtree1, tvb, p - 2,
+ 2 + clen,
+ "Cooperative route filtering capability (%u %s)",
+ 2 + clen, (clen == 1) ? "byte" : "bytes");
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree2, tvb, p - 2,
+ 1, "Capability code: Cooperative route filtering (%d)",
+ ctype);
+ proto_tree_add_text(subtree2, tvb, p - 1,
+ 1, "Capability length: %u %s", clen,
+ (clen == 1) ? "byte" : "bytes");
+ ti = proto_tree_add_text(subtree2, tvb, p,
clen, "Capability value");
- subtree3 = proto_item_add_subtree(ti,
- ett_bgp_option);
- /* AFI */
- i = tvb_get_ntohs(tvb, p);
- proto_tree_add_text(subtree3, tvb, p,
- 2, "Address family identifier: %s (%u)",
- val_to_str(i, afnumber, "Unknown"), i);
- p += 2;
- /* Reserved */
- proto_tree_add_text(subtree3, tvb, p,
- 1, "Reserved: 1 byte");
- p++;
- /* SAFI */
- i = tvb_get_guint8(tvb, p);
- proto_tree_add_text(subtree3, tvb, p,
- 1, "Subsequent address family identifier: %s (%u)",
- val_to_str(i, bgpattr_nlri_safi,
- i >= 128 ? "Vendor specific" : "Unknown"), i);
- p++;
- }
- break;
- case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
- case BGP_CAPABILITY_ROUTE_REFRESH:
- ti = proto_tree_add_text(subtree, tvb, p - 4,
- 2 + plen, "Route refresh capability (%u %s)", 2 + plen,
- (plen == 1) ? "byte" : "bytes");
- subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
- proto_tree_add_text(subtree2, tvb, p - 4,
- 1, "Parameter type: Capabilities (2)");
- proto_tree_add_text(subtree2, tvb, p - 3,
- 1, "Parameter length: %u %s", plen,
- (plen == 1) ? "byte" : "bytes");
- proto_tree_add_text(subtree2, tvb, p - 2,
- 1, "Capability code: Route refresh (%d)", ctype);
- if (clen != 0) {
- proto_tree_add_text(subtree2, tvb, p,
- clen, "Capability value: Invalid");
- }
- else {
- proto_tree_add_text(subtree2, tvb, p - 1,
+ subtree3 = proto_item_add_subtree(ti, ett_bgp_option);
+ /* AFI */
+ i = tvb_get_ntohs(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 2, "Address family identifier: %s (%u)",
+ val_to_str(i, afn_vals, "Unknown"), i);
+ p += 2;
+ /* Reserved */
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "Reserved: 1 byte");
+ p++;
+ /* SAFI */
+ i = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "Subsequent address family identifier: %s (%u)",
+ val_to_str(i, bgpattr_nlri_safi,
+ i >= 128 ? "Vendor specific" : "Unknown"), i);
+ p++;
+ /* Number of ORFs */
+ orfnum = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "Number of ORFs: %u", orfnum);
+ p++;
+ for (i=0; i<orfnum; i++) {
+ /* ORF Type */
+ orftype = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "ORF Type: %s (%u)",
+ val_to_str(orftype, orf_type_vals,"Unknown"),
+ orftype);
+ p++;
+ /* Send/Receive */
+ orfsendrecv = tvb_get_guint8(tvb, p);
+ proto_tree_add_text(subtree3, tvb, p,
+ 1, "Send/Receive: %s (%u)",
+ val_to_str(orfsendrecv, orf_send_recv_vals,
+ "Uknown"), orfsendrecv);
+ p++;
+ }
+ break;
+ /* unknown capability */
+ default:
+ ti = proto_tree_add_text(subtree, tvb, p - 2,
+ 2 + clen, "Unknown capability (%u %s)", 2 + clen,
+ (clen == 1) ? "byte" : "bytes");
+ subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+ proto_tree_add_text(subtree2, tvb, p - 2,
+ 1, "Capability code: %s (%d)",
+ ctype >= 128 ? "Private use" : "Unknown", ctype);
+ proto_tree_add_text(subtree2, tvb, p - 1,
1, "Capability length: %u %s", clen,
(clen == 1) ? "byte" : "bytes");
- }
- p += clen;
- break;
- /* unknown capability */
- default:
- ti = proto_tree_add_text(subtree, tvb, p - 4,
- 2 + plen, "Unknown capability (%u %s)", 2 + plen,
- (plen == 1) ? "byte" : "bytes");
- subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
- proto_tree_add_text(subtree2, tvb, p - 4,
- 1, "Parameter type: Capabilities (2)");
- proto_tree_add_text(subtree2, tvb, p - 3,
- 1, "Parameter length: %u %s", plen,
- (plen == 1) ? "byte" : "bytes");
- proto_tree_add_text(subtree2, tvb, p - 2,
- 1, "Capability code: %s (%d)",
- ctype >= 128 ? "Private use" : "Unknown", ctype);
- proto_tree_add_text(subtree2, tvb, p - 1,
- 1, "Capability length: %u %s", clen,
- (clen == 1) ? "byte" : "bytes");
- if (clen != 0) {
- proto_tree_add_text(subtree2, tvb, p,
- clen, "Capability value: Unknown");
- }
- p += clen;
- break;
- }
+ if (clen != 0) {
+ proto_tree_add_text(subtree2, tvb, p,
+ clen, "Capability value: Unknown");
+ }
+ p += clen;
+ break;
+ }
+ }
break;
default:
proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
af = tvb_get_ntohs(tvb, o + i + aoff);
proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
"Address family: %s (%u)",
- val_to_str(af, afnumber, "Unknown"), af);
+ val_to_str(af, afn_vals, "Unknown"), af);
saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
"Subsequent address family identifier: %s (%u)",
af = tvb_get_ntohs(tvb, o + i + aoff);
proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
"Address family: %s (%u)",
- val_to_str(af, afnumber, "Unknown"), af);
+ val_to_str(af, afn_vals, "Unknown"), af);
saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
"Subsequent address family identifier: %s (%u)",
i = tvb_get_ntohs(tvb, offset + BGP_HEADER_SIZE);
proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 2,
"Address family identifier: %s (%u)",
- val_to_str(i, afnumber, "Unknown"), i);
+ val_to_str(i, afn_vals, "Unknown"), i);
offset += 2;
/* Reserved */
- proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE + 2, 1,
+ proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 1,
"Reserved: 1 byte");
offset++;
/* SAFI */
- i = tvb_get_guint8(tvb, offset);
- proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE + 3, 1,
+ i = tvb_get_guint8(tvb, offset + BGP_HEADER_SIZE);
+ proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 1,
"Subsequent address family identifier: %s (%u)",
val_to_str(i, bgpattr_nlri_safi,
i >= 128 ? "Vendor specific" : "Unknown"),