* Routines for BGP packet dissection.
* Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
*
- * $Id: packet-bgp.c,v 1.45 2001/07/09 11:08:39 guy Exp $
+ * $Id: packet-bgp.c,v 1.53 2002/01/21 07:36:32 guy Exp $
*
* Supports:
* RFC1771 A Border Gateway Protocol 4 (BGP-4)
# include "snprintf.h"
#endif
-#include "packet.h"
+#include <epan/packet.h>
#include "packet-bgp.h"
#include "packet-ipv6.h"
+#include "afn.h"
+#include "prefs.h"
static const value_string bgptypevals[] = {
{ BGP_OPEN, "OPEN Message" },
/* 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
static gint ett_bgp_options = -1; /* optional parameters tree */
static gint ett_bgp_option = -1; /* an optional parameter tree */
static gint ett_bgp_extended_communities = -1 ; /* extended communities list tree */
+
+/* desegmentation */
+static gboolean bgp_desegment = TRUE;
+
/*
* Decode an IPv4 prefix.
*/
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,
"bytes");
break;
case BGPTYPE_AS_PATH:
- /* (o + i + 3) =
- (o + current attribute + 3 bytes to first tuple) */
- end = o + alen + i + 3;
- q = o + i + 3;
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
/* must be freed by second switch! */
/* "alen * 6" (5 digits + space) should be a good estimate
of how long the AS path string could be */
if (alen % 4 != 0)
goto default_attribute_top;
- /* (o + i + 3) =
- (o + current attribute + 3 bytes to first tuple) */
- end = o + alen + i + 3;
- q = o + i + 3;
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
/* must be freed by second switch! */
/* "alen * 12" (5 digits, a :, 5 digits + space ) should be
a good estimate of how long the communities string could
if (alen % 4 != 0)
goto default_attribute_top;
- /* (o + i + 3) =
- (o + current attribute + 3 bytes to first tuple) */
- end = o + alen + i + 3;
- q = o + i + 3;
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
/* must be freed by second switch! */
/* "alen * 16" (12 digits, 3 dots + space ) should be
a good estimate of how long the cluster_list string could
case BGPTYPE_EXTENDED_COMMUNITY:
if (alen %8 != 0)
goto default_attribute_top;
- q = o + i + aoff ;
- end = o + i + aoff + alen ;
- ext_com_str = malloc((alen / 8)*MAX_SIZE_OF_EXT_COM_NAMES) ;
- if (ext_com_str == NULL) break ;
- ext_com_str[0] = '\0' ;
+
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
+ ext_com_str = malloc((alen / 8)*MAX_SIZE_OF_EXT_COM_NAMES);
+ if (ext_com_str == NULL) break;
+ ext_com_str[0] = '\0';
while (q < end) {
- ext_com = tvb_get_ntohs(tvb,q) ;
+ ext_com = tvb_get_ntohs(tvb, q);
snprintf(junk_buf, sizeof(junk_buf), "%s", val_to_str(ext_com,bgpext_com_type,"Unknown"));
- strncat(ext_com_str,junk_buf,sizeof(junk_buf));
- q = q + 8 ;
- if (q<end) strncat(ext_com_str,",",1);
+ strncat(ext_com_str, junk_buf, sizeof(junk_buf));
+ q = q + 8;
+ if (q < end) strncat(ext_com_str, ",", 1);
}
ti = proto_tree_add_text(subtree,tvb,o+i,alen+aoff,
"%s : %s (%u %s)",
val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
ext_com_str,
alen,
- (alen ==1 ) ? "byte" : "bytes");
- free(ext_com_str) ;
+ (alen == 1) ? "byte" : "bytes");
+ free(ext_com_str);
break;
default:
"AS path: %s", as_path_str);
as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
- /* (o + i + 3) =
- (o + current attribute + 3 bytes to first tuple) */
- end = o + alen + i + 3;
- q = o + i + 3;
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
/* snarf each AS path tuple, we have to step through each one
again to make a separate subtree so we can't just reuse
communities_tree = proto_item_add_subtree(ti,
ett_bgp_communities);
- /* (o + i + 3) =
- (o + current attribute + 3 bytes to first tuple) */
- end = o + alen + i + 3;
- q = o + i + 3;
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
/* snarf each community */
while (q < end) {
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)",
cluster_list_tree = proto_item_add_subtree(ti,
ett_bgp_cluster_list);
- /* (p + i + 3) =
- (p + current attribute + 3 bytes to first tuple) */
- end = o + alen + i + 3;
- q = o + i + 3;
+ /* (o + i + aoff) =
+ (o + current attribute + aoff bytes to first tuple) */
+ q = o + i + aoff;
+ end = q + alen;
/* snarf each cluster identifier */
while (q < end) {
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"),
int hlen; /* BGP header length */
char *typ; /* BGP message type */
- if (check_col(pinfo->fd, COL_PROTOCOL))
- col_set_str(pinfo->fd, COL_PROTOCOL, "BGP");
- if (check_col(pinfo->fd, COL_INFO))
- col_clear(pinfo->fd, COL_INFO);
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
- l = tvb_length(tvb);
+ l = tvb_reported_length(tvb);
i = 0;
found = -1;
/* run through the TCP packet looking for BGP headers */
- /* this is done twice, but this way each message type can be
- printed in the COL_INFO field */
while (i + BGP_HEADER_SIZE <= l) {
tvb_memcpy(tvb, bgp.bgp_marker, i, BGP_HEADER_SIZE);
found++;
hlen = ntohs(bgp.bgp_len);
+
+ /*
+ * Desegmentation check.
+ */
+ if (bgp_desegment) {
+ if (hlen > tvb_length_remaining(tvb, i) && pinfo->can_desegment) {
+ /*
+ * Not all of this packet is in the data we've been
+ * handed, but we can do reassembly on it.
+ *
+ * Tell the TCP dissector where the data for
+ * this message starts in the data it handed
+ * us, and how many more bytes we need, and
+ * return.
+ */
+ pinfo->desegment_offset = i;
+ pinfo->desegment_len = hlen - tvb_length_remaining(tvb, i);
+ return;
+ }
+ }
+
typ = val_to_str(bgp.bgp_type, bgptypevals, "Unknown Message");
- if (check_col(pinfo->fd, COL_INFO)) {
+ if (check_col(pinfo->cinfo, COL_INFO)) {
if (found == 0)
- col_add_fstr(pinfo->fd, COL_INFO, "%s", typ);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", typ);
else
- col_append_fstr(pinfo->fd, COL_INFO, ", %s", typ);
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
}
- i += hlen;
- }
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_bgp, tvb, i, hlen, FALSE);
+ bgp_tree = proto_item_add_subtree(ti, ett_bgp);
- if (tree) {
- ti = proto_tree_add_item(tree, proto_bgp, tvb, 0,
- l, FALSE);
- bgp_tree = proto_item_add_subtree(ti, ett_bgp);
-
- i = 0;
- /* now, run through the TCP packet again, this time dissect */
- /* each message that we find */
- while (i + BGP_HEADER_SIZE <= l) {
- tvb_memcpy(tvb, bgp.bgp_marker, i, BGP_HEADER_SIZE);
-
- /* look for bgp header */
- if (memcmp(bgp.bgp_marker, marker, sizeof(marker)) != 0) {
- i++;
- continue;
- }
+ ti = proto_tree_add_text(bgp_tree, tvb, i, hlen, "%s", typ);
- hlen = ntohs(bgp.bgp_len);
- typ = val_to_str(bgp.bgp_type, bgptypevals, "Unknown Message");
- if (l < hlen) {
- ti = proto_tree_add_text(bgp_tree, tvb, i,
- l, "%s (truncated)", typ);
- } else {
- ti = proto_tree_add_text(bgp_tree, tvb, i, hlen,
- "%s", typ);
- }
/* add a different tree for each message type */
switch (bgp.bgp_type) {
case BGP_OPEN:
default:
break;
}
-
- i += hlen;
}
+
+ i += hlen;
}
}
&ett_bgp_option,
&ett_bgp_extended_communities
};
+ module_t *bgp_module;
proto_bgp = proto_register_protocol("Border Gateway Protocol",
"BGP", "bgp");
proto_register_field_array(proto_bgp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+ bgp_module = prefs_register_protocol(proto_bgp, NULL);
+ prefs_register_bool_preference(bgp_module, "desegment",
+ "Desegment all BGP messages spanning multiple TCP segments",
+ "Whether the BGP dissector should desegment all messages spanning multiple TCP segments",
+ &bgp_desegment);
}
void
proto_reg_handoff_bgp(void)
{
- dissector_add("tcp.port", BGP_TCP_PORT, dissect_bgp, proto_bgp);
+ dissector_handle_t bgp_handle;
+
+ bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
+ dissector_add("tcp.port", BGP_TCP_PORT, bgp_handle);
}