2 * Routines for BGP packet dissection.
3 * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
5 * $Id: packet-bgp.c,v 1.76 2003/04/24 09:00:27 guy Exp $
8 * RFC1771 A Border Gateway Protocol 4 (BGP-4)
9 * RFC1965 Autonomous System Confederations for BGP
10 * RFC1997 BGP Communities Attribute
11 * RFC2547 BGP/MPLS VPNs
12 * RFC2796 BGP Route Reflection An alternative to full mesh IBGP
13 * RFC2842 Capabilities Advertisement with BGP-4
14 * RFC2858 Multiprotocol Extensions for BGP-4
15 * RFC2918 Route Refresh Capability for BGP-4
16 * RFC3107 Carrying Label Information in BGP-4
17 * Draft Ramahandra on Extended Communities Extentions
18 * draft-ietf-idr-as4bytes-06
19 * draft-ietf-idr-dynamic-cap-03
22 * Destination Preference Attribute for BGP (work in progress)
23 * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
25 * Ethereal - Network traffic analyzer
26 * By Gerald Combs <gerald@ethereal.com>
27 * Copyright 1998 Gerald Combs
29 * This program is free software; you can redistribute it and/or
30 * modify it under the terms of the GNU General Public License
31 * as published by the Free Software Foundation; either version 2
32 * of the License, or (at your option) any later version.
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
54 #ifdef NEED_SNPRINTF_H
55 # include "snprintf.h"
58 #include <epan/packet.h>
59 #include "packet-bgp.h"
60 #include "packet-ipv6.h"
61 #include "packet-frame.h"
65 static const value_string bgptypevals[] = {
66 { BGP_OPEN, "OPEN Message" },
67 { BGP_UPDATE, "UPDATE Message" },
68 { BGP_NOTIFICATION, "NOTIFICATION Message" },
69 { BGP_KEEPALIVE, "KEEPALIVE Message" },
70 { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
71 { BGP_CAPABILITY, "CAPABILITY Message" },
72 { BGP_ROUTE_REFRESH_CISCO, "Cisco ROUTE-REFRESH Message" },
76 static const value_string bgpnotify_major[] = {
77 { 1, "Message Header Error" },
78 { 2, "OPEN Message Error" },
79 { 3, "UPDATE Message Error" },
80 { 4, "Hold Timer Expired" },
81 { 5, "Finite State Machine Error" },
83 { 7, "CAPABILITY Message Error" },
87 static const value_string bgpnotify_minor_1[] = {
88 { 1, "Connection Not Synchronized" },
89 { 2, "Bad Message Length" },
90 { 3, "Bad Message Type" },
94 static const value_string bgpnotify_minor_2[] = {
95 { 1, "Unsupported Version Number" },
97 { 3, "Bad BGP Identifier" },
98 { 4, "Unsupported Optional Parameter" },
99 { 5, "Authentication Failure" },
100 { 6, "Unacceptable Hold Time" },
101 { 7, "Unsupported Capability" },
105 static const value_string bgpnotify_minor_3[] = {
106 { 1, "Malformed Attribute List" },
107 { 2, "Unrecognized Well-known Attribute" },
108 { 3, "Missing Well-known Attribute" },
109 { 4, "Attribute Flags Error" },
110 { 5, "Attribute Length Error" },
111 { 6, "Invalid ORIGIN Attribute" },
112 { 7, "AS Routing Loop" },
113 { 8, "Invalid NEXT_HOP Attribute" },
114 { 9, "Optional Attribute Error" },
115 { 10, "Invalid Network Field" },
116 { 11, "Malformed AS_PATH" },
120 static const value_string bgpnotify_minor_7[] = {
121 { 1, "Invalid Action Value" },
122 { 2, "Invalid Capability Length" },
123 { 3, "Malformed Capability Value" },
124 { 4, "Unsopported Capability Code" },
128 static const value_string *bgpnotify_minor[] = {
129 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3,
132 static const value_string bgpattr_origin[] = {
139 static const value_string as_segment_type[] = {
141 { 2, "AS_SEQUENCE" },
142 /* RFC1965 has the wrong values, corrected in */
143 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
144 { 4, "AS_CONFED_SET" },
145 { 3, "AS_CONFED_SEQUENCE" },
149 static const value_string bgpattr_type[] = {
150 { BGPTYPE_ORIGIN, "ORIGIN" },
151 { BGPTYPE_AS_PATH, "AS_PATH" },
152 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
153 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
154 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
155 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
156 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
157 { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
158 { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
159 { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
160 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
161 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
162 { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
163 { BGPTYPE_NEW_AS_PATH, "NEW_AS_PATH" },
164 { BGPTYPE_NEW_AGGREGATOR, "NEW_AGGREGATOR" },
168 /* Beware : See also MAX_SIZE_OF_EXT_COM_NAMES */
169 static const value_string bgpext_com_type[] = {
170 { BGP_EXT_COM_RT_0, "Route Target" },
171 { BGP_EXT_COM_RT_1, "Route Target" },
172 { BGP_EXT_COM_RO_0, "Route Origin" },
173 { BGP_EXT_COM_RO_1, "Route Origin" },
174 { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
175 { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
176 { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
177 { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
178 { BGP_EXT_COM_L2INFO, "Layer 2 Information" },
182 static const value_string bgp_l2vpn_encaps[] = {
185 { 2, "ATM AAL5 VCC transport"},
186 { 3, "ATM transparent cell transport"},
187 { 4, "Ethernet VLAN"},
192 { 9, "ATM VCC cell transport"},
193 { 10, "ATM VPC cell transport"},
196 { 64, "IP-interworking"},
200 static const value_string bgpext_ospf_rtype[] = {
201 { BGP_OSPF_RTYPE_RTR, "Router" },
202 { BGP_OSPF_RTYPE_NET, "Network" },
203 { BGP_OSPF_RTYPE_SUM, "Summary" },
204 { BGP_OSPF_RTYPE_EXT, "External" },
205 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
206 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
211 /* MUST be resized if a longer named extended community is added */
212 #define MAX_SIZE_OF_EXT_COM_NAMES 20
214 /* Subsequent address family identifier, RFC2858 */
215 static const value_string bgpattr_nlri_safi[] = {
217 { SAFNUM_UNICAST, "Unicast" },
218 { SAFNUM_MULCAST, "Multicast" },
219 { SAFNUM_UNIMULC, "Unicast+Multicast" },
220 { SAFNUM_MPLS_LABEL, "Labeled Unicast"},
221 { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */
222 { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
223 { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
227 /* ORF Type, draft-ietf-idr-route-filter-04.txt */
228 static const value_string orf_type_vals[] = {
229 { 2, "Communities ORF-Type" },
230 { 3, "Extended Communities ORF-Type" },
231 { 128, "Cisco PrefixList ORF-Type" },
232 { 129, "Cisco CommunityList ORF-Type" },
233 { 130, "Cisco Extended CommunityList ORF-Type" },
234 { 131, "Cisco AsPathList ORF-Type" },
238 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
239 static const value_string orf_send_recv_vals[] = {
246 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
247 static const value_string orf_when_vals[] = {
253 static const value_string orf_entry_action_vals[] = {
256 { 0x80, "RemoveAll" },
260 static const value_string orf_entry_match_vals[] = {
266 static const value_string capability_vals[] = {
267 { BGP_CAPABILITY_RESERVED, "Reserved capability" },
268 { BGP_CAPABILITY_MULTIPROTOCOL, "Multiprotocol extensions capability" },
269 { BGP_CAPABILITY_ROUTE_REFRESH, "Route refresh capability" },
270 { BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING, "Cooperative route filtering capability" },
271 { BGP_CAPABILITY_GRACEFUL_RESTART, "Graceful Restart capability" },
272 { BGP_CAPABILITY_4_OCTET_AS_NUMBER, "Support for 4-octet AS number capability" },
273 { BGP_CAPABILITY_DYNAMIC_CAPABILITY, "Support for Dynamic capability" },
274 { BGP_CAPABILITY_ROUTE_REFRESH_CISCO, "Route refresh capability" },
275 { BGP_CAPABILITY_ORF_CISCO, "Cooperative route filtering capability" },
278 /* Capability Message action code */
279 static const value_string bgpcap_action[] = {
280 { 0, "advertising a capability" },
281 { 1, "removing a capability" },
286 /* Maximal size of an IP address string */
287 #define MAX_SIZE_OF_IP_ADDR_STRING 16
289 static int proto_bgp = -1;
290 static int hf_bgp_type = -1;
291 static int hf_bgp_next_hop = -1;
292 static int hf_bgp_as_path = -1;
293 static int hf_bgp_cluster_identifier = -1;
294 static int hf_bgp_community_as = -1;
295 static int hf_bgp_community_value = -1;
296 static int hf_bgp_origin = -1;
297 static int hf_bgp_cluster_list = -1;
298 static int hf_bgp_originator_id = -1;
299 static int hf_bgp_local_pref = -1;
300 static int hf_bgp_multi_exit_disc = -1;
301 static int hf_bgp_aggregator_as = -1;
302 static int hf_bgp_aggregator_origin = -1;
303 static int hf_bgp_mp_reach_nlri_ipv4_prefix = -1;
304 static int hf_bgp_mp_unreach_nlri_ipv4_prefix = -1;
305 static int hf_bgp_withdrawn_prefix = -1;
306 static int hf_bgp_nlri_prefix = -1;
308 static gint ett_bgp = -1;
309 static gint ett_bgp_prefix = -1;
310 static gint ett_bgp_unfeas = -1;
311 static gint ett_bgp_attrs = -1;
312 static gint ett_bgp_attr = -1;
313 static gint ett_bgp_attr_flags = -1;
314 static gint ett_bgp_mp_nhna = -1;
315 static gint ett_bgp_mp_reach_nlri = -1;
316 static gint ett_bgp_mp_unreach_nlri = -1;
317 static gint ett_bgp_mp_snpa = -1;
318 static gint ett_bgp_nlri = -1;
319 static gint ett_bgp_open = -1;
320 static gint ett_bgp_update = -1;
321 static gint ett_bgp_notification = -1;
322 static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
323 static gint ett_bgp_capability = -1;
324 static gint ett_bgp_as_paths = -1;
325 static gint ett_bgp_as_path_segments = -1;
326 static gint ett_bgp_communities = -1;
327 static gint ett_bgp_cluster_list = -1; /* cluster list tree */
328 static gint ett_bgp_options = -1; /* optional parameters tree */
329 static gint ett_bgp_option = -1; /* an optional parameter tree */
330 static gint ett_bgp_extended_communities = -1 ; /* extended communities list tree */
331 static gint ett_bgp_orf = -1; /* orf (outbound route filter) tree */
332 static gint ett_bgp_orf_entry = -1; /* orf entry tree */
335 static gboolean bgp_desegment = TRUE;
337 static gint bgp_asn_len = 0;
340 * Decode an IPv4 prefix.
343 decode_prefix4(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
344 guint16 tlen, char *tag)
347 proto_tree *prefix_tree;
349 guint8 addr_bytes[4];
351 } ip_addr; /* IP address */
352 guint8 plen; /* prefix length */
353 int length; /* number of octets needed for prefix */
356 plen = tvb_get_guint8(tvb, offset);
358 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid",
362 length = (plen + 7) / 8;
365 memset((void *)&ip_addr, 0, sizeof(ip_addr));
366 tvb_memcpy(tvb, ip_addr.addr_bytes, offset + 1, length);
368 ip_addr.addr_bytes[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
370 /* put prefix into protocol tree */
371 ti = proto_tree_add_text(tree, tvb, offset,
372 tlen != 0 ? tlen : 1 + length, "%s/%u",
373 ip_to_str(ip_addr.addr_bytes), plen);
374 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
375 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
378 proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 1, length,
381 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
382 "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
388 * Decode an IPv6 prefix.
391 decode_prefix6(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
392 guint16 tlen, char *tag)
395 proto_tree *prefix_tree;
396 struct e_in6_addr addr; /* IPv6 address */
397 int plen; /* prefix length */
398 int length; /* number of octets needed for prefix */
401 plen = tvb_get_guint8(tvb, offset);
403 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid",
407 length = (plen + 7) / 8;
410 memset(&addr, 0, sizeof(addr));
411 tvb_memcpy(tvb, (guint8 *)&addr, offset + 1, length);
413 addr.s6_addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
415 /* put prefix into protocol tree */
416 ti = proto_tree_add_text(tree, tvb, offset,
417 tlen != 0 ? tlen : 1 + length, "%s/%u",
418 ip6_to_str(&addr), plen);
419 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
420 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
423 proto_tree_add_ipv6(prefix_tree, hf_addr, tvb, offset + 1, length,
426 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
427 "%s prefix: %s", tag, ip6_to_str(&addr));
435 * Decode an MPLS label stack
438 decode_MPLS_stack(tvbuff_t *tvb, gint offset, char *buf, size_t buflen)
440 guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
441 gint index; /* index for the label stack */
442 char junk_buf[256]; /* tmp */
445 label_entry = 0x000000 ;
449 while ((label_entry & 0x000001) == 0) {
451 label_entry = tvb_get_ntoh24(tvb, index) ;
453 /* withdrawn routes may contain 0 or 0x800000 in the first label */
454 if((index-offset)==0&&(label_entry==0||label_entry==0x800000)) {
455 snprintf(buf, buflen, "0 (withdrawn)");
459 snprintf(junk_buf, sizeof(junk_buf),"%u%s", (label_entry >> 4), ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
460 if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
461 strcat(buf, junk_buf);
464 if ((label_entry & 0x000001) == 0) {
465 /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
466 strcpy(junk_buf, " (BOGUS: Bottom of Stack NOT set!)");
467 if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
468 strcat(buf, junk_buf);
473 return((index - offset) / 3);
477 * Decode a multiprotocol address
481 mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *buf, int buflen)
483 int length; /* length of the address in byte */
484 guint8 ip4addr[4],ip4addr2[4]; /* IPv4 address */
485 guint16 rd_type; /* Route Distinguisher type */
486 struct e_in6_addr ip6addr; /* IPv6 address */
495 case SAFNUM_MPLS_LABEL:
497 tvb_memcpy(tvb, ip4addr, offset, sizeof(ip4addr));
498 snprintf(buf, buflen, "%s", ip_to_str(ip4addr));
500 case SAFNUM_LAB_VPNUNICAST:
501 case SAFNUM_LAB_VPNMULCAST:
502 case SAFNUM_LAB_VPNUNIMULC:
503 rd_type=tvb_get_ntohs(tvb,offset) ;
506 length = 8 + sizeof(ip4addr);
507 tvb_memcpy(tvb, ip4addr, offset + 8, sizeof(ip4addr)); /* Next Hop */
508 snprintf(buf, buflen, "Empty Label Stack RD=%u:%u IP=%s",
509 tvb_get_ntohs(tvb, offset + 2),
510 tvb_get_ntohl(tvb, offset + 4),
514 length = 8 + sizeof(ip4addr);
515 tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr)); /* IP part of the RD */
516 tvb_memcpy(tvb, ip4addr2, offset + 8, sizeof(ip4addr)); /* Next Hop */
517 snprintf(buf, buflen, "Empty Label Stack RD=%s:%u IP=%s",
519 tvb_get_ntohs(tvb, offset + 6),
520 ip_to_str(ip4addr2));
524 snprintf(buf, buflen, "Unknown (0x%04x)labeled VPN address format",rd_type);
530 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
540 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8,offset, 16);
541 snprintf(buf, buflen, "%s", ip6_to_str(&ip6addr));
543 case SAFNUM_LAB_VPNUNICAST:
544 case SAFNUM_LAB_VPNMULCAST:
545 case SAFNUM_LAB_VPNUNIMULC:
546 rd_type=tvb_get_ntohs(tvb,offset) ;
550 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, 16); /* Next Hop */
551 snprintf(buf, buflen, "Empty Label Stack RD=%u:%u IP=%s",
552 tvb_get_ntohs(tvb, offset + 2),
553 tvb_get_ntohl(tvb, offset + 4),
554 ip6_to_str(&ip6addr));
558 tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr)); /* IP part of the RD */
559 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, 16); /* Next Hop */
560 snprintf(buf, buflen, "Empty Label Stack RD=%s:%u IP=%s",
562 tvb_get_ntohs(tvb, offset + 6),
563 ip6_to_str(&ip6addr));
567 snprintf(buf, buflen, "Unknown (0x%04x)labeled VPN address format",rd_type);
573 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
579 case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
580 case SAFNUM_LAB_VPNMULCAST:
581 case SAFNUM_LAB_VPNUNIMULC:
582 length = 4; /* the next-hop is simply an ipv4 addr */
583 tvb_memcpy(tvb, ip4addr, offset + 0, 4);
584 snprintf(buf, buflen, "IP=%s",
589 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
595 snprintf(buf, buflen, "Unknown AFI (%u) value", afi);
602 * Decode a multiprotocol prefix
605 decode_prefix_MP(proto_tree *tree, int hf_addr4, int hf_addr6,
606 guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *tag)
608 int start_offset = offset;
610 proto_tree *prefix_tree;
611 int total_length; /* length of the entire item */
612 int length; /* length of the prefix address, in bytes */
613 guint8 plen; /* length of the prefix address, in bits */
614 int labnum; /* number of labels */
615 int ce_id,labblk_off;
617 guint8 addr_bytes[4];
619 } ip4addr, ip4addr2; /* IPv4 address */
620 struct e_in6_addr ip6addr; /* IPv6 address */
621 guint16 rd_type; /* Route Distinguisher type */
622 char lab_stk[256]; /* label stack */
632 total_length = decode_prefix4(tree, hf_addr4, tvb, offset, 0, tag);
633 if (total_length < 0)
637 case SAFNUM_MPLS_LABEL:
638 plen = tvb_get_guint8(tvb, offset);
639 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
641 offset += (1 + labnum * 3);
642 if (plen <= (labnum * 3*8)) {
643 proto_tree_add_text(tree, tvb, start_offset, 1,
644 "%s IPv4 prefix length %u invalid", tag, plen);
647 plen -= (labnum * 3*8);
649 proto_tree_add_text(tree, tvb, start_offset, 1,
650 "%s IPv4 prefix length %u invalid",
651 tag, plen + (labnum * 3*8));
655 length = (plen + 7) / 8;
656 memset((void *)&ip4addr, 0, sizeof(ip4addr));
657 tvb_memcpy(tvb, (void *)ip4addr.addr_bytes, offset, length);
659 ip4addr.addr_bytes[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
661 ti = proto_tree_add_text(tree, tvb, start_offset,
662 (offset + 1 + length) - start_offset,
663 "Label Stack=%s IP=%s/%u",
664 lab_stk, ip_to_str(ip4addr.addr_bytes), plen);
665 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
666 if (hf_addr4 != -1) {
667 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset + 1,
668 length, ip4addr.addr);
670 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
671 "%s IPv4 prefix: %s",
672 tag, ip_to_str(ip4addr.addr_bytes));
674 total_length = (1 + labnum*3) + length;
677 case SAFNUM_LAB_VPNUNICAST:
678 case SAFNUM_LAB_VPNMULCAST:
679 case SAFNUM_LAB_VPNUNIMULC:
680 plen = tvb_get_guint8(tvb, offset);
681 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
683 offset += (1 + labnum * 3);
684 if (plen <= (labnum * 3*8)) {
685 proto_tree_add_text(tree, tvb, start_offset, 1,
686 "%s IPv4 prefix length %u invalid", tag, plen);
689 plen -= (labnum * 3*8);
691 rd_type = tvb_get_ntohs(tvb, offset);
693 proto_tree_add_text(tree, tvb, start_offset, 1,
694 "%s IPv4 prefix length %u invalid",
695 tag, plen + (labnum * 3*8));
702 case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
704 proto_tree_add_text(tree, tvb, start_offset, 1,
705 "%s IPv4 prefix length %u invalid",
706 tag, plen + (labnum * 3*8) + 8*8);
710 length = (plen + 7) / 8;
711 memset(ip4addr.addr_bytes, 0, 4);
712 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 8, length);
714 ip4addr.addr_bytes[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
716 ti = proto_tree_add_text(tree, tvb, start_offset,
717 (offset + 8 + length) - start_offset,
718 "Label Stack=%s RD=%u:%u, IP=%s/%u",
720 tvb_get_ntohs(tvb, offset + 2),
721 tvb_get_ntohl(tvb, offset + 4),
722 ip_to_str(ip4addr.addr_bytes), plen);
723 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
724 if (hf_addr4 != -1) {
725 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
726 offset + 8, length, ip4addr.addr);
728 proto_tree_add_text(prefix_tree, tvb, offset + 8,
729 length, "%s IPv4 prefix: %s", tag,
730 ip_to_str(ip4addr.addr_bytes));
732 total_length = (1 + labnum * 3 + 8) + length;
735 case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
736 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
739 proto_tree_add_text(tree, tvb, start_offset, 1,
740 "%s IPv4 prefix length %u invalid",
741 tag, plen + (labnum * 3*8) + 8*8);
745 length = (plen + 7) / 8;
746 memset((void *)&ip4addr2, 0, sizeof(ip4addr2));
747 tvb_memcpy(tvb, ip4addr2.addr_bytes, offset + 8, length);
749 ip4addr2.addr_bytes[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
751 ti = proto_tree_add_text(tree, tvb, start_offset,
752 (offset + 8 + length) - start_offset,
753 "Label Stack=%s RD=%s:%u, IP=%s/%u",
755 ip_to_str(ip4addr.addr_bytes),
756 tvb_get_ntohs(tvb, offset + 6),
757 ip_to_str(ip4addr2.addr_bytes),
759 total_length = (1 + labnum * 3 + 8) + length;
763 proto_tree_add_text(tree, tvb, start_offset,
764 (offset - start_offset) + 2,
765 "Unknown labeled VPN address format %u", rd_type);
771 proto_tree_add_text(tree, tvb, start_offset, 0,
772 "Unknown SAFI (%u) for AFI %u", safi, afi);
783 total_length = decode_prefix6(tree, hf_addr6, tvb, offset, 0, tag);
784 if (total_length < 0)
788 case SAFNUM_LAB_VPNUNICAST:
789 case SAFNUM_LAB_VPNMULCAST:
790 case SAFNUM_LAB_VPNUNIMULC:
791 plen = tvb_get_guint8(tvb, offset);
792 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
794 offset += (1 + labnum * 3);
795 if (plen <= (labnum * 3*8)) {
796 proto_tree_add_text(tree, tvb, start_offset, 1,
797 "%s IPv6 prefix length %u invalid", tag, plen);
800 plen -= (labnum * 3*8);
802 rd_type = tvb_get_ntohs(tvb,offset);
804 proto_tree_add_text(tree, tvb, start_offset, 1,
805 "%s IPv6 prefix length %u invalid",
806 tag, plen + (labnum * 3*8));
815 proto_tree_add_text(tree, tvb, start_offset, 1,
816 "%s IPv6 prefix length %u invalid",
817 tag, plen + (labnum * 3*8) + 8*8);
821 length = (plen + 7) / 8;
822 memset(ip6addr.u6_addr.u6_addr8, 0, 16);
823 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, length);
825 ip6addr.u6_addr.u6_addr8[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
827 ti = proto_tree_add_text(tree, tvb, start_offset,
828 (offset + 8 + length) - start_offset,
829 "Label Stack=%s RD=%u:%u, IP=%s/%u",
831 tvb_get_ntohs(tvb, offset + 2),
832 tvb_get_ntohl(tvb, offset + 4),
833 ip6_to_str(&ip6addr), plen);
834 total_length = (1 + labnum * 3 + 8) + length;
838 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
841 proto_tree_add_text(tree, tvb, start_offset, 1,
842 "%s IPv6 prefix length %u invalid",
843 tag, plen + (labnum * 3*8) + 8*8);
846 length = (plen + 7) / 8;
847 memset(ip6addr.u6_addr.u6_addr8, 0, 16);
848 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, length);
850 ip6addr.u6_addr.u6_addr8[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
852 ti = proto_tree_add_text(tree, tvb, start_offset,
853 (offset + 8 + length) - start_offset,
854 "Label Stack=%s RD=%s:%u, IP=%s/%u",
856 ip_to_str(ip4addr.addr_bytes),
857 tvb_get_ntohs(tvb, offset + 6),
858 ip6_to_str(&ip6addr), plen);
859 total_length = (1 + labnum * 3 + 8) + length;
863 proto_tree_add_text(tree, tvb, start_offset, 0,
864 "Unknown labeled VPN address format %u", rd_type);
870 proto_tree_add_text(tree, tvb, start_offset, 0,
871 "Unknown SAFI (%u) for AFI %u", safi, afi);
879 case SAFNUM_LAB_VPNUNICAST:
880 case SAFNUM_LAB_VPNMULCAST:
881 case SAFNUM_LAB_VPNUNIMULC:
882 plen = tvb_get_ntohs(tvb,offset);
883 rd_type=tvb_get_ntohs(tvb,offset+2);
884 ce_id=tvb_get_ntohs(tvb,offset+10);
885 labblk_off=tvb_get_ntohs(tvb,offset+12);
886 labnum = decode_MPLS_stack(tvb, offset + 14, lab_stk, sizeof(lab_stk));
891 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 6, 4);
892 proto_tree_add_text(tree, tvb, start_offset,
893 (offset + plen + 1) - start_offset,
894 "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
895 tvb_get_ntohs(tvb, offset + 4),
896 ip_to_str(ip4addr.addr_bytes),
903 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 4, 4);
904 proto_tree_add_text(tree, tvb, offset,
905 (offset + plen + 1) - start_offset,
906 "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
907 ip_to_str(ip4addr.addr_bytes),
908 tvb_get_ntohs(tvb, offset + 8),
915 proto_tree_add_text(tree, tvb, start_offset,
916 (offset - start_offset) + 2,
917 "Unknown labeled VPN address format %u", rd_type);
920 /* FIXME there are subTLVs left to decode ... for now lets omit them */
921 total_length = plen+2;
925 proto_tree_add_text(tree, tvb, start_offset, 0,
926 "Unknown SAFI (%u) for AFI %u", safi, afi);
932 proto_tree_add_text(tree, tvb, start_offset, 0,
933 "Unknown AFI (%u) value", afi);
936 return(total_length);
940 * Dissect a BGP capability.
943 dissect_bgp_capability_item(tvbuff_t *tvb, int *p, proto_tree *tree, int ctype, int clen)
947 guint8 orfnum; /* number of ORFs */
948 guint8 orftype; /* ORF Type */
949 guint8 orfsendrecv; /* ORF Send/Receive */
950 int tclen; /* capability length */
953 /* check the capability type */
955 case BGP_CAPABILITY_RESERVED:
956 proto_tree_add_text(tree, tvb, *p - 2, 1,
957 "Capability code: %s (%d)", val_to_str(ctype,
958 capability_vals, "Unknown capability"), ctype);
959 proto_tree_add_text(tree, tvb, *p - 1,
960 1, "Capability length: %u %s", clen,
961 (clen == 1) ? "byte" : "bytes");
963 proto_tree_add_text(tree, tvb, *p,
964 clen, "Capability value: Unknown");
968 case BGP_CAPABILITY_MULTIPROTOCOL:
969 proto_tree_add_text(tree, tvb, *p - 2, 1,
970 "Capability code: %s (%d)", val_to_str(ctype,
971 capability_vals, "Unknown capability"), ctype);
973 proto_tree_add_text(tree, tvb, *p - 1,
974 1, "Capability length: Invalid");
975 proto_tree_add_text(tree, tvb, *p,
976 clen, "Capability value: Unknown");
979 proto_tree_add_text(tree, tvb, *p - 1,
980 1, "Capability length: %u %s", clen,
981 (clen == 1) ? "byte" : "bytes");
982 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
983 subtree = proto_item_add_subtree(ti, ett_bgp_option);
985 i = tvb_get_ntohs(tvb, *p);
986 proto_tree_add_text(subtree, tvb, *p,
987 2, "Address family identifier: %s (%u)",
988 val_to_str(i, afn_vals, "Unknown"), i);
991 proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
994 i = tvb_get_guint8(tvb, *p);
995 proto_tree_add_text(subtree, tvb, *p,
996 1, "Subsequent address family identifier: %s (%u)",
997 val_to_str(i, bgpattr_nlri_safi,
998 i >= 128 ? "Vendor specific" : "Unknown"), i);
1002 case BGP_CAPABILITY_GRACEFUL_RESTART:
1003 proto_tree_add_text(tree, tvb, *p - 2, 1,
1004 "Capability code: %s (%d)", val_to_str(ctype,
1005 capability_vals, "Unknown capability"), ctype);
1007 proto_tree_add_text(tree, tvb, *p,
1008 clen, "Capability value: Invalid");
1011 proto_tree_add_text(tree, tvb, *p - 1,
1012 1, "Capability length: %u %s", clen,
1013 (clen == 1) ? "byte" : "bytes");
1014 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1015 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1017 i = tvb_get_ntohs(tvb, *p);
1018 proto_tree_add_text(subtree, tvb, *p,
1019 2, "Restart Flags: [%s], Restart Time %us",
1020 (i&0x8000) ? "R" : "none", i&0xfff);
1024 * what follows is alist of AFI/SAFI/flag triplets
1025 * read it until the TLV ends
1029 i = tvb_get_ntohs(tvb, *p);
1030 proto_tree_add_text(subtree, tvb, *p,
1031 2, "Address family identifier: %s (%u)",
1032 val_to_str(i, afn_vals, "Unknown"), i);
1035 i = tvb_get_guint8(tvb, *p);
1036 proto_tree_add_text(subtree, tvb, *p,
1037 1, "Subsequent address family identifier: %s (%u)",
1038 val_to_str(i, bgpattr_nlri_safi,
1039 i >= 128 ? "Vendor specific" : "Unknown"), i);
1042 i = tvb_get_guint8(tvb, *p);
1043 proto_tree_add_text(subtree, tvb, *p, 1,
1044 "Preserve forwarding state: %s",
1045 (i&0x80) ? "yes" : "no");
1052 case BGP_CAPABILITY_4_OCTET_AS_NUMBER:
1053 proto_tree_add_text(tree, tvb, *p - 2, 1,
1054 "Capability code: %s (%d)", val_to_str(ctype,
1055 capability_vals, "Unknown capability"), ctype);
1057 proto_tree_add_text(tree, tvb, *p,
1058 clen, "Capability value: Invalid");
1061 proto_tree_add_text(tree, tvb, *p - 1,
1062 1, "Capability length: %u %s", clen,
1063 (clen == 1) ? "byte" : "bytes");
1064 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1065 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1066 proto_tree_add_text(subtree, tvb, *p, 4,
1067 "AS number: %d", tvb_get_ntohl(tvb, *p));
1071 case BGP_CAPABILITY_DYNAMIC_CAPABILITY:
1072 proto_tree_add_text(tree, tvb, *p - 2, 1,
1073 "Capability code: %s (%d)", val_to_str(ctype,
1074 capability_vals, "Unknown capability"), ctype);
1075 proto_tree_add_text(tree, tvb, *p - 1, 1,
1076 "Capability length: %u %s", clen,
1077 (clen == 1) ? "byte" : "bytes");
1079 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1080 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1081 for (i = 0; (int)i <= clen; i++) {
1082 proto_tree_add_text(subtree, tvb, *p, 1,
1083 "Capability code: %s (%d)", val_to_str(ctype,
1084 capability_vals, "Unknown capability"),
1085 tvb_get_guint8(tvb, *p));
1090 case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
1091 case BGP_CAPABILITY_ROUTE_REFRESH:
1092 proto_tree_add_text(tree, tvb, *p - 2, 1,
1093 "Capability code: %s (%d)", val_to_str(ctype,
1094 capability_vals, "Unknown capability"), ctype);
1096 proto_tree_add_text(tree, tvb, *p,
1097 clen, "Capability value: Invalid");
1100 proto_tree_add_text(tree, tvb, *p - 1,
1101 1, "Capability length: %u %s", clen,
1102 (clen == 1) ? "byte" : "bytes");
1106 case BGP_CAPABILITY_ORF_CISCO:
1107 case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
1108 proto_tree_add_text(tree, tvb, *p - 2, 1,
1109 "Capability code: %s (%d)", val_to_str(ctype,
1110 capability_vals, "Unknown capability"), ctype);
1111 proto_tree_add_text(tree, tvb, *p - 1,
1112 1, "Capability length: %u %s", clen,
1113 (clen == 1) ? "byte" : "bytes");
1114 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1115 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1117 i = tvb_get_ntohs(tvb, *p);
1118 proto_tree_add_text(subtree, tvb, *p,
1119 2, "Address family identifier: %s (%u)",
1120 val_to_str(i, afn_vals, "Unknown"), i);
1123 proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
1126 i = tvb_get_guint8(tvb, *p);
1127 proto_tree_add_text(subtree, tvb, *p,
1128 1, "Subsequent address family identifier: %s (%u)",
1129 val_to_str(i, bgpattr_nlri_safi,
1130 i >= 128 ? "Vendor specific" : "Unknown"), i);
1132 /* Number of ORFs */
1133 orfnum = tvb_get_guint8(tvb, *p);
1134 proto_tree_add_text(subtree, tvb, *p, 1, "Number of ORFs: %u", orfnum);
1136 for (i=0; i<orfnum; i++) {
1138 orftype = tvb_get_guint8(tvb, *p);
1139 proto_tree_add_text(subtree, tvb, *p, 1, "ORF Type: %s (%u)",
1140 val_to_str(orftype, orf_type_vals,"Unknown"), orftype);
1143 orfsendrecv = tvb_get_guint8(tvb, *p);
1144 proto_tree_add_text(subtree, tvb, *p,
1145 1, "Send/Receive: %s (%u)",
1146 val_to_str(orfsendrecv, orf_send_recv_vals,
1147 "Uknown"), orfsendrecv);
1151 /* unknown capability */
1153 proto_tree_add_text(tree, tvb, *p - 2, 1,
1154 "Capability code: %s (%d)", val_to_str(ctype,
1155 capability_vals, "Unknown capability"), ctype);
1156 proto_tree_add_text(tree, tvb, *p - 2,
1157 1, "Capability code: %s (%d)",
1158 ctype >= 128 ? "Private use" : "Unknown", ctype);
1159 proto_tree_add_text(tree, tvb, *p - 1,
1160 1, "Capability length: %u %s", clen,
1161 (clen == 1) ? "byte" : "bytes");
1163 proto_tree_add_text(tree, tvb, *p,
1164 clen, "Capability value: Unknown");
1173 * Dissect a BGP OPEN message.
1175 static const value_string community_vals[] = {
1176 { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
1177 { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
1178 { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
1183 dissect_bgp_open(tvbuff_t *tvb, proto_tree *tree)
1185 struct bgp_open bgpo; /* BGP OPEN message */
1186 int hlen; /* message length */
1187 int ptype; /* parameter type */
1188 int plen; /* parameter length */
1189 int ctype; /* capability type */
1190 int clen; /* capability length */
1191 int cend; /* capabilities end */
1192 int ostart; /* options start */
1193 int oend; /* options end */
1194 int p; /* tvb offset counter */
1195 proto_item *ti; /* tree item */
1196 proto_tree *subtree; /* subtree for options */
1197 proto_tree *subtree1; /* subtree for an option */
1198 proto_tree *subtree2; /* subtree for an option */
1200 /* snarf OPEN message */
1201 tvb_memcpy(tvb, bgpo.bgpo_marker, 0, BGP_MIN_OPEN_MSG_SIZE);
1202 hlen = g_ntohs(bgpo.bgpo_len);
1204 proto_tree_add_text(tree, tvb,
1205 offsetof(struct bgp_open, bgpo_version), 1,
1206 "Version: %u", bgpo.bgpo_version);
1207 proto_tree_add_text(tree, tvb,
1208 offsetof(struct bgp_open, bgpo_myas), 2,
1209 "My AS: %u", g_ntohs(bgpo.bgpo_myas));
1210 proto_tree_add_text(tree, tvb,
1211 offsetof(struct bgp_open, bgpo_holdtime), 2,
1212 "Hold time: %u", g_ntohs(bgpo.bgpo_holdtime));
1213 proto_tree_add_text(tree, tvb,
1214 offsetof(struct bgp_open, bgpo_id), 4,
1215 "BGP identifier: %s", ip_to_str((guint8 *)&bgpo.bgpo_id));
1216 proto_tree_add_text(tree, tvb,
1217 offsetof(struct bgp_open, bgpo_optlen), 1,
1218 "Optional parameters length: %u %s", bgpo.bgpo_optlen,
1219 (bgpo.bgpo_optlen == 1) ? "byte" : "bytes");
1221 /* optional parameters */
1222 if (bgpo.bgpo_optlen > 0) {
1223 /* add a subtree and setup some offsets */
1224 ostart = BGP_MIN_OPEN_MSG_SIZE;
1225 ti = proto_tree_add_text(tree, tvb, ostart, bgpo.bgpo_optlen,
1226 "Optional parameters");
1227 subtree = proto_item_add_subtree(ti, ett_bgp_options);
1229 oend = p + bgpo.bgpo_optlen;
1231 /* step through all of the optional parameters */
1234 /* grab the type and length */
1235 ptype = tvb_get_guint8(tvb, p++);
1236 plen = tvb_get_guint8(tvb, p++);
1238 /* check the type */
1240 case BGP_OPTION_AUTHENTICATION:
1241 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
1242 "Authentication information (%u %s)", plen,
1243 (plen == 1) ? "byte" : "bytes");
1245 case BGP_OPTION_CAPABILITY:
1246 /* grab the capability code */
1247 cend = p - 1 + plen;
1248 ctype = tvb_get_guint8(tvb, p++);
1249 clen = tvb_get_guint8(tvb, p++);
1250 ti = proto_tree_add_text(subtree, tvb, p - 4,
1251 2 + plen, "Capabilities Advertisement (%u bytes)",
1253 subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
1254 proto_tree_add_text(subtree1, tvb, p - 4,
1255 1, "Parameter type: Capabilities (2)");
1256 proto_tree_add_text(subtree1, tvb, p - 3,
1257 1, "Parameter length: %u %s", plen,
1258 (plen == 1) ? "byte" : "bytes");
1261 /* step through all of the capabilities */
1263 ctype = tvb_get_guint8(tvb, p++);
1264 clen = tvb_get_guint8(tvb, p++);
1266 ti = proto_tree_add_text(subtree1, tvb, p - 2,
1267 2 + clen, "%s (%u %s)", val_to_str(ctype,
1268 capability_vals, "Unknown capability"),
1269 2 + clen, (clen == 1) ? "byte" : "bytes");
1270 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
1271 dissect_bgp_capability_item(tvb, &p,
1272 subtree2, ctype, clen);
1276 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
1277 "Unknown optional parameter");
1285 * Dissect a BGP UPDATE message.
1288 dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree)
1290 struct bgp_attr bgpa; /* path attributes */
1291 guint16 hlen; /* message length */
1292 gint o; /* packet offset */
1294 gint end; /* message end */
1295 guint16 ext_com; /* EXTENDED COMMUNITY type */
1296 guint16 len; /* tmp */
1297 int advance; /* tmp */
1298 proto_item *ti; /* tree item */
1299 proto_tree *subtree; /* subtree for attributes */
1300 proto_tree *subtree2; /* subtree for attributes */
1301 proto_tree *subtree3; /* subtree for attributes */
1302 proto_tree *subtree4; /* subtree for attributes */
1303 proto_tree *as_paths_tree; /* subtree for AS_PATHs */
1304 proto_tree *as_path_tree; /* subtree for AS_PATH */
1305 proto_tree *as_path_segment_tree; /* subtree for AS_PATH segments */
1306 proto_tree *communities_tree; /* subtree for COMMUNITIES */
1307 proto_tree *community_tree; /* subtree for a community */
1308 proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
1310 guint8 length; /* AS_PATH length */
1311 guint8 type; /* AS_PATH type */
1312 guint32 as_path_item; /* item in AS_PATH segment */
1313 char *as_path_str = NULL; /* AS_PATH string */
1314 char *communities_str = NULL; /* COMMUNITIES string */
1315 char *cluster_list_str = NULL; /* CLUSTER_LIST string */
1316 char junk_buf[256]; /* tmp */
1317 int junk_buf_len; /* tmp len */
1318 guint8 ipaddr[4]; /* IPv4 address */
1319 guint32 aggregator_as;
1321 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
1322 o = BGP_HEADER_SIZE;
1324 /* check for withdrawals */
1325 len = tvb_get_ntohs(tvb, o);
1326 proto_tree_add_text(tree, tvb, o, 2,
1327 "Unfeasible routes length: %u %s", len, (len == 1) ? "byte" : "bytes");
1330 /* parse unfeasible prefixes */
1332 ti = proto_tree_add_text(tree, tvb, o, len, "Withdrawn routes:");
1333 subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
1335 /* parse each prefix */
1338 i = decode_prefix4(subtree, hf_bgp_withdrawn_prefix, tvb, o, len,
1346 /* check for advertisements */
1347 len = tvb_get_ntohs(tvb, o);
1348 proto_tree_add_text(tree, tvb, o, 2, "Total path attribute length: %u %s",
1349 len, (len == 1) ? "byte" : "bytes");
1351 /* path attributes */
1353 ti = proto_tree_add_text(tree, tvb, o + 2, len, "Path attributes");
1354 subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
1360 guint16 alen, tlen, aoff;
1366 tvb_memcpy(tvb, (guint8 *)&bgpa, o + i, sizeof(bgpa));
1367 /* check for the Extended Length bit */
1368 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1369 alen = tvb_get_ntohs(tvb, o + i + sizeof(bgpa));
1370 aoff = sizeof(bgpa) + 2;
1372 alen = tvb_get_guint8(tvb, o + i + sizeof(bgpa));
1373 aoff = sizeof(bgpa) + 1;
1377 /* This is kind of ugly - similar code appears twice, but it
1378 helps browsing attrs. */
1379 /* the first switch prints things in the title of the subtree */
1380 switch (bgpa.bgpa_type) {
1381 case BGPTYPE_ORIGIN:
1383 goto default_attribute_top;
1384 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
1385 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1387 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1388 msg, tlen + aoff, (tlen + aoff == 1) ? "byte" :
1391 case BGPTYPE_AS_PATH:
1392 case BGPTYPE_NEW_AS_PATH:
1394 (o + current attribute + aoff bytes to first tuple) */
1397 /* must be freed by second switch! */
1398 /* "tlen * 11" (10 digits + space) should be a good estimate
1399 of how long the AS path string could be */
1400 as_path_str = malloc((tlen + 1) * 11);
1401 if (as_path_str == NULL) break;
1402 as_path_str[0] = '\0';
1404 /* estimate the length of the AS number */
1405 if (bgpa.bgpa_type == BGPTYPE_NEW_AS_PATH)
1408 if (bgp_asn_len == 0) {
1412 length = tvb_get_guint8(tvb, k++);
1415 asn_len = (k == end) ? 2 : 4;
1418 asn_len = bgp_asn_len;
1422 /* snarf each AS path */
1424 type = tvb_get_guint8(tvb, q++);
1425 if (strlen(as_path_str) != 0 &&
1426 as_path_str[strlen(as_path_str) - 1] != ' ')
1427 strcat(as_path_str, " ");
1428 if (type == AS_SET) {
1429 strcat(as_path_str, "{");
1431 else if (type == AS_CONFED_SET) {
1432 strcat(as_path_str, "[");
1434 else if (type == AS_CONFED_SEQUENCE) {
1435 strcat(as_path_str, "(");
1437 length = tvb_get_guint8(tvb, q++);
1439 /* snarf each value in path */
1440 for (j = 0; j < length; j++) {
1441 snprintf(junk_buf, sizeof(junk_buf), "%u%s",
1443 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1444 (type == AS_SET || type == AS_CONFED_SET) ?
1446 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1450 /* cleanup end of string */
1451 if (type == AS_SET) {
1452 as_path_str[strlen(as_path_str) - 2] = '}';
1453 as_path_str[strlen(as_path_str) - 1] = '\0';
1455 else if (type == AS_CONFED_SET) {
1456 as_path_str[strlen(as_path_str) - 2] = ']';
1457 as_path_str[strlen(as_path_str) - 1] = '\0';
1459 else if (type == AS_CONFED_SEQUENCE) {
1460 as_path_str[strlen(as_path_str) - 1] = ')';
1463 as_path_str[strlen(as_path_str) - 1] = '\0';
1467 /* check for empty AS_PATH */
1469 strncpy(as_path_str, "empty", 6);
1471 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1473 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1474 as_path_str, tlen + aoff,
1475 (tlen + aoff == 1) ? "byte" : "bytes");
1477 case BGPTYPE_NEXT_HOP:
1479 goto default_attribute_top;
1480 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1481 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1483 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1484 ip_to_str(ipaddr), tlen + aoff, (tlen + aoff == 1)
1485 ? "byte" : "bytes");
1487 case BGPTYPE_MULTI_EXIT_DISC:
1489 goto default_attribute_top;
1490 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1492 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1493 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1494 (tlen + aoff == 1) ? "byte" : "bytes");
1496 case BGPTYPE_LOCAL_PREF:
1498 goto default_attribute_top;
1499 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1501 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1502 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1503 (tlen + aoff == 1) ? "byte" : "bytes");
1505 case BGPTYPE_ATOMIC_AGGREGATE:
1507 goto default_attribute_top;
1508 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1510 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1511 tlen + aoff, (tlen + aoff == 1) ? "byte" : "bytes");
1513 case BGPTYPE_AGGREGATOR:
1514 if (tlen != 6 && tlen != 8)
1515 goto default_attribute_top;
1516 case BGPTYPE_NEW_AGGREGATOR:
1517 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
1518 goto default_attribute_top;
1520 tvb_memcpy(tvb, ipaddr, o + i + aoff + asn_len, 4);
1521 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1522 "%s: AS: %u origin: %s (%u %s)",
1523 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1524 (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) :
1525 tvb_get_ntohl(tvb, o + i + aoff),
1526 ip_to_str(ipaddr), tlen + aoff,
1527 (tlen + aoff == 1) ? "byte" : "bytes");
1529 case BGPTYPE_COMMUNITIES:
1531 goto default_attribute_top;
1534 (o + current attribute + aoff bytes to first tuple) */
1537 /* must be freed by second switch! */
1538 /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be
1539 a good estimate of how long the communities string could
1541 communities_str = malloc((tlen + 1) * 12);
1542 if (communities_str == NULL) break;
1543 communities_str[0] = '\0';
1544 memset(junk_buf, 0, sizeof(junk_buf));
1546 /* snarf each community */
1548 /* check for well-known communities */
1549 if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
1550 strncpy(junk_buf, "NO_EXPORT ", 10);
1551 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
1552 strncpy(junk_buf, "NO_ADVERTISE ", 13);
1553 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
1554 strncpy(junk_buf, "NO_EXPORT_SUBCONFED ", 20);
1556 snprintf(junk_buf, sizeof(junk_buf), "%u:%u ",
1557 tvb_get_ntohs(tvb, q),
1558 tvb_get_ntohs(tvb, q + 2));
1562 strncat(communities_str, junk_buf, sizeof(junk_buf));
1564 /* cleanup end of string */
1565 communities_str[strlen(communities_str) - 1] = '\0';
1567 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1569 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1570 communities_str, tlen + aoff,
1571 (tlen + aoff == 1) ? "byte" : "bytes");
1573 case BGPTYPE_ORIGINATOR_ID:
1575 goto default_attribute_top;
1576 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1577 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1579 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1580 ip_to_str(ipaddr), tlen + aoff, (tlen + aoff == 1)
1581 ? "byte" : "bytes");
1583 case BGPTYPE_CLUSTER_LIST:
1585 goto default_attribute_top;
1588 (o + current attribute + aoff bytes to first tuple) */
1591 /* must be freed by second switch! */
1592 /* "tlen * 16" (12 digits, 3 dots + space ) should be
1593 a good estimate of how long the cluster_list string could
1595 cluster_list_str = malloc((tlen + 1) * 16);
1596 if (cluster_list_str == NULL) break;
1597 cluster_list_str[0] = '\0';
1598 memset(junk_buf, 0, sizeof(junk_buf));
1600 /* snarf each cluster list */
1601 tvb_memcpy(tvb, ipaddr, q, 4);
1603 snprintf(junk_buf, sizeof(junk_buf), "%s ", ip_to_str(ipaddr));
1604 strncat(cluster_list_str, junk_buf, sizeof(junk_buf));
1607 /* cleanup end of string */
1608 cluster_list_str[strlen(cluster_list_str) - 1] = '\0';
1610 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1612 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1613 cluster_list_str, tlen + aoff,
1614 (tlen + aoff == 1) ? "byte" : "bytes");
1616 case BGPTYPE_EXTENDED_COMMUNITY:
1619 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
1621 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
1623 (tlen + aoff == 1) ? "byte" : "bytes");
1627 default_attribute_top:
1628 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1630 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1631 tlen + aoff, (tlen + aoff == 1) ? "byte" : "bytes");
1632 } /* end of first switch */
1633 subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
1635 /* figure out flags */
1637 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) {
1638 strncat(junk_buf, "Optional, ", 10);
1641 strncat(junk_buf, "Well-known, ", 12);
1643 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) {
1644 strncat(junk_buf, "Transitive, ", 12);
1647 strncat(junk_buf, "Non-transitive, ", 16);
1649 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_PARTIAL) {
1650 strncat(junk_buf, "Partial, ", 9);
1653 strncat(junk_buf, "Complete, ", 10);
1655 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1656 strncat(junk_buf, "Extended Length, ", 17);
1658 /* stomp last ", " */
1659 j = strlen(junk_buf);
1660 junk_buf[j - 2] = '\0';
1661 ti = proto_tree_add_text(subtree2, tvb,
1662 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1663 "Flags: 0x%02x (%s)", bgpa.bgpa_flags, junk_buf);
1664 subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags);
1666 /* add flag bitfield subtrees */
1667 proto_tree_add_text(subtree3, tvb,
1668 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1669 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1670 BGP_ATTR_FLAG_OPTIONAL, 8, "Optional", "Well-known"));
1671 proto_tree_add_text(subtree3, tvb,
1672 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1673 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1674 BGP_ATTR_FLAG_TRANSITIVE, 8, "Transitive",
1676 proto_tree_add_text(subtree3, tvb,
1677 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1678 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1679 BGP_ATTR_FLAG_PARTIAL, 8, "Partial", "Complete"));
1680 proto_tree_add_text(subtree3, tvb,
1681 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1682 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1683 BGP_ATTR_FLAG_EXTENDED_LENGTH, 8, "Extended length",
1686 proto_tree_add_text(subtree2, tvb,
1687 o + i + offsetof(struct bgp_attr, bgpa_type), 1,
1688 "Type code: %s (%u)",
1689 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1692 proto_tree_add_text(subtree2, tvb, o + i + sizeof(bgpa),
1693 aoff - sizeof(bgpa), "Length: %d %s", tlen,
1694 (tlen == 1) ? "byte" : "bytes");
1696 /* the second switch prints things in the actual subtree of each
1698 switch (bgpa.bgpa_type) {
1699 case BGPTYPE_ORIGIN:
1701 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1702 "Origin (invalid): %u %s", tlen,
1703 (tlen == 1) ? "byte" : "bytes");
1705 proto_tree_add_item(subtree2, hf_bgp_origin, tvb,
1706 o + i + aoff, 1, FALSE);
1709 case BGPTYPE_AS_PATH:
1710 case BGPTYPE_NEW_AS_PATH:
1711 /* check for empty AS_PATH */
1717 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1718 "AS path: %s", as_path_str);
1719 as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1722 (o + current attribute + aoff bytes to first tuple) */
1726 /* snarf each AS path tuple, we have to step through each one
1727 again to make a separate subtree so we can't just reuse
1728 as_path_str from above */
1730 as_path_str[0] = '\0';
1731 type = tvb_get_guint8(tvb, q++);
1732 if (type == AS_SET) {
1733 snprintf(as_path_str, 2, "{");
1735 else if (type == AS_CONFED_SET) {
1736 snprintf(as_path_str, 2, "[");
1738 else if (type == AS_CONFED_SEQUENCE) {
1739 snprintf(as_path_str, 2, "(");
1741 length = tvb_get_guint8(tvb, q++);
1743 /* snarf each value in path, we're just going to reuse
1744 as_path_str since we already have it malloced */
1745 for (j = 0; j < length; j++) {
1746 snprintf(junk_buf, sizeof(junk_buf), "%u%s",
1748 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1749 (type == AS_SET || type == AS_CONFED_SET) ? ", " : " ");
1750 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1754 /* cleanup end of string */
1755 if (type == AS_SET) {
1756 as_path_str[strlen(as_path_str) - 2] = '}';
1758 else if (type == AS_CONFED_SET) {
1759 as_path_str[strlen(as_path_str) - 2] = ']';
1761 else if (type == AS_CONFED_SEQUENCE) {
1762 as_path_str[strlen(as_path_str) - 1] = ')';
1765 as_path_str[strlen(as_path_str) - 1] = '\0';
1768 /* length here means number of ASs, ie length * 2 bytes */
1769 ti = proto_tree_add_text(as_paths_tree, tvb,
1770 q - length * asn_len - 2,
1771 length * asn_len + 2, "AS path segment: %s", as_path_str);
1772 as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1773 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 2,
1774 1, "Path segment type: %s (%u)",
1775 val_to_str(type, as_segment_type, "Unknown"), type);
1776 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 1,
1777 1, "Path segment length: %u %s", length,
1778 (length == 1) ? "AS" : "ASs");
1780 /* backup and reprint path segment value(s) only */
1781 q -= asn_len * length;
1782 ti = proto_tree_add_text(as_path_tree, tvb, q,
1783 length * asn_len, "Path segment value:");
1784 as_path_segment_tree = proto_item_add_subtree(ti,
1785 ett_bgp_as_path_segments);
1786 for (j = 0; j < length; j++) {
1787 as_path_item = (asn_len == 2) ?
1788 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q);
1789 proto_item_append_text(ti, " %u", as_path_item);
1790 proto_tree_add_uint_hidden(as_path_tree, hf_bgp_as_path, tvb,
1791 q, asn_len, as_path_item);
1798 case BGPTYPE_NEXT_HOP:
1800 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1801 "Next hop (invalid): %u %s", tlen,
1802 (tlen == 1) ? "byte" : "bytes");
1804 proto_tree_add_item(subtree2, hf_bgp_next_hop, tvb,
1805 o + i + aoff, tlen, FALSE);
1808 case BGPTYPE_MULTI_EXIT_DISC:
1810 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1811 "Multiple exit discriminator (invalid): %u %s",
1812 tlen, (tlen == 1) ? "byte" : "bytes");
1814 proto_tree_add_item(subtree2, hf_bgp_multi_exit_disc, tvb,
1815 o + i + aoff, tlen, FALSE);
1818 case BGPTYPE_LOCAL_PREF:
1820 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1821 "Local preference (invalid): %u %s", tlen,
1822 (tlen == 1) ? "byte" : "bytes");
1824 proto_tree_add_uint(subtree2, hf_bgp_local_pref, tvb,
1825 o + i + aoff, tlen, FALSE);
1828 case BGPTYPE_ATOMIC_AGGREGATE:
1830 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1831 "Atomic aggregate (invalid): %u %s", tlen,
1832 (tlen == 1) ? "byte" : "bytes");
1835 case BGPTYPE_AGGREGATOR:
1836 if (tlen != 6 && tlen != 8) {
1837 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1838 "Aggregator (invalid): %u %s", tlen,
1839 (tlen == 1) ? "byte" : "bytes");
1842 case BGPTYPE_NEW_AGGREGATOR:
1843 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
1844 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1845 "Aggregator (invalid): %u %s", tlen,
1846 (tlen == 1) ? "byte" : "bytes");
1849 aggregator_as = (asn_len == 2) ?
1850 tvb_get_ntohs(tvb, o + i + aoff) :
1851 tvb_get_ntohl(tvb, o + i + aoff);
1852 proto_tree_add_uint(subtree2, hf_bgp_aggregator_as, tvb,
1853 o + i + aoff, asn_len, aggregator_as);
1854 proto_tree_add_item(subtree2, hf_bgp_aggregator_origin, tvb,
1855 o + i + aoff + asn_len, 4, FALSE);
1858 case BGPTYPE_COMMUNITIES:
1859 if (tlen % 4 != 0) {
1860 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1861 "Communities (invalid): %u %s", tlen,
1862 (tlen == 1) ? "byte" : "bytes");
1863 free(communities_str);
1867 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1868 "Communities: %s", communities_str);
1869 communities_tree = proto_item_add_subtree(ti,
1870 ett_bgp_communities);
1873 (o + current attribute + aoff bytes to first tuple) */
1877 /* snarf each community */
1879 /* check for reserved values */
1880 guint32 community = tvb_get_ntohl(tvb, q);
1881 if ((community & 0xFFFF0000) == FOURHEX0 ||
1882 (community & 0xFFFF0000) == FOURHEXF) {
1883 proto_tree_add_text(communities_tree, tvb,
1885 "Community: %s (0x%08x)",
1886 val_to_str(community, community_vals, "(reserved)"),
1890 ti = proto_tree_add_text(communities_tree, tvb,
1891 q - 3 + aoff, 4, "Community: %u:%u",
1892 tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
1893 community_tree = proto_item_add_subtree(ti,
1894 ett_bgp_communities);
1895 proto_tree_add_item(community_tree, hf_bgp_community_as,
1896 tvb, q - 3 + aoff, 2, FALSE);
1897 proto_tree_add_item(community_tree, hf_bgp_community_value,
1898 tvb, q - 1 + aoff, 2, FALSE);
1904 free(communities_str);
1906 case BGPTYPE_ORIGINATOR_ID:
1908 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1909 "Originator identifier (invalid): %u %s", tlen,
1910 (tlen == 1) ? "byte" : "bytes");
1912 proto_tree_add_item(subtree2, hf_bgp_originator_id, tvb,
1913 o + i + aoff, tlen, FALSE);
1916 case BGPTYPE_MP_REACH_NLRI:
1918 * RFC 2545 specifies that there may be more than one
1919 * address in the MP_REACH_NLRI attribute in section
1920 * 3, "Constructing the Next Hop field".
1922 * Yes, RFC 2858 says you can't do that, and, yes, RFC
1923 * 2858 obsoletes RFC 2283, which says you can do that,
1924 * but that doesn't mean we shouldn't dissect packets
1925 * that conform to RFC 2283 but not RFC 2858, as some
1926 * device on the network might implement the 2283-style
1927 * BGP extensions rather than RFC 2858-style extensions.
1929 af = tvb_get_ntohs(tvb, o + i + aoff);
1930 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1931 "Address family: %s (%u)",
1932 val_to_str(af, afn_vals, "Unknown"), af);
1933 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
1934 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
1935 "Subsequent address family identifier: %s (%u)",
1936 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
1938 if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
1940 * The addresses don't contain lengths, so if we
1941 * don't understand the address family type, we
1942 * cannot parse the subsequent addresses as we
1943 * don't know how long they are.
1945 * XXX - we should put a protocol tree item in for
1946 * this, as an unknown blob.
1950 nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
1951 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
1953 "Next hop network address (%d %s)",
1954 nexthop_len, plurality(nexthop_len, "byte", "bytes"));
1955 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
1957 while (j < nexthop_len) {
1958 advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
1959 junk_buf, sizeof(junk_buf)) ;
1960 if (advance == 0) /* catch if this is a unknown AFI type*/
1962 if (j + advance > nexthop_len)
1964 proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
1965 advance, "Next hop: %s (%u)", junk_buf, advance);
1968 tlen -= nexthop_len + 4;
1969 aoff += nexthop_len + 4 ;
1972 snpa = tvb_get_guint8(tvb, o + i + aoff);
1973 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
1974 "Subnetwork points of attachment: %u", snpa);
1977 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
1978 for (/*nothing*/; snpa > 0; snpa--) {
1979 proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
1980 "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
1982 proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
1983 tvb_get_guint8(tvb, o + i + aoff + off - 1),
1984 "SNPA (%u %s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
1985 (tvb_get_guint8(tvb, o + i + aoff + off - 1) == 1) ? "byte" : "bytes");
1986 off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
1992 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1993 "Network layer reachability information (%u %s)",
1994 tlen, (tlen == 1) ? "byte" : "bytes");
1996 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
1999 advance = decode_prefix_MP(subtree3,
2000 hf_bgp_mp_reach_nlri_ipv4_prefix,
2003 tvb, o + i + aoff, "MP Reach NLRI");
2011 case BGPTYPE_MP_UNREACH_NLRI:
2012 af = tvb_get_ntohs(tvb, o + i + aoff);
2013 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
2014 "Address family: %s (%u)",
2015 val_to_str(af, afn_vals, "Unknown"), af);
2016 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
2017 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
2018 "Subsequent address family identifier: %s (%u)",
2019 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
2021 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
2022 tlen - 3, "Withdrawn routes (%u %s)", tlen - 3,
2023 (tlen - 3 == 1) ? "byte" : "bytes");
2028 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
2031 advance = decode_prefix_MP(subtree3,
2032 hf_bgp_mp_unreach_nlri_ipv4_prefix,
2035 tvb, o + i + aoff, "MP Unreach NLRI");
2043 case BGPTYPE_CLUSTER_LIST:
2044 if (tlen % 4 != 0) {
2045 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2046 "Cluster list (invalid): %u %s", tlen,
2047 (tlen == 1) ? "byte" : "bytes");
2048 free(cluster_list_str);
2052 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2053 "Cluster list: %s", cluster_list_str);
2054 cluster_list_tree = proto_item_add_subtree(ti,
2055 ett_bgp_cluster_list);
2058 (o + current attribute + aoff bytes to first tuple) */
2062 /* snarf each cluster identifier */
2064 proto_tree_add_item(cluster_list_tree, hf_bgp_cluster_list,
2065 tvb, q - 3 + aoff, 4, FALSE);
2069 free(cluster_list_str);
2071 case BGPTYPE_EXTENDED_COMMUNITY:
2073 proto_tree_add_text(subtree3, tvb, o + i + aoff, tlen, "Extended community (invalid) : %u %s", tlen,
2074 (tlen == 1) ? "byte" : "bytes") ;
2077 end = o + i + aoff + tlen ;
2078 ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
2079 subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
2083 ext_com = tvb_get_ntohs(tvb,q) ;
2084 junk_buf_len=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf), "%s",
2085 val_to_str(ext_com,bgpext_com_type,"Unknown"));
2087 case BGP_EXT_COM_RT_0:
2088 case BGP_EXT_COM_RO_0:
2089 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %u%s%d",
2090 tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
2091 junk_buf[junk_buf_len]='\0';
2092 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2094 case BGP_EXT_COM_RT_1:
2095 case BGP_EXT_COM_RO_1:
2096 tvb_memcpy(tvb,ipaddr,q+2,4);
2097 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s%s%u",
2098 ip_to_str(ipaddr),":",tvb_get_ntohs(tvb,q+6));
2099 junk_buf[junk_buf_len]='\0';
2100 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2102 case BGP_EXT_COM_VPN_ORIGIN:
2103 case BGP_EXT_COM_OSPF_RID:
2104 tvb_memcpy(tvb,ipaddr,q+2,4);
2105 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s",
2107 junk_buf[junk_buf_len]='\0';
2108 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2110 case BGP_EXT_COM_OSPF_RTYPE:
2111 tvb_memcpy(tvb,ipaddr,q+2,4);
2112 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": Area:%s %s",
2114 val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
2115 /* print OSPF Metric type if selected */
2116 /* always print E2 even if not external route -- receiving router should ignore */
2117 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
2118 junk_buf_len+=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf)-junk_buf_len," E2");
2119 } else if (tvb_get_guint8(tvb,q+6)==(BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA ) ) {
2120 junk_buf_len+=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf)-junk_buf_len," E1");
2122 junk_buf[junk_buf_len]='\0';
2123 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2125 case BGP_EXT_COM_LINKBAND:
2126 tvb_memcpy(tvb,ipaddr,q+2,4); /* need to check on IEEE format on all platforms */
2127 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %.3f Mbps",
2128 ((double)*ipaddr)*8/1000000);
2129 junk_buf[junk_buf_len]='\0';
2130 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2132 case BGP_EXT_COM_L2INFO:
2133 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len,
2134 ": %s, Control Flags: %s%s%s%s%s, MTU: %u %s",
2135 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"),
2136 tvb_get_guint8(tvb,q+3) ? "" : "none",
2137 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q" : "",
2138 tvb_get_ntohs(tvb,q+3)&0x04 ? "F" : "",
2139 tvb_get_ntohs(tvb,q+3)&0x02 ? "C" : "",
2140 tvb_get_ntohs(tvb,q+3)&0x01 ? "S" : "",
2141 tvb_get_ntohs(tvb,q+4),
2142 tvb_get_ntohs(tvb,q+4)==1 ? "byte" : "bytes");
2143 junk_buf[junk_buf_len]='\0';
2144 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2146 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
2147 proto_tree_add_text(subtree4,tvb,q+2,1, "Encapsulation: %s",
2148 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"));
2149 proto_tree_add_text(subtree4,tvb,q+3,1, "Control Flags: %s%sControl Word %s required, Sequenced delivery %s required",
2150 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q flag (Reserved) set" : "",
2151 tvb_get_ntohs(tvb,q+3)&0x04 ? "F flag (reserved) set" : "",
2152 tvb_get_ntohs(tvb,q+3)&0x02 ? "is" : "not",
2153 tvb_get_ntohs(tvb,q+3)&0x01 ? "is" : "not");
2154 proto_tree_add_text(subtree4,tvb,q+4,2, "MTU: %u %s",
2155 tvb_get_ntohs(tvb,q+4),
2156 tvb_get_ntohs(tvb,q+4)==1 ? "byte" : "bytes");
2159 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, " ");
2160 junk_buf[junk_buf_len]='\0';
2161 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2169 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2170 "Unknown (%d %s)", tlen, (tlen == 1) ? "byte" :
2173 } /* end of second switch */
2183 /* parse prefixes */
2185 ti = proto_tree_add_text(tree, tvb, o, len,
2186 "Network layer reachability information: %u %s", len,
2187 (len == 1) ? "byte" : "bytes");
2188 subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
2191 i = decode_prefix4(subtree, hf_bgp_nlri_prefix, tvb, o, 0,
2202 * Dissect a BGP NOTIFICATION message.
2205 dissect_bgp_notification(tvbuff_t *tvb, proto_tree *tree)
2207 struct bgp_notification bgpn; /* BGP NOTIFICATION message */
2208 int hlen; /* message length */
2209 char *p; /* string pointer */
2212 tvb_memcpy(tvb, bgpn.bgpn_marker, 0, BGP_MIN_NOTIFICATION_MSG_SIZE);
2213 hlen = g_ntohs(bgpn.bgpn_len);
2215 /* print error code */
2216 proto_tree_add_text(tree, tvb,
2217 offsetof(struct bgp_notification, bgpn_major), 1,
2218 "Error code: %s (%u)",
2219 val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
2222 /* print error subcode */
2223 if (bgpn.bgpn_major < array_length(bgpnotify_minor)
2224 && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
2225 p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
2227 } else if (bgpn.bgpn_minor == 0)
2231 proto_tree_add_text(tree, tvb,
2232 offsetof(struct bgp_notification, bgpn_minor), 1,
2233 "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
2235 /* only print if there is optional data */
2236 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
2237 proto_tree_add_text(tree, tvb, BGP_MIN_NOTIFICATION_MSG_SIZE,
2238 hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
2243 * Dissect a BGP ROUTE-REFRESH message.
2246 dissect_bgp_route_refresh(tvbuff_t *tvb, proto_tree *tree)
2248 guint16 i; /* tmp */
2249 int p; /* tvb offset counter */
2250 int pend; /* end of list of entries for one orf type */
2251 guint16 hlen; /* tvb RR msg length */
2252 proto_item *ti; /* tree item */
2253 proto_item *ti1; /* tree item */
2254 proto_tree *subtree; /* tree for orf */
2255 proto_tree *subtree1; /* tree for orf entry */
2256 guint8 orftype; /* ORF Type */
2257 guint8 orfwhen; /* ORF flag: immediate, defer */
2258 guint16 orflen; /* ORF len */
2259 guint8 entryflag; /* ORF Entry flag: action(add,del,delall) match(permit,deny) */
2260 guint32 entryseq; /* ORF Entry sequence number */
2261 int entrylen; /* ORF Entry length */
2262 guint8 pfx_ge; /* ORF PrefixList mask lower bound */
2263 guint8 pfx_le; /* ORF PrefixList mask upper bound */
2264 int advance; /* tmp */
2270 00 01 00 01 afi,safi= ipv4-unicast
2271 02 80 00 01 defer, prefix-orf, len=1
2275 00 01 00 01 afi,saif= ipv4-unicast
2276 01 80 00 0a immediate, prefix-orf, len=10
2278 00 00 00 05 seqno = 5
2281 10 07 02 prefix = 7.2.0.0/16
2283 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
2284 p = BGP_HEADER_SIZE;
2286 i = tvb_get_ntohs(tvb, p);
2287 proto_tree_add_text(tree, tvb, p, 2,
2288 "Address family identifier: %s (%u)",
2289 val_to_str(i, afn_vals, "Unknown"), i);
2292 proto_tree_add_text(tree, tvb, p, 1,
2293 "Reserved: 1 byte");
2296 i = tvb_get_guint8(tvb, p);
2297 proto_tree_add_text(tree, tvb, p, 1,
2298 "Subsequent address family identifier: %s (%u)",
2299 val_to_str(i, bgpattr_nlri_safi,
2300 i >= 128 ? "Vendor specific" : "Unknown"),
2303 if ( hlen == BGP_HEADER_SIZE + 4 )
2307 orfwhen = tvb_get_guint8(tvb, p);
2308 orftype = tvb_get_guint8(tvb, p+1);
2309 orflen = tvb_get_ntohs(tvb, p+2);
2310 ti = proto_tree_add_text(tree, tvb, p , orflen + 4 , "ORF information (%u bytes)", orflen + 4);
2311 subtree = proto_item_add_subtree(ti, ett_bgp_orf);
2312 proto_tree_add_text(subtree, tvb, p , 1, "ORF flag: %s", val_to_str(orfwhen, orf_when_vals,"UNKNOWN"));
2313 proto_tree_add_text(subtree, tvb, p+1 , 1, "ORF type: %s", val_to_str(orftype, orf_type_vals,"UNKNOWN"));
2314 proto_tree_add_text(subtree, tvb, p+2 , 2, "ORF len: %u %s", orflen, (orflen == 1) ? "byte" : "bytes");
2317 if (orftype != BGP_ORF_PREFIX_CISCO) {
2318 proto_tree_add_text(subtree, tvb, p, orflen,
2319 "ORFEntry-Unknown (%u bytes)", orflen);
2325 entryflag = tvb_get_guint8(tvb, p);
2326 if ((entryflag & BGP_ORF_ACTION) == BGP_ORF_REMOVEALL) {
2327 ti1 = proto_tree_add_text(subtree, tvb, p, 1,
2328 "ORFEntry-PrefixList (1 byte)");
2329 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2330 proto_tree_add_text(subtree1, tvb, p , 1, "RemoveAll");
2333 ti1 = proto_tree_add_text(subtree, tvb, p, -1,
2334 "ORFEntry-PrefixList");
2335 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2336 proto_tree_add_text(subtree1, tvb, p, 1,
2337 "ACTION: %s MATCH: %s",
2338 val_to_str(entryflag&BGP_ORF_ACTION,
2339 orf_entry_action_vals, "UNKNOWN"),
2340 val_to_str(entryflag&BGP_ORF_MATCH,
2341 orf_entry_match_vals, "UNKNOWN"));
2343 entryseq = tvb_get_ntohl(tvb, p);
2344 proto_tree_add_text(subtree1, tvb, p, 4,
2345 "Entry Sequence No: %u", entryseq);
2347 pfx_ge = tvb_get_guint8(tvb, p);
2348 proto_tree_add_text(subtree1, tvb, p, 1,
2349 "PrefixMask length lower bound: %u", pfx_ge);
2351 pfx_le = tvb_get_guint8(tvb, p);
2352 proto_tree_add_text(subtree1, tvb, p, 1,
2353 "PrefixMask length upper bound: %u", pfx_le);
2356 advance = decode_prefix4(subtree1, -1, tvb, p, 0, "ORF");
2359 entrylen = 7 + 1 + advance;
2361 proto_item_append_text(ti1, " (%u bytes)", entrylen);
2362 proto_item_set_len(ti1, entrylen);
2370 * Dissect a BGP CAPABILITY message.
2373 dissect_bgp_capability(tvbuff_t *tvb, proto_tree *tree)
2377 proto_tree *subtree;
2383 mend = offset + tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2384 offset += BGP_HEADER_SIZE;
2385 /* step through all of the capabilities */
2386 while (offset < mend) {
2387 action = tvb_get_guint8(tvb, offset++);
2388 ctype = tvb_get_guint8(tvb, offset++);
2389 clen = tvb_get_guint8(tvb, offset++);
2391 ti = proto_tree_add_text(tree, tvb, offset - 2, 2 + clen,
2392 "%s (%u %s)", val_to_str(ctype, capability_vals,
2393 "Unknown capability"), 2 + clen, (clen == 1) ? "byte" : "bytes");
2394 subtree = proto_item_add_subtree(ti, ett_bgp_option);
2395 proto_tree_add_text(subtree, tvb, offset-2, 1, "Action: %d (%s)",
2396 action, val_to_str(action, bgpcap_action, "Invalid action value"));
2397 dissect_bgp_capability_item(tvb, &offset, subtree, ctype, clen);
2402 dissect_bgp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2405 guint16 bgp_len; /* Message length */
2406 guint8 bgp_type; /* Message type */
2407 char *typ; /* Message type (string) */
2408 proto_item *ti; /* tree item */
2409 proto_tree *bgp_tree; /* BGP packet tree */
2410 proto_tree *bgp1_tree; /* BGP message tree */
2412 bgp_len = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
2413 bgp_type = tvb_get_guint8(tvb, BGP_MARKER_SIZE + 2);
2414 typ = val_to_str(bgp_type, bgptypevals, "Unknown message type (0x%02x)");
2416 if (check_col(pinfo->cinfo, COL_INFO)) {
2418 col_add_fstr(pinfo->cinfo, COL_INFO, "%s", typ);
2420 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
2424 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, FALSE);
2425 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
2427 ti = proto_tree_add_text(bgp_tree, tvb, 0, -1, "%s", typ);
2429 /* add a different tree for each message type */
2432 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_open);
2435 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_update);
2437 case BGP_NOTIFICATION:
2438 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_notification);
2441 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
2443 case BGP_ROUTE_REFRESH_CISCO:
2444 case BGP_ROUTE_REFRESH:
2445 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
2447 case BGP_CAPABILITY:
2448 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_capability);
2451 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
2455 proto_tree_add_text(bgp1_tree, tvb, 0, BGP_MARKER_SIZE,
2456 "Marker: 16 bytes");
2458 if (bgp_len < BGP_HEADER_SIZE || bgp_len > BGP_MAX_PACKET_SIZE) {
2459 proto_tree_add_text(bgp1_tree, tvb, BGP_MARKER_SIZE, 2,
2460 "Length (invalid): %u %s", bgp_len,
2461 (bgp_len == 1) ? "byte" : "bytes");
2464 proto_tree_add_text(bgp1_tree, tvb, BGP_MARKER_SIZE, 2,
2465 "Length: %u %s", bgp_len,
2466 (bgp_len == 1) ? "byte" : "bytes");
2469 proto_tree_add_uint(bgp1_tree, hf_bgp_type, tvb,
2470 BGP_MARKER_SIZE + 2, 1,
2475 dissect_bgp_open(tvb, bgp1_tree);
2478 dissect_bgp_update(tvb, bgp1_tree);
2480 case BGP_NOTIFICATION:
2481 dissect_bgp_notification(tvb, bgp1_tree);
2484 /* no data in KEEPALIVE messages */
2486 case BGP_ROUTE_REFRESH_CISCO:
2487 case BGP_ROUTE_REFRESH:
2488 dissect_bgp_route_refresh(tvb, bgp1_tree);
2490 case BGP_CAPABILITY:
2491 dissect_bgp_capability(tvb, bgp1_tree);
2500 * Dissect a BGP packet.
2503 dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2505 volatile int offset = 0; /* offset into the tvbuff */
2506 gint reported_length_remaining;
2507 guint8 bgp_marker[BGP_MARKER_SIZE]; /* Marker (should be all ones */
2508 static guchar marker[] = { /* BGP message marker */
2509 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2510 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2512 proto_item *ti; /* tree item */
2513 proto_tree *bgp_tree; /* BGP packet tree */
2514 guint16 bgp_len; /* Message length */
2516 guint length_remaining;
2518 volatile gboolean first = TRUE; /* TRUE for the first BGP message in packet */
2521 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2522 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
2523 if (check_col(pinfo->cinfo, COL_INFO))
2524 col_clear(pinfo->cinfo, COL_INFO);
2527 * Scan through the TCP payload looking for a BGP marker.
2529 while ((reported_length_remaining = tvb_reported_length_remaining(tvb, offset))
2532 * "reported_length_remaining" is the number of bytes of TCP payload
2533 * remaining. If it's more than the length of a BGP marker,
2534 * we check only the number of bytes in a BGP marker.
2536 if (reported_length_remaining > BGP_MARKER_SIZE)
2537 reported_length_remaining = BGP_MARKER_SIZE;
2540 * OK, is there a BGP marker starting at the specified offset -
2541 * or, at least, the beginning of a BGP marker running to the end
2542 * of the TCP payload?
2544 * This will throw an exception if the frame is short; that's what
2547 tvb_memcpy(tvb, bgp_marker, offset, reported_length_remaining);
2548 if (memcmp(bgp_marker, marker, reported_length_remaining) == 0) {
2550 * Yes - stop scanning and start processing BGP packets.
2556 * No - keep scanning through the tvbuff to try to find a marker.
2562 * If we skipped any bytes, mark it as a BGP continuation.
2565 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, FALSE);
2566 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
2568 proto_tree_add_text(bgp_tree, tvb, 0, offset, "Continuation");
2572 * Now process the BGP packets in the TCP payload.
2574 * XXX - perhaps "tcp_dissect_pdus()" should take a starting
2575 * offset, in which case we can replace the loop below with
2576 * a call to "tcp_dissect_pdus()".
2578 while (tvb_reported_length_remaining(tvb, offset) != 0) {
2580 * This will throw an exception if we don't have any data left.
2581 * That's what we want. (See "tcp_dissect_pdus()", which is
2584 length_remaining = tvb_ensure_length_remaining(tvb, offset);
2587 * Can we do reassembly?
2589 if (bgp_desegment && pinfo->can_desegment) {
2591 * Yes - would a BGP header starting at this offset be split
2592 * across segment boundaries?
2594 if (length_remaining < BGP_HEADER_SIZE) {
2596 * Yes. Tell the TCP dissector where the data for this
2597 * message starts in the data it handed us, and how many
2598 * more bytes we need, and return.
2600 pinfo->desegment_offset = offset;
2601 pinfo->desegment_len = BGP_HEADER_SIZE - length_remaining;
2607 * Get the length and type from the BGP header.
2609 bgp_len = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2610 if (bgp_len < BGP_HEADER_SIZE) {
2612 * The BGP length doesn't include the BGP header; report that
2614 * Report this as an error.
2616 show_reported_bounds_error(tvb, pinfo, tree);
2621 * Can we do reassembly?
2623 if (bgp_desegment && pinfo->can_desegment) {
2625 * Yes - is the PDU split across segment boundaries?
2627 if (length_remaining < bgp_len) {
2629 * Yes. Tell the TCP dissector where the data for this
2630 * message starts in the data it handed us, and how many
2631 * more bytes we need, and return.
2633 pinfo->desegment_offset = offset;
2634 pinfo->desegment_len = bgp_len - length_remaining;
2640 * Construct a tvbuff containing the amount of the payload we have
2641 * available. Make its reported length the amount of data in the PDU.
2643 * XXX - if reassembly isn't enabled. the subdissector will throw a
2644 * BoundsError exception, rather than a ReportedBoundsError exception.
2645 * We really want a tvbuff where the length is "length", the reported
2646 * length is "plen", and the "if the snapshot length were infinite"
2647 * length is the minimum of the reported length of the tvbuff handed
2648 * to us and "plen", with a new type of exception thrown if the offset
2649 * is within the reported length but beyond that third length, with
2650 * that exception getting the "Unreassembled Packet" error.
2652 length = length_remaining;
2653 if (length > bgp_len)
2655 next_tvb = tvb_new_subset(tvb, offset, length, bgp_len);
2660 * Catch the ReportedBoundsError exception; if this particular message
2661 * happens to get a ReportedBoundsError exception, that doesn't mean
2662 * that we should stop dissecting PDUs within this frame or chunk of
2665 * If it gets a BoundsError, we can stop, as there's nothing more to
2666 * see, so we just re-throw it.
2669 dissect_bgp_pdu(next_tvb, pinfo, tree, first);
2671 CATCH(BoundsError) {
2674 CATCH(ReportedBoundsError) {
2675 show_reported_bounds_error(tvb, pinfo, tree);
2682 * Step to the next PDU.
2683 * Make sure we don't overflow.
2685 offset_before = offset;
2687 if (offset <= offset_before)
2693 * Register ourselves.
2696 proto_register_bgp(void)
2699 static hf_register_info hf[] = {
2701 { "Type", "bgp.type", FT_UINT8, BASE_DEC,
2702 VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
2703 { &hf_bgp_aggregator_as,
2704 { "Aggregator AS", "bgp.aggregator_as", FT_UINT16, BASE_DEC,
2705 NULL, 0x0, "", HFILL}},
2706 { &hf_bgp_aggregator_origin,
2707 { "Aggregator origin", "bgp.aggregator_origin", FT_IPv4, BASE_NONE,
2708 NULL, 0x0, "", HFILL}},
2710 { "AS Path", "bgp.as_path", FT_UINT16, BASE_DEC,
2711 NULL, 0x0, "", HFILL}},
2712 { &hf_bgp_cluster_identifier,
2713 { "Cluster identifier", "bgp.cluster_identifier", FT_IPv4, BASE_NONE,
2714 NULL, 0x0, "", HFILL}},
2715 { &hf_bgp_community_as,
2716 { "Community AS", "bgp.community_as", FT_UINT16, BASE_DEC,
2717 NULL, 0x0, "", HFILL}},
2718 { &hf_bgp_community_value,
2719 { "Community value", "bgp.community_value", FT_UINT16, BASE_DEC,
2720 NULL, 0x0, "", HFILL}},
2721 { &hf_bgp_local_pref,
2722 { "Local preference", "bgp.local_pref", FT_UINT32, BASE_DEC,
2723 NULL, 0x0, "", HFILL}},
2724 { &hf_bgp_mp_reach_nlri_ipv4_prefix,
2725 { "MP Reach NLRI IPv4 prefix", "bgp.mp_reach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
2726 NULL, 0x0, "", HFILL}},
2727 { &hf_bgp_mp_unreach_nlri_ipv4_prefix,
2728 { "MP Unreach NLRI IPv4 prefix", "bgp.mp_unreach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
2729 NULL, 0x0, "", HFILL}},
2730 { &hf_bgp_multi_exit_disc,
2731 { "Multiple exit discriminator", "bgp.multi_exit_disc", FT_UINT32, BASE_DEC,
2732 NULL, 0x0, "", HFILL}},
2734 { "Next hop", "bgp.next_hop", FT_IPv4, BASE_NONE,
2735 NULL, 0x0, "", HFILL}},
2736 { &hf_bgp_nlri_prefix,
2737 { "NLRI prefix", "bgp.nlri_prefix", FT_IPv4, BASE_NONE,
2738 NULL, 0x0, "", HFILL}},
2740 { "Origin", "bgp.origin", FT_UINT8, BASE_DEC,
2741 VALS(bgpattr_origin), 0x0, "", HFILL}},
2742 { &hf_bgp_originator_id,
2743 { "Originator identifier", "bgp.originator_id", FT_IPv4, BASE_NONE,
2744 NULL, 0x0, "", HFILL}},
2745 { &hf_bgp_withdrawn_prefix,
2746 { "Withdrawn prefix", "bgp.withdrawn_prefix", FT_IPv4, BASE_NONE,
2747 NULL, 0x0, "", HFILL}},
2750 static gint *ett[] = {
2756 &ett_bgp_attr_flags,
2758 &ett_bgp_mp_reach_nlri,
2759 &ett_bgp_mp_unreach_nlri,
2764 &ett_bgp_notification,
2765 &ett_bgp_route_refresh,
2766 &ett_bgp_capability,
2768 &ett_bgp_as_path_segments,
2769 &ett_bgp_communities,
2770 &ett_bgp_cluster_list,
2773 &ett_bgp_extended_communities,
2777 module_t *bgp_module;
2778 static enum_val_t asn_len[] = {
2785 proto_bgp = proto_register_protocol("Border Gateway Protocol",
2787 proto_register_field_array(proto_bgp, hf, array_length(hf));
2788 proto_register_subtree_array(ett, array_length(ett));
2790 bgp_module = prefs_register_protocol(proto_bgp, NULL);
2791 prefs_register_bool_preference(bgp_module, "desegment",
2792 "Desegment all BGP messages spanning multiple TCP segments",
2793 "Whether the BGP dissector should desegment all messages spanning multiple TCP segments",
2795 prefs_register_enum_preference(bgp_module, "asn_len",
2796 "Length of the AS number",
2797 "BGP dissector detect the length of the AS number in AS_PATH attributes automatically or manually (NOTE: Automatic detection is not 100% accurate)",
2798 &bgp_asn_len, asn_len, FALSE);
2802 proto_reg_handoff_bgp(void)
2804 dissector_handle_t bgp_handle;
2806 bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
2807 dissector_add("tcp.port", BGP_TCP_PORT, bgp_handle);