2 * Routines for BGP packet dissection.
3 * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * RFC1771 A Border Gateway Protocol 4 (BGP-4)
27 * RFC1965 Autonomous System Confederations for BGP
28 * RFC1997 BGP Communities Attribute
29 * RFC2547 BGP/MPLS VPNs
30 * RFC2796 BGP Route Reflection An alternative to full mesh IBGP
31 * RFC2842 Capabilities Advertisement with BGP-4
32 * RFC2858 Multiprotocol Extensions for BGP-4
33 * RFC2918 Route Refresh Capability for BGP-4
34 * RFC3107 Carrying Label Information in BGP-4
35 * draft-ietf-idr-as4bytes-06
36 * draft-ietf-idr-dynamic-cap-03
37 * draft-ietf-idr-bgp-ext-communities-05
38 * draft-knoll-idr-qos-attribute-03
41 * Destination Preference Attribute for BGP (work in progress)
42 * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
55 #include <epan/packet.h>
56 #include <epan/addr_and_mask.h>
57 #include "packet-bgp.h"
58 #include "packet-ipv6.h"
59 #include "packet-frame.h"
61 #include <epan/prefs.h>
62 #include <epan/emem.h>
64 /* #define MAX_STR_LEN 256 */
66 static const value_string bgptypevals[] = {
67 { BGP_OPEN, "OPEN Message" },
68 { BGP_UPDATE, "UPDATE Message" },
69 { BGP_NOTIFICATION, "NOTIFICATION Message" },
70 { BGP_KEEPALIVE, "KEEPALIVE Message" },
71 { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
72 { BGP_CAPABILITY, "CAPABILITY Message" },
73 { BGP_ROUTE_REFRESH_CISCO, "Cisco ROUTE-REFRESH Message" },
77 static const value_string bgpnotify_major[] = {
78 { 1, "Message Header Error" },
79 { 2, "OPEN Message Error" },
80 { 3, "UPDATE Message Error" },
81 { 4, "Hold Timer Expired" },
82 { 5, "Finite State Machine Error" },
84 { 7, "CAPABILITY Message Error" },
88 static const value_string bgpnotify_minor_1[] = {
89 { 1, "Connection Not Synchronized" },
90 { 2, "Bad Message Length" },
91 { 3, "Bad Message Type" },
95 static const value_string bgpnotify_minor_2[] = {
96 { 1, "Unsupported Version Number" },
98 { 3, "Bad BGP Identifier" },
99 { 4, "Unsupported Optional Parameter" },
100 { 5, "Authentication Failure" },
101 { 6, "Unacceptable Hold Time" },
102 { 7, "Unsupported Capability" },
106 static const value_string bgpnotify_minor_3[] = {
107 { 1, "Malformed Attribute List" },
108 { 2, "Unrecognized Well-known Attribute" },
109 { 3, "Missing Well-known Attribute" },
110 { 4, "Attribute Flags Error" },
111 { 5, "Attribute Length Error" },
112 { 6, "Invalid ORIGIN Attribute" },
113 { 7, "AS Routing Loop" },
114 { 8, "Invalid NEXT_HOP Attribute" },
115 { 9, "Optional Attribute Error" },
116 { 10, "Invalid Network Field" },
117 { 11, "Malformed AS_PATH" },
121 /* draft-ietf-idr-cease-subcode-02 */
122 static const value_string bgpnotify_minor_6[] = {
123 { 1, "Maximum Number of Prefixes Reached"},
124 { 2, "Administratively Shutdown"},
125 { 3, "Peer Unconfigured"},
126 { 4, "Administratively Reset"},
127 { 5, "Connection Rejected"},
128 { 6, "Other Configuration Change"},
129 { 7, "Connection Collision Resolution"},
133 static const value_string bgpnotify_minor_7[] = {
134 { 1, "Invalid Action Value" },
135 { 2, "Invalid Capability Length" },
136 { 3, "Malformed Capability Value" },
137 { 4, "Unsupported Capability Code" },
141 static const value_string *bgpnotify_minor[] = {
143 bgpnotify_minor_1, /* open */
144 bgpnotify_minor_2, /* update */
145 bgpnotify_minor_3, /* notification */
146 NULL, /* hold-timer expired */
147 NULL, /* FSM error */
148 bgpnotify_minor_6, /* cease */
149 bgpnotify_minor_7 /* capability */
152 static const value_string bgpattr_origin[] = {
159 static const value_string as_segment_type[] = {
161 { 2, "AS_SEQUENCE" },
162 /* RFC1965 has the wrong values, corrected in */
163 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
164 { 4, "AS_CONFED_SET" },
165 { 3, "AS_CONFED_SEQUENCE" },
169 static const value_string bgpattr_type[] = {
170 { BGPTYPE_ORIGIN, "ORIGIN" },
171 { BGPTYPE_AS_PATH, "AS_PATH" },
172 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
173 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
174 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
175 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
176 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
177 { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
178 { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
179 { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
180 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
181 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
182 { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
183 { BGPTYPE_NEW_AS_PATH, "NEW_AS_PATH" },
184 { BGPTYPE_NEW_AGGREGATOR, "NEW_AGGREGATOR" },
185 { BGPTYPE_SAFI_SPECIFIC_ATTR, "SAFI_SPECIFIC_ATTRIBUTE" },
189 static const value_string bgpext_com8_type[] = {
190 { BGP_EXT_COM_QOS_MARK_T, "QoS Marking - transitive" },
191 { BGP_EXT_COM_QOS_MARK_NT, "QoS Marking - non-transitive" },
192 { BGP_EXT_COM_COS_CAP_T, "CoS Capability - transitive" },
196 static const value_string bgpext_com_type[] = {
197 { BGP_EXT_COM_RT_0, "Route Target" },
198 { BGP_EXT_COM_RT_1, "Route Target" },
199 { BGP_EXT_COM_RT_2, "Route Target" },
200 { BGP_EXT_COM_RO_0, "Route Origin" },
201 { BGP_EXT_COM_RO_1, "Route Origin" },
202 { BGP_EXT_COM_RO_2, "Route Origin" },
203 { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
204 { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
205 { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
206 { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
207 { BGP_EXT_COM_L2INFO, "Layer 2 Information" },
211 static const value_string qos_tech_type[] = {
212 { QOS_TECH_TYPE_DSCP, "DiffServ enabled IP (DSCP encoding)" },
213 { QOS_TECH_TYPE_802_1q, "Ethernet using 802.1q priority tag" },
214 { QOS_TECH_TYPE_E_LSP, "MPLS using E-LSP" },
215 { QOS_TECH_TYPE_VC, "Virtual Channel (VC) encoding" },
216 { QOS_TECH_TYPE_GMPLS_TIME, "GMPLS - time slot encoding" },
217 { QOS_TECH_TYPE_GMPLS_LAMBDA, "GMPLS - lambda encoding" },
218 { QOS_TECH_TYPE_GMPLS_FIBRE, "GMPLS - fibre encoding" },
222 static const value_string bgp_ssa_type[] = {
223 { BGP_SSA_L2TPv3 , "L2TPv3 Tunnel" },
224 { BGP_SSA_mGRE , "mGRE Tunnel" },
225 { BGP_SSA_IPSec , "IPSec Tunnel" },
226 { BGP_SSA_MPLS , "MPLS Tunnel" },
230 static const value_string bgp_l2vpn_encaps[] = {
233 { 2, "ATM AAL5 VCC transport"},
234 { 3, "ATM transparent cell transport"},
235 { 4, "Ethernet VLAN"},
240 { 9, "ATM VCC cell transport"},
241 { 10, "ATM VPC cell transport"},
244 { 64, "IP-interworking"},
248 static const value_string bgpext_ospf_rtype[] = {
249 { BGP_OSPF_RTYPE_RTR, "Router" },
250 { BGP_OSPF_RTYPE_NET, "Network" },
251 { BGP_OSPF_RTYPE_SUM, "Summary" },
252 { BGP_OSPF_RTYPE_EXT, "External" },
253 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
254 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
258 /* Subsequent address family identifier, RFC2858 */
259 static const value_string bgpattr_nlri_safi[] = {
261 { SAFNUM_UNICAST, "Unicast" },
262 { SAFNUM_MULCAST, "Multicast" },
263 { SAFNUM_UNIMULC, "Unicast+Multicast" },
264 { SAFNUM_MPLS_LABEL, "Labeled Unicast"},
265 { SAFNUM_TUNNEL, "Tunnel"},
266 { SAFNUM_VPLS, "VPLS"},
267 { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */
268 { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
269 { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
273 /* ORF Type, draft-ietf-idr-route-filter-04.txt */
274 static const value_string orf_type_vals[] = {
275 { 2, "Communities ORF-Type" },
276 { 3, "Extended Communities ORF-Type" },
277 { 128, "Cisco PrefixList ORF-Type" },
278 { 129, "Cisco CommunityList ORF-Type" },
279 { 130, "Cisco Extended CommunityList ORF-Type" },
280 { 131, "Cisco AsPathList ORF-Type" },
284 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
285 static const value_string orf_send_recv_vals[] = {
292 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
293 static const value_string orf_when_vals[] = {
299 static const value_string orf_entry_action_vals[] = {
302 { 0x80, "RemoveAll" },
306 static const value_string orf_entry_match_vals[] = {
312 static const value_string capability_vals[] = {
313 { BGP_CAPABILITY_RESERVED, "Reserved capability" },
314 { BGP_CAPABILITY_MULTIPROTOCOL, "Multiprotocol extensions capability" },
315 { BGP_CAPABILITY_ROUTE_REFRESH, "Route refresh capability" },
316 { BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING, "Cooperative route filtering capability" },
317 { BGP_CAPABILITY_GRACEFUL_RESTART, "Graceful Restart capability" },
318 { BGP_CAPABILITY_4_OCTET_AS_NUMBER, "Support for 4-octet AS number capability" },
319 { BGP_CAPABILITY_DYNAMIC_CAPABILITY, "Support for Dynamic capability" },
320 { BGP_CAPABILITY_ROUTE_REFRESH_CISCO, "Route refresh capability" },
321 { BGP_CAPABILITY_ORF_CISCO, "Cooperative route filtering capability" },
325 /* Capability Message action code */
326 static const value_string bgpcap_action[] = {
327 { 0, "advertising a capability" },
328 { 1, "removing a capability" },
333 /* Maximal size of an IP address string */
334 #define MAX_SIZE_OF_IP_ADDR_STRING 16
336 static int proto_bgp = -1;
337 static int hf_bgp_type = -1;
338 static int hf_bgp_next_hop = -1;
339 static int hf_bgp_as_path = -1;
340 static int hf_bgp_cluster_identifier = -1;
341 static int hf_bgp_community_as = -1;
342 static int hf_bgp_community_value = -1;
343 static int hf_bgp_origin = -1;
344 static int hf_bgp_cluster_list = -1;
345 static int hf_bgp_originator_id = -1;
346 static int hf_bgp_ssa_t = -1;
347 static int hf_bgp_ssa_type = -1;
348 static int hf_bgp_ssa_len = -1;
349 static int hf_bgp_ssa_value = -1;
350 static int hf_bgp_ssa_l2tpv3_pref = -1;
351 static int hf_bgp_ssa_l2tpv3_s = -1;
352 static int hf_bgp_ssa_l2tpv3_unused = -1;
353 static int hf_bgp_ssa_l2tpv3_cookie_len = -1;
354 static int hf_bgp_ssa_l2tpv3_session_id = -1;
355 static int hf_bgp_ssa_l2tpv3_cookie = -1;
356 static int hf_bgp_local_pref = -1;
357 static int hf_bgp_multi_exit_disc = -1;
358 static int hf_bgp_aggregator_as = -1;
359 static int hf_bgp_aggregator_origin = -1;
360 static int hf_bgp_mp_reach_nlri_ipv4_prefix = -1;
361 static int hf_bgp_mp_unreach_nlri_ipv4_prefix = -1;
362 static int hf_bgp_mp_nlri_tnl_id = -1;
363 static int hf_bgp_withdrawn_prefix = -1;
364 static int hf_bgp_nlri_prefix = -1;
366 static gint ett_bgp = -1;
367 static gint ett_bgp_prefix = -1;
368 static gint ett_bgp_unfeas = -1;
369 static gint ett_bgp_attrs = -1;
370 static gint ett_bgp_attr = -1;
371 static gint ett_bgp_attr_flags = -1;
372 static gint ett_bgp_mp_nhna = -1;
373 static gint ett_bgp_mp_reach_nlri = -1;
374 static gint ett_bgp_mp_unreach_nlri = -1;
375 static gint ett_bgp_mp_snpa = -1;
376 static gint ett_bgp_nlri = -1;
377 static gint ett_bgp_open = -1;
378 static gint ett_bgp_update = -1;
379 static gint ett_bgp_notification = -1;
380 static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
381 static gint ett_bgp_capability = -1;
382 static gint ett_bgp_as_paths = -1;
383 static gint ett_bgp_as_path_segments = -1;
384 static gint ett_bgp_communities = -1;
385 static gint ett_bgp_cluster_list = -1; /* cluster list tree */
386 static gint ett_bgp_options = -1; /* optional parameters tree */
387 static gint ett_bgp_option = -1; /* an optional parameter tree */
388 static gint ett_bgp_extended_communities = -1; /* extended communities list tree */
389 static gint ett_bgp_ext_com_flags = -1; /* extended communities flags tree */
390 static gint ett_bgp_ssa = -1; /* safi specific attribute */
391 static gint ett_bgp_ssa_subtree = -1; /* safi specific attribute Subtrees */
392 static gint ett_bgp_orf = -1; /* orf (outbound route filter) tree */
393 static gint ett_bgp_orf_entry = -1; /* orf entry tree */
396 static gboolean bgp_desegment = TRUE;
398 static gint bgp_asn_len = 0;
401 * Decode an IPv4 prefix.
404 decode_prefix4(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
405 guint16 tlen, const char *tag)
408 proto_tree *prefix_tree;
410 guint8 addr_bytes[4];
412 } ip_addr; /* IP address */
413 guint8 plen; /* prefix length */
414 int length; /* number of octets needed for prefix */
416 /* snarf length and prefix */
417 plen = tvb_get_guint8(tvb, offset);
418 length = ipv4_addr_and_mask(tvb, offset + 1, ip_addr.addr_bytes, plen);
420 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid (> 32)",
425 /* put prefix into protocol tree */
426 ti = proto_tree_add_text(tree, tvb, offset,
427 tlen != 0 ? tlen : 1 + length, "%s/%u",
428 ip_to_str(ip_addr.addr_bytes), plen);
429 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
430 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
433 proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 1, length,
436 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
437 "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
443 * Decode an IPv6 prefix.
446 decode_prefix6(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
447 guint16 tlen, const char *tag)
450 proto_tree *prefix_tree;
451 struct e_in6_addr addr; /* IPv6 address */
452 int plen; /* prefix length */
453 int length; /* number of octets needed for prefix */
455 /* snarf length and prefix */
456 plen = tvb_get_guint8(tvb, offset);
457 length = ipv6_addr_and_mask(tvb, offset + 1, &addr, plen);
459 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid",
464 /* put prefix into protocol tree */
465 ti = proto_tree_add_text(tree, tvb, offset,
466 tlen != 0 ? tlen : 1 + length, "%s/%u",
467 ip6_to_str(&addr), plen);
468 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
469 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
472 proto_tree_add_ipv6(prefix_tree, hf_addr, tvb, offset + 1, length,
475 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
476 "%s prefix: %s", tag, ip6_to_str(&addr));
484 * Decode an MPLS label stack
485 * XXX - We should change *buf to **buf, use ep_alloc() and drop the buflen
489 decode_MPLS_stack(tvbuff_t *tvb, gint offset, emem_strbuf_t *stack_strbuf)
491 guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
492 gint indx; /* index for the label stack */
495 label_entry = 0x000000 ;
497 ep_strbuf_truncate(stack_strbuf, 0);
499 while ((label_entry & 0x000001) == 0) {
501 label_entry = tvb_get_ntoh24(tvb, indx) ;
503 /* withdrawn routes may contain 0 or 0x800000 in the first label */
504 if((indx-offset)==0&&(label_entry==0||label_entry==0x800000)) {
505 ep_strbuf_append(stack_strbuf, "0 (withdrawn)");
509 ep_strbuf_append_printf(stack_strbuf, "%u%s", label_entry >> 4,
510 ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
514 if ((label_entry & 0x000001) == 0) {
515 /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
516 ep_strbuf_append(stack_strbuf, " (BOGUS: Bottom of Stack NOT set!)");
521 return((indx - offset) / 3);
525 * Decode a multiprotocol address
529 mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, emem_strbuf_t *strbuf)
531 int length; /* length of the address in byte */
532 guint32 ip4addr,ip4addr2; /* IPv4 address */
533 guint16 rd_type; /* Route Distinguisher type */
534 struct e_in6_addr ip6addr; /* IPv6 address */
543 case SAFNUM_MPLS_LABEL:
546 ip4addr = tvb_get_ipv4(tvb, offset);
547 ep_strbuf_append(strbuf, ip_to_str((guint8 *)&ip4addr));
549 case SAFNUM_LAB_VPNUNICAST:
550 case SAFNUM_LAB_VPNMULCAST:
551 case SAFNUM_LAB_VPNUNIMULC:
552 rd_type=tvb_get_ntohs(tvb,offset) ;
555 length = 8 + sizeof(ip4addr);
556 ip4addr = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
557 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%u:%u IPv4=%s",
558 tvb_get_ntohs(tvb, offset + 2),
559 tvb_get_ntohl(tvb, offset + 4),
560 ip_to_str((guint8 *)&ip4addr));
563 length = 8 + sizeof(ip4addr);
564 ip4addr = tvb_get_ipv4(tvb, offset + 2); /* IP part of the RD */
565 ip4addr2 = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
566 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%s:%u IPv4=%s",
567 ip_to_str((guint8 *)&ip4addr),
568 tvb_get_ntohs(tvb, offset + 6),
569 ip_to_str((guint8 *)&ip4addr2));
573 ep_strbuf_printf(strbuf, "Unknown (0x%04x) labeled VPN IPv4 address format",rd_type);
579 ep_strbuf_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
588 case SAFNUM_MPLS_LABEL:
591 tvb_get_ipv6(tvb, offset, &ip6addr);
592 ep_strbuf_printf(strbuf, "%s", ip6_to_str(&ip6addr));
594 case SAFNUM_LAB_VPNUNICAST:
595 case SAFNUM_LAB_VPNMULCAST:
596 case SAFNUM_LAB_VPNUNIMULC:
597 rd_type=tvb_get_ntohs(tvb,offset) ;
601 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
602 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%u:%u IPv6=%s",
603 tvb_get_ntohs(tvb, offset + 2),
604 tvb_get_ntohl(tvb, offset + 4),
605 ip6_to_str(&ip6addr));
609 ip4addr = tvb_get_ipv4(tvb, offset + 2); /* IP part of the RD */
610 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
611 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%s:%u IPv6=%s",
612 ip_to_str((guint8 *)&ip4addr),
613 tvb_get_ntohs(tvb, offset + 6),
614 ip6_to_str(&ip6addr));
618 ep_strbuf_printf(strbuf, "Unknown (0x%04x) labeled VPN IPv6 address format",rd_type);
624 ep_strbuf_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
629 case AFNUM_L2VPN_OLD:
631 case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
632 case SAFNUM_LAB_VPNMULCAST:
633 case SAFNUM_LAB_VPNUNIMULC:
635 length = 4; /* the next-hop is simply an ipv4 addr */
636 ip4addr = tvb_get_ipv4(tvb, offset + 0);
637 ep_strbuf_printf(strbuf, "IPv4=%s",
638 ip_to_str((guint8 *)&ip4addr));
642 ep_strbuf_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
648 ep_strbuf_printf(strbuf, "Unknown AFI (%u) value", afi);
655 * Decode a multiprotocol prefix
658 decode_prefix_MP(proto_tree *tree, int hf_addr4, int hf_addr6,
659 guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, const char *tag)
661 int start_offset = offset;
663 proto_tree *prefix_tree;
664 int total_length; /* length of the entire item */
665 int length; /* length of the prefix address, in bytes */
666 guint plen; /* length of the prefix address, in bits */
667 guint labnum; /* number of labels */
668 guint16 tnl_id; /* Tunnel Identifier */
669 int ce_id,labblk_off,labblk_size;
671 guint8 addr_bytes[4];
673 } ip4addr, ip4addr2; /* IPv4 address */
674 struct e_in6_addr ip6addr; /* IPv6 address */
675 guint16 rd_type; /* Route Distinguisher type */
676 emem_strbuf_t *stack_strbuf; /* label stack */
686 total_length = decode_prefix4(tree, hf_addr4, tvb, offset, 0, tag);
687 if (total_length < 0)
691 case SAFNUM_MPLS_LABEL:
692 plen = tvb_get_guint8(tvb, offset);
693 stack_strbuf = ep_strbuf_new_label(NULL);
694 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
696 offset += (1 + labnum * 3);
697 if (plen <= (labnum * 3*8)) {
698 proto_tree_add_text(tree, tvb, start_offset, 1,
699 "%s Labeled IPv4 prefix length %u invalid",
703 plen -= (labnum * 3*8);
704 length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
706 proto_tree_add_text(tree, tvb, start_offset, 1,
707 "%s Labeled IPv4 prefix length %u invalid",
708 tag, plen + (labnum * 3*8));
712 ti = proto_tree_add_text(tree, tvb, start_offset,
713 (offset + length) - start_offset,
714 "Label Stack=%s IPv4=%s/%u",
715 stack_strbuf->str, ip_to_str(ip4addr.addr_bytes), plen);
716 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
717 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
718 tag, plen + labnum * 3 * 8);
719 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum, "%s Label Stack: %s",
720 tag, stack_strbuf->str);
721 if (hf_addr4 != -1) {
722 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset,
723 length, ip4addr.addr);
725 proto_tree_add_text(prefix_tree, tvb, offset, length,
726 "%s IPv4 prefix: %s",
727 tag, ip_to_str(ip4addr.addr_bytes));
729 total_length = (1 + labnum*3) + length;
733 plen = tvb_get_guint8(tvb, offset);
735 proto_tree_add_text(tree, tvb, start_offset, 1,
736 "%s Tunnel IPv4 prefix length %u invalid",
740 tnl_id = tvb_get_ntohs(tvb, offset + 1);
741 offset += 3; /* Length + Tunnel Id */
742 plen -= 16; /* 2-octet Identifier */
743 length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
745 proto_tree_add_text(tree, tvb, start_offset, 1,
746 "%s Tunnel IPv4 prefix length %u invalid",
750 ti = proto_tree_add_text(tree, tvb, start_offset,
751 (offset + length) - start_offset,
752 "Tunnel Identifier=0x%x IPv4=%s/%u",
753 tnl_id, ip_to_str(ip4addr.addr_bytes), plen);
754 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
756 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
758 proto_tree_add_item(prefix_tree, hf_bgp_mp_nlri_tnl_id, tvb,
759 start_offset + 1, 2, FALSE);
760 if (hf_addr4 != -1) {
761 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset,
762 length, ip4addr.addr);
764 proto_tree_add_text(prefix_tree, tvb, offset, length,
765 "%s IPv4 prefix: %s",
766 tag, ip_to_str(ip4addr.addr_bytes));
768 total_length = 1 + 2 + length; /* length field + Tunnel Id + IPv4 len */
771 case SAFNUM_LAB_VPNUNICAST:
772 case SAFNUM_LAB_VPNMULCAST:
773 case SAFNUM_LAB_VPNUNIMULC:
774 plen = tvb_get_guint8(tvb, offset);
775 stack_strbuf = ep_strbuf_new_label(NULL);
776 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
778 offset += (1 + labnum * 3);
779 if (plen <= (labnum * 3*8)) {
780 proto_tree_add_text(tree, tvb, start_offset, 1,
781 "%s Labeled VPN IPv4 prefix length %u invalid",
785 plen -= (labnum * 3*8);
787 rd_type = tvb_get_ntohs(tvb, offset);
789 proto_tree_add_text(tree, tvb, start_offset, 1,
790 "%s Labeled VPN IPv4 prefix length %u invalid",
791 tag, plen + (labnum * 3*8));
798 case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
799 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr.addr_bytes, plen);
801 proto_tree_add_text(tree, tvb, start_offset, 1,
802 "%s Labeled VPN IPv4 prefix length %u invalid",
803 tag, plen + (labnum * 3*8) + 8*8);
807 ti = proto_tree_add_text(tree, tvb, start_offset,
808 (offset + 8 + length) - start_offset,
809 "Label Stack=%s RD=%u:%u, IPv4=%s/%u",
811 tvb_get_ntohs(tvb, offset + 2),
812 tvb_get_ntohl(tvb, offset + 4),
813 ip_to_str(ip4addr.addr_bytes), plen);
814 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
815 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
816 tag, plen + labnum * 3 * 8 + 8 * 8);
817 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
818 "%s Label Stack: %s", tag, stack_strbuf->str);
819 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
820 "%s Route Distinguisher: %u:%u", tag, tvb_get_ntohs(tvb, offset + 2),
821 tvb_get_ntohl(tvb, offset + 4));
822 if (hf_addr4 != -1) {
823 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
824 offset + 8, length, ip4addr.addr);
826 proto_tree_add_text(prefix_tree, tvb, offset + 8,
827 length, "%s IPv4 prefix: %s", tag,
828 ip_to_str(ip4addr.addr_bytes));
830 total_length = (1 + labnum * 3 + 8) + length;
833 case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
834 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
836 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr2.addr_bytes, plen);
838 proto_tree_add_text(tree, tvb, start_offset, 1,
839 "%s Labeled VPN IPv4 prefix length %u invalid",
840 tag, plen + (labnum * 3*8) + 8*8);
844 ti = proto_tree_add_text(tree, tvb, start_offset,
845 (offset + 8 + length) - start_offset,
846 "Label Stack=%s RD=%s:%u, IPv4=%s/%u",
848 ip_to_str(ip4addr.addr_bytes),
849 tvb_get_ntohs(tvb, offset + 6),
850 ip_to_str(ip4addr2.addr_bytes),
852 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
853 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
854 tag, plen + labnum * 3 * 8 + 8 * 8);
855 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
856 "%s Label Stack: %s", tag, stack_strbuf->str);
857 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
858 "%s Route Distinguisher: %s:%u", tag, ip_to_str(ip4addr.addr_bytes),
859 tvb_get_ntohs(tvb, offset + 6));
860 if (hf_addr4 != -1) {
861 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
862 offset + 8, length, ip4addr2.addr);
864 proto_tree_add_text(prefix_tree, tvb, offset + 8,
865 length, "%s IPv4 prefix: %s", tag,
866 ip_to_str(ip4addr2.addr_bytes));
868 total_length = (1 + labnum * 3 + 8) + length;
872 proto_tree_add_text(tree, tvb, start_offset,
873 (offset - start_offset) + 2,
874 "Unknown labeled VPN IPv4 address format %u", rd_type);
880 proto_tree_add_text(tree, tvb, start_offset, 0,
881 "Unknown SAFI (%u) for AFI %u", safi, afi);
892 total_length = decode_prefix6(tree, hf_addr6, tvb, offset, 0, tag);
893 if (total_length < 0)
897 case SAFNUM_MPLS_LABEL:
898 plen = tvb_get_guint8(tvb, offset);
899 stack_strbuf = ep_strbuf_new_label(NULL);
900 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
902 offset += (1 + labnum * 3);
903 if (plen <= (labnum * 3*8)) {
904 proto_tree_add_text(tree, tvb, start_offset, 1,
905 "%s Labeled IPv6 prefix length %u invalid", tag, plen);
908 plen -= (labnum * 3*8);
910 length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
912 proto_tree_add_text(tree, tvb, start_offset, 1,
913 "%s Labeled IPv6 prefix length %u invalid",
914 tag, plen + (labnum * 3*8));
918 ti = proto_tree_add_text(tree, tvb, start_offset,
919 (offset + length) - start_offset,
920 "Label Stack=%s, IPv6=%s/%u",
922 ip6_to_str(&ip6addr), plen);
923 total_length = (1 + labnum * 3) + length;
927 plen = tvb_get_guint8(tvb, offset);
929 proto_tree_add_text(tree, tvb, start_offset, 1,
930 "%s Tunnel IPv6 prefix length %u invalid",
934 tnl_id = tvb_get_ntohs(tvb, offset + 1);
935 offset += 3; /* Length + Tunnel Id */
936 plen -= 16; /* 2-octet Identifier */
937 length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
939 proto_tree_add_text(tree, tvb, start_offset, 1,
940 "%s Tunnel IPv6 prefix length %u invalid",
944 ti = proto_tree_add_text(tree, tvb, start_offset,
945 (offset + length) - start_offset,
946 "Tunnel Identifier=0x%x IPv6=%s/%u",
947 tnl_id, ip6_to_str(&ip6addr), plen);
948 total_length = (1 + 2) + length; /* length field + Tunnel Id + IPv4 len */
951 case SAFNUM_LAB_VPNUNICAST:
952 case SAFNUM_LAB_VPNMULCAST:
953 case SAFNUM_LAB_VPNUNIMULC:
954 plen = tvb_get_guint8(tvb, offset);
955 stack_strbuf = ep_strbuf_new_label(NULL);
956 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
958 offset += (1 + labnum * 3);
959 if (plen <= (labnum * 3*8)) {
960 proto_tree_add_text(tree, tvb, start_offset, 1,
961 "%s Labeled VPN IPv6 prefix length %u invalid", tag, plen);
964 plen -= (labnum * 3*8);
966 rd_type = tvb_get_ntohs(tvb,offset);
968 proto_tree_add_text(tree, tvb, start_offset, 1,
969 "%s Labeled VPN IPv6 prefix length %u invalid",
970 tag, plen + (labnum * 3*8));
978 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
980 proto_tree_add_text(tree, tvb, start_offset, 1,
981 "%s Labeled VPN IPv6 prefix length %u invalid",
982 tag, plen + (labnum * 3*8) + 8*8);
986 ti = proto_tree_add_text(tree, tvb, start_offset,
987 (offset + 8 + length) - start_offset,
988 "Label Stack=%s RD=%u:%u, IPv6=%s/%u",
990 tvb_get_ntohs(tvb, offset + 2),
991 tvb_get_ntohl(tvb, offset + 4),
992 ip6_to_str(&ip6addr), plen);
993 total_length = (1 + labnum * 3 + 8) + length;
997 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
999 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
1001 proto_tree_add_text(tree, tvb, start_offset, 1,
1002 "%s Labeled VPN IPv6 prefix length %u invalid",
1003 tag, plen + (labnum * 3*8) + 8*8);
1007 ti = proto_tree_add_text(tree, tvb, start_offset,
1008 (offset + 8 + length) - start_offset,
1009 "Label Stack=%s RD=%s:%u, IPv6=%s/%u",
1011 ip_to_str(ip4addr.addr_bytes),
1012 tvb_get_ntohs(tvb, offset + 6),
1013 ip6_to_str(&ip6addr), plen);
1014 total_length = (1 + labnum * 3 + 8) + length;
1018 proto_tree_add_text(tree, tvb, start_offset, 0,
1019 "Unknown labeled VPN IPv6 address format %u", rd_type);
1025 proto_tree_add_text(tree, tvb, start_offset, 0,
1026 "Unknown SAFI (%u) for AFI %u", safi, afi);
1032 case AFNUM_L2VPN_OLD:
1035 case SAFNUM_LAB_VPNUNICAST:
1036 case SAFNUM_LAB_VPNMULCAST:
1037 case SAFNUM_LAB_VPNUNIMULC:
1039 plen = tvb_get_ntohs(tvb,offset);
1040 rd_type=tvb_get_ntohs(tvb,offset+2);
1041 ce_id=tvb_get_ntohs(tvb,offset+10);
1042 labblk_off=tvb_get_ntohs(tvb,offset+12);
1043 labblk_size=tvb_get_ntohs(tvb,offset+14);
1044 stack_strbuf = ep_strbuf_new_label(NULL);
1045 labnum = decode_MPLS_stack(tvb, offset + 16, stack_strbuf);
1049 case FORMAT_AS2_LOC:
1050 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 6, 4);
1051 proto_tree_add_text(tree, tvb, start_offset,
1052 (offset + plen + 1) - start_offset,
1053 "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, "
1054 "Label-Block Size: %u Label Base %s",
1055 tvb_get_ntohs(tvb, offset + 4),
1056 ip_to_str(ip4addr.addr_bytes),
1064 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 4, 4);
1065 proto_tree_add_text(tree, tvb, offset,
1066 (offset + plen + 1) - start_offset,
1067 "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, "
1068 "Label-Block Size: %u, Label Base %s",
1069 ip_to_str(ip4addr.addr_bytes),
1070 tvb_get_ntohs(tvb, offset + 8),
1078 proto_tree_add_text(tree, tvb, start_offset,
1079 (offset - start_offset) + 2,
1080 "Unknown labeled VPN address format %u", rd_type);
1083 /* FIXME there are subTLVs left to decode ... for now lets omit them */
1084 total_length = plen+2;
1088 proto_tree_add_text(tree, tvb, start_offset, 0,
1089 "Unknown SAFI (%u) for AFI %u", safi, afi);
1095 proto_tree_add_text(tree, tvb, start_offset, 0,
1096 "Unknown AFI (%u) value", afi);
1099 return(total_length);
1103 * Dissect a BGP capability.
1106 dissect_bgp_capability_item(tvbuff_t *tvb, int *p, proto_tree *tree, int ctype, int clen)
1108 proto_tree *subtree;
1110 guint8 orfnum; /* number of ORFs */
1111 guint8 orftype; /* ORF Type */
1112 guint8 orfsendrecv; /* ORF Send/Receive */
1113 int tclen; /* capability length */
1116 /* check the capability type */
1118 case BGP_CAPABILITY_RESERVED:
1119 proto_tree_add_text(tree, tvb, *p - 2, 1,
1120 "Capability code: %s (%d)", val_to_str(ctype,
1121 capability_vals, "Unknown capability"), ctype);
1122 proto_tree_add_text(tree, tvb, *p - 1,
1123 1, "Capability length: %u byte%s", clen,
1124 plurality(clen, "", "s"));
1126 proto_tree_add_text(tree, tvb, *p,
1127 clen, "Capability value: Unknown");
1131 case BGP_CAPABILITY_MULTIPROTOCOL:
1132 proto_tree_add_text(tree, tvb, *p - 2, 1,
1133 "Capability code: %s (%d)", val_to_str(ctype,
1134 capability_vals, "Unknown capability"), ctype);
1136 proto_tree_add_text(tree, tvb, *p - 1,
1137 1, "Capability length: Invalid");
1138 proto_tree_add_text(tree, tvb, *p,
1139 clen, "Capability value: Unknown");
1142 proto_tree_add_text(tree, tvb, *p - 1,
1143 1, "Capability length: %u byte%s", clen,
1144 plurality(clen, "", "s"));
1145 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1146 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1148 i = tvb_get_ntohs(tvb, *p);
1149 proto_tree_add_text(subtree, tvb, *p,
1150 2, "Address family identifier: %s (%u)",
1151 val_to_str(i, afn_vals, "Unknown"), i);
1154 proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
1157 i = tvb_get_guint8(tvb, *p);
1158 proto_tree_add_text(subtree, tvb, *p,
1159 1, "Subsequent address family identifier: %s (%u)",
1160 val_to_str(i, bgpattr_nlri_safi,
1161 i >= 128 ? "Vendor specific" : "Unknown"), i);
1165 case BGP_CAPABILITY_GRACEFUL_RESTART:
1166 proto_tree_add_text(tree, tvb, *p - 2, 1,
1167 "Capability code: %s (%d)", val_to_str(ctype,
1168 capability_vals, "Unknown capability"), ctype);
1170 proto_tree_add_text(tree, tvb, *p,
1171 clen, "Capability value: Invalid");
1175 proto_tree_add_text(tree, tvb, *p - 1,
1176 1, "Capability length: %u byte%s", clen,
1177 plurality(clen, "", "s"));
1178 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1179 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1181 i = tvb_get_ntohs(tvb, *p);
1182 proto_tree_add_text(subtree, tvb, *p,
1183 2, "Restart Flags: [%s], Restart Time %us",
1184 (i&0x8000) ? "R" : "none", i&0xfff);
1188 * what follows is alist of AFI/SAFI/flag triplets
1189 * read it until the TLV ends
1193 i = tvb_get_ntohs(tvb, *p);
1194 proto_tree_add_text(subtree, tvb, *p,
1195 2, "Address family identifier: %s (%u)",
1196 val_to_str(i, afn_vals, "Unknown"), i);
1199 i = tvb_get_guint8(tvb, *p);
1200 proto_tree_add_text(subtree, tvb, *p,
1201 1, "Subsequent address family identifier: %s (%u)",
1202 val_to_str(i, bgpattr_nlri_safi,
1203 i >= 128 ? "Vendor specific" : "Unknown"), i);
1206 i = tvb_get_guint8(tvb, *p);
1207 proto_tree_add_text(subtree, tvb, *p, 1,
1208 "Preserve forwarding state: %s",
1209 (i&0x80) ? "yes" : "no");
1215 case BGP_CAPABILITY_4_OCTET_AS_NUMBER:
1216 proto_tree_add_text(tree, tvb, *p - 2, 1,
1217 "Capability code: %s (%d)", val_to_str(ctype,
1218 capability_vals, "Unknown capability"), ctype);
1220 proto_tree_add_text(tree, tvb, *p,
1221 clen, "Capability value: Invalid");
1224 proto_tree_add_text(tree, tvb, *p - 1,
1225 1, "Capability length: %u byte%s", clen,
1226 plurality(clen, "", "s"));
1227 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1228 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1229 proto_tree_add_text(subtree, tvb, *p, 4,
1230 "AS number: %d", tvb_get_ntohl(tvb, *p));
1234 case BGP_CAPABILITY_DYNAMIC_CAPABILITY:
1235 proto_tree_add_text(tree, tvb, *p - 2, 1,
1236 "Capability code: %s (%d)", val_to_str(ctype,
1237 capability_vals, "Unknown capability"), ctype);
1238 proto_tree_add_text(tree, tvb, *p - 1, 1,
1239 "Capability length: %u byte%s", clen,
1240 plurality(clen, "", "s"));
1242 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1243 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1244 for (i = 0; (int)i <= clen; i++) {
1245 proto_tree_add_text(subtree, tvb, *p, 1,
1246 "Capability code: %s (%d)", val_to_str(ctype,
1247 capability_vals, "Unknown capability"),
1248 tvb_get_guint8(tvb, *p));
1253 case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
1254 case BGP_CAPABILITY_ROUTE_REFRESH:
1255 proto_tree_add_text(tree, tvb, *p - 2, 1,
1256 "Capability code: %s (%d)", val_to_str(ctype,
1257 capability_vals, "Unknown capability"), ctype);
1259 proto_tree_add_text(tree, tvb, *p,
1260 clen, "Capability value: Invalid");
1263 proto_tree_add_text(tree, tvb, *p - 1,
1264 1, "Capability length: %u byte%s", clen,
1265 plurality(clen, "", "s"));
1269 case BGP_CAPABILITY_ORF_CISCO:
1270 case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
1271 proto_tree_add_text(tree, tvb, *p - 2, 1,
1272 "Capability code: %s (%d)", val_to_str(ctype,
1273 capability_vals, "Unknown capability"), ctype);
1274 proto_tree_add_text(tree, tvb, *p - 1,
1275 1, "Capability length: %u byte%s", clen,
1276 plurality(clen, "", "s"));
1277 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
1278 subtree = proto_item_add_subtree(ti, ett_bgp_option);
1280 i = tvb_get_ntohs(tvb, *p);
1281 proto_tree_add_text(subtree, tvb, *p,
1282 2, "Address family identifier: %s (%u)",
1283 val_to_str(i, afn_vals, "Unknown"), i);
1286 proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
1289 i = tvb_get_guint8(tvb, *p);
1290 proto_tree_add_text(subtree, tvb, *p,
1291 1, "Subsequent address family identifier: %s (%u)",
1292 val_to_str(i, bgpattr_nlri_safi,
1293 i >= 128 ? "Vendor specific" : "Unknown"), i);
1295 /* Number of ORFs */
1296 orfnum = tvb_get_guint8(tvb, *p);
1297 proto_tree_add_text(subtree, tvb, *p, 1, "Number of ORFs: %u", orfnum);
1299 for (i=0; i<orfnum; i++) {
1301 orftype = tvb_get_guint8(tvb, *p);
1302 proto_tree_add_text(subtree, tvb, *p, 1, "ORF Type: %s (%u)",
1303 val_to_str(orftype, orf_type_vals,"Unknown"), orftype);
1306 orfsendrecv = tvb_get_guint8(tvb, *p);
1307 proto_tree_add_text(subtree, tvb, *p,
1308 1, "Send/Receive: %s (%u)",
1309 val_to_str(orfsendrecv, orf_send_recv_vals,
1310 "Uknown"), orfsendrecv);
1314 /* unknown capability */
1316 proto_tree_add_text(tree, tvb, *p - 2, 1,
1317 "Capability code: %s (%d)", val_to_str(ctype,
1318 capability_vals, "Unknown capability"), ctype);
1319 proto_tree_add_text(tree, tvb, *p - 2,
1320 1, "Capability code: %s (%d)",
1321 ctype >= 128 ? "Private use" : "Unknown", ctype);
1322 proto_tree_add_text(tree, tvb, *p - 1,
1323 1, "Capability length: %u byte%s", clen,
1324 plurality(clen, "", "s"));
1326 proto_tree_add_text(tree, tvb, *p,
1327 clen, "Capability value: Unknown");
1336 * Dissect a BGP OPEN message.
1338 static const value_string community_vals[] = {
1339 { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
1340 { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
1341 { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
1346 dissect_bgp_open(tvbuff_t *tvb, proto_tree *tree)
1348 struct bgp_open bgpo; /* BGP OPEN message */
1349 int hlen; /* message length */
1350 int ptype; /* parameter type */
1351 int plen; /* parameter length */
1352 int ctype; /* capability type */
1353 int clen; /* capability length */
1354 int cend; /* capabilities end */
1355 int ostart; /* options start */
1356 int oend; /* options end */
1357 int p; /* tvb offset counter */
1358 proto_item *ti; /* tree item */
1359 proto_tree *subtree; /* subtree for options */
1360 proto_tree *subtree1; /* subtree for an option */
1361 proto_tree *subtree2; /* subtree for an option */
1363 /* snarf OPEN message */
1364 tvb_memcpy(tvb, bgpo.bgpo_marker, 0, BGP_MIN_OPEN_MSG_SIZE);
1365 hlen = g_ntohs(bgpo.bgpo_len);
1367 proto_tree_add_text(tree, tvb,
1368 offsetof(struct bgp_open, bgpo_version), 1,
1369 "Version: %u", bgpo.bgpo_version);
1370 proto_tree_add_text(tree, tvb,
1371 offsetof(struct bgp_open, bgpo_myas), 2,
1372 "My AS: %u", g_ntohs(bgpo.bgpo_myas));
1373 proto_tree_add_text(tree, tvb,
1374 offsetof(struct bgp_open, bgpo_holdtime), 2,
1375 "Hold time: %u", g_ntohs(bgpo.bgpo_holdtime));
1376 proto_tree_add_text(tree, tvb,
1377 offsetof(struct bgp_open, bgpo_id), 4,
1378 "BGP identifier: %s", ip_to_str((guint8 *)&bgpo.bgpo_id));
1379 proto_tree_add_text(tree, tvb,
1380 offsetof(struct bgp_open, bgpo_optlen), 1,
1381 "Optional parameters length: %u byte%s", bgpo.bgpo_optlen,
1382 plurality(bgpo.bgpo_optlen, "", "s"));
1384 /* optional parameters */
1385 if (bgpo.bgpo_optlen > 0) {
1386 /* add a subtree and setup some offsets */
1387 ostart = BGP_MIN_OPEN_MSG_SIZE;
1388 ti = proto_tree_add_text(tree, tvb, ostart, bgpo.bgpo_optlen,
1389 "Optional parameters");
1390 subtree = proto_item_add_subtree(ti, ett_bgp_options);
1392 oend = p + bgpo.bgpo_optlen;
1394 /* step through all of the optional parameters */
1397 /* grab the type and length */
1398 ptype = tvb_get_guint8(tvb, p++);
1399 plen = tvb_get_guint8(tvb, p++);
1401 /* check the type */
1403 case BGP_OPTION_AUTHENTICATION:
1404 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
1405 "Authentication information (%u byte%s)", plen,
1406 plurality(plen, "", "s"));
1408 case BGP_OPTION_CAPABILITY:
1409 /* grab the capability code */
1410 cend = p - 1 + plen;
1411 ctype = tvb_get_guint8(tvb, p++);
1412 clen = tvb_get_guint8(tvb, p++);
1413 ti = proto_tree_add_text(subtree, tvb, p - 4,
1414 2 + plen, "Capabilities Advertisement (%u bytes)",
1416 subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
1417 proto_tree_add_text(subtree1, tvb, p - 4,
1418 1, "Parameter type: Capabilities (2)");
1419 proto_tree_add_text(subtree1, tvb, p - 3,
1420 1, "Parameter length: %u byte%s", plen,
1421 plurality(plen, "", "s"));
1424 /* step through all of the capabilities */
1426 ctype = tvb_get_guint8(tvb, p++);
1427 clen = tvb_get_guint8(tvb, p++);
1429 ti = proto_tree_add_text(subtree1, tvb, p - 2,
1430 2 + clen, "%s (%u byte%s)", val_to_str(ctype,
1431 capability_vals, "Unknown capability"),
1432 2 + clen, plurality(clen, "", "s"));
1433 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
1434 dissect_bgp_capability_item(tvb, &p,
1435 subtree2, ctype, clen);
1439 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
1440 "Unknown optional parameter");
1448 * Dissect a BGP UPDATE message.
1451 dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree)
1453 struct bgp_attr bgpa; /* path attributes */
1454 guint16 hlen; /* message length */
1455 gint o; /* packet offset */
1457 gint end; /* message end */
1458 guint16 ext_com; /* EXTENDED COMMUNITY extended length type */
1459 guint8 ext_com8; /* EXTENDED COMMUNITY regular type */
1460 gboolean is_regular_type; /* flag for regular types */
1461 gboolean is_extended_type; /* flag for extended types */
1462 guint16 len; /* tmp */
1463 int advance; /* tmp */
1464 proto_item *ti; /* tree item */
1465 proto_tree *subtree; /* subtree for attributes */
1466 proto_tree *subtree2; /* subtree for attributes */
1467 proto_tree *subtree3; /* subtree for attributes */
1468 proto_tree *subtree4; /* subtree for attributes */
1469 proto_tree *subtree5; /* subtree for attributes */
1470 proto_tree *as_paths_tree; /* subtree for AS_PATHs */
1471 proto_tree *as_path_tree; /* subtree for AS_PATH */
1472 proto_tree *as_path_segment_tree; /* subtree for AS_PATH segments */
1473 proto_tree *communities_tree; /* subtree for COMMUNITIES */
1474 proto_tree *community_tree; /* subtree for a community */
1475 proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
1477 guint8 length; /* AS_PATH length */
1478 guint8 type; /* AS_PATH type */
1479 guint32 as_path_item; /* item in AS_PATH segment */
1480 emem_strbuf_t *as_path_emstr = NULL; /* AS_PATH */
1481 emem_strbuf_t *communities_emstr = NULL; /* COMMUNITIES */
1482 emem_strbuf_t *cluster_list_emstr = NULL; /* CLUSTER_LIST */
1483 emem_strbuf_t *junk_emstr; /* tmp */
1484 guint32 ipaddr; /* IPv4 address */
1485 guint32 aggregator_as;
1486 guint16 ssa_type; /* SSA T + Type */
1487 guint16 ssa_len; /* SSA TLV Length */
1488 guint8 ssa_v3_len; /* SSA L2TPv3 Cookie Length */
1489 gfloat linkband; /* Link bandwidth */
1491 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
1492 o = BGP_HEADER_SIZE;
1493 junk_emstr = ep_strbuf_new_label(NULL);
1495 /* check for withdrawals */
1496 len = tvb_get_ntohs(tvb, o);
1497 proto_tree_add_text(tree, tvb, o, 2,
1498 "Unfeasible routes length: %u byte%s", len, plurality(len, "", "s"));
1501 /* parse unfeasible prefixes */
1503 ti = proto_tree_add_text(tree, tvb, o, len, "Withdrawn routes:");
1504 subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
1506 /* parse each prefix */
1509 i = decode_prefix4(subtree, hf_bgp_withdrawn_prefix, tvb, o, len,
1517 /* check for advertisements */
1518 len = tvb_get_ntohs(tvb, o);
1519 proto_tree_add_text(tree, tvb, o, 2, "Total path attribute length: %u byte%s",
1520 len, plurality(len, "", "s"));
1522 /* path attributes */
1524 ti = proto_tree_add_text(tree, tvb, o + 2, len, "Path attributes");
1525 subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
1528 proto_item *hidden_item;
1532 guint16 alen, tlen, aoff, aoff_save;
1538 tvb_memcpy(tvb, (guint8 *)&bgpa, o + i, sizeof(bgpa));
1539 /* check for the Extended Length bit */
1540 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1541 alen = tvb_get_ntohs(tvb, o + i + sizeof(bgpa));
1542 aoff = sizeof(bgpa) + 2;
1544 alen = tvb_get_guint8(tvb, o + i + sizeof(bgpa));
1545 aoff = sizeof(bgpa) + 1;
1549 /* This is kind of ugly - similar code appears twice, but it
1550 helps browsing attrs. */
1551 /* the first switch prints things in the title of the subtree */
1552 switch (bgpa.bgpa_type) {
1553 case BGPTYPE_ORIGIN:
1555 goto default_attribute_top;
1556 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
1557 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1558 "%s: %s (%u byte%s)",
1559 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1560 msg, tlen + aoff, plurality(tlen + aoff, "", "s"));
1562 case BGPTYPE_AS_PATH:
1563 case BGPTYPE_NEW_AS_PATH:
1565 (o + current attribute + aoff bytes to first tuple) */
1568 /* must be freed by second switch! */
1569 /* "tlen * 11" (10 digits + space) should be a good estimate
1570 of how long the AS path string could be */
1571 if (as_path_emstr == NULL)
1572 as_path_emstr = ep_strbuf_sized_new((tlen + 1) * 11, 0);
1573 ep_strbuf_truncate(as_path_emstr, 0);
1575 /* estimate the length of the AS number */
1576 if (bgpa.bgpa_type == BGPTYPE_NEW_AS_PATH)
1579 if (bgp_asn_len == 0) {
1583 length = tvb_get_guint8(tvb, k++);
1586 asn_len = (k == end) ? 2 : 4;
1589 asn_len = bgp_asn_len;
1593 /* snarf each AS path */
1595 type = tvb_get_guint8(tvb, q++);
1596 if (as_path_emstr->len > 1 &&
1597 as_path_emstr->str[as_path_emstr->len - 1] != ' ')
1598 ep_strbuf_append_c(as_path_emstr, ' ');
1599 if (type == AS_SET) {
1600 ep_strbuf_append_c(as_path_emstr, '{');
1602 else if (type == AS_CONFED_SET) {
1603 ep_strbuf_append_c(as_path_emstr, '[');
1605 else if (type == AS_CONFED_SEQUENCE) {
1606 ep_strbuf_append_c(as_path_emstr, '(');
1608 length = tvb_get_guint8(tvb, q++);
1610 /* snarf each value in path */
1611 for (j = 0; j < length; j++) {
1612 ep_strbuf_append_printf(as_path_emstr, "%u%s",
1614 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1615 (type == AS_SET || type == AS_CONFED_SET) ?
1620 /* cleanup end of string */
1621 if (type == AS_SET) {
1622 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
1623 ep_strbuf_append_c(as_path_emstr, '}');
1625 else if (type == AS_CONFED_SET) {
1626 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
1627 ep_strbuf_append_c(as_path_emstr, ']');
1629 else if (type == AS_CONFED_SEQUENCE) {
1630 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
1631 ep_strbuf_append_c(as_path_emstr, ')');
1634 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
1638 /* check for empty AS_PATH */
1640 ep_strbuf_printf(as_path_emstr, "empty");
1642 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1643 "%s: %s (%u byte%s)",
1644 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1645 as_path_emstr->str, tlen + aoff,
1646 plurality(tlen + aoff, "", "s"));
1648 case BGPTYPE_NEXT_HOP:
1650 goto default_attribute_top;
1651 ipaddr = tvb_get_ipv4(tvb, o + i + aoff);
1652 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1653 "%s: %s (%u byte%s)",
1654 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1655 ip_to_str((guint8 *)&ipaddr), tlen + aoff,
1656 plurality(tlen + aoff, "", "s"));
1658 case BGPTYPE_MULTI_EXIT_DISC:
1660 goto default_attribute_top;
1661 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1662 "%s: %u (%u byte%s)",
1663 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1664 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1665 plurality(tlen + aoff, "", "s"));
1667 case BGPTYPE_LOCAL_PREF:
1669 goto default_attribute_top;
1670 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1671 "%s: %u (%u byte%s)",
1672 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1673 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1674 plurality(tlen + aoff, "", "s"));
1676 case BGPTYPE_ATOMIC_AGGREGATE:
1678 goto default_attribute_top;
1679 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1681 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1682 tlen + aoff, plurality(tlen + aoff, "", "s"));
1684 case BGPTYPE_AGGREGATOR:
1685 if (tlen != 6 && tlen != 8)
1686 goto default_attribute_top;
1687 case BGPTYPE_NEW_AGGREGATOR:
1688 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
1689 goto default_attribute_top;
1691 ipaddr = tvb_get_ipv4(tvb, o + i + aoff + asn_len);
1692 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1693 "%s: AS: %u origin: %s (%u byte%s)",
1694 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1695 (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) :
1696 tvb_get_ntohl(tvb, o + i + aoff),
1697 ip_to_str((guint8 *)&ipaddr),
1698 tlen + aoff, plurality(tlen + aoff, "", "s"));
1700 case BGPTYPE_COMMUNITIES:
1702 goto default_attribute_top;
1705 (o + current attribute + aoff bytes to first tuple) */
1708 /* must be freed by second switch! */
1709 /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be
1710 a good estimate of how long the communities string could
1712 if (communities_emstr == NULL)
1713 communities_emstr = ep_strbuf_sized_new((tlen + 1) * 12, 0);
1714 ep_strbuf_truncate(communities_emstr, 0);
1716 /* snarf each community */
1718 /* check for well-known communities */
1719 if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
1720 ep_strbuf_append(communities_emstr, "NO_EXPORT ");
1721 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
1722 ep_strbuf_append(communities_emstr, "NO_ADVERTISE ");
1723 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
1724 ep_strbuf_append(communities_emstr, "NO_EXPORT_SUBCONFED ");
1726 ep_strbuf_append_printf(communities_emstr, "%u:%u ",
1727 tvb_get_ntohs(tvb, q),
1728 tvb_get_ntohs(tvb, q + 2));
1732 /* cleanup end of string */
1733 ep_strbuf_truncate(communities_emstr, communities_emstr->len - 1);
1735 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1736 "%s: %s (%u byte%s)",
1737 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1738 communities_emstr->str, tlen + aoff,
1739 plurality(tlen + aoff, "", "s"));
1741 case BGPTYPE_ORIGINATOR_ID:
1743 goto default_attribute_top;
1744 ipaddr = tvb_get_ipv4(tvb, o + i + aoff);
1745 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1746 "%s: %s (%u byte%s)",
1747 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1748 ip_to_str((guint8 *)&ipaddr),
1749 tlen + aoff, plurality(tlen + aoff, "", "s"));
1751 case BGPTYPE_CLUSTER_LIST:
1753 goto default_attribute_top;
1756 (o + current attribute + aoff bytes to first tuple) */
1759 /* must be freed by second switch! */
1760 /* "tlen * 16" (12 digits, 3 dots + space ) should be
1761 a good estimate of how long the cluster_list string could
1763 if (cluster_list_emstr == NULL)
1764 cluster_list_emstr = ep_strbuf_sized_new((tlen + 1) * 16, 0);
1765 ep_strbuf_truncate(cluster_list_emstr, 0);
1767 /* snarf each cluster list */
1769 ipaddr = tvb_get_ipv4(tvb, q);
1770 ep_strbuf_append_printf(cluster_list_emstr, "%s ", ip_to_str((guint8 *)&ipaddr));
1773 /* cleanup end of string */
1774 ep_strbuf_truncate(cluster_list_emstr, cluster_list_emstr->len - 1);
1776 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1777 "%s: %s (%u byte%s)",
1778 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1779 cluster_list_emstr->str, tlen + aoff,
1780 plurality(tlen + aoff, "", "s"));
1782 case BGPTYPE_EXTENDED_COMMUNITY:
1785 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
1787 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
1789 plurality(tlen + aoff, "", "s"));
1791 case BGPTYPE_SAFI_SPECIFIC_ATTR:
1792 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
1794 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
1796 plurality(tlen + aoff, "", "s"));
1800 default_attribute_top:
1801 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1803 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1804 tlen + aoff, plurality(tlen + aoff, "", "s"));
1805 } /* end of first switch */
1806 subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
1808 /* figure out flags */
1809 ep_strbuf_truncate(junk_emstr, 0);
1810 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) {
1811 ep_strbuf_append(junk_emstr, "Optional, ");
1814 ep_strbuf_append(junk_emstr, "Well-known, ");
1816 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) {
1817 ep_strbuf_append(junk_emstr, "Transitive, ");
1820 ep_strbuf_append(junk_emstr, "Non-transitive, ");
1822 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_PARTIAL) {
1823 ep_strbuf_append(junk_emstr, "Partial");
1826 ep_strbuf_append(junk_emstr, "Complete");
1828 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1829 ep_strbuf_append(junk_emstr, ", Extended Length");
1831 ti = proto_tree_add_text(subtree2, tvb,
1832 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1833 "Flags: 0x%02x (%s)", bgpa.bgpa_flags, junk_emstr->str);
1834 subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags);
1836 /* add flag bitfield subtrees */
1837 proto_tree_add_text(subtree3, tvb,
1838 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1839 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1840 BGP_ATTR_FLAG_OPTIONAL, 8, "Optional", "Well-known"));
1841 proto_tree_add_text(subtree3, tvb,
1842 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1843 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1844 BGP_ATTR_FLAG_TRANSITIVE, 8, "Transitive",
1846 proto_tree_add_text(subtree3, tvb,
1847 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1848 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1849 BGP_ATTR_FLAG_PARTIAL, 8, "Partial", "Complete"));
1850 proto_tree_add_text(subtree3, tvb,
1851 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1852 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1853 BGP_ATTR_FLAG_EXTENDED_LENGTH, 8, "Extended length",
1856 proto_tree_add_text(subtree2, tvb,
1857 o + i + offsetof(struct bgp_attr, bgpa_type), 1,
1858 "Type code: %s (%u)",
1859 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1862 proto_tree_add_text(subtree2, tvb, o + i + sizeof(bgpa),
1863 aoff - sizeof(bgpa), "Length: %d byte%s", tlen,
1864 plurality(tlen, "", "s"));
1866 /* the second switch prints things in the actual subtree of each
1868 switch (bgpa.bgpa_type) {
1869 case BGPTYPE_ORIGIN:
1871 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1872 "Origin (invalid): %u byte%s", tlen,
1873 plurality(tlen, "", "s"));
1875 proto_tree_add_item(subtree2, hf_bgp_origin, tvb,
1876 o + i + aoff, 1, FALSE);
1879 case BGPTYPE_AS_PATH:
1880 case BGPTYPE_NEW_AS_PATH:
1881 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1882 "AS path: %s", as_path_emstr->str);
1883 as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1886 (o + current attribute + aoff bytes to first tuple) */
1890 /* snarf each AS path tuple, we have to step through each one
1891 again to make a separate subtree so we can't just reuse
1892 as_path_gstr from above */
1893 /* XXX - Can we use some g_string*() trickery instead, e.g.
1894 g_string_erase()? */
1896 ep_strbuf_truncate(as_path_emstr, 0);
1897 type = tvb_get_guint8(tvb, q++);
1898 if (type == AS_SET) {
1899 ep_strbuf_append_c(as_path_emstr, '{');
1901 else if (type == AS_CONFED_SET) {
1902 ep_strbuf_append_c(as_path_emstr, '[');
1904 else if (type == AS_CONFED_SEQUENCE) {
1905 ep_strbuf_append_c(as_path_emstr, '(');
1907 length = tvb_get_guint8(tvb, q++);
1909 /* snarf each value in path */
1910 for (j = 0; j < length; j++) {
1911 ep_strbuf_append_printf(as_path_emstr, "%u%s",
1913 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1914 (type == AS_SET || type == AS_CONFED_SET) ? ", " : " ");
1918 /* cleanup end of string */
1919 if (type == AS_SET) {
1920 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
1921 ep_strbuf_append_c(as_path_emstr, '}');
1923 else if (type == AS_CONFED_SET) {
1924 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
1925 ep_strbuf_append_c(as_path_emstr, ']');
1927 else if (type == AS_CONFED_SEQUENCE) {
1928 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
1929 ep_strbuf_append_c(as_path_emstr, ')');
1932 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
1935 /* length here means number of ASs, ie length * 2 bytes */
1936 ti = proto_tree_add_text(as_paths_tree, tvb,
1937 q - length * asn_len - 2,
1938 length * asn_len + 2, "AS path segment: %s", as_path_emstr->str);
1939 as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1940 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 2,
1941 1, "Path segment type: %s (%u)",
1942 val_to_str(type, as_segment_type, "Unknown"), type);
1943 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 1,
1944 1, "Path segment length: %u AS%s", length,
1945 plurality(length, "", "s"));
1947 /* backup and reprint path segment value(s) only */
1948 q -= asn_len * length;
1949 ti = proto_tree_add_text(as_path_tree, tvb, q,
1950 length * asn_len, "Path segment value:");
1951 as_path_segment_tree = proto_item_add_subtree(ti,
1952 ett_bgp_as_path_segments);
1953 for (j = 0; j < length; j++) {
1954 as_path_item = (asn_len == 2) ?
1955 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q);
1956 proto_item_append_text(ti, " %u", as_path_item);
1957 hidden_item = proto_tree_add_uint(as_path_tree, hf_bgp_as_path, tvb,
1958 q, asn_len, as_path_item);
1959 PROTO_ITEM_SET_HIDDEN(hidden_item);
1965 case BGPTYPE_NEXT_HOP:
1967 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1968 "Next hop (invalid): %u byte%s", tlen,
1969 plurality(tlen, "", "s"));
1971 proto_tree_add_item(subtree2, hf_bgp_next_hop, tvb,
1972 o + i + aoff, tlen, FALSE);
1975 case BGPTYPE_MULTI_EXIT_DISC:
1977 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1978 "Multiple exit discriminator (invalid): %u byte%s",
1979 tlen, plurality(tlen, "", "s"));
1981 proto_tree_add_item(subtree2, hf_bgp_multi_exit_disc, tvb,
1982 o + i + aoff, tlen, FALSE);
1985 case BGPTYPE_LOCAL_PREF:
1987 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1988 "Local preference (invalid): %u byte%s", tlen,
1989 plurality(tlen, "", "s"));
1991 proto_tree_add_item(subtree2, hf_bgp_local_pref, tvb,
1992 o + i + aoff, tlen, FALSE);
1995 case BGPTYPE_ATOMIC_AGGREGATE:
1997 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1998 "Atomic aggregate (invalid): %u byte%s", tlen,
1999 plurality(tlen, "", "s"));
2002 case BGPTYPE_AGGREGATOR:
2003 if (tlen != 6 && tlen != 8) {
2004 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2005 "Aggregator (invalid): %u byte%s", tlen,
2006 plurality(tlen, "", "s"));
2009 case BGPTYPE_NEW_AGGREGATOR:
2010 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
2011 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2012 "Aggregator (invalid): %u byte%s", tlen,
2013 plurality(tlen, "", "s"));
2016 aggregator_as = (asn_len == 2) ?
2017 tvb_get_ntohs(tvb, o + i + aoff) :
2018 tvb_get_ntohl(tvb, o + i + aoff);
2019 proto_tree_add_uint(subtree2, hf_bgp_aggregator_as, tvb,
2020 o + i + aoff, asn_len, aggregator_as);
2021 proto_tree_add_item(subtree2, hf_bgp_aggregator_origin, tvb,
2022 o + i + aoff + asn_len, 4, FALSE);
2025 case BGPTYPE_COMMUNITIES:
2026 if (tlen % 4 != 0) {
2027 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2028 "Communities (invalid): %u byte%s", tlen,
2029 plurality(tlen, "", "s"));
2033 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2034 "Communities: %s", communities_emstr->str);
2035 communities_tree = proto_item_add_subtree(ti,
2036 ett_bgp_communities);
2039 (o + current attribute + aoff bytes to first tuple) */
2043 /* snarf each community */
2045 /* check for reserved values */
2046 guint32 community = tvb_get_ntohl(tvb, q);
2047 if ((community & 0xFFFF0000) == FOURHEX0 ||
2048 (community & 0xFFFF0000) == FOURHEXF) {
2049 proto_tree_add_text(communities_tree, tvb,
2051 "Community: %s (0x%08x)",
2052 val_to_str(community, community_vals, "(reserved)"),
2056 ti = proto_tree_add_text(communities_tree, tvb,
2057 q - 3 + aoff, 4, "Community: %u:%u",
2058 tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
2059 community_tree = proto_item_add_subtree(ti,
2060 ett_bgp_communities);
2061 proto_tree_add_item(community_tree, hf_bgp_community_as,
2062 tvb, q - 3 + aoff, 2, FALSE);
2063 proto_tree_add_item(community_tree, hf_bgp_community_value,
2064 tvb, q - 1 + aoff, 2, FALSE);
2071 case BGPTYPE_ORIGINATOR_ID:
2073 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2074 "Originator identifier (invalid): %u byte%s", tlen,
2075 plurality(tlen, "", "s"));
2077 proto_tree_add_item(subtree2, hf_bgp_originator_id, tvb,
2078 o + i + aoff, tlen, FALSE);
2081 case BGPTYPE_MP_REACH_NLRI:
2083 * RFC 2545 specifies that there may be more than one
2084 * address in the MP_REACH_NLRI attribute in section
2085 * 3, "Constructing the Next Hop field".
2087 * Yes, RFC 2858 says you can't do that, and, yes, RFC
2088 * 2858 obsoletes RFC 2283, which says you can do that,
2089 * but that doesn't mean we shouldn't dissect packets
2090 * that conform to RFC 2283 but not RFC 2858, as some
2091 * device on the network might implement the 2283-style
2092 * BGP extensions rather than RFC 2858-style extensions.
2094 af = tvb_get_ntohs(tvb, o + i + aoff);
2095 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
2096 "Address family: %s (%u)",
2097 val_to_str(af, afn_vals, "Unknown"), af);
2098 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
2099 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
2100 "Subsequent address family identifier: %s (%u)",
2101 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
2103 nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
2104 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
2106 "Next hop network address (%d byte%s)",
2107 nexthop_len, plurality(nexthop_len, "", "s"));
2108 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
2111 * The addresses don't contain lengths, so if we
2112 * don't understand the address family type, we
2113 * cannot parse the subsequent addresses as we
2114 * don't know how long they are.
2118 proto_tree_add_text(subtree3, tvb, o + i + aoff + 4,
2119 nexthop_len, "Unknown Address Family");
2125 case AFNUM_L2VPN_OLD:
2128 while (j < nexthop_len) {
2129 advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
2131 if (advance == 0) /* catch if this is a unknown AFI type*/
2133 if (j + advance > nexthop_len)
2135 proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
2136 advance, "Next hop: %s (%u)", junk_emstr->str, advance);
2143 tlen -= nexthop_len + 4;
2144 aoff += nexthop_len + 4 ;
2147 snpa = tvb_get_guint8(tvb, o + i + aoff);
2148 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
2149 "Subnetwork points of attachment: %u", snpa);
2152 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
2153 for (/*nothing*/; snpa > 0; snpa--) {
2154 proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
2155 "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
2157 proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
2158 tvb_get_guint8(tvb, o + i + aoff + off - 1),
2159 "SNPA (%u byte%s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
2160 plurality(tvb_get_guint8(tvb, o + i + aoff + off - 1), "", "s"));
2161 off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
2167 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2168 "Network layer reachability information (%u byte%s)",
2169 tlen, plurality(tlen, "", "s"));
2171 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
2172 if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
2173 proto_tree_add_text(subtree3, tvb, o + i + aoff,
2174 tlen, "Unknown Address Family");
2177 advance = decode_prefix_MP(subtree3,
2178 hf_bgp_mp_reach_nlri_ipv4_prefix,
2181 tvb, o + i + aoff, "MP Reach NLRI");
2191 case BGPTYPE_MP_UNREACH_NLRI:
2192 af = tvb_get_ntohs(tvb, o + i + aoff);
2193 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
2194 "Address family: %s (%u)",
2195 val_to_str(af, afn_vals, "Unknown"), af);
2196 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
2197 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
2198 "Subsequent address family identifier: %s (%u)",
2199 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
2201 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
2202 tlen - 3, "Withdrawn routes (%u byte%s)", tlen - 3,
2203 plurality(tlen - 3, "", "s"));
2209 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
2212 advance = decode_prefix_MP(subtree3,
2213 hf_bgp_mp_unreach_nlri_ipv4_prefix,
2216 tvb, o + i + aoff, "MP Unreach NLRI");
2225 case BGPTYPE_CLUSTER_LIST:
2226 if (tlen % 4 != 0) {
2227 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2228 "Cluster list (invalid): %u byte%s", tlen,
2229 plurality(tlen, "", "s"));
2233 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2234 "Cluster list: %s", cluster_list_emstr->str);
2235 cluster_list_tree = proto_item_add_subtree(ti,
2236 ett_bgp_cluster_list);
2239 (o + current attribute + aoff bytes to first tuple) */
2243 /* snarf each cluster identifier */
2245 proto_tree_add_item(cluster_list_tree, hf_bgp_cluster_list,
2246 tvb, q - 3 + aoff, 4, FALSE);
2251 case BGPTYPE_EXTENDED_COMMUNITY:
2253 proto_tree_add_text(subtree3, tvb, o + i + aoff, tlen, "Extended community (invalid) : %u byte%s", tlen,
2254 plurality(tlen, "", "s"));
2257 end = o + i + aoff + tlen ;
2258 ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
2259 subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2262 ext_com8 = tvb_get_guint8(tvb,q); /* handle regular types (8 bit) */
2263 ext_com = tvb_get_ntohs(tvb,q); /* handle extended length types (16 bit) */
2264 ep_strbuf_printf(junk_emstr, "%s", val_to_str(ext_com8,bgpext_com8_type,"Unknown"));
2265 is_regular_type = FALSE;
2266 is_extended_type = FALSE;
2267 /* handle regular types (8 bit) */
2269 case BGP_EXT_COM_QOS_MARK_T:
2270 case BGP_EXT_COM_QOS_MARK_NT:
2271 is_regular_type = TRUE;
2272 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2274 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2275 ti = proto_tree_add_text(subtree4, tvb, q, 1,
2276 "Type: 0x%02x", tvb_get_guint8(tvb,q));
2277 ti = proto_tree_add_text(subtree4, tvb, q+1, 1,
2278 "Flags: 0x%02x", tvb_get_guint8(tvb,q+1));
2279 subtree5 = proto_item_add_subtree(ti,ett_bgp_ext_com_flags);
2280 /* add flag bitfield */
2281 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2282 0x10, 8, "Remarking", "No Remarking"));
2283 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2284 0x08, 8, "Ignored marking", "No Ignored marking"));
2285 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2286 0x04, 8, "Aggregation of markings", "No Aggregation of markings"));
2288 ti = proto_tree_add_text(subtree4, tvb, q+2, 1,
2289 "QoS Set Number: 0x%02x", tvb_get_guint8(tvb,q+2));
2290 ti = proto_tree_add_text(subtree4, tvb, q+3, 1,
2291 "Technology Type: 0x%02x (%s)", tvb_get_guint8(tvb,q+3),
2292 val_to_str(tvb_get_guint8(tvb,q+3),qos_tech_type,"Unknown"));
2293 ti = proto_tree_add_text(subtree4, tvb, q+4, 2,
2294 "QoS Marking O (16 bit): %s", decode_numeric_bitfield(tvb_get_ntohs(tvb,q+4),
2295 0xffff, 16, "0x%04x"));
2296 ti = proto_tree_add_text(subtree4, tvb, q+6, 1,
2297 "QoS Marking A (8 bit): %s (decimal %d)", decode_numeric_bitfield(tvb_get_guint8(tvb,q+6),
2298 0xff, 8, "0x%02x"), tvb_get_guint8(tvb,q+6));
2299 ti = proto_tree_add_text(subtree4, tvb, q+7, 1,
2300 "Defaults to zero: 0x%02x", tvb_get_guint8(tvb,q+7));
2302 case BGP_EXT_COM_COS_CAP_T:
2303 is_regular_type = TRUE;
2304 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2306 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2307 ti = proto_tree_add_text(subtree4, tvb, q, 1,
2308 "Type: 0x%02x", tvb_get_guint8(tvb,q));
2309 ti = proto_tree_add_text(subtree4, tvb, q+1, 1,
2310 "Flags byte 1 : 0x%02x", tvb_get_guint8(tvb,q+1));
2311 subtree5 = proto_item_add_subtree(ti,ett_bgp_ext_com_flags);
2312 /* add flag bitfield */
2313 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2314 0x80, 8, "BE class supported", "BE class NOT supported"));
2315 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2316 0x40, 8, "EF class supported", "EF class NOT supported"));
2317 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2318 0x20, 8, "AF class supported", "AF class NOT supported"));
2319 ti = proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2320 0x10, 8, "LE class supported", "LE class NOT supported"));
2321 ti = proto_tree_add_text(subtree4, tvb, q+2, 1,
2322 "Flags byte 2..7 : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
2323 tvb_get_guint8(tvb,q+2),tvb_get_guint8(tvb,q+3),tvb_get_guint8(tvb,q+4),
2324 tvb_get_guint8(tvb,q+5),tvb_get_guint8(tvb,q+6),tvb_get_guint8(tvb,q+7));
2328 if (!is_regular_type) {
2329 ep_strbuf_append(junk_emstr, val_to_str(ext_com,bgpext_com_type,"Unknown"));
2331 /* handle extended length types (16 bit) */
2333 case BGP_EXT_COM_RT_0:
2334 case BGP_EXT_COM_RT_2:
2335 case BGP_EXT_COM_RO_0:
2336 case BGP_EXT_COM_RO_2:
2337 is_extended_type = TRUE;
2338 ep_strbuf_append_printf(junk_emstr, ": %u%s%d",
2339 tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
2340 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2342 case BGP_EXT_COM_RT_1:
2343 case BGP_EXT_COM_RO_1:
2344 is_extended_type = TRUE;
2345 ipaddr = tvb_get_ipv4(tvb,q+2);
2346 ep_strbuf_append_printf(junk_emstr, ": %s%s%u",
2347 ip_to_str((guint8 *)&ipaddr),":",tvb_get_ntohs(tvb,q+6));
2348 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2350 case BGP_EXT_COM_VPN_ORIGIN:
2351 case BGP_EXT_COM_OSPF_RID:
2352 is_extended_type = TRUE;
2353 ipaddr = tvb_get_ipv4(tvb,q+2);
2354 ep_strbuf_append_printf(junk_emstr, ": %s", ip_to_str((guint8 *)&ipaddr));
2355 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2357 case BGP_EXT_COM_OSPF_RTYPE:
2358 is_extended_type = TRUE;
2359 ipaddr = tvb_get_ipv4(tvb,q+2);
2360 ep_strbuf_append_printf(junk_emstr, ": Area: %s, Type: %s", ip_to_str((guint8 *)&ipaddr),
2361 val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
2362 /* print OSPF Metric type if selected */
2363 /* always print E2 even if not external route -- receiving router should ignore */
2364 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
2365 ep_strbuf_append(junk_emstr, " E2");
2366 } else if ((tvb_get_guint8(tvb,q+6)==BGP_OSPF_RTYPE_EXT) || (tvb_get_guint8(tvb,q+6)==BGP_OSPF_RTYPE_NSSA)) {
2367 ep_strbuf_append(junk_emstr, " E1");
2369 ep_strbuf_append(junk_emstr, ", no options");
2371 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2373 case BGP_EXT_COM_LINKBAND:
2374 is_extended_type = TRUE;
2375 linkband = tvb_get_ntohieee_float(tvb,q+2);
2376 ep_strbuf_append_printf(junk_emstr, ": %.3f Mbps", linkband*8/1000000);
2377 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2379 case BGP_EXT_COM_L2INFO:
2380 is_extended_type = TRUE;
2381 ep_strbuf_append_printf(junk_emstr,
2382 ": %s, Control Flags: %s%s%s%s%s, MTU: %u byte%s",
2383 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"),
2384 tvb_get_guint8(tvb,q+3) ? "" : "none",
2385 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q" : "",
2386 tvb_get_ntohs(tvb,q+3)&0x04 ? "F" : "",
2387 tvb_get_ntohs(tvb,q+3)&0x02 ? "C" : "",
2388 tvb_get_ntohs(tvb,q+3)&0x01 ? "S" : "",
2389 tvb_get_ntohs(tvb,q+4),
2390 plurality(tvb_get_ntohs(tvb,q+4), "", "s"));
2391 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2393 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2394 proto_tree_add_text(subtree4,tvb,q+2,1, "Encapsulation: %s",
2395 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"));
2396 proto_tree_add_text(subtree4,tvb,q+3,1, "Control Flags: %s%sControl Word %s required, Sequenced delivery %s required",
2397 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q flag (Reserved) set" : "",
2398 tvb_get_ntohs(tvb,q+3)&0x04 ? "F flag (reserved) set" : "",
2399 tvb_get_ntohs(tvb,q+3)&0x02 ? "is" : "not",
2400 tvb_get_ntohs(tvb,q+3)&0x01 ? "is" : "not");
2401 proto_tree_add_text(subtree4,tvb,q+4,2, "MTU: %u byte%s",
2402 tvb_get_ntohs(tvb,q+4),
2403 plurality(tvb_get_ntohs(tvb,q+4), "", "s"));
2407 if (!is_regular_type && !is_extended_type)
2408 proto_tree_add_text(subtree3,tvb,q,8, "%s","Unknown");
2413 case BGPTYPE_SAFI_SPECIFIC_ATTR:
2415 end = o + i + aoff + tlen ;
2418 ssa_type = tvb_get_ntohs(tvb, q) & BGP_SSA_TYPE;
2419 ssa_len = tvb_get_ntohs(tvb, q + 2);
2421 ti = proto_tree_add_text(subtree2, tvb, q, MIN(ssa_len + 4, end - q),
2423 val_to_str(ssa_type, bgp_ssa_type, "Unknown SSA"));
2424 subtree3 = proto_item_add_subtree(ti, ett_bgp_ssa);
2426 proto_tree_add_item(subtree3, hf_bgp_ssa_t, tvb,
2428 hidden_item = proto_tree_add_item(subtree3, hf_bgp_ssa_type, tvb,
2430 PROTO_ITEM_SET_HIDDEN(hidden_item);
2431 proto_tree_add_text(subtree3, tvb, q, 2,
2432 "Type: %s", val_to_str(ssa_type, bgp_ssa_type, "Unknown"));
2433 if ((ssa_len == 0) || (q + ssa_len > end)) {
2434 proto_tree_add_text(subtree3, tvb, q + 2, end - q - 2,
2435 "Invalid Length of %u", ssa_len);
2438 proto_tree_add_item(subtree3, hf_bgp_ssa_len, tvb,
2442 case BGP_SSA_L2TPv3:
2443 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_pref, tvb,
2446 ti = proto_tree_add_text(subtree3, tvb, q + 6, 1, "Flags");
2447 subtree4 = proto_item_add_subtree(ti, ett_bgp_ssa_subtree) ;
2448 proto_tree_add_item(subtree4, hf_bgp_ssa_l2tpv3_s, tvb,
2450 proto_tree_add_item(subtree4, hf_bgp_ssa_l2tpv3_unused, tvb,
2453 ssa_v3_len = tvb_get_guint8(tvb, q + 7);
2454 if (ssa_v3_len + 8 == ssa_len){
2455 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_cookie_len, tvb,
2458 proto_tree_add_text(subtree3, tvb, q + 7, 1,
2459 "Invalid Cookie Length of %u", ssa_v3_len);
2462 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_session_id, tvb,
2465 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_cookie, tvb,
2466 q + 12, ssa_v3_len, FALSE);
2472 proto_tree_add_item(subtree3, hf_bgp_ssa_value, tvb,
2473 q + 4, ssa_len, FALSE);
2476 q = q + ssa_len + 4; /* 4 from type and length */
2481 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2482 "Unknown (%u byte%s)", tlen, plurality(tlen, "", "s"));
2484 } /* end of second switch */
2494 /* parse prefixes */
2496 ti = proto_tree_add_text(tree, tvb, o, len,
2497 "Network layer reachability information: %u byte%s", len,
2498 plurality(len, "", "s"));
2499 subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
2502 i = decode_prefix4(subtree, hf_bgp_nlri_prefix, tvb, o, 0,
2513 * Dissect a BGP NOTIFICATION message.
2516 dissect_bgp_notification(tvbuff_t *tvb, proto_tree *tree)
2518 struct bgp_notification bgpn; /* BGP NOTIFICATION message */
2519 int hlen; /* message length */
2520 const char *p; /* string pointer */
2523 tvb_memcpy(tvb, bgpn.bgpn_marker, 0, BGP_MIN_NOTIFICATION_MSG_SIZE);
2524 hlen = g_ntohs(bgpn.bgpn_len);
2526 /* print error code */
2527 proto_tree_add_text(tree, tvb,
2528 offsetof(struct bgp_notification, bgpn_major), 1,
2529 "Error code: %s (%u)",
2530 val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
2533 /* print error subcode */
2534 if (bgpn.bgpn_major < array_length(bgpnotify_minor)
2535 && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
2536 p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
2538 } else if (bgpn.bgpn_minor == 0)
2542 proto_tree_add_text(tree, tvb,
2543 offsetof(struct bgp_notification, bgpn_minor), 1,
2544 "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
2546 /* only print if there is optional data */
2547 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
2548 proto_tree_add_text(tree, tvb, BGP_MIN_NOTIFICATION_MSG_SIZE,
2549 hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
2554 * Dissect a BGP ROUTE-REFRESH message.
2557 dissect_bgp_route_refresh(tvbuff_t *tvb, proto_tree *tree)
2559 guint16 i; /* tmp */
2560 int p; /* tvb offset counter */
2561 int pend; /* end of list of entries for one orf type */
2562 guint16 hlen; /* tvb RR msg length */
2563 proto_item *ti; /* tree item */
2564 proto_item *ti1; /* tree item */
2565 proto_tree *subtree; /* tree for orf */
2566 proto_tree *subtree1; /* tree for orf entry */
2567 guint8 orftype; /* ORF Type */
2568 guint8 orfwhen; /* ORF flag: immediate, defer */
2569 guint16 orflen; /* ORF len */
2570 guint8 entryflag; /* ORF Entry flag: action(add,del,delall) match(permit,deny) */
2571 guint32 entryseq; /* ORF Entry sequence number */
2572 int entrylen; /* ORF Entry length */
2573 guint8 pfx_ge; /* ORF PrefixList mask lower bound */
2574 guint8 pfx_le; /* ORF PrefixList mask upper bound */
2575 int advance; /* tmp */
2581 00 01 00 01 afi,safi= ipv4-unicast
2582 02 80 00 01 defer, prefix-orf, len=1
2586 00 01 00 01 afi,saif= ipv4-unicast
2587 01 80 00 0a immediate, prefix-orf, len=10
2589 00 00 00 05 seqno = 5
2592 10 07 02 prefix = 7.2.0.0/16
2594 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
2595 p = BGP_HEADER_SIZE;
2597 i = tvb_get_ntohs(tvb, p);
2598 proto_tree_add_text(tree, tvb, p, 2,
2599 "Address family identifier: %s (%u)",
2600 val_to_str(i, afn_vals, "Unknown"), i);
2603 proto_tree_add_text(tree, tvb, p, 1,
2604 "Reserved: 1 byte");
2607 i = tvb_get_guint8(tvb, p);
2608 proto_tree_add_text(tree, tvb, p, 1,
2609 "Subsequent address family identifier: %s (%u)",
2610 val_to_str(i, bgpattr_nlri_safi,
2611 i >= 128 ? "Vendor specific" : "Unknown"),
2614 if ( hlen == BGP_HEADER_SIZE + 4 )
2618 orfwhen = tvb_get_guint8(tvb, p);
2619 orftype = tvb_get_guint8(tvb, p+1);
2620 orflen = tvb_get_ntohs(tvb, p+2);
2621 ti = proto_tree_add_text(tree, tvb, p , orflen + 4 , "ORF information (%u bytes)", orflen + 4);
2622 subtree = proto_item_add_subtree(ti, ett_bgp_orf);
2623 proto_tree_add_text(subtree, tvb, p , 1, "ORF flag: %s", val_to_str(orfwhen, orf_when_vals,"UNKNOWN"));
2624 proto_tree_add_text(subtree, tvb, p+1 , 1, "ORF type: %s", val_to_str(orftype, orf_type_vals,"UNKNOWN"));
2625 proto_tree_add_text(subtree, tvb, p+2 , 2, "ORF len: %u byte%s", orflen, plurality(orflen, "", "s"));
2628 if (orftype != BGP_ORF_PREFIX_CISCO) {
2629 proto_tree_add_text(subtree, tvb, p, orflen,
2630 "ORFEntry-Unknown (%u bytes)", orflen);
2636 entryflag = tvb_get_guint8(tvb, p);
2637 if ((entryflag & BGP_ORF_ACTION) == BGP_ORF_REMOVEALL) {
2638 ti1 = proto_tree_add_text(subtree, tvb, p, 1,
2639 "ORFEntry-PrefixList (1 byte)");
2640 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2641 proto_tree_add_text(subtree1, tvb, p , 1, "RemoveAll");
2644 ti1 = proto_tree_add_text(subtree, tvb, p, -1,
2645 "ORFEntry-PrefixList");
2646 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2647 proto_tree_add_text(subtree1, tvb, p, 1,
2648 "ACTION: %s MATCH: %s",
2649 val_to_str(entryflag&BGP_ORF_ACTION,
2650 orf_entry_action_vals, "UNKNOWN"),
2651 val_to_str(entryflag&BGP_ORF_MATCH,
2652 orf_entry_match_vals, "UNKNOWN"));
2654 entryseq = tvb_get_ntohl(tvb, p);
2655 proto_tree_add_text(subtree1, tvb, p, 4,
2656 "Entry Sequence No: %u", entryseq);
2658 pfx_ge = tvb_get_guint8(tvb, p);
2659 proto_tree_add_text(subtree1, tvb, p, 1,
2660 "PrefixMask length lower bound: %u", pfx_ge);
2662 pfx_le = tvb_get_guint8(tvb, p);
2663 proto_tree_add_text(subtree1, tvb, p, 1,
2664 "PrefixMask length upper bound: %u", pfx_le);
2667 advance = decode_prefix4(subtree1, -1, tvb, p, 0, "ORF");
2670 entrylen = 7 + 1 + advance;
2672 proto_item_append_text(ti1, " (%u bytes)", entrylen);
2673 proto_item_set_len(ti1, entrylen);
2681 * Dissect a BGP CAPABILITY message.
2684 dissect_bgp_capability(tvbuff_t *tvb, proto_tree *tree)
2688 proto_tree *subtree;
2694 mend = offset + tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2695 offset += BGP_HEADER_SIZE;
2696 /* step through all of the capabilities */
2697 while (offset < mend) {
2698 action = tvb_get_guint8(tvb, offset++);
2699 ctype = tvb_get_guint8(tvb, offset++);
2700 clen = tvb_get_guint8(tvb, offset++);
2702 ti = proto_tree_add_text(tree, tvb, offset - 2, 2 + clen,
2703 "%s (%u byte%s)", val_to_str(ctype, capability_vals,
2704 "Unknown capability"), 2 + clen, plurality(clen, "", "s"));
2705 subtree = proto_item_add_subtree(ti, ett_bgp_option);
2706 proto_tree_add_text(subtree, tvb, offset-2, 1, "Action: %d (%s)",
2707 action, val_to_str(action, bgpcap_action, "Invalid action value"));
2708 dissect_bgp_capability_item(tvb, &offset, subtree, ctype, clen);
2713 dissect_bgp_pdu(tvbuff_t *volatile tvb, packet_info *pinfo, proto_tree *tree,
2716 guint16 bgp_len; /* Message length */
2717 guint8 bgp_type; /* Message type */
2718 const char *typ; /* Message type (string) */
2719 proto_item *ti; /* tree item */
2720 proto_tree *bgp_tree; /* BGP packet tree */
2721 proto_tree *bgp1_tree; /* BGP message tree */
2723 bgp_len = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
2724 bgp_type = tvb_get_guint8(tvb, BGP_MARKER_SIZE + 2);
2725 typ = val_to_str(bgp_type, bgptypevals, "Unknown message type (0x%02x)");
2727 if (check_col(pinfo->cinfo, COL_INFO)) {
2729 col_add_str(pinfo->cinfo, COL_INFO, typ);
2731 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
2735 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, FALSE);
2736 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
2738 ti = proto_tree_add_text(bgp_tree, tvb, 0, -1, "%s", typ);
2740 /* add a different tree for each message type */
2743 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_open);
2746 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_update);
2748 case BGP_NOTIFICATION:
2749 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_notification);
2752 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
2754 case BGP_ROUTE_REFRESH_CISCO:
2755 case BGP_ROUTE_REFRESH:
2756 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
2758 case BGP_CAPABILITY:
2759 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_capability);
2762 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
2766 proto_tree_add_text(bgp1_tree, tvb, 0, BGP_MARKER_SIZE,
2767 "Marker: 16 bytes");
2769 if (bgp_len < BGP_HEADER_SIZE || bgp_len > BGP_MAX_PACKET_SIZE) {
2770 proto_tree_add_text(bgp1_tree, tvb, BGP_MARKER_SIZE, 2,
2771 "Length (invalid): %u byte%s", bgp_len,
2772 plurality(bgp_len, "", "s"));
2775 proto_tree_add_text(bgp1_tree, tvb, BGP_MARKER_SIZE, 2,
2776 "Length: %u byte%s", bgp_len,
2777 plurality(bgp_len, "", "s"));
2780 proto_tree_add_uint(bgp1_tree, hf_bgp_type, tvb,
2781 BGP_MARKER_SIZE + 2, 1,
2786 dissect_bgp_open(tvb, bgp1_tree);
2789 dissect_bgp_update(tvb, bgp1_tree);
2791 case BGP_NOTIFICATION:
2792 dissect_bgp_notification(tvb, bgp1_tree);
2795 /* no data in KEEPALIVE messages */
2797 case BGP_ROUTE_REFRESH_CISCO:
2798 case BGP_ROUTE_REFRESH:
2799 dissect_bgp_route_refresh(tvb, bgp1_tree);
2801 case BGP_CAPABILITY:
2802 dissect_bgp_capability(tvb, bgp1_tree);
2811 * Dissect a BGP packet.
2814 dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2816 volatile int offset = 0; /* offset into the tvbuff */
2817 gint reported_length_remaining;
2818 guint8 bgp_marker[BGP_MARKER_SIZE]; /* Marker (should be all ones */
2819 static guchar marker[] = { /* BGP message marker */
2820 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2821 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2823 proto_item *ti; /* tree item */
2824 proto_tree *bgp_tree; /* BGP packet tree */
2825 guint16 bgp_len; /* Message length */
2827 guint length_remaining;
2829 volatile gboolean first = TRUE; /* TRUE for the first BGP message in packet */
2830 tvbuff_t *volatile next_tvb;
2832 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
2833 if (check_col(pinfo->cinfo, COL_INFO))
2834 col_clear(pinfo->cinfo, COL_INFO);
2837 * Scan through the TCP payload looking for a BGP marker.
2839 while ((reported_length_remaining = tvb_reported_length_remaining(tvb, offset))
2842 * "reported_length_remaining" is the number of bytes of TCP payload
2843 * remaining. If it's more than the length of a BGP marker,
2844 * we check only the number of bytes in a BGP marker.
2846 if (reported_length_remaining > BGP_MARKER_SIZE)
2847 reported_length_remaining = BGP_MARKER_SIZE;
2850 * OK, is there a BGP marker starting at the specified offset -
2851 * or, at least, the beginning of a BGP marker running to the end
2852 * of the TCP payload?
2854 * This will throw an exception if the frame is short; that's what
2857 tvb_memcpy(tvb, bgp_marker, offset, reported_length_remaining);
2858 if (memcmp(bgp_marker, marker, reported_length_remaining) == 0) {
2860 * Yes - stop scanning and start processing BGP packets.
2866 * No - keep scanning through the tvbuff to try to find a marker.
2872 * If we skipped any bytes, mark it as a BGP continuation.
2875 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, FALSE);
2876 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
2878 proto_tree_add_text(bgp_tree, tvb, 0, offset, "Continuation");
2882 * Now process the BGP packets in the TCP payload.
2884 * XXX - perhaps "tcp_dissect_pdus()" should take a starting
2885 * offset, in which case we can replace the loop below with
2886 * a call to "tcp_dissect_pdus()".
2888 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2890 * This will throw an exception if we don't have any data left.
2891 * That's what we want. (See "tcp_dissect_pdus()", which is
2894 length_remaining = tvb_ensure_length_remaining(tvb, offset);
2897 * Can we do reassembly?
2899 if (bgp_desegment && pinfo->can_desegment) {
2901 * Yes - would a BGP header starting at this offset be split
2902 * across segment boundaries?
2904 if (length_remaining < BGP_HEADER_SIZE) {
2906 * Yes. Tell the TCP dissector where the data for this
2907 * message starts in the data it handed us, and how many
2908 * more bytes we need, and return.
2910 pinfo->desegment_offset = offset;
2911 pinfo->desegment_len = BGP_HEADER_SIZE - length_remaining;
2917 * Get the length and type from the BGP header.
2919 bgp_len = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2920 if (bgp_len < BGP_HEADER_SIZE) {
2922 * The BGP length doesn't include the BGP header; report that
2925 show_reported_bounds_error(tvb, pinfo, tree);
2930 * Can we do reassembly?
2932 if (bgp_desegment && pinfo->can_desegment) {
2934 * Yes - is the PDU split across segment boundaries?
2936 if (length_remaining < bgp_len) {
2938 * Yes. Tell the TCP dissector where the data for this
2939 * message starts in the data it handed us, and how many
2940 * more bytes we need, and return.
2942 pinfo->desegment_offset = offset;
2943 pinfo->desegment_len = bgp_len - length_remaining;
2949 * Construct a tvbuff containing the amount of the payload we have
2950 * available. Make its reported length the amount of data in the PDU.
2952 * XXX - if reassembly isn't enabled. the subdissector will throw a
2953 * BoundsError exception, rather than a ReportedBoundsError exception.
2954 * We really want a tvbuff where the length is "length", the reported
2955 * length is "plen", and the "if the snapshot length were infinite"
2956 * length is the minimum of the reported length of the tvbuff handed
2957 * to us and "plen", with a new type of exception thrown if the offset
2958 * is within the reported length but beyond that third length, with
2959 * that exception getting the "Unreassembled Packet" error.
2961 length = length_remaining;
2962 if (length > bgp_len)
2964 next_tvb = tvb_new_subset(tvb, offset, length, bgp_len);
2969 * Catch the ReportedBoundsError exception; if this particular message
2970 * happens to get a ReportedBoundsError exception, that doesn't mean
2971 * that we should stop dissecting PDUs within this frame or chunk of
2974 * If it gets a BoundsError, we can stop, as there's nothing more to
2975 * see, so we just re-throw it.
2978 dissect_bgp_pdu(next_tvb, pinfo, tree, first);
2980 CATCH(BoundsError) {
2983 CATCH(ReportedBoundsError) {
2984 show_reported_bounds_error(tvb, pinfo, tree);
2991 * Step to the next PDU.
2992 * Make sure we don't overflow.
2994 offset_before = offset;
2996 if (offset <= offset_before)
3002 * Register ourselves.
3005 proto_register_bgp(void)
3008 static hf_register_info hf[] = {
3010 { "Type", "bgp.type", FT_UINT8, BASE_DEC,
3011 VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
3012 { &hf_bgp_aggregator_as,
3013 { "Aggregator AS", "bgp.aggregator_as", FT_UINT16, BASE_DEC,
3014 NULL, 0x0, NULL, HFILL}},
3015 { &hf_bgp_aggregator_origin,
3016 { "Aggregator origin", "bgp.aggregator_origin", FT_IPv4, BASE_NONE,
3017 NULL, 0x0, NULL, HFILL}},
3019 { "AS Path", "bgp.as_path", FT_UINT16, BASE_DEC,
3020 NULL, 0x0, NULL, HFILL}},
3021 { &hf_bgp_cluster_identifier,
3022 { "Cluster identifier", "bgp.cluster_identifier", FT_IPv4, BASE_NONE,
3023 NULL, 0x0, NULL, HFILL}},
3024 { &hf_bgp_community_as,
3025 { "Community AS", "bgp.community_as", FT_UINT16, BASE_DEC,
3026 NULL, 0x0, NULL, HFILL}},
3027 { &hf_bgp_community_value,
3028 { "Community value", "bgp.community_value", FT_UINT16, BASE_DEC,
3029 NULL, 0x0, NULL, HFILL}},
3030 { &hf_bgp_local_pref,
3031 { "Local preference", "bgp.local_pref", FT_UINT32, BASE_DEC,
3032 NULL, 0x0, NULL, HFILL}},
3033 { &hf_bgp_mp_reach_nlri_ipv4_prefix,
3034 { "MP Reach NLRI IPv4 prefix", "bgp.mp_reach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
3035 NULL, 0x0, NULL, HFILL}},
3036 { &hf_bgp_mp_unreach_nlri_ipv4_prefix,
3037 { "MP Unreach NLRI IPv4 prefix", "bgp.mp_unreach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
3038 NULL, 0x0, NULL, HFILL}},
3039 { &hf_bgp_mp_nlri_tnl_id,
3040 { "MP Reach NLRI Tunnel Identifier", "bgp.mp_nlri_tnl_id", FT_UINT16, BASE_HEX,
3041 NULL, 0x0, NULL, HFILL}},
3042 { &hf_bgp_multi_exit_disc,
3043 { "Multiple exit discriminator", "bgp.multi_exit_disc", FT_UINT32, BASE_DEC,
3044 NULL, 0x0, NULL, HFILL}},
3046 { "Next hop", "bgp.next_hop", FT_IPv4, BASE_NONE,
3047 NULL, 0x0, NULL, HFILL}},
3048 { &hf_bgp_nlri_prefix,
3049 { "NLRI prefix", "bgp.nlri_prefix", FT_IPv4, BASE_NONE,
3050 NULL, 0x0, NULL, HFILL}},
3052 { "Origin", "bgp.origin", FT_UINT8, BASE_DEC,
3053 VALS(bgpattr_origin), 0x0, NULL, HFILL}},
3054 { &hf_bgp_originator_id,
3055 { "Originator identifier", "bgp.originator_id", FT_IPv4, BASE_NONE,
3056 NULL, 0x0, NULL, HFILL}},
3058 { "Transitive bit", "bgp.ssa_t", FT_BOOLEAN, 8,
3059 NULL, 0x80, "SSA Transitive bit", HFILL}},
3061 { "SSA Type", "bgp.ssa_type", FT_UINT16, BASE_DEC,
3062 VALS(bgp_ssa_type), 0x7FFF, NULL, HFILL}},
3064 { "Length", "bgp.ssa_len", FT_UINT16, BASE_DEC,
3065 NULL, 0x0, "SSA Length", HFILL}},
3066 { &hf_bgp_ssa_value,
3067 { "Value", "bgp.ssa_value", FT_BYTES, BASE_NONE,
3068 NULL, 0x0, "SSA Value", HFILL}},
3069 { &hf_bgp_ssa_l2tpv3_pref,
3070 { "Preference", "bgp.ssa_l2tpv3_pref", FT_UINT16, BASE_DEC,
3071 NULL, 0x0, NULL, HFILL}},
3072 { &hf_bgp_ssa_l2tpv3_s,
3073 { "Sequencing bit", "bgp.ssa_l2tpv3_s", FT_BOOLEAN, 8,
3074 NULL, 0x80, "Sequencing S-bit", HFILL}},
3075 { &hf_bgp_ssa_l2tpv3_unused,
3076 { "Unused", "bgp.ssa_l2tpv3_Unused", FT_BOOLEAN, 8,
3077 NULL, 0x7F, "Unused Flags", HFILL}},
3078 { &hf_bgp_ssa_l2tpv3_cookie_len,
3079 { "Cookie Length", "bgp.ssa_l2tpv3_cookie_len", FT_UINT8, BASE_DEC,
3080 NULL, 0x0, NULL, HFILL}},
3081 { &hf_bgp_ssa_l2tpv3_session_id,
3082 { "Session ID", "bgp.ssa_l2tpv3_session_id", FT_UINT32, BASE_DEC,
3083 NULL, 0x0, NULL, HFILL}},
3084 { &hf_bgp_ssa_l2tpv3_cookie,
3085 { "Cookie", "bgp.ssa_l2tpv3_cookie", FT_BYTES, BASE_NONE,
3086 NULL, 0x0, NULL, HFILL}},
3087 { &hf_bgp_withdrawn_prefix,
3088 { "Withdrawn prefix", "bgp.withdrawn_prefix", FT_IPv4, BASE_NONE,
3089 NULL, 0x0, NULL, HFILL}},
3090 { &hf_bgp_cluster_list,
3091 { "Cluster List", "bgp.cluster_list", FT_BYTES, BASE_NONE,
3092 NULL, 0x0, NULL, HFILL}}
3095 static gint *ett[] = {
3101 &ett_bgp_attr_flags,
3103 &ett_bgp_mp_reach_nlri,
3104 &ett_bgp_mp_unreach_nlri,
3109 &ett_bgp_notification,
3110 &ett_bgp_route_refresh,
3111 &ett_bgp_capability,
3113 &ett_bgp_as_path_segments,
3114 &ett_bgp_communities,
3115 &ett_bgp_cluster_list,
3118 &ett_bgp_extended_communities,
3119 &ett_bgp_ext_com_flags,
3121 &ett_bgp_ssa_subtree,
3125 module_t *bgp_module;
3126 static enum_val_t asn_len[] = {
3127 {"auto-detect", "Auto-detect", 0},
3128 {"2", "2 octet", 2},
3129 {"4", "4 octet", 4},
3133 proto_bgp = proto_register_protocol("Border Gateway Protocol",
3135 proto_register_field_array(proto_bgp, hf, array_length(hf));
3136 proto_register_subtree_array(ett, array_length(ett));
3138 bgp_module = prefs_register_protocol(proto_bgp, NULL);
3139 prefs_register_bool_preference(bgp_module, "desegment",
3140 "Reassemble BGP messages spanning multiple TCP segments",
3141 "Whether the BGP dissector should reassemble messages spanning multiple TCP segments."
3142 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3144 prefs_register_enum_preference(bgp_module, "asn_len",
3145 "Length of the AS number",
3146 "BGP dissector detect the length of the AS number in AS_PATH attributes automatically or manually (NOTE: Automatic detection is not 100% accurate)",
3147 &bgp_asn_len, asn_len, FALSE);
3151 proto_reg_handoff_bgp(void)
3153 dissector_handle_t bgp_handle;
3155 bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
3156 dissector_add("tcp.port", BGP_TCP_PORT, bgp_handle);