bgp route refresh/MP capability option.
Greg Hankins <gregh@twoguys.org> svn path=/trunk/; revision=2780
This commit is contained in:
parent
9314e65702
commit
b56e34d396
236
packet-bgp.c
236
packet-bgp.c
|
@ -2,14 +2,16 @@
|
|||
* Routines for BGP packet dissection.
|
||||
* Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
|
||||
*
|
||||
* $Id: packet-bgp.c,v 1.28 2000/11/19 08:53:55 guy Exp $
|
||||
* $Id: packet-bgp.c,v 1.29 2000/12/25 05:28:40 itojun Exp $
|
||||
*
|
||||
* Supports:
|
||||
* RFC1771 A Border Gateway Protocol 4 (BGP-4)
|
||||
* RFC1965 Autonomous System Confederations for BGP
|
||||
* RFC1966 BGP Route Reflection An alternative to full mesh IBGP
|
||||
* RFC1997 BGP Communities Attribute
|
||||
* RFC2283 Multiprotocol Extensions for BGP-4
|
||||
* RFC2796 BGP Route Reflection An alternative to full mesh IBGP
|
||||
* RFC2842 Capabilities Advertisement with BGP-4
|
||||
* RFC2858 Multiprotocol Extensions for BGP-4
|
||||
* RFC2918 Route Refresh Capability for BGP-4
|
||||
*
|
||||
* TODO:
|
||||
* Destination Preference Attribute for BGP (work in progress)
|
||||
|
@ -64,13 +66,12 @@
|
|||
#include "packet-bgp.h"
|
||||
#include "packet-ipv6.h"
|
||||
|
||||
#define TCP_PORT_BGP 179
|
||||
|
||||
static const value_string bgptypevals[] = {
|
||||
{ BGP_OPEN, "OPEN Message" },
|
||||
{ BGP_UPDATE, "UPDATE Message" },
|
||||
{ BGP_NOTIFICATION, "NOTIFICATION Message" },
|
||||
{ BGP_KEEPALIVE, "KEEPALIVE Message" },
|
||||
{ BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
|
@ -197,9 +198,12 @@ static gint ett_bgp_nlri = -1;
|
|||
static gint ett_bgp_open = -1;
|
||||
static gint ett_bgp_update = -1;
|
||||
static gint ett_bgp_notification = -1;
|
||||
static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
|
||||
static gint ett_bgp_as_paths = -1;
|
||||
static gint ett_bgp_communities = -1;
|
||||
static gint ett_bgp_cluster_list = -1;
|
||||
static gint ett_bgp_cluster_list = -1; /* cluster list tree */
|
||||
static gint ett_bgp_options = -1; /* optional parameters tree */
|
||||
static gint ett_bgp_option = -1; /* an optional parameter tree */
|
||||
|
||||
/*
|
||||
* Decode an IPv4 prefix.
|
||||
|
@ -261,8 +265,20 @@ decode_prefix6(const u_char *pd, char *buf, int buflen)
|
|||
static void
|
||||
dissect_bgp_open(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
||||
{
|
||||
struct bgp_open bgpo; /* BGP OPEN message */
|
||||
int hlen; /* message length */
|
||||
struct bgp_open bgpo; /* BGP OPEN message */
|
||||
int hlen; /* message length */
|
||||
u_int i; /* tmp */
|
||||
int ptype; /* parameter type */
|
||||
int plen; /* parameter length */
|
||||
int ctype; /* capability type */
|
||||
int clen; /* capability length */
|
||||
int ostart; /* options start */
|
||||
const u_char *oend; /* options end */
|
||||
const u_char *p; /* packet offset pointer */
|
||||
proto_item *ti; /* tree item */
|
||||
proto_tree *subtree; /* subtree for options */
|
||||
proto_tree *subtree2; /* subtree for an option */
|
||||
proto_tree *subtree3; /* subtree for an option */
|
||||
|
||||
/* snarf OPEN message */
|
||||
memcpy(&bgpo, &pd[offset], sizeof(bgpo));
|
||||
|
@ -285,12 +301,159 @@ dissect_bgp_open(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
"Optional parameters length: %u %s", bgpo.bgpo_optlen,
|
||||
(bgpo.bgpo_optlen == 1) ? "byte" : "bytes");
|
||||
|
||||
if (hlen > sizeof(struct bgp_open)) {
|
||||
int openoff;
|
||||
openoff = ((char *)&bgpo.bgpo_optlen - (char *)&bgpo) + 1;
|
||||
proto_tree_add_text(tree, NullTVB,
|
||||
offset + openoff, hlen - openoff,
|
||||
"Optional parameters");
|
||||
/* optional parameters */
|
||||
if (bgpo.bgpo_optlen > 0) {
|
||||
/* add a subtree and setup some offsets */
|
||||
ostart = offset + sizeof(bgpo) - 3;
|
||||
ti = proto_tree_add_text(tree, NullTVB, ostart, bgpo.bgpo_optlen,
|
||||
"Optional parameters");
|
||||
subtree = proto_item_add_subtree(ti, ett_bgp_options);
|
||||
p = &pd[ostart];
|
||||
oend = p + bgpo.bgpo_optlen;
|
||||
|
||||
/* step through all of the optional parameters */
|
||||
while (p < oend) {
|
||||
|
||||
/* grab the type and length */
|
||||
ptype = *p++;
|
||||
plen = *p++;
|
||||
|
||||
/* check the type */
|
||||
switch (ptype) {
|
||||
case BGP_OPTION_AUTHENTICATION:
|
||||
proto_tree_add_text(subtree, NullTVB, p - pd - 2, 2 + plen,
|
||||
"Authentication information (%u %s)", plen,
|
||||
(plen == 1) ? "byte" : "bytes");
|
||||
break;
|
||||
case BGP_OPTION_CAPABILITY:
|
||||
/* grab the capability code */
|
||||
ctype = *p++;
|
||||
clen = *p++;
|
||||
|
||||
/* check the capability type */
|
||||
switch (ctype) {
|
||||
case BGP_CAPABILITY_RESERVED:
|
||||
ti = proto_tree_add_text(subtree, NullTVB, p - pd - 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, NullTVB, p - pd - 4,
|
||||
1, "Parameter type: Capabilities (2)");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 3,
|
||||
1, "Parameter length: %u %s", plen,
|
||||
(plen == 1) ? "byte" : "bytes");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 2,
|
||||
1, "Capability code: Reserved (0)");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 1,
|
||||
1, "Capability length: %u %s", clen,
|
||||
(clen == 1) ? "byte" : "bytes");
|
||||
if (clen != 0) {
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd,
|
||||
clen, "Capability value: Unknown");
|
||||
}
|
||||
p += clen;
|
||||
break;
|
||||
case BGP_CAPABILITY_MULTIPROTOCOL:
|
||||
ti = proto_tree_add_text(subtree, NullTVB, p - pd - 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, NullTVB, p - pd - 4,
|
||||
1, "Parameter type: Capabilities (2)");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 3,
|
||||
1, "Parameter length: %u %s", plen,
|
||||
(plen == 1) ? "byte" : "bytes");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 2,
|
||||
1, "Capability code: Multiprotocol extensions (%d)",
|
||||
ctype);
|
||||
if (clen != 4) {
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 1,
|
||||
1, "Capability length: Invalid");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd,
|
||||
clen, "Capability value: Unknown");
|
||||
}
|
||||
else {
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 1,
|
||||
1, "Capability length: %u %s", clen,
|
||||
(clen == 1) ? "byte" : "bytes");
|
||||
ti = proto_tree_add_text(subtree2, NullTVB, p - pd,
|
||||
clen, "Capability value");
|
||||
subtree3 = proto_item_add_subtree(ti,
|
||||
ett_bgp_option);
|
||||
/* AFI */
|
||||
i = pntohs(p);
|
||||
proto_tree_add_text(subtree3, NullTVB, p - pd,
|
||||
2, "Address family identifier: %s (%u)",
|
||||
val_to_str(i, afnumber, "Unknown"), i);
|
||||
p += 2;
|
||||
/* Reserved */
|
||||
proto_tree_add_text(subtree3, NullTVB, p - pd,
|
||||
1, "Reserved: 1 byte");
|
||||
p++;
|
||||
/* SAFI */
|
||||
i = *p;
|
||||
proto_tree_add_text(subtree3, NullTVB, p - pd,
|
||||
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:
|
||||
ti = proto_tree_add_text(subtree, NullTVB, p - pd - 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, NullTVB, p - pd - 4,
|
||||
1, "Parameter type: Capabilities (2)");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 3,
|
||||
1, "Parameter length: %u %s", plen,
|
||||
(plen == 1) ? "byte" : "bytes");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 2,
|
||||
1, "Capability code: Route refresh (%d)", ctype);
|
||||
if (clen != 0) {
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd,
|
||||
clen, "Capability value: Invalid");
|
||||
}
|
||||
else {
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 1,
|
||||
1, "Capability length: %u %s", clen,
|
||||
(clen == 1) ? "byte" : "bytes");
|
||||
}
|
||||
p += clen;
|
||||
break;
|
||||
/* unknown capability */
|
||||
default:
|
||||
ti = proto_tree_add_text(subtree, NullTVB, p - pd - 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, NullTVB, p - pd - 4,
|
||||
1, "Parameter type: Capabilities (2)");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 3,
|
||||
1, "Parameter length: %u %s", plen,
|
||||
(plen == 1) ? "byte" : "bytes");
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 2,
|
||||
1, "Capability code: %s (%d)",
|
||||
ctype >= 128 ? "Private use" : "Unknown", ctype);
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd - 1,
|
||||
1, "Capability length: %u %s", clen,
|
||||
(clen == 1) ? "byte" : "bytes");
|
||||
if (clen != 0) {
|
||||
proto_tree_add_text(subtree2, NullTVB, p - pd,
|
||||
clen, "Capability value: Unknown");
|
||||
}
|
||||
p += clen;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
proto_tree_add_text(subtree, NullTVB, p - pd - 2, 2 + plen,
|
||||
"Unknown optional parameter");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1118,6 +1281,36 @@ dissect_bgp_notification(const u_char *pd, int offset, frame_data *fd,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dissect a BGP ROUTE-REFRESH message.
|
||||
*/
|
||||
static void
|
||||
dissect_bgp_route_refresh(const u_char *pd, int offset, frame_data *fd,
|
||||
proto_tree *tree)
|
||||
{
|
||||
const u_char *p; /* string pointer */
|
||||
u_int i; /* tmp */
|
||||
|
||||
/* AFI */
|
||||
p = &pd[offset + BGP_HEADER_SIZE];
|
||||
i = pntohs(p);
|
||||
proto_tree_add_text(tree, NullTVB, offset + BGP_HEADER_SIZE, 2,
|
||||
"Address family identifier: %s (%u)",
|
||||
val_to_str(i, afnumber, "Unknown"), i);
|
||||
p += 2;
|
||||
/* Reserved */
|
||||
proto_tree_add_text(tree, NullTVB, offset + BGP_HEADER_SIZE + 2, 1,
|
||||
"Reserved: 1 byte");
|
||||
p++;
|
||||
/* SAFI */
|
||||
i = *p;
|
||||
proto_tree_add_text(tree, NullTVB, offset + BGP_HEADER_SIZE + 3, 1,
|
||||
"Subsequent address family identifier: %s (%u)",
|
||||
val_to_str(i, bgpattr_nlri_safi,
|
||||
i >= 128 ? "Vendor specific" : "Unknown"),
|
||||
i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dissect a BGP packet.
|
||||
*/
|
||||
|
@ -1203,8 +1396,8 @@ dissect_bgp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
hlen = ntohs(bgp.bgp_len);
|
||||
typ = val_to_str(bgp.bgp_type, bgptypevals, "Unknown Message");
|
||||
if (END_OF_FRAME < hlen) {
|
||||
ti = proto_tree_add_text(bgp_tree, NullTVB, offset + i, END_OF_FRAME,
|
||||
"%s (truncated)", typ);
|
||||
ti = proto_tree_add_text(bgp_tree, NullTVB, offset + i,
|
||||
END_OF_FRAME, "%s (truncated)", typ);
|
||||
} else {
|
||||
ti = proto_tree_add_text(bgp_tree, NullTVB, offset + i, hlen,
|
||||
"%s", typ);
|
||||
|
@ -1223,6 +1416,9 @@ dissect_bgp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
case BGP_KEEPALIVE:
|
||||
bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
|
||||
break;
|
||||
case BGP_ROUTE_REFRESH:
|
||||
bgp1_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
|
||||
break;
|
||||
default:
|
||||
bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
|
||||
break;
|
||||
|
@ -1265,6 +1461,9 @@ dissect_bgp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
|
|||
case BGP_KEEPALIVE:
|
||||
/* no data in KEEPALIVE messages */
|
||||
break;
|
||||
case BGP_ROUTE_REFRESH:
|
||||
dissect_bgp_route_refresh(pd, offset + i, fd, bgp1_tree);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1299,9 +1498,12 @@ proto_register_bgp(void)
|
|||
&ett_bgp_open,
|
||||
&ett_bgp_update,
|
||||
&ett_bgp_notification,
|
||||
&ett_bgp_route_refresh,
|
||||
&ett_bgp_as_paths,
|
||||
&ett_bgp_communities,
|
||||
&ett_bgp_cluster_list,
|
||||
&ett_bgp_options,
|
||||
&ett_bgp_option,
|
||||
};
|
||||
|
||||
proto_bgp = proto_register_protocol("Border Gateway Protocol", "bgp");
|
||||
|
@ -1312,5 +1514,5 @@ proto_register_bgp(void)
|
|||
void
|
||||
proto_reg_handoff_bgp(void)
|
||||
{
|
||||
old_dissector_add("tcp.port", TCP_PORT_BGP, dissect_bgp);
|
||||
old_dissector_add("tcp.port", BGP_TCP_PORT, dissect_bgp);
|
||||
}
|
||||
|
|
37
packet-bgp.h
37
packet-bgp.h
|
@ -1,7 +1,7 @@
|
|||
/* packet-bgp.c
|
||||
* Definitions for BGP packet disassembly structures and routine
|
||||
*
|
||||
* $Id: packet-bgp.h,v 1.9 2000/04/11 14:21:37 itojun Exp $
|
||||
* $Id: packet-bgp.h,v 1.10 2000/12/25 05:28:40 itojun Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@zing.org>
|
||||
|
@ -33,12 +33,14 @@
|
|||
#define BGP_MIN_UPDATE_MSG_SIZE 23
|
||||
#define BGP_MIN_NOTIFICATION_MSG_SIZE 21
|
||||
#define BGP_MIN_KEEPALVE_MSG_SIZE BGP_HEADER_SIZE
|
||||
#define BGP_TCP_PORT 179
|
||||
|
||||
/* BGP message types */
|
||||
#define BGP_OPEN 1
|
||||
#define BGP_UPDATE 2
|
||||
#define BGP_NOTIFICATION 3
|
||||
#define BGP_KEEPALIVE 4
|
||||
#define BGP_ROUTE_REFRESH 5
|
||||
|
||||
/* BGP header */
|
||||
struct bgp {
|
||||
|
@ -70,6 +72,16 @@ struct bgp_notification {
|
|||
/* data should follow */
|
||||
};
|
||||
|
||||
/* BGP ROUTE-REFRESH message */
|
||||
struct bgp_route_refresh {
|
||||
guint8 bgpr_marker[BGP_MARKER_SIZE];
|
||||
guint16 bgpr_len;
|
||||
guint8 bgpr_type;
|
||||
guint16 bgpr_afi;
|
||||
guint8 bgpr_reserved;
|
||||
guint8 bgpr_safi;
|
||||
};
|
||||
|
||||
/* path attribute */
|
||||
struct bgp_attr {
|
||||
guint8 bgpa_flags;
|
||||
|
@ -85,10 +97,17 @@ struct bgp_attr {
|
|||
/* AS_PATH segment types */
|
||||
#define AS_SET 1 /* RFC1771 */
|
||||
#define AS_SEQUENCE 2 /* RFC1771 */
|
||||
/* This is wrong according to the RFC... in the Zebra code they say that
|
||||
cisco reversed it. Packet traces seem to agree. */
|
||||
#define AS_CONFED_SET 4 /* RFC1965 */
|
||||
#define AS_CONFED_SEQUENCE 3 /* RFC1965 */
|
||||
#define AS_CONFED_SET 4 /* RFC1965 has the wrong values, corrected in */
|
||||
#define AS_CONFED_SEQUENCE 3 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
|
||||
|
||||
/* OPEN message Optional Parameter types */
|
||||
#define BGP_OPTION_AUTHENTICATION 1 /* RFC1771 */
|
||||
#define BGP_OPTION_CAPABILITY 2 /* RFC2842 */
|
||||
|
||||
/* BGP capability code */
|
||||
#define BGP_CAPABILITY_RESERVED 0 /* RFC2434 */
|
||||
#define BGP_CAPABILITY_MULTIPROTOCOL 1 /* RFC2858 */
|
||||
#define BGP_CAPABILITY_ROUTE_REFRESH 2 /* RFC2918 */
|
||||
|
||||
/* well-known communities, from RFC1997 */
|
||||
#define BGP_COMM_NO_EXPORT 0xFFFFFF01
|
||||
|
@ -106,13 +125,13 @@ struct bgp_attr {
|
|||
#define BGPTYPE_ATOMIC_AGGREGATE 6 /* RFC1771 */
|
||||
#define BGPTYPE_AGGREGATOR 7 /* RFC1771 */
|
||||
#define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
|
||||
#define BGPTYPE_ORIGINATOR_ID 9 /* RFC1966 */
|
||||
#define BGPTYPE_CLUSTER_LIST 10 /* RFC1966 */
|
||||
#define BGPTYPE_ORIGINATOR_ID 9 /* RFC2796 */
|
||||
#define BGPTYPE_CLUSTER_LIST 10 /* RFC2796 */
|
||||
#define BGPTYPE_DPA 11 /* work in progress */
|
||||
#define BGPTYPE_ADVERTISER 12 /* RFC1863 */
|
||||
#define BGPTYPE_RCID_PATH 13 /* RFC1863 */
|
||||
#define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
|
||||
#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
|
||||
#define BGPTYPE_MP_REACH_NLRI 14 /* RFC2858 */
|
||||
#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2858 */
|
||||
|
||||
/* RFC1700 address family numbers */
|
||||
#define AFNUM_INET 1
|
||||
|
|
Loading…
Reference in New Issue