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
39 * draft-nalawade-kapoor-tunnel-safi-05
40 * draft-ietf-idr-add-paths-04 Additional-Path for BGP-4
43 * Destination Preference Attribute for BGP (work in progress)
44 * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
54 #include <epan/packet.h>
55 #include <epan/addr_and_mask.h>
56 #include "packet-bgp.h"
57 #include "packet-frame.h"
59 #include <epan/prefs.h>
60 #include <epan/emem.h>
61 #include <epan/expert.h>
63 /* #define MAX_STR_LEN 256 */
65 static const value_string bgptypevals[] = {
66 { BGP_OPEN, "OPEN Message" },
67 { BGP_UPDATE, "UPDATE Message" },
68 { BGP_NOTIFICATION, "NOTIFICATION Message" },
69 { BGP_KEEPALIVE, "KEEPALIVE Message" },
70 { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
71 { BGP_CAPABILITY, "CAPABILITY Message" },
72 { BGP_ROUTE_REFRESH_CISCO, "Cisco ROUTE-REFRESH Message" },
76 static const value_string bgpnotify_major[] = {
77 { 1, "Message Header Error" },
78 { 2, "OPEN Message Error" },
79 { 3, "UPDATE Message Error" },
80 { 4, "Hold Timer Expired" },
81 { 5, "Finite State Machine Error" },
83 { 7, "CAPABILITY Message Error" },
87 static const value_string bgpnotify_minor_1[] = {
88 { 1, "Connection Not Synchronized" },
89 { 2, "Bad Message Length" },
90 { 3, "Bad Message Type" },
94 static const value_string bgpnotify_minor_2[] = {
95 { 1, "Unsupported Version Number" },
97 { 3, "Bad BGP Identifier" },
98 { 4, "Unsupported Optional Parameter" },
99 { 5, "Authentication Failure" },
100 { 6, "Unacceptable Hold Time" },
101 { 7, "Unsupported Capability" },
105 static const value_string bgpnotify_minor_3[] = {
106 { 1, "Malformed Attribute List" },
107 { 2, "Unrecognized Well-known Attribute" },
108 { 3, "Missing Well-known Attribute" },
109 { 4, "Attribute Flags Error" },
110 { 5, "Attribute Length Error" },
111 { 6, "Invalid ORIGIN Attribute" },
112 { 7, "AS Routing Loop" },
113 { 8, "Invalid NEXT_HOP Attribute" },
114 { 9, "Optional Attribute Error" },
115 { 10, "Invalid Network Field" },
116 { 11, "Malformed AS_PATH" },
120 /* draft-ietf-idr-cease-subcode-02 */
121 static const value_string bgpnotify_minor_6[] = {
122 { 1, "Maximum Number of Prefixes Reached"},
123 { 2, "Administratively Shutdown"},
124 { 3, "Peer Unconfigured"},
125 { 4, "Administratively Reset"},
126 { 5, "Connection Rejected"},
127 { 6, "Other Configuration Change"},
128 { 7, "Connection Collision Resolution"},
132 static const value_string bgpnotify_minor_7[] = {
133 { 1, "Invalid Action Value" },
134 { 2, "Invalid Capability Length" },
135 { 3, "Malformed Capability Value" },
136 { 4, "Unsupported Capability Code" },
140 static const value_string *bgpnotify_minor[] = {
142 bgpnotify_minor_1, /* open */
143 bgpnotify_minor_2, /* update */
144 bgpnotify_minor_3, /* notification */
145 NULL, /* hold-timer expired */
146 NULL, /* FSM error */
147 bgpnotify_minor_6, /* cease */
148 bgpnotify_minor_7 /* capability */
151 static const value_string bgpattr_origin[] = {
158 static const value_string bgp_open_opt_vals[] = {
159 { BGP_OPTION_AUTHENTICATION, "Authentication" },
160 { BGP_OPTION_CAPABILITY, "Capability" },
164 static const value_string as_segment_type[] = {
166 { 2, "AS_SEQUENCE" },
167 /* RFC1965 has the wrong values, corrected in */
168 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
169 { 4, "AS_CONFED_SET" },
170 { 3, "AS_CONFED_SEQUENCE" },
174 static const value_string bgpattr_type[] = {
175 { BGPTYPE_ORIGIN, "ORIGIN" },
176 { BGPTYPE_AS_PATH, "AS_PATH" },
177 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
178 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
179 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
180 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
181 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
182 { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
183 { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
184 { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
185 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
186 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
187 { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
188 { BGPTYPE_NEW_AS_PATH, "NEW_AS_PATH" },
189 { BGPTYPE_NEW_AGGREGATOR, "NEW_AGGREGATOR" },
190 { BGPTYPE_SAFI_SPECIFIC_ATTR, "SAFI_SPECIFIC_ATTRIBUTE" },
194 static const value_string bgpext_com8_type[] = {
195 { BGP_EXT_COM_QOS_MARK_T, "QoS Marking - transitive" },
196 { BGP_EXT_COM_QOS_MARK_NT, "QoS Marking - non-transitive" },
197 { BGP_EXT_COM_COS_CAP_T, "CoS Capability - transitive" },
201 static const value_string bgpext_com_type[] = {
202 { BGP_EXT_COM_RT_0, "two-octet AS specific Route Target" },
203 { BGP_EXT_COM_RT_1, "IPv4 address specific Route Target" },
204 { BGP_EXT_COM_RT_2, "four-octet AS specific Route Target" },
205 { BGP_EXT_COM_RO_0, "two-octet AS specific Route Origin" },
206 { BGP_EXT_COM_RO_1, "IPv4 address specific Route Origin" },
207 { BGP_EXT_COM_RO_2, "four-octet AS specific Route Origin" },
208 { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
209 { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
210 { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
211 { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
212 { BGP_EXT_COM_L2INFO, "Layer 2 Information" },
216 static const value_string qos_tech_type[] = {
217 { QOS_TECH_TYPE_DSCP, "DiffServ enabled IP (DSCP encoding)" },
218 { QOS_TECH_TYPE_802_1q, "Ethernet using 802.1q priority tag" },
219 { QOS_TECH_TYPE_E_LSP, "MPLS using E-LSP" },
220 { QOS_TECH_TYPE_VC, "Virtual Channel (VC) encoding" },
221 { QOS_TECH_TYPE_GMPLS_TIME, "GMPLS - time slot encoding" },
222 { QOS_TECH_TYPE_GMPLS_LAMBDA, "GMPLS - lambda encoding" },
223 { QOS_TECH_TYPE_GMPLS_FIBRE, "GMPLS - fibre encoding" },
227 static const value_string bgp_ssa_type[] = {
228 { BGP_SSA_L2TPv3 , "L2TPv3 Tunnel" },
229 { BGP_SSA_mGRE , "mGRE Tunnel" },
230 { BGP_SSA_IPSec , "IPSec Tunnel" },
231 { BGP_SSA_MPLS , "MPLS Tunnel" },
232 { BGP_SSA_L2TPv3_IN_IPSec , "L2TPv3 in IPSec Tunnel" },
233 { BGP_SSA_mGRE_IN_IPSec , "mGRE in IPSec Tunnel" },
237 static const value_string bgp_l2vpn_encaps[] = {
240 { 2, "ATM AAL5 VCC transport"},
241 { 3, "ATM transparent cell transport"},
242 { 4, "Ethernet VLAN"},
247 { 9, "ATM VCC cell transport"},
248 { 10, "ATM VPC cell transport"},
251 { 64, "IP-interworking"},
255 static const value_string bgpext_ospf_rtype[] = {
256 { BGP_OSPF_RTYPE_RTR, "Router" },
257 { BGP_OSPF_RTYPE_NET, "Network" },
258 { BGP_OSPF_RTYPE_SUM, "Summary" },
259 { BGP_OSPF_RTYPE_EXT, "External" },
260 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
261 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
265 /* Subsequent address family identifier, RFC2858 */
266 static const value_string bgpattr_nlri_safi[] = {
268 { SAFNUM_UNICAST, "Unicast" },
269 { SAFNUM_MULCAST, "Multicast" },
270 { SAFNUM_UNIMULC, "Unicast+Multicast" },
271 { SAFNUM_MPLS_LABEL, "Labeled Unicast"},
272 { SAFNUM_TUNNEL, "Tunnel"},
273 { SAFNUM_VPLS, "VPLS"},
274 { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */
275 { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
276 { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
280 /* ORF Type, draft-ietf-idr-route-filter-04.txt */
281 static const value_string orf_type_vals[] = {
282 { 2, "Communities ORF-Type" },
283 { 3, "Extended Communities ORF-Type" },
284 { 128, "Cisco PrefixList ORF-Type" },
285 { 129, "Cisco CommunityList ORF-Type" },
286 { 130, "Cisco Extended CommunityList ORF-Type" },
287 { 131, "Cisco AsPathList ORF-Type" },
291 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
292 static const value_string orf_send_recv_vals[] = {
299 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
300 static const value_string orf_when_vals[] = {
306 static const value_string orf_entry_action_vals[] = {
309 { 0x80, "RemoveAll" },
313 static const value_string orf_entry_match_vals[] = {
319 static const value_string capability_vals[] = {
320 { BGP_CAPABILITY_RESERVED, "Reserved capability" },
321 { BGP_CAPABILITY_MULTIPROTOCOL, "Multiprotocol extensions capability" },
322 { BGP_CAPABILITY_ROUTE_REFRESH, "Route refresh capability" },
323 { BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING, "Cooperative route filtering capability" },
324 { BGP_CAPABILITY_GRACEFUL_RESTART, "Graceful Restart capability" },
325 { BGP_CAPABILITY_4_OCTET_AS_NUMBER, "Support for 4-octet AS number capability" },
326 { BGP_CAPABILITY_DYNAMIC_CAPABILITY, "Support for Dynamic capability" },
327 { BGP_CAPABILITY_ADDITIONAL_PATHS, "Support for Additional Paths" },
328 { BGP_CAPABILITY_ROUTE_REFRESH_CISCO, "Route refresh capability" },
329 { BGP_CAPABILITY_ORF_CISCO, "Cooperative route filtering capability" },
333 /* Capability Message action code */
334 static const value_string bgpcap_action[] = {
335 { 0, "advertising a capability" },
336 { 1, "removing a capability" },
341 /* Maximal size of an IP address string */
342 #define MAX_SIZE_OF_IP_ADDR_STRING 16
344 static int proto_bgp = -1;
345 static int hf_bgp_marker = -1;
346 static int hf_bgp_length = -1;
347 static int hf_bgp_type = -1;
348 static int hf_bgp_open_version = -1;
349 static int hf_bgp_open_myas = -1;
350 static int hf_bgp_open_holdtime = -1;
351 static int hf_bgp_open_identifier = -1;
352 static int hf_bgp_open_opt_len = -1;
353 static int hf_bgp_open_opt_params = -1;
354 static int hf_bgp_open_opt_param = -1;
355 static int hf_bgp_open_opt_param_type = -1;
356 static int hf_bgp_open_opt_param_len = -1;
357 static int hf_bgp_open_opt_param_auth = -1;
358 static int hf_bgp_open_opt_param_unknown = -1;
359 static int hf_bgp_cap = -1;
360 static int hf_bgp_cap_type = -1;
361 static int hf_bgp_cap_length = -1;
362 static int hf_bgp_cap_action = -1;
363 static int hf_bgp_cap_unknown = -1;
364 static int hf_bgp_cap_reserved = -1;
365 static int hf_bgp_cap_mp_afi = -1;
366 static int hf_bgp_cap_mp_safi = -1;
367 static int hf_bgp_cap_gr_timers = -1;
368 static int hf_bgp_cap_gr_timers_restart_flag = -1;
369 static int hf_bgp_cap_gr_timers_restart_time = -1;
370 static int hf_bgp_cap_gr_afi = -1;
371 static int hf_bgp_cap_gr_safi = -1;
372 static int hf_bgp_cap_gr_flag = -1;
373 static int hf_bgp_cap_gr_flag_pfs = -1;
374 static int hf_bgp_cap_4as = -1;
375 static int hf_bgp_cap_dc = -1;
376 static int hf_bgp_cap_ap_afi = -1;
377 static int hf_bgp_cap_ap_safi = -1;
378 static int hf_bgp_cap_ap_sendreceive = -1;
379 static int hf_bgp_cap_orf_afi = -1;
380 static int hf_bgp_cap_orf_safi = -1;
381 static int hf_bgp_cap_orf_number = -1;
382 static int hf_bgp_cap_orf_type = -1;
383 static int hf_bgp_cap_orf_sendreceive = -1;
385 static int hf_bgp_next_hop = -1;
386 static int hf_bgp_as_path = -1;
387 static int hf_bgp_community_as = -1;
388 static int hf_bgp_community_value = -1;
389 static int hf_bgp_origin = -1;
390 static int hf_bgp_cluster_list = -1;
391 static int hf_bgp_originator_id = -1;
392 static int hf_bgp_ssa_t = -1;
393 static int hf_bgp_ssa_type = -1;
394 static int hf_bgp_ssa_len = -1;
395 static int hf_bgp_ssa_value = -1;
396 static int hf_bgp_ssa_l2tpv3_pref = -1;
397 static int hf_bgp_ssa_l2tpv3_s = -1;
398 static int hf_bgp_ssa_l2tpv3_unused = -1;
399 static int hf_bgp_ssa_l2tpv3_cookie_len = -1;
400 static int hf_bgp_ssa_l2tpv3_session_id = -1;
401 static int hf_bgp_ssa_l2tpv3_cookie = -1;
402 static int hf_bgp_local_pref = -1;
403 static int hf_bgp_multi_exit_disc = -1;
404 static int hf_bgp_aggregator_as = -1;
405 static int hf_bgp_aggregator_origin = -1;
406 static int hf_bgp_mp_reach_nlri_ipv4_prefix = -1;
407 static int hf_bgp_mp_unreach_nlri_ipv4_prefix = -1;
408 static int hf_bgp_mp_nlri_tnl_id = -1;
409 static int hf_bgp_withdrawn_prefix = -1;
410 static int hf_bgp_nlri_prefix = -1;
411 static int hf_bgp_nlri_path_id = -1;
413 static gint ett_bgp = -1;
414 static gint ett_bgp_prefix = -1;
415 static gint ett_bgp_unfeas = -1;
416 static gint ett_bgp_attrs = -1;
417 static gint ett_bgp_attr = -1;
418 static gint ett_bgp_attr_flags = -1;
419 static gint ett_bgp_mp_nhna = -1;
420 static gint ett_bgp_mp_reach_nlri = -1;
421 static gint ett_bgp_mp_unreach_nlri = -1;
422 static gint ett_bgp_mp_snpa = -1;
423 static gint ett_bgp_nlri = -1;
424 static gint ett_bgp_open = -1;
425 static gint ett_bgp_update = -1;
426 static gint ett_bgp_notification = -1;
427 static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
428 static gint ett_bgp_capability = -1;
429 static gint ett_bgp_as_paths = -1;
430 static gint ett_bgp_as_path_segments = -1;
431 static gint ett_bgp_communities = -1;
432 static gint ett_bgp_cluster_list = -1; /* cluster list tree */
433 static gint ett_bgp_options = -1; /* optional parameters tree */
434 static gint ett_bgp_option = -1; /* an optional parameter tree */
435 static gint ett_bgp_cap = -1; /* an cap parameter tree */
436 static gint ett_bgp_extended_communities = -1; /* extended communities list tree */
437 static gint ett_bgp_ext_com_flags = -1; /* extended communities flags tree */
438 static gint ett_bgp_ssa = -1; /* safi specific attribute */
439 static gint ett_bgp_ssa_subtree = -1; /* safi specific attribute Subtrees */
440 static gint ett_bgp_orf = -1; /* orf (outbound route filter) tree */
441 static gint ett_bgp_orf_entry = -1; /* orf entry tree */
444 static gboolean bgp_desegment = TRUE;
446 static gint bgp_asn_len = 0;
449 * Detect IPv4 prefixes conform to BGP Additional Path but NOT conform to standard BGP
451 * A real BGP speaker would rely on the BGP Additional Path in the BGP Open messages.
452 * But it is not suitable for a packet analyse because the BGP sessions are not supposed to
453 * restart very often, and Open messages from both sides of the session would be needed
454 * to determine the result of the capability negociation.
455 * Code inspired from the decode_prefix4 function
458 detect_add_path_prefix4(tvbuff_t *tvb, gint offset, gint end) {
462 /* Must be compatible with BGP Additional Path */
463 for (o = offset + 4; o < end; o += 4) {
464 prefix_len = tvb_get_guint8(tvb, o);
465 if( prefix_len > 32) {
466 return 0; /* invalid prefix lenght - not BGP add-path */
468 addr_len = (prefix_len + 7) / 8;
471 return 0; /* invalid offset - not BGP add-path */
473 if (prefix_len % 8) {
474 /* detect bits set after the end of the prefix */
475 if( tvb_get_guint8(tvb, o - 1 ) & (0xFF >> (prefix_len % 8)) ) {
476 return 0; /* invalid prefix content - not BGP add-path */
480 /* Must NOT be compatible with standard BGP */
481 for (o = offset; o < end; ) {
482 prefix_len = tvb_get_guint8(tvb, o);
483 if( prefix_len > 32) {
484 return 1; /* invalid prefix lenght - may be BGP add-path */
486 addr_len = (prefix_len + 7) / 8;
489 return 1; /* invalid offset - may be BGP add-path */
491 if (prefix_len % 8) {
492 /* detect bits set after the end of the prefix */
493 if( tvb_get_guint8(tvb, o - 1 ) & (0xFF >> (prefix_len % 8)) ) {
494 return 1; /* invalid prefix content - may be BGP add-path (or a bug) */
498 return 0; /* valid - do not assume Additional Path */
501 * Decode an IPv4 prefix with Path Identifier
502 * Code inspired from the decode_prefix4 function
505 decode_path_prefix4(proto_tree *tree, int hf_path_id, int hf_addr, tvbuff_t *tvb, gint offset,
509 proto_tree *prefix_tree;
511 guint8 addr_bytes[4];
513 } ip_addr; /* IP address */
514 guint8 plen; /* prefix length */
515 int length; /* number of octets needed for prefix */
516 guint32 path_identifier;
517 /* snarf path identifier length and prefix */
518 path_identifier = tvb_get_ntohl(tvb, offset);
519 plen = tvb_get_guint8(tvb, offset + 4);
520 length = ipv4_addr_and_mask(tvb, offset + 4 + 1, ip_addr.addr_bytes, plen);
522 proto_tree_add_text(tree, tvb, offset + 4 , 1, "%s length %u invalid (> 32)",
526 /* put prefix into protocol tree */
527 ti = proto_tree_add_text(tree, tvb, offset,
528 4 + 1 + length, "%s/%u PathId %u ",
529 ip_to_str(ip_addr.addr_bytes), plen, path_identifier);
530 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
531 if (hf_path_id != -1) {
532 proto_tree_add_uint(prefix_tree, hf_path_id, tvb, offset, 4,
535 proto_tree_add_text(prefix_tree, tvb, offset, 4,
536 "%s Path Id: %u", tag, path_identifier);
538 proto_tree_add_text(prefix_tree, tvb, offset + 4, 1, "%s prefix length: %u",
541 proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 4 + 1, length,
544 proto_tree_add_text(prefix_tree, tvb, offset + 4 + 1, length,
545 "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
547 return(4 + 1 + length);
551 * Decode an IPv4 prefix.
554 decode_prefix4(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
555 guint16 tlen, const char *tag)
558 proto_tree *prefix_tree;
560 guint8 addr_bytes[4];
562 } ip_addr; /* IP address */
563 guint8 plen; /* prefix length */
564 int length; /* number of octets needed for prefix */
566 /* snarf length and prefix */
567 plen = tvb_get_guint8(tvb, offset);
568 length = ipv4_addr_and_mask(tvb, offset + 1, ip_addr.addr_bytes, plen);
570 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid (> 32)",
575 /* put prefix into protocol tree */
576 ti = proto_tree_add_text(tree, tvb, offset,
577 tlen != 0 ? tlen : 1 + length, "%s/%u",
578 ip_to_str(ip_addr.addr_bytes), plen);
579 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
580 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
583 proto_tree_add_ipv4(prefix_tree, hf_addr, tvb, offset + 1, length,
586 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
587 "%s prefix: %s", tag, ip_to_str(ip_addr.addr_bytes));
593 * Decode an IPv6 prefix.
596 decode_prefix6(proto_tree *tree, int hf_addr, tvbuff_t *tvb, gint offset,
597 guint16 tlen, const char *tag)
600 proto_tree *prefix_tree;
601 struct e_in6_addr addr; /* IPv6 address */
602 int plen; /* prefix length */
603 int length; /* number of octets needed for prefix */
605 /* snarf length and prefix */
606 plen = tvb_get_guint8(tvb, offset);
607 length = ipv6_addr_and_mask(tvb, offset + 1, &addr, plen);
609 proto_tree_add_text(tree, tvb, offset, 1, "%s length %u invalid",
614 /* put prefix into protocol tree */
615 ti = proto_tree_add_text(tree, tvb, offset,
616 tlen != 0 ? tlen : 1 + length, "%s/%u",
617 ip6_to_str(&addr), plen);
618 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
619 proto_tree_add_text(prefix_tree, tvb, offset, 1, "%s prefix length: %u",
622 proto_tree_add_ipv6(prefix_tree, hf_addr, tvb, offset + 1, length,
625 proto_tree_add_text(prefix_tree, tvb, offset + 1, length,
626 "%s prefix: %s", tag, ip6_to_str(&addr));
634 * Decode an MPLS label stack
635 * XXX - We should change *buf to **buf, use ep_alloc() and drop the buflen
639 decode_MPLS_stack(tvbuff_t *tvb, gint offset, emem_strbuf_t *stack_strbuf)
641 guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
642 gint indx; /* index for the label stack */
645 label_entry = 0x000000 ;
647 ep_strbuf_truncate(stack_strbuf, 0);
649 while ((label_entry & 0x000001) == 0) {
651 label_entry = tvb_get_ntoh24(tvb, indx) ;
653 /* withdrawn routes may contain 0 or 0x800000 in the first label */
654 if((indx-offset)==0&&(label_entry==0||label_entry==0x800000)) {
655 ep_strbuf_append(stack_strbuf, "0 (withdrawn)");
659 ep_strbuf_append_printf(stack_strbuf, "%u%s", label_entry >> 4,
660 ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
664 if ((label_entry & 0x000001) == 0) {
665 /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
666 ep_strbuf_append(stack_strbuf, " (BOGUS: Bottom of Stack NOT set!)");
671 return((indx - offset) / 3);
675 * Decode a multiprotocol address
679 mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, emem_strbuf_t *strbuf)
681 int length; /* length of the address in byte */
682 guint32 ip4addr,ip4addr2; /* IPv4 address */
683 guint16 rd_type; /* Route Distinguisher type */
684 struct e_in6_addr ip6addr; /* IPv6 address */
692 case SAFNUM_MPLS_LABEL:
695 ip4addr = tvb_get_ipv4(tvb, offset);
696 ep_strbuf_append(strbuf, ip_to_str((guint8 *)&ip4addr));
698 case SAFNUM_LAB_VPNUNICAST:
699 case SAFNUM_LAB_VPNMULCAST:
700 case SAFNUM_LAB_VPNUNIMULC:
701 rd_type=tvb_get_ntohs(tvb,offset) ;
704 length = 8 + sizeof(ip4addr);
705 ip4addr = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
706 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%u:%u IPv4=%s",
707 tvb_get_ntohs(tvb, offset + 2),
708 tvb_get_ntohl(tvb, offset + 4),
709 ip_to_str((guint8 *)&ip4addr));
712 length = 8 + sizeof(ip4addr);
713 ip4addr = tvb_get_ipv4(tvb, offset + 2); /* IP part of the RD */
714 ip4addr2 = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
715 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%s:%u IPv4=%s",
716 ip_to_str((guint8 *)&ip4addr),
717 tvb_get_ntohs(tvb, offset + 6),
718 ip_to_str((guint8 *)&ip4addr2));
721 length = 8 + sizeof(ip4addr);
722 ip4addr = tvb_get_ipv4(tvb, offset + 8); /* Next Hop */
723 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%u.%u:%u IPv4=%s",
724 tvb_get_ntohs(tvb, offset + 2),
725 tvb_get_ntohs(tvb, offset + 4),
726 tvb_get_ntohs(tvb, offset + 6),
727 ip_to_str((guint8 *)&ip4addr));
731 ep_strbuf_printf(strbuf, "Unknown (0x%04x) labeled VPN IPv4 address format",rd_type);
733 } /* switch (rd_type) */
737 ep_strbuf_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
739 } /* switch (safi) */
746 case SAFNUM_MPLS_LABEL:
749 tvb_get_ipv6(tvb, offset, &ip6addr);
750 ep_strbuf_printf(strbuf, "%s", ip6_to_str(&ip6addr));
752 case SAFNUM_LAB_VPNUNICAST:
753 case SAFNUM_LAB_VPNMULCAST:
754 case SAFNUM_LAB_VPNUNIMULC:
755 rd_type=tvb_get_ntohs(tvb,offset) ;
759 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
760 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%u:%u IPv6=%s",
761 tvb_get_ntohs(tvb, offset + 2),
762 tvb_get_ntohl(tvb, offset + 4),
763 ip6_to_str(&ip6addr));
767 ip4addr = tvb_get_ipv4(tvb, offset + 2); /* IP part of the RD */
768 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
769 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%s:%u IPv6=%s",
770 ip_to_str((guint8 *)&ip4addr),
771 tvb_get_ntohs(tvb, offset + 6),
772 ip6_to_str(&ip6addr));
776 tvb_get_ipv6(tvb, offset + 8, &ip6addr); /* Next Hop */
777 ep_strbuf_printf(strbuf, "Empty Label Stack RD=%u:%u IPv6=%s",
778 tvb_get_ntohl(tvb, offset + 2),
779 tvb_get_ntohs(tvb, offset + 6),
780 ip6_to_str(&ip6addr));
784 ep_strbuf_printf(strbuf, "Unknown (0x%04x) labeled VPN IPv6 address format",rd_type);
786 } /* switch (rd_type) */
790 ep_strbuf_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
792 } /* switch (safi) */
795 case AFNUM_L2VPN_OLD:
797 case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
798 case SAFNUM_LAB_VPNMULCAST:
799 case SAFNUM_LAB_VPNUNIMULC:
801 length = 4; /* the next-hop is simply an ipv4 addr */
802 ip4addr = tvb_get_ipv4(tvb, offset + 0);
803 ep_strbuf_printf(strbuf, "IPv4=%s",
804 ip_to_str((guint8 *)&ip4addr));
808 ep_strbuf_printf(strbuf, "Unknown SAFI (%u) for AFI %u", safi, afi);
810 } /* switch (safi) */
814 ep_strbuf_printf(strbuf, "Unknown AFI (%u) value", afi);
821 * Decode a multiprotocol prefix
824 decode_prefix_MP(proto_tree *tree, int hf_addr4, int hf_addr6,
825 guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset,
828 int start_offset = offset;
830 proto_tree *prefix_tree;
831 int total_length; /* length of the entire item */
832 int length; /* length of the prefix address, in bytes */
833 guint plen; /* length of the prefix address, in bits */
834 guint labnum; /* number of labels */
835 guint16 tnl_id; /* Tunnel Identifier */
836 int ce_id,labblk_off,labblk_size;
838 guint8 addr_bytes[4];
840 } ip4addr, ip4addr2; /* IPv4 address */
841 struct e_in6_addr ip6addr; /* IPv6 address */
842 guint16 rd_type; /* Route Distinguisher type */
843 emem_strbuf_t *stack_strbuf; /* label stack */
853 total_length = decode_prefix4(tree, hf_addr4, tvb, offset, 0, tag);
854 if (total_length < 0)
858 case SAFNUM_MPLS_LABEL:
859 plen = tvb_get_guint8(tvb, offset);
860 stack_strbuf = ep_strbuf_new_label(NULL);
861 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
863 offset += (1 + labnum * 3);
864 if (plen <= (labnum * 3*8)) {
865 proto_tree_add_text(tree, tvb, start_offset, 1,
866 "%s Labeled IPv4 prefix length %u invalid",
870 plen -= (labnum * 3*8);
871 length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
873 proto_tree_add_text(tree, tvb, start_offset, 1,
874 "%s Labeled IPv4 prefix length %u invalid",
875 tag, plen + (labnum * 3*8));
879 ti = proto_tree_add_text(tree, tvb, start_offset,
880 (offset + length) - start_offset,
881 "Label Stack=%s IPv4=%s/%u",
882 stack_strbuf->str, ip_to_str(ip4addr.addr_bytes), plen);
883 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
884 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
885 tag, plen + labnum * 3 * 8);
886 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum, "%s Label Stack: %s",
887 tag, stack_strbuf->str);
888 if (hf_addr4 != -1) {
889 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset,
890 length, ip4addr.addr);
892 proto_tree_add_text(prefix_tree, tvb, offset, length,
893 "%s IPv4 prefix: %s",
894 tag, ip_to_str(ip4addr.addr_bytes));
896 total_length = (1 + labnum*3) + length;
900 plen = tvb_get_guint8(tvb, offset);
902 proto_tree_add_text(tree, tvb, start_offset, 1,
903 "%s Tunnel IPv4 prefix length %u invalid",
907 tnl_id = tvb_get_ntohs(tvb, offset + 1);
908 offset += 3; /* Length + Tunnel Id */
909 plen -= 16; /* 2-octet Identifier */
910 length = ipv4_addr_and_mask(tvb, offset, ip4addr.addr_bytes, plen);
912 proto_tree_add_text(tree, tvb, start_offset, 1,
913 "%s Tunnel IPv4 prefix length %u invalid",
917 ti = proto_tree_add_text(tree, tvb, start_offset,
918 (offset + length) - start_offset,
919 "Tunnel Identifier=0x%x IPv4=%s/%u",
920 tnl_id, ip_to_str(ip4addr.addr_bytes), plen);
921 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
923 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
925 proto_tree_add_item(prefix_tree, hf_bgp_mp_nlri_tnl_id, tvb,
926 start_offset + 1, 2, ENC_BIG_ENDIAN);
927 if (hf_addr4 != -1) {
928 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb, offset,
929 length, ip4addr.addr);
931 proto_tree_add_text(prefix_tree, tvb, offset, length,
932 "%s IPv4 prefix: %s",
933 tag, ip_to_str(ip4addr.addr_bytes));
935 total_length = 1 + 2 + length; /* length field + Tunnel Id + IPv4 len */
938 case SAFNUM_LAB_VPNUNICAST:
939 case SAFNUM_LAB_VPNMULCAST:
940 case SAFNUM_LAB_VPNUNIMULC:
941 plen = tvb_get_guint8(tvb, offset);
942 stack_strbuf = ep_strbuf_new_label(NULL);
943 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
945 offset += (1 + labnum * 3);
946 if (plen <= (labnum * 3*8)) {
947 proto_tree_add_text(tree, tvb, start_offset, 1,
948 "%s Labeled VPN IPv4 prefix length %u invalid",
952 plen -= (labnum * 3*8);
954 rd_type = tvb_get_ntohs(tvb, offset);
956 proto_tree_add_text(tree, tvb, start_offset, 1,
957 "%s Labeled VPN IPv4 prefix length %u invalid",
958 tag, plen + (labnum * 3*8));
965 case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
966 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr.addr_bytes, plen);
968 proto_tree_add_text(tree, tvb, start_offset, 1,
969 "%s Labeled VPN IPv4 prefix length %u invalid",
970 tag, plen + (labnum * 3*8) + 8*8);
974 ti = proto_tree_add_text(tree, tvb, start_offset,
975 (offset + 8 + length) - start_offset,
976 "Label Stack=%s RD=%u:%u, IPv4=%s/%u",
978 tvb_get_ntohs(tvb, offset + 2),
979 tvb_get_ntohl(tvb, offset + 4),
980 ip_to_str(ip4addr.addr_bytes), plen);
981 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
982 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
983 tag, plen + labnum * 3 * 8 + 8 * 8);
984 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
985 "%s Label Stack: %s", tag, stack_strbuf->str);
986 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
987 "%s Route Distinguisher: %u:%u", tag, tvb_get_ntohs(tvb, offset + 2),
988 tvb_get_ntohl(tvb, offset + 4));
989 if (hf_addr4 != -1) {
990 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
991 offset + 8, length, ip4addr.addr);
993 proto_tree_add_text(prefix_tree, tvb, offset + 8,
994 length, "%s IPv4 prefix: %s", tag,
995 ip_to_str(ip4addr.addr_bytes));
997 total_length = (1 + labnum * 3 + 8) + length;
1000 case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
1001 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
1003 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr2.addr_bytes, plen);
1005 proto_tree_add_text(tree, tvb, start_offset, 1,
1006 "%s Labeled VPN IPv4 prefix length %u invalid",
1007 tag, plen + (labnum * 3*8) + 8*8);
1011 ti = proto_tree_add_text(tree, tvb, start_offset,
1012 (offset + 8 + length) - start_offset,
1013 "Label Stack=%s RD=%s:%u, IPv4=%s/%u",
1015 ip_to_str(ip4addr.addr_bytes),
1016 tvb_get_ntohs(tvb, offset + 6),
1017 ip_to_str(ip4addr2.addr_bytes),
1019 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
1020 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
1021 tag, plen + labnum * 3 * 8 + 8 * 8);
1022 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
1023 "%s Label Stack: %s", tag, stack_strbuf->str);
1024 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
1025 "%s Route Distinguisher: %s:%u", tag, ip_to_str(ip4addr.addr_bytes),
1026 tvb_get_ntohs(tvb, offset + 6));
1027 if (hf_addr4 != -1) {
1028 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
1029 offset + 8, length, ip4addr2.addr);
1031 proto_tree_add_text(prefix_tree, tvb, offset + 8,
1032 length, "%s IPv4 prefix: %s", tag,
1033 ip_to_str(ip4addr2.addr_bytes));
1035 total_length = (1 + labnum * 3 + 8) + length;
1038 case FORMAT_AS4_LOC: /* Code borrowed from the decode_prefix4 function */
1039 length = ipv4_addr_and_mask(tvb, offset + 8, ip4addr.addr_bytes, plen);
1041 proto_tree_add_text(tree, tvb, start_offset, 1,
1042 "%s Labeled VPN IPv4 prefix length %u invalid",
1043 tag, plen + (labnum * 3*8) + 8*8);
1047 ti = proto_tree_add_text(tree, tvb, start_offset,
1048 (offset + 8 + length) - start_offset,
1049 "Label Stack=%s RD=%u.%u:%u, IPv4=%s/%u",
1051 tvb_get_ntohs(tvb, offset + 2),
1052 tvb_get_ntohs(tvb, offset + 4),
1053 tvb_get_ntohs(tvb, offset + 6),
1054 ip_to_str(ip4addr.addr_bytes), plen);
1055 prefix_tree = proto_item_add_subtree(ti, ett_bgp_prefix);
1056 proto_tree_add_text(prefix_tree, tvb, start_offset, 1, "%s Prefix length: %u",
1057 tag, plen + labnum * 3 * 8 + 8 * 8);
1058 proto_tree_add_text(prefix_tree, tvb, start_offset + 1, 3 * labnum,
1059 "%s Label Stack: %s", tag, stack_strbuf->str);
1060 proto_tree_add_text(prefix_tree, tvb, start_offset + 1 + 3 * labnum, 8,
1061 "%s Route Distinguisher: %u.%u:%u", tag, tvb_get_ntohs(tvb, offset + 2),
1062 tvb_get_ntohs(tvb, offset + 4), tvb_get_ntohs(tvb, offset + 6));
1063 if (hf_addr4 != -1) {
1064 proto_tree_add_ipv4(prefix_tree, hf_addr4, tvb,
1065 offset + 8, length, ip4addr.addr);
1067 proto_tree_add_text(prefix_tree, tvb, offset + 8,
1068 length, "%s IPv4 prefix: %s", tag,
1069 ip_to_str(ip4addr.addr_bytes));
1071 total_length = (1 + labnum * 3 + 8) + length;
1075 proto_tree_add_text(tree, tvb, start_offset,
1076 (offset - start_offset) + 2,
1077 "Unknown labeled VPN IPv4 address format %u", rd_type);
1079 } /* switch (rd_type) */
1083 proto_tree_add_text(tree, tvb, start_offset, 0,
1084 "Unknown SAFI (%u) for AFI %u", safi, afi);
1086 } /* switch (safi) */
1092 case SAFNUM_UNICAST:
1093 case SAFNUM_MULCAST:
1094 case SAFNUM_UNIMULC:
1095 total_length = decode_prefix6(tree, hf_addr6, tvb, offset, 0, tag);
1096 if (total_length < 0)
1100 case SAFNUM_MPLS_LABEL:
1101 plen = tvb_get_guint8(tvb, offset);
1102 stack_strbuf = ep_strbuf_new_label(NULL);
1103 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
1105 offset += (1 + labnum * 3);
1106 if (plen <= (labnum * 3*8)) {
1107 proto_tree_add_text(tree, tvb, start_offset, 1,
1108 "%s Labeled IPv6 prefix length %u invalid", tag, plen);
1111 plen -= (labnum * 3*8);
1113 length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
1115 proto_tree_add_text(tree, tvb, start_offset, 1,
1116 "%s Labeled IPv6 prefix length %u invalid",
1117 tag, plen + (labnum * 3*8));
1121 proto_tree_add_text(tree, tvb, start_offset,
1122 (offset + length) - start_offset,
1123 "Label Stack=%s, IPv6=%s/%u",
1125 ip6_to_str(&ip6addr), plen);
1126 total_length = (1 + labnum * 3) + length;
1130 plen = tvb_get_guint8(tvb, offset);
1132 proto_tree_add_text(tree, tvb, start_offset, 1,
1133 "%s Tunnel IPv6 prefix length %u invalid",
1137 tnl_id = tvb_get_ntohs(tvb, offset + 1);
1138 offset += 3; /* Length + Tunnel Id */
1139 plen -= 16; /* 2-octet Identifier */
1140 length = ipv6_addr_and_mask(tvb, offset, &ip6addr, plen);
1142 proto_tree_add_text(tree, tvb, start_offset, 1,
1143 "%s Tunnel IPv6 prefix length %u invalid",
1147 proto_tree_add_text(tree, tvb, start_offset,
1148 (offset + length) - start_offset,
1149 "Tunnel Identifier=0x%x IPv6=%s/%u",
1150 tnl_id, ip6_to_str(&ip6addr), plen);
1151 total_length = (1 + 2) + length; /* length field + Tunnel Id + IPv4 len */
1154 case SAFNUM_LAB_VPNUNICAST:
1155 case SAFNUM_LAB_VPNMULCAST:
1156 case SAFNUM_LAB_VPNUNIMULC:
1157 plen = tvb_get_guint8(tvb, offset);
1158 stack_strbuf = ep_strbuf_new_label(NULL);
1159 labnum = decode_MPLS_stack(tvb, offset + 1, stack_strbuf);
1161 offset += (1 + labnum * 3);
1162 if (plen <= (labnum * 3*8)) {
1163 proto_tree_add_text(tree, tvb, start_offset, 1,
1164 "%s Labeled VPN IPv6 prefix length %u invalid", tag, plen);
1167 plen -= (labnum * 3*8);
1169 rd_type = tvb_get_ntohs(tvb,offset);
1171 proto_tree_add_text(tree, tvb, start_offset, 1,
1172 "%s Labeled VPN IPv6 prefix length %u invalid",
1173 tag, plen + (labnum * 3*8));
1180 case FORMAT_AS2_LOC:
1181 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
1183 proto_tree_add_text(tree, tvb, start_offset, 1,
1184 "%s Labeled VPN IPv6 prefix length %u invalid",
1185 tag, plen + (labnum * 3*8) + 8*8);
1189 proto_tree_add_text(tree, tvb, start_offset,
1190 (offset + 8 + length) - start_offset,
1191 "Label Stack=%s RD=%u:%u, IPv6=%s/%u",
1193 tvb_get_ntohs(tvb, offset + 2),
1194 tvb_get_ntohl(tvb, offset + 4),
1195 ip6_to_str(&ip6addr), plen);
1196 total_length = (1 + labnum * 3 + 8) + length;
1200 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 2, 4);
1202 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
1204 proto_tree_add_text(tree, tvb, start_offset, 1,
1205 "%s Labeled VPN IPv6 prefix length %u invalid",
1206 tag, plen + (labnum * 3*8) + 8*8);
1210 proto_tree_add_text(tree, tvb, start_offset,
1211 (offset + 8 + length) - start_offset,
1212 "Label Stack=%s RD=%s:%u, IPv6=%s/%u",
1214 ip_to_str(ip4addr.addr_bytes),
1215 tvb_get_ntohs(tvb, offset + 6),
1216 ip6_to_str(&ip6addr), plen);
1217 total_length = (1 + labnum * 3 + 8) + length;
1220 case FORMAT_AS4_LOC:
1221 length = ipv6_addr_and_mask(tvb, offset + 8, &ip6addr, plen);
1223 proto_tree_add_text(tree, tvb, start_offset, 1,
1224 "%s Labeled VPN IPv6 prefix length %u invalid",
1225 tag, plen + (labnum * 3*8) + 8*8);
1229 proto_tree_add_text(tree, tvb, start_offset,
1230 (offset + 8 + length) - start_offset,
1231 "Label Stack=%s RD=%u.%u:%u, IPv6=%s/%u",
1233 tvb_get_ntohs(tvb, offset + 2),
1234 tvb_get_ntohs(tvb, offset + 4),
1235 tvb_get_ntohs(tvb, offset + 6),
1236 ip6_to_str(&ip6addr), plen);
1237 total_length = (1 + labnum * 3 + 8) + length;
1240 proto_tree_add_text(tree, tvb, start_offset, 0,
1241 "Unknown labeled VPN IPv6 address format %u", rd_type);
1243 } /* switch (rd_type) */
1247 proto_tree_add_text(tree, tvb, start_offset, 0,
1248 "Unknown SAFI (%u) for AFI %u", safi, afi);
1250 } /* switch (safi) */
1254 case AFNUM_L2VPN_OLD:
1257 case SAFNUM_LAB_VPNUNICAST:
1258 case SAFNUM_LAB_VPNMULCAST:
1259 case SAFNUM_LAB_VPNUNIMULC:
1261 plen = tvb_get_ntohs(tvb,offset);
1262 rd_type=tvb_get_ntohs(tvb,offset+2);
1264 /* RFC6074 Section 7 BGP-AD and VPLS-BGP Interoperability
1265 Both BGP-AD and VPLS-BGP [RFC4761] use the same AFI/SAFI. In order
1266 for both BGP-AD and VPLS-BGP to co-exist, the NLRI length must be
1267 used as a demultiplexer.
1269 The BGP-AD NLRI has an NLRI length of 12 bytes, containing only an
1270 8-byte RD and a 4-byte VSI-ID. VPLS-BGP [RFC4761] uses a 17-byte
1271 NLRI length. Therefore, implementations of BGP-AD must ignore NLRI
1272 that are greater than 12 bytes.
1274 if(plen == 12) /* BGP-AD */
1278 case FORMAT_AS2_LOC:
1279 proto_tree_add_text(tree, tvb, start_offset,
1280 (offset + plen + 2) - start_offset,
1281 "RD: %u:%u, PE_addr: %s",
1282 tvb_get_ntohs(tvb, offset + 4),
1283 tvb_get_ntohl(tvb, offset + 6),
1284 tvb_ip_to_str(tvb, offset + 10));
1288 proto_tree_add_text(tree, tvb, offset,
1289 (offset + plen + 2) - start_offset,
1290 "RD: %s:%u, PE_addr: %s",
1291 tvb_ip_to_str(tvb, offset + 10),
1292 tvb_get_ntohs(tvb, offset + 8),
1293 tvb_ip_to_str(tvb, offset + 10));
1295 case FORMAT_AS4_LOC:
1296 proto_tree_add_text(tree, tvb, start_offset,
1297 (offset + plen + 2) - start_offset,
1298 "RD: %u.%u:%u, PE_addr: %s",
1299 tvb_get_ntohs(tvb, offset + 4),
1300 tvb_get_ntohs(tvb, offset + 6),
1301 tvb_get_ntohs(tvb, offset + 8),
1302 tvb_ip_to_str(tvb, offset + 10));
1305 proto_tree_add_text(tree, tvb, start_offset,
1306 (offset - start_offset) + 2,
1307 "Unknown labeled VPN address format %u", rd_type);
1309 } /* switch (rd_type) */
1310 }else{ /* VPLS-BGP */
1311 ce_id=tvb_get_ntohs(tvb,offset+10);
1312 labblk_off=tvb_get_ntohs(tvb,offset+12);
1313 labblk_size=tvb_get_ntohs(tvb,offset+14);
1314 stack_strbuf = ep_strbuf_new_label(NULL);
1315 decode_MPLS_stack(tvb, offset + 16, stack_strbuf);
1318 case FORMAT_AS2_LOC:
1319 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 6, 4);
1320 proto_tree_add_text(tree, tvb, start_offset,
1321 (offset + plen + 1) - start_offset,
1322 "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, "
1323 "Label-Block Size: %u Label Base %s",
1324 tvb_get_ntohs(tvb, offset + 4),
1325 ip_to_str(ip4addr.addr_bytes),
1333 tvb_memcpy(tvb, ip4addr.addr_bytes, offset + 4, 4);
1334 proto_tree_add_text(tree, tvb, offset,
1335 (offset + plen + 1) - start_offset,
1336 "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, "
1337 "Label-Block Size: %u, Label Base %s",
1338 ip_to_str(ip4addr.addr_bytes),
1339 tvb_get_ntohs(tvb, offset + 8),
1345 case FORMAT_AS4_LOC:
1346 proto_tree_add_text(tree, tvb, offset,
1347 (offset + plen + 1) - start_offset,
1348 "RD: %u.%u:%u, CE-ID: %u, Label-Block Offset: %u, "
1349 "Label-Block Size: %u, Label Base %s",
1350 tvb_get_ntohs(tvb, offset + 4),
1351 tvb_get_ntohs(tvb, offset + 6),
1352 tvb_get_ntohs(tvb, offset + 8),
1359 proto_tree_add_text(tree, tvb, start_offset,
1360 (offset - start_offset) + 2,
1361 "Unknown labeled VPN address format %u", rd_type);
1363 } /* switch (rd_type) */
1365 /* FIXME there are subTLVs left to decode ... for now lets omit them */
1366 total_length = plen+2;
1370 proto_tree_add_text(tree, tvb, start_offset, 0,
1371 "Unknown SAFI (%u) for AFI %u", safi, afi);
1373 } /* switch (safi) */
1377 proto_tree_add_text(tree, tvb, start_offset, 0,
1378 "Unknown AFI (%u) value", afi);
1380 } /* switch (afi) */
1381 return(total_length);
1385 * Dissect a BGP capability.
1388 dissect_bgp_capability_item(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, gboolean action)
1390 proto_tree *cap_tree;
1396 ti = proto_tree_add_item(tree, hf_bgp_cap, tvb, offset, -1, ENC_NA);
1397 cap_tree = proto_item_add_subtree(ti, ett_bgp_cap);
1399 proto_tree_add_item(cap_tree, hf_bgp_cap_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1400 ctype = tvb_get_guint8(tvb, offset);
1401 proto_item_append_text(ti, ": %s", val_to_str(ctype, capability_vals, "Unknown capability %d"));
1404 ti_len = proto_tree_add_item(cap_tree, hf_bgp_cap_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1405 clen = tvb_get_guint8(tvb, offset);
1406 proto_item_set_len(ti, clen+2);
1410 proto_tree_add_item(cap_tree, hf_bgp_cap_action, tvb, offset, 1, ENC_BIG_ENDIAN);
1411 proto_item_set_len(ti, clen+3);
1415 /* check the capability type */
1417 case BGP_CAPABILITY_RESERVED:
1419 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u wrong, must be = 0", clen);
1420 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1424 case BGP_CAPABILITY_MULTIPROTOCOL:
1426 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u is wrong, must be = 4", clen);
1427 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1432 proto_tree_add_item(cap_tree, hf_bgp_cap_mp_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
1436 proto_tree_add_item(cap_tree, hf_bgp_cap_reserved, tvb, offset, 1, ENC_NA);
1440 proto_tree_add_item(cap_tree, hf_bgp_cap_mp_safi, tvb, offset, 1, ENC_NA);
1445 case BGP_CAPABILITY_GRACEFUL_RESTART:
1447 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u too short, must be greater than 6", clen);
1448 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1452 int eclen = offset + clen;
1453 proto_tree *sub_tree;
1456 ti = proto_tree_add_item(cap_tree, hf_bgp_cap_gr_timers, tvb, offset, 2, ENC_NA);
1457 sub_tree = proto_item_add_subtree(ti, ett_bgp_cap);
1458 proto_tree_add_item(sub_tree, hf_bgp_cap_gr_timers_restart_flag, tvb, offset, 2, ENC_BIG_ENDIAN);
1459 proto_tree_add_item(sub_tree, hf_bgp_cap_gr_timers_restart_time, tvb, offset, 2, ENC_BIG_ENDIAN);
1463 * what follows is alist of AFI/SAFI/flag triplets
1464 * read it until the TLV ends
1466 while (offset < eclen) {
1468 proto_tree_add_item(cap_tree, hf_bgp_cap_gr_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
1472 proto_tree_add_item(cap_tree, hf_bgp_cap_gr_safi, tvb, offset, 1, ENC_BIG_ENDIAN);
1476 ti = proto_tree_add_item(cap_tree, hf_bgp_cap_gr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1477 sub_tree = proto_item_add_subtree(ti, ett_bgp_cap);
1478 proto_tree_add_item(sub_tree, hf_bgp_cap_gr_flag_pfs, tvb, offset, 1, ENC_BIG_ENDIAN);
1483 case BGP_CAPABILITY_4_OCTET_AS_NUMBER:
1485 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u is wrong, must be = 4", clen);
1486 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1490 proto_tree_add_item(cap_tree, hf_bgp_cap_4as, tvb, offset, 4, ENC_BIG_ENDIAN);
1494 case BGP_CAPABILITY_DYNAMIC_CAPABILITY:
1496 int eclen = offset + clen;
1498 while (offset < eclen) {
1499 proto_tree_add_item(cap_tree, hf_bgp_cap_dc, tvb, offset, 1, ENC_BIG_ENDIAN);
1504 case BGP_CAPABILITY_ADDITIONAL_PATHS:
1506 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u is wrong, must be = 4", clen);
1507 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1510 else { /* AFI SAFI Send-receive*/
1512 proto_tree_add_item(cap_tree, hf_bgp_cap_ap_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
1516 proto_tree_add_item(cap_tree, hf_bgp_cap_ap_safi, tvb, offset, 1, ENC_BIG_ENDIAN);
1520 proto_tree_add_item(cap_tree, hf_bgp_cap_ap_sendreceive, tvb, offset, 1, ENC_BIG_ENDIAN);
1526 case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
1527 case BGP_CAPABILITY_ROUTE_REFRESH:
1529 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u wrong, must be = 0", clen);
1530 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1534 case BGP_CAPABILITY_ORF_CISCO:
1535 case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
1537 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Capability length %u too short, must be greater than 6", clen);
1538 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1542 guint8 orfnum; /* number of ORFs */
1545 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
1549 proto_tree_add_item(cap_tree, hf_bgp_cap_reserved, tvb, offset, 1, ENC_NA);
1553 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_safi, tvb, offset, 1, ENC_BIG_ENDIAN);
1556 /* Number of ORFs */
1557 orfnum = tvb_get_guint8(tvb, offset);
1558 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1560 for (i=0; i<orfnum; i++) {
1562 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1566 proto_tree_add_item(cap_tree, hf_bgp_cap_orf_sendreceive, tvb, offset, 1, ENC_BIG_ENDIAN);
1572 /* unknown capability */
1575 proto_tree_add_item(cap_tree, hf_bgp_cap_unknown, tvb, offset, clen, ENC_NA);
1579 } /* switch (ctype) */
1584 * Dissect a BGP OPEN message.
1586 static const value_string community_vals[] = {
1587 { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
1588 { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
1589 { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
1594 dissect_bgp_open(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
1596 guint8 optlen; /* Option Length */
1597 int ptype; /* parameter type */
1598 int plen; /* parameter length */
1599 int cend; /* capabilities end */
1600 int oend; /* options end */
1601 int offset; /* tvb offset counter */
1602 proto_item *ti; /* tree item */
1603 proto_tree *opt_tree; /* subtree for options */
1604 proto_tree *par_tree; /* subtree for par options */
1606 offset = BGP_MARKER_SIZE + 2 + 1;
1608 proto_tree_add_item(tree, hf_bgp_open_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1611 proto_tree_add_item(tree, hf_bgp_open_myas, tvb, offset, 2, ENC_BIG_ENDIAN);
1614 proto_tree_add_item(tree, hf_bgp_open_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
1617 proto_tree_add_item(tree, hf_bgp_open_identifier, tvb, offset, 4, ENC_NA);
1620 proto_tree_add_item(tree, hf_bgp_open_opt_len, tvb, offset, 1, ENC_BIG_ENDIAN);
1621 optlen = tvb_get_guint8(tvb, offset);
1624 /* optional parameters */
1626 oend = offset + optlen;
1629 ti = proto_tree_add_item(tree, hf_bgp_open_opt_params, tvb, offset, optlen, ENC_NA);
1630 opt_tree = proto_item_add_subtree(ti, ett_bgp_options);
1632 /* step through all of the optional parameters */
1633 while (offset < oend) {
1636 ti = proto_tree_add_item(opt_tree, hf_bgp_open_opt_param, tvb, offset, -1, ENC_NA);
1637 par_tree = proto_item_add_subtree(ti, ett_bgp_options);
1639 /* display and grab the type ... */
1640 proto_tree_add_item(par_tree, hf_bgp_open_opt_param_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1641 ptype = tvb_get_guint8(tvb, offset);
1642 proto_item_append_text(ti, ": %s", val_to_str(ptype, bgp_open_opt_vals, "Unknown Parameter %d"));
1645 /* ... and length */
1646 proto_tree_add_item(par_tree, hf_bgp_open_opt_param_len, tvb, offset, 1, ENC_BIG_ENDIAN);
1647 plen = tvb_get_guint8(tvb, offset);
1648 proto_item_set_len(ti, plen+2);
1651 /* check the type */
1653 case BGP_OPTION_AUTHENTICATION:
1654 proto_tree_add_item(par_tree, hf_bgp_open_opt_param_auth, tvb, offset, plen, ENC_NA);
1657 case BGP_OPTION_CAPABILITY:
1658 /* grab the capability code */
1659 cend = offset + plen;
1661 /* step through all of the capabilities */
1662 while (offset < cend) {
1663 offset = dissect_bgp_capability_item(tvb, par_tree, pinfo, offset, FALSE);
1667 proto_tree_add_item(opt_tree, hf_bgp_open_opt_param_unknown, tvb, offset, plen, ENC_NA);
1669 } /* switch (ptype) */
1675 * Dissect a BGP UPDATE message.
1678 dissect_bgp_update(tvbuff_t *tvb, proto_tree *tree)
1680 struct bgp_attr bgpa; /* path attributes */
1681 guint16 hlen; /* message length */
1682 gint o; /* packet offset */
1684 gint end; /* message end */
1685 guint16 ext_com; /* EXTENDED COMMUNITY extended length type */
1686 guint8 ext_com8; /* EXTENDED COMMUNITY regular type */
1687 gboolean is_regular_type; /* flag for regular types */
1688 gboolean is_extended_type; /* flag for extended types */
1689 guint16 len; /* tmp */
1690 int advance; /* tmp */
1691 proto_item *ti; /* tree item */
1692 proto_tree *subtree; /* subtree for attributes */
1693 proto_tree *subtree2; /* subtree for attributes */
1694 proto_tree *subtree3; /* subtree for attributes */
1695 proto_tree *subtree4; /* subtree for attributes */
1696 proto_tree *subtree5; /* subtree for attributes */
1697 proto_tree *as_paths_tree; /* subtree for AS_PATHs */
1698 proto_tree *as_path_tree; /* subtree for AS_PATH */
1699 proto_tree *as_path_segment_tree; /* subtree for AS_PATH segments */
1700 proto_tree *communities_tree; /* subtree for COMMUNITIES */
1701 proto_tree *community_tree; /* subtree for a community */
1702 proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
1704 guint8 length; /* AS_PATH length */
1705 guint8 type; /* AS_PATH type */
1706 guint32 as_path_item; /* item in AS_PATH segment */
1707 emem_strbuf_t *as_path_emstr = NULL; /* AS_PATH */
1708 emem_strbuf_t *communities_emstr = NULL; /* COMMUNITIES */
1709 emem_strbuf_t *cluster_list_emstr = NULL; /* CLUSTER_LIST */
1710 emem_strbuf_t *junk_emstr; /* tmp */
1711 guint32 ipaddr; /* IPv4 address */
1712 guint32 aggregator_as;
1713 guint16 ssa_type; /* SSA T + Type */
1714 guint16 ssa_len; /* SSA TLV Length */
1715 guint8 ssa_v3_len; /* SSA L2TPv3 Cookie Length */
1716 gfloat linkband; /* Link bandwidth */
1717 guint16 as_num; /* Autonomous System Number */
1719 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
1720 o = BGP_HEADER_SIZE;
1721 junk_emstr = ep_strbuf_new_label(NULL);
1723 /* check for withdrawals */
1724 len = tvb_get_ntohs(tvb, o);
1725 proto_tree_add_text(tree, tvb, o, 2,
1726 "Unfeasible routes length: %u byte%s", len, plurality(len, "", "s"));
1729 /* parse unfeasible prefixes */
1731 ti = proto_tree_add_text(tree, tvb, o, len, "Withdrawn routes:");
1732 subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
1733 /* parse each prefix */
1735 /* Heuristic to detect if IPv4 prefix are using Path Identifiers */
1736 if( detect_add_path_prefix4(tvb, o, end) ) {
1737 /* IPv4 prefixes with Path Id */
1739 i = decode_path_prefix4(subtree, hf_bgp_nlri_path_id, hf_bgp_withdrawn_prefix, tvb, o,
1747 i = decode_prefix4(subtree, hf_bgp_withdrawn_prefix, tvb, o, len,
1756 /* check for advertisements */
1757 len = tvb_get_ntohs(tvb, o);
1758 proto_tree_add_text(tree, tvb, o, 2, "Total path attribute length: %u byte%s",
1759 len, plurality(len, "", "s"));
1761 /* path attributes */
1763 ti = proto_tree_add_text(tree, tvb, o + 2, len, "Path attributes");
1764 subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
1767 proto_item *hidden_item;
1771 guint16 alen, tlen, aoff, aoff_save;
1777 tvb_memcpy(tvb, (guint8 *)&bgpa, o + i, sizeof(bgpa));
1778 /* check for the Extended Length bit */
1779 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1780 alen = tvb_get_ntohs(tvb, o + i + sizeof(bgpa));
1781 aoff = sizeof(bgpa) + 2;
1783 alen = tvb_get_guint8(tvb, o + i + sizeof(bgpa));
1784 aoff = sizeof(bgpa) + 1;
1788 /* This is kind of ugly - similar code appears twice, but it
1789 helps browsing attrs. */
1790 /* the first switch prints things in the title of the subtree */
1791 switch (bgpa.bgpa_type) {
1792 case BGPTYPE_ORIGIN:
1794 goto default_attribute_top;
1795 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
1796 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1797 "%s: %s (%u byte%s)",
1798 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1799 msg, tlen + aoff, plurality(tlen + aoff, "", "s"));
1801 case BGPTYPE_AS_PATH:
1802 case BGPTYPE_NEW_AS_PATH:
1804 (o + current attribute + aoff bytes to first tuple) */
1807 /* must be freed by second switch! */
1808 /* "tlen * 11" (10 digits + space) should be a good estimate
1809 of how long the AS path string could be */
1810 if (as_path_emstr == NULL)
1811 as_path_emstr = ep_strbuf_sized_new((tlen + 1) * 11, 0);
1812 ep_strbuf_truncate(as_path_emstr, 0);
1814 /* estimate the length of the AS number */
1815 if (bgpa.bgpa_type == BGPTYPE_NEW_AS_PATH)
1818 if (bgp_asn_len == 0) {
1819 guint unknown_segment_type = 0;
1820 guint asn_is_null = 0;
1826 type = tvb_get_guint8(tvb, k++);
1828 /* type of segment is unknown */
1829 if (type != AS_SET &&
1830 type != AS_SEQUENCE &&
1831 type != AS_CONFED_SEQUENCE &&
1832 type != AS_CONFED_SEQUENCE)
1833 unknown_segment_type = 1;
1835 length = tvb_get_guint8(tvb, k++);
1837 /* Check for invalid ASN */
1838 for (d = 0; d < length; d++)
1840 if(tvb_get_ntohs(tvb, k) == 0)
1845 if(k != end || unknown_segment_type || asn_is_null)
1849 asn_len = bgp_asn_len;
1853 /* snarf each AS path */
1855 type = tvb_get_guint8(tvb, q++);
1856 if (as_path_emstr->len > 1 &&
1857 as_path_emstr->str[as_path_emstr->len - 1] != ' ')
1858 ep_strbuf_append_c(as_path_emstr, ' ');
1859 if (type == AS_SET) {
1860 ep_strbuf_append_c(as_path_emstr, '{');
1862 else if (type == AS_CONFED_SET) {
1863 ep_strbuf_append_c(as_path_emstr, '[');
1865 else if (type == AS_CONFED_SEQUENCE) {
1866 ep_strbuf_append_c(as_path_emstr, '(');
1868 length = tvb_get_guint8(tvb, q++);
1870 /* snarf each value in path */
1871 for (j = 0; j < length; j++) {
1872 ep_strbuf_append_printf(as_path_emstr, "%u%s",
1874 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1875 (type == AS_SET || type == AS_CONFED_SET) ?
1880 /* cleanup end of string */
1881 if (type == AS_SET) {
1882 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
1883 ep_strbuf_append_c(as_path_emstr, '}');
1885 else if (type == AS_CONFED_SET) {
1886 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
1887 ep_strbuf_append_c(as_path_emstr, ']');
1889 else if (type == AS_CONFED_SEQUENCE) {
1890 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
1891 ep_strbuf_append_c(as_path_emstr, ')');
1894 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
1898 /* check for empty AS_PATH */
1900 ep_strbuf_printf(as_path_emstr, "empty");
1902 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1903 "%s: %s (%u byte%s)",
1904 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1905 as_path_emstr->str, tlen + aoff,
1906 plurality(tlen + aoff, "", "s"));
1908 case BGPTYPE_NEXT_HOP:
1910 goto default_attribute_top;
1911 ipaddr = tvb_get_ipv4(tvb, o + i + aoff);
1912 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1913 "%s: %s (%u byte%s)",
1914 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1915 ip_to_str((guint8 *)&ipaddr), tlen + aoff,
1916 plurality(tlen + aoff, "", "s"));
1918 case BGPTYPE_MULTI_EXIT_DISC:
1920 goto default_attribute_top;
1921 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1922 "%s: %u (%u byte%s)",
1923 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1924 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1925 plurality(tlen + aoff, "", "s"));
1927 case BGPTYPE_LOCAL_PREF:
1929 goto default_attribute_top;
1930 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1931 "%s: %u (%u byte%s)",
1932 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1933 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1934 plurality(tlen + aoff, "", "s"));
1936 case BGPTYPE_ATOMIC_AGGREGATE:
1938 goto default_attribute_top;
1939 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1941 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1942 tlen + aoff, plurality(tlen + aoff, "", "s"));
1944 case BGPTYPE_AGGREGATOR:
1945 if (tlen != 6 && tlen != 8)
1946 goto default_attribute_top;
1947 case BGPTYPE_NEW_AGGREGATOR:
1948 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
1949 goto default_attribute_top;
1951 ipaddr = tvb_get_ipv4(tvb, o + i + aoff + asn_len);
1952 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1953 "%s: AS: %u origin: %s (%u byte%s)",
1954 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1955 (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) :
1956 tvb_get_ntohl(tvb, o + i + aoff),
1957 ip_to_str((guint8 *)&ipaddr),
1958 tlen + aoff, plurality(tlen + aoff, "", "s"));
1960 case BGPTYPE_COMMUNITIES:
1962 goto default_attribute_top;
1965 (o + current attribute + aoff bytes to first tuple) */
1968 /* must be freed by second switch! */
1969 /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be
1970 a good estimate of how long the communities string could
1972 if (communities_emstr == NULL)
1973 communities_emstr = ep_strbuf_sized_new((tlen + 1) * 12, 0);
1974 ep_strbuf_truncate(communities_emstr, 0);
1976 /* snarf each community */
1978 /* check for well-known communities */
1979 if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
1980 ep_strbuf_append(communities_emstr, "NO_EXPORT ");
1981 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
1982 ep_strbuf_append(communities_emstr, "NO_ADVERTISE ");
1983 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
1984 ep_strbuf_append(communities_emstr, "NO_EXPORT_SUBCONFED ");
1986 ep_strbuf_append_printf(communities_emstr, "%u:%u ",
1987 tvb_get_ntohs(tvb, q),
1988 tvb_get_ntohs(tvb, q + 2));
1992 /* cleanup end of string */
1993 ep_strbuf_truncate(communities_emstr, communities_emstr->len - 1);
1995 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1996 "%s: %s (%u byte%s)",
1997 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1998 communities_emstr->str, tlen + aoff,
1999 plurality(tlen + aoff, "", "s"));
2001 case BGPTYPE_ORIGINATOR_ID:
2003 goto default_attribute_top;
2004 ipaddr = tvb_get_ipv4(tvb, o + i + aoff);
2005 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
2006 "%s: %s (%u byte%s)",
2007 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
2008 ip_to_str((guint8 *)&ipaddr),
2009 tlen + aoff, plurality(tlen + aoff, "", "s"));
2011 case BGPTYPE_CLUSTER_LIST:
2013 goto default_attribute_top;
2016 (o + current attribute + aoff bytes to first tuple) */
2019 /* must be freed by second switch! */
2020 /* "tlen * 16" (12 digits, 3 dots + space ) should be
2021 a good estimate of how long the cluster_list string could
2023 if (cluster_list_emstr == NULL)
2024 cluster_list_emstr = ep_strbuf_sized_new((tlen + 1) * 16, 0);
2025 ep_strbuf_truncate(cluster_list_emstr, 0);
2027 /* snarf each cluster list */
2029 ipaddr = tvb_get_ipv4(tvb, q);
2030 ep_strbuf_append_printf(cluster_list_emstr, "%s ", ip_to_str((guint8 *)&ipaddr));
2033 /* cleanup end of string */
2034 ep_strbuf_truncate(cluster_list_emstr, cluster_list_emstr->len - 1);
2036 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
2037 "%s: %s (%u byte%s)",
2038 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
2039 cluster_list_emstr->str, tlen + aoff,
2040 plurality(tlen + aoff, "", "s"));
2042 case BGPTYPE_EXTENDED_COMMUNITY:
2045 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
2047 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
2049 plurality(tlen + aoff, "", "s"));
2051 case BGPTYPE_SAFI_SPECIFIC_ATTR:
2052 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
2054 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
2056 plurality(tlen + aoff, "", "s"));
2060 default_attribute_top:
2061 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
2063 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
2064 tlen + aoff, plurality(tlen + aoff, "", "s"));
2065 } /* switch (bgpa.bgpa_type) */ /* end of first switch */
2066 subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
2068 /* figure out flags */
2069 ep_strbuf_truncate(junk_emstr, 0);
2070 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) {
2071 ep_strbuf_append(junk_emstr, "Optional, ");
2074 ep_strbuf_append(junk_emstr, "Well-known, ");
2076 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) {
2077 ep_strbuf_append(junk_emstr, "Transitive, ");
2080 ep_strbuf_append(junk_emstr, "Non-transitive, ");
2082 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_PARTIAL) {
2083 ep_strbuf_append(junk_emstr, "Partial");
2086 ep_strbuf_append(junk_emstr, "Complete");
2088 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
2089 ep_strbuf_append(junk_emstr, ", Extended Length");
2091 ti = proto_tree_add_text(subtree2, tvb,
2092 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
2093 "Flags: 0x%02x (%s)", bgpa.bgpa_flags, junk_emstr->str);
2094 subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags);
2096 /* add flag bitfield subtrees */
2097 proto_tree_add_text(subtree3, tvb,
2098 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
2099 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
2100 BGP_ATTR_FLAG_OPTIONAL, 8, "Optional", "Well-known"));
2101 proto_tree_add_text(subtree3, tvb,
2102 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
2103 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
2104 BGP_ATTR_FLAG_TRANSITIVE, 8, "Transitive",
2106 proto_tree_add_text(subtree3, tvb,
2107 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
2108 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
2109 BGP_ATTR_FLAG_PARTIAL, 8, "Partial", "Complete"));
2110 proto_tree_add_text(subtree3, tvb,
2111 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
2112 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
2113 BGP_ATTR_FLAG_EXTENDED_LENGTH, 8, "Extended length",
2116 proto_tree_add_text(subtree2, tvb,
2117 o + i + offsetof(struct bgp_attr, bgpa_type), 1,
2118 "Type code: %s (%u)",
2119 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
2122 proto_tree_add_text(subtree2, tvb, o + i + sizeof(bgpa),
2123 aoff - sizeof(bgpa), "Length: %d byte%s", tlen,
2124 plurality(tlen, "", "s"));
2126 /* the second switch prints things in the actual subtree of each
2128 switch (bgpa.bgpa_type) {
2129 case BGPTYPE_ORIGIN:
2131 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2132 "Origin (invalid): %u byte%s", tlen,
2133 plurality(tlen, "", "s"));
2135 proto_tree_add_item(subtree2, hf_bgp_origin, tvb,
2136 o + i + aoff, 1, ENC_BIG_ENDIAN);
2139 case BGPTYPE_AS_PATH:
2140 case BGPTYPE_NEW_AS_PATH:
2141 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2142 "AS path: %s", as_path_emstr->str);
2143 as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
2146 (o + current attribute + aoff bytes to first tuple) */
2150 /* snarf each AS path tuple, we have to step through each one
2151 again to make a separate subtree so we can't just reuse
2152 as_path_gstr from above */
2153 /* XXX - Can we use some g_string*() trickery instead, e.g.
2154 g_string_erase()? */
2156 ep_strbuf_truncate(as_path_emstr, 0);
2157 type = tvb_get_guint8(tvb, q++);
2158 if (type == AS_SET) {
2159 ep_strbuf_append_c(as_path_emstr, '{');
2161 else if (type == AS_CONFED_SET) {
2162 ep_strbuf_append_c(as_path_emstr, '[');
2164 else if (type == AS_CONFED_SEQUENCE) {
2165 ep_strbuf_append_c(as_path_emstr, '(');
2167 length = tvb_get_guint8(tvb, q++);
2169 /* snarf each value in path */
2170 for (j = 0; j < length; j++) {
2171 ep_strbuf_append_printf(as_path_emstr, "%u%s",
2173 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
2174 (type == AS_SET || type == AS_CONFED_SET) ? ", " : " ");
2178 /* cleanup end of string */
2179 if (type == AS_SET) {
2180 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
2181 ep_strbuf_append_c(as_path_emstr, '}');
2183 else if (type == AS_CONFED_SET) {
2184 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 2);
2185 ep_strbuf_append_c(as_path_emstr, ']');
2187 else if (type == AS_CONFED_SEQUENCE) {
2188 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
2189 ep_strbuf_append_c(as_path_emstr, ')');
2192 ep_strbuf_truncate(as_path_emstr, as_path_emstr->len - 1);
2195 /* length here means number of ASs, ie length * 2 bytes */
2196 ti = proto_tree_add_text(as_paths_tree, tvb,
2197 q - length * asn_len - 2,
2198 length * asn_len + 2, "AS path segment: %s", as_path_emstr->str);
2199 as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
2200 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 2,
2201 1, "Path segment type: %s (%u)",
2202 val_to_str(type, as_segment_type, "Unknown"), type);
2203 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 1,
2204 1, "Path segment length: %u AS%s", length,
2205 plurality(length, "", "s"));
2207 /* backup and reprint path segment value(s) only */
2208 q -= asn_len * length;
2209 ti = proto_tree_add_text(as_path_tree, tvb, q,
2210 length * asn_len, "Path segment value:");
2211 as_path_segment_tree = proto_item_add_subtree(ti,
2212 ett_bgp_as_path_segments);
2213 for (j = 0; j < length; j++) {
2214 as_path_item = (asn_len == 2) ?
2215 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q);
2216 proto_item_append_text(ti, " %u", as_path_item);
2217 hidden_item = proto_tree_add_uint(as_path_segment_tree, hf_bgp_as_path, tvb,
2218 q, asn_len, as_path_item);
2219 PROTO_ITEM_SET_HIDDEN(hidden_item);
2225 case BGPTYPE_NEXT_HOP:
2227 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2228 "Next hop (invalid): %u byte%s", tlen,
2229 plurality(tlen, "", "s"));
2231 proto_tree_add_item(subtree2, hf_bgp_next_hop, tvb,
2232 o + i + aoff, tlen, ENC_BIG_ENDIAN);
2235 case BGPTYPE_MULTI_EXIT_DISC:
2237 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2238 "Multiple exit discriminator (invalid): %u byte%s",
2239 tlen, plurality(tlen, "", "s"));
2241 proto_tree_add_item(subtree2, hf_bgp_multi_exit_disc, tvb,
2242 o + i + aoff, tlen, ENC_BIG_ENDIAN);
2245 case BGPTYPE_LOCAL_PREF:
2247 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2248 "Local preference (invalid): %u byte%s", tlen,
2249 plurality(tlen, "", "s"));
2251 proto_tree_add_item(subtree2, hf_bgp_local_pref, tvb,
2252 o + i + aoff, tlen, ENC_BIG_ENDIAN);
2255 case BGPTYPE_ATOMIC_AGGREGATE:
2257 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2258 "Atomic aggregate (invalid): %u byte%s", tlen,
2259 plurality(tlen, "", "s"));
2262 case BGPTYPE_AGGREGATOR:
2263 if (tlen != 6 && tlen != 8) {
2264 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2265 "Aggregator (invalid): %u byte%s", tlen,
2266 plurality(tlen, "", "s"));
2269 case BGPTYPE_NEW_AGGREGATOR:
2270 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
2271 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2272 "Aggregator (invalid): %u byte%s", tlen,
2273 plurality(tlen, "", "s"));
2276 aggregator_as = (asn_len == 2) ?
2277 tvb_get_ntohs(tvb, o + i + aoff) :
2278 tvb_get_ntohl(tvb, o + i + aoff);
2279 proto_tree_add_uint(subtree2, hf_bgp_aggregator_as, tvb,
2280 o + i + aoff, asn_len, aggregator_as);
2281 proto_tree_add_item(subtree2, hf_bgp_aggregator_origin, tvb,
2282 o + i + aoff + asn_len, 4, ENC_BIG_ENDIAN);
2285 case BGPTYPE_COMMUNITIES:
2286 if (tlen % 4 != 0) {
2287 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2288 "Communities (invalid): %u byte%s", tlen,
2289 plurality(tlen, "", "s"));
2293 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2294 "Communities: %s", communities_emstr ? communities_emstr->str : "<none>");
2295 communities_tree = proto_item_add_subtree(ti,
2296 ett_bgp_communities);
2299 (o + current attribute + aoff bytes to first tuple) */
2303 /* snarf each community */
2305 /* check for reserved values */
2306 guint32 community = tvb_get_ntohl(tvb, q);
2307 if ((community & 0xFFFF0000) == FOURHEX0 ||
2308 (community & 0xFFFF0000) == FOURHEXF) {
2309 proto_tree_add_text(communities_tree, tvb,
2311 "Community: %s (0x%08x)",
2312 val_to_str(community, community_vals, "(reserved)"),
2316 ti = proto_tree_add_text(communities_tree, tvb,
2317 q - 3 + aoff, 4, "Community: %u:%u",
2318 tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
2319 community_tree = proto_item_add_subtree(ti,
2320 ett_bgp_communities);
2321 proto_tree_add_item(community_tree, hf_bgp_community_as,
2322 tvb, q - 3 + aoff, 2, ENC_BIG_ENDIAN);
2323 proto_tree_add_item(community_tree, hf_bgp_community_value,
2324 tvb, q - 1 + aoff, 2, ENC_BIG_ENDIAN);
2331 case BGPTYPE_ORIGINATOR_ID:
2333 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2334 "Originator identifier (invalid): %u byte%s", tlen,
2335 plurality(tlen, "", "s"));
2337 proto_tree_add_item(subtree2, hf_bgp_originator_id, tvb,
2338 o + i + aoff, tlen, ENC_BIG_ENDIAN);
2341 case BGPTYPE_MP_REACH_NLRI:
2343 * RFC 2545 specifies that there may be more than one
2344 * address in the MP_REACH_NLRI attribute in section
2345 * 3, "Constructing the Next Hop field".
2347 * Yes, RFC 2858 says you can't do that, and, yes, RFC
2348 * 2858 obsoletes RFC 2283, which says you can do that,
2349 * but that doesn't mean we shouldn't dissect packets
2350 * that conform to RFC 2283 but not RFC 2858, as some
2351 * device on the network might implement the 2283-style
2352 * BGP extensions rather than RFC 2858-style extensions.
2354 af = tvb_get_ntohs(tvb, o + i + aoff);
2355 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
2356 "Address family: %s (%u)",
2357 val_to_str(af, afn_vals, "Unknown"), af);
2358 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
2359 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
2360 "Subsequent address family identifier: %s (%u)",
2361 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
2363 nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
2364 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
2366 "Next hop network address (%d byte%s)",
2367 nexthop_len, plurality(nexthop_len, "", "s"));
2368 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
2371 * The addresses don't contain lengths, so if we
2372 * don't understand the address family type, we
2373 * cannot parse the subsequent addresses as we
2374 * don't know how long they are.
2378 proto_tree_add_text(subtree3, tvb, o + i + aoff + 4,
2379 nexthop_len, "Unknown Address Family");
2385 case AFNUM_L2VPN_OLD:
2388 while (j < nexthop_len) {
2389 advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
2391 if (advance == 0) /* catch if this is a unknown AFI type*/
2393 if (j + advance > nexthop_len)
2395 proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
2396 advance, "Next hop: %s (%u)", junk_emstr->str, advance);
2403 tlen -= nexthop_len + 4;
2404 aoff += nexthop_len + 4 ;
2407 snpa = tvb_get_guint8(tvb, o + i + aoff);
2408 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
2409 "Subnetwork points of attachment: %u", snpa);
2412 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
2413 for (/*nothing*/; snpa > 0; snpa--) {
2414 proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
2415 "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
2417 proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
2418 tvb_get_guint8(tvb, o + i + aoff + off - 1),
2419 "SNPA (%u byte%s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
2420 plurality(tvb_get_guint8(tvb, o + i + aoff + off - 1), "", "s"));
2421 off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
2427 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2428 "Network layer reachability information (%u byte%s)",
2429 tlen, plurality(tlen, "", "s"));
2431 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
2432 if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
2433 proto_tree_add_text(subtree3, tvb, o + i + aoff,
2434 tlen, "Unknown Address Family");
2437 advance = decode_prefix_MP(subtree3,
2438 hf_bgp_mp_reach_nlri_ipv4_prefix,
2441 tvb, o + i + aoff, "MP Reach NLRI");
2451 case BGPTYPE_MP_UNREACH_NLRI:
2452 af = tvb_get_ntohs(tvb, o + i + aoff);
2453 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
2454 "Address family: %s (%u)",
2455 val_to_str(af, afn_vals, "Unknown"), af);
2456 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
2457 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
2458 "Subsequent address family identifier: %s (%u)",
2459 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
2461 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
2462 tlen - 3, "Withdrawn routes (%u byte%s)", tlen - 3,
2463 plurality(tlen - 3, "", "s"));
2469 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
2472 advance = decode_prefix_MP(subtree3,
2473 hf_bgp_mp_unreach_nlri_ipv4_prefix,
2476 tvb, o + i + aoff, "MP Unreach NLRI");
2485 case BGPTYPE_CLUSTER_LIST:
2486 if (tlen % 4 != 0) {
2487 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2488 "Cluster list (invalid): %u byte%s", tlen,
2489 plurality(tlen, "", "s"));
2493 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2494 "Cluster list: %s", cluster_list_emstr ? cluster_list_emstr->str : "<none>");
2495 cluster_list_tree = proto_item_add_subtree(ti,
2496 ett_bgp_cluster_list);
2499 (o + current attribute + aoff bytes to first tuple) */
2503 /* snarf each cluster identifier */
2505 proto_tree_add_item(cluster_list_tree, hf_bgp_cluster_list,
2506 tvb, q - 3 + aoff, 4, ENC_NA);
2511 case BGPTYPE_EXTENDED_COMMUNITY:
2513 proto_tree_add_text(subtree3, tvb, o + i + aoff, tlen, "Extended community (invalid) : %u byte%s", tlen,
2514 plurality(tlen, "", "s"));
2517 end = o + i + aoff + tlen ;
2518 ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
2519 subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2522 ext_com8 = tvb_get_guint8(tvb,q); /* handle regular types (8 bit) */
2523 ext_com = tvb_get_ntohs(tvb,q); /* handle extended length types (16 bit) */
2524 ep_strbuf_printf(junk_emstr, "%s", val_to_str(ext_com8,bgpext_com8_type,"Unknown %d"));
2525 is_regular_type = FALSE;
2526 is_extended_type = FALSE;
2527 /* handle regular types (8 bit) */
2529 case BGP_EXT_COM_QOS_MARK_T:
2530 case BGP_EXT_COM_QOS_MARK_NT:
2531 is_regular_type = TRUE;
2532 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2534 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2535 proto_tree_add_text(subtree4, tvb, q, 1,
2536 "Type: 0x%02x", tvb_get_guint8(tvb,q));
2537 ti = proto_tree_add_text(subtree4, tvb, q+1, 1,
2538 "Flags: 0x%02x", tvb_get_guint8(tvb,q+1));
2539 subtree5 = proto_item_add_subtree(ti,ett_bgp_ext_com_flags);
2540 /* add flag bitfield */
2541 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2542 0x10, 8, "Remarking", "No Remarking"));
2543 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2544 0x08, 8, "Ignored marking", "No Ignored marking"));
2545 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2546 0x04, 8, "Aggregation of markings", "No Aggregation of markings"));
2548 proto_tree_add_text(subtree4, tvb, q+2, 1,
2549 "QoS Set Number: 0x%02x", tvb_get_guint8(tvb,q+2));
2550 proto_tree_add_text(subtree4, tvb, q+3, 1,
2551 "Technology Type: 0x%02x (%s)", tvb_get_guint8(tvb,q+3),
2552 val_to_str(tvb_get_guint8(tvb,q+3),qos_tech_type,"Unknown"));
2553 proto_tree_add_text(subtree4, tvb, q+4, 2,
2554 "QoS Marking O (16 bit): %s", decode_numeric_bitfield(tvb_get_ntohs(tvb,q+4),
2555 0xffff, 16, "0x%04x"));
2556 proto_tree_add_text(subtree4, tvb, q+6, 1,
2557 "QoS Marking A (8 bit): %s (decimal %d)", decode_numeric_bitfield(tvb_get_guint8(tvb,q+6),
2558 0xff, 8, "0x%02x"), tvb_get_guint8(tvb,q+6));
2559 proto_tree_add_text(subtree4, tvb, q+7, 1,
2560 "Defaults to zero: 0x%02x", tvb_get_guint8(tvb,q+7));
2562 case BGP_EXT_COM_COS_CAP_T:
2563 is_regular_type = TRUE;
2564 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2566 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2567 proto_tree_add_text(subtree4, tvb, q, 1,
2568 "Type: 0x%02x", tvb_get_guint8(tvb,q));
2569 ti = proto_tree_add_text(subtree4, tvb, q+1, 1,
2570 "Flags byte 1 : 0x%02x", tvb_get_guint8(tvb,q+1));
2571 subtree5 = proto_item_add_subtree(ti,ett_bgp_ext_com_flags);
2572 /* add flag bitfield */
2573 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2574 0x80, 8, "BE class supported", "BE class NOT supported"));
2575 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2576 0x40, 8, "EF class supported", "EF class NOT supported"));
2577 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2578 0x20, 8, "AF class supported", "AF class NOT supported"));
2579 proto_tree_add_text(subtree5, tvb, q+1, 1, "%s", decode_boolean_bitfield(tvb_get_guint8(tvb,q+1),
2580 0x10, 8, "LE class supported", "LE class NOT supported"));
2581 proto_tree_add_text(subtree4, tvb, q+2, 1,
2582 "Flags byte 2..7 : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
2583 tvb_get_guint8(tvb,q+2),tvb_get_guint8(tvb,q+3),tvb_get_guint8(tvb,q+4),
2584 tvb_get_guint8(tvb,q+5),tvb_get_guint8(tvb,q+6),tvb_get_guint8(tvb,q+7));
2586 } /* switch (ext_com8) */
2588 if (!is_regular_type) {
2589 ep_strbuf_printf(junk_emstr, "%s", val_to_str(ext_com,bgpext_com_type,"Unknown %d"));
2591 /* handle extended length types (16 bit) */
2593 case BGP_EXT_COM_RT_0:
2594 case BGP_EXT_COM_RO_0:
2595 is_extended_type = TRUE;
2596 ep_strbuf_append_printf(junk_emstr, ": %u%s%d",
2597 tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
2598 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2600 case BGP_EXT_COM_RT_1:
2601 case BGP_EXT_COM_RO_1:
2602 is_extended_type = TRUE;
2603 ipaddr = tvb_get_ipv4(tvb,q+2);
2604 ep_strbuf_append_printf(junk_emstr, ": %s%s%u",
2605 ip_to_str((guint8 *)&ipaddr),":",tvb_get_ntohs(tvb,q+6));
2606 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2608 case BGP_EXT_COM_RT_2:
2609 case BGP_EXT_COM_RO_2:
2610 is_extended_type = TRUE;
2611 ep_strbuf_append_printf(junk_emstr, ": %u.%u:%u",
2612 tvb_get_ntohs(tvb,q+2),tvb_get_ntohs(tvb,q+4) ,tvb_get_ntohs(tvb,q+6));
2613 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2615 case BGP_EXT_COM_VPN_ORIGIN:
2616 case BGP_EXT_COM_OSPF_RID:
2617 is_extended_type = TRUE;
2618 ipaddr = tvb_get_ipv4(tvb,q+2);
2619 ep_strbuf_append_printf(junk_emstr, ": %s", ip_to_str((guint8 *)&ipaddr));
2620 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2622 case BGP_EXT_COM_OSPF_RTYPE:
2623 is_extended_type = TRUE;
2624 ipaddr = tvb_get_ipv4(tvb,q+2);
2625 ep_strbuf_append_printf(junk_emstr, ": Area: %s, Type: %s", ip_to_str((guint8 *)&ipaddr),
2626 val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
2627 /* print OSPF Metric type if selected */
2628 /* always print E2 even if not external route -- receiving router should ignore */
2629 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
2630 ep_strbuf_append(junk_emstr, " E2");
2631 } else if ((tvb_get_guint8(tvb,q+6)==BGP_OSPF_RTYPE_EXT) || (tvb_get_guint8(tvb,q+6)==BGP_OSPF_RTYPE_NSSA)) {
2632 ep_strbuf_append(junk_emstr, " E1");
2634 ep_strbuf_append(junk_emstr, ", no options");
2636 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2638 case BGP_EXT_COM_LINKBAND:
2639 is_extended_type = TRUE;
2640 as_num = tvb_get_ntohs(tvb,q+2);
2641 linkband = tvb_get_ntohieee_float(tvb,q+4);
2642 ep_strbuf_append_printf(junk_emstr, ": ASN %u, %.3f Mbps", as_num,linkband*8/1000000);
2643 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2645 case BGP_EXT_COM_L2INFO:
2646 is_extended_type = TRUE;
2647 ep_strbuf_append_printf(junk_emstr,
2648 ": %s, Control Flags: %s%s%s%s%s, MTU: %u byte%s",
2649 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"),
2650 tvb_get_guint8(tvb,q+3) ? "" : "none",
2651 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q" : "",
2652 tvb_get_ntohs(tvb,q+3)&0x04 ? "F" : "",
2653 tvb_get_ntohs(tvb,q+3)&0x02 ? "C" : "",
2654 tvb_get_ntohs(tvb,q+3)&0x01 ? "S" : "",
2655 tvb_get_ntohs(tvb,q+4),
2656 plurality(tvb_get_ntohs(tvb,q+4), "", "s"));
2657 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_emstr->str);
2659 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities);
2660 proto_tree_add_text(subtree4,tvb,q+2,1, "Encapsulation: %s",
2661 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"));
2662 proto_tree_add_text(subtree4,tvb,q+3,1, "Control Flags: %s%sControl Word %s required, Sequenced delivery %s required",
2663 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q flag (Reserved) set" : "",
2664 tvb_get_ntohs(tvb,q+3)&0x04 ? "F flag (reserved) set" : "",
2665 tvb_get_ntohs(tvb,q+3)&0x02 ? "is" : "not",
2666 tvb_get_ntohs(tvb,q+3)&0x01 ? "is" : "not");
2667 proto_tree_add_text(subtree4,tvb,q+4,2, "MTU: %u byte%s",
2668 tvb_get_ntohs(tvb,q+4),
2669 plurality(tvb_get_ntohs(tvb,q+4), "", "s"));
2671 } /* switch (ext_com) */
2673 if (!is_regular_type && !is_extended_type)
2674 proto_tree_add_text(subtree3,tvb,q,8, "%s","Unknown");
2679 case BGPTYPE_SAFI_SPECIFIC_ATTR:
2681 end = o + i + aoff + tlen ;
2684 ssa_type = tvb_get_ntohs(tvb, q) & BGP_SSA_TYPE;
2685 ssa_len = tvb_get_ntohs(tvb, q + 2);
2687 ti = proto_tree_add_text(subtree2, tvb, q, MIN(ssa_len + 4, end - q),
2689 val_to_str(ssa_type, bgp_ssa_type, "Unknown SSA"));
2690 subtree3 = proto_item_add_subtree(ti, ett_bgp_ssa);
2692 proto_tree_add_item(subtree3, hf_bgp_ssa_t, tvb,
2693 q, 1, ENC_BIG_ENDIAN);
2694 hidden_item = proto_tree_add_item(subtree3, hf_bgp_ssa_type, tvb,
2695 q, 2, ENC_BIG_ENDIAN);
2696 PROTO_ITEM_SET_HIDDEN(hidden_item);
2697 proto_tree_add_text(subtree3, tvb, q, 2,
2698 "Type: %s", val_to_str(ssa_type, bgp_ssa_type, "Unknown"));
2699 if ((ssa_len == 0) || (q + ssa_len > end)) {
2700 proto_tree_add_text(subtree3, tvb, q + 2, end - q - 2,
2701 "Invalid Length of %u", ssa_len);
2704 proto_tree_add_item(subtree3, hf_bgp_ssa_len, tvb,
2705 q + 2, 2, ENC_BIG_ENDIAN);
2708 case BGP_SSA_L2TPv3:
2709 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_pref, tvb,
2710 q + 4, 2, ENC_BIG_ENDIAN);
2712 ti = proto_tree_add_text(subtree3, tvb, q + 6, 1, "Flags");
2713 subtree4 = proto_item_add_subtree(ti, ett_bgp_ssa_subtree) ;
2714 proto_tree_add_item(subtree4, hf_bgp_ssa_l2tpv3_s, tvb,
2715 q + 6, 1, ENC_BIG_ENDIAN);
2716 proto_tree_add_item(subtree4, hf_bgp_ssa_l2tpv3_unused, tvb,
2717 q + 6, 1, ENC_BIG_ENDIAN);
2719 ssa_v3_len = tvb_get_guint8(tvb, q + 7);
2720 if (ssa_v3_len + 8 == ssa_len){
2721 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_cookie_len, tvb,
2722 q + 7, 1, ENC_BIG_ENDIAN);
2724 proto_tree_add_text(subtree3, tvb, q + 7, 1,
2725 "Invalid Cookie Length of %u", ssa_v3_len);
2726 q += ssa_len + 4; /* 4 from type and length */
2729 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_session_id, tvb,
2730 q + 8, 4, ENC_BIG_ENDIAN);
2732 proto_tree_add_item(subtree3, hf_bgp_ssa_l2tpv3_cookie, tvb,
2733 q + 12, ssa_v3_len, ENC_NA);
2734 q += ssa_len + 4; /* 4 from type and length */
2740 proto_tree_add_item(subtree3, hf_bgp_ssa_value, tvb,
2741 q + 4, ssa_len, ENC_NA);
2742 q += ssa_len + 4; /* 4 from type and length */
2744 case BGP_SSA_L2TPv3_IN_IPSec:
2745 case BGP_SSA_mGRE_IN_IPSec:
2746 /* These contain BGP_SSA_IPSec and BGP_SSA_L2TPv3/BGP_SSA_mGRE */
2747 q += 4; /* 4 from type and length */
2749 } /* switch (bgpa.bgpa_type) */
2754 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2755 "Unknown (%u byte%s)", tlen, plurality(tlen, "", "s"));
2757 } /* switch (bgpa.bgpa_type) */ /* end of second switch */
2767 /* parse prefixes */
2769 ti = proto_tree_add_text(tree, tvb, o, len,
2770 "Network layer reachability information: %u byte%s", len,
2771 plurality(len, "", "s"));
2772 subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
2774 /* Heuristic to detect if IPv4 prefix are using Path Identifiers */
2775 if( detect_add_path_prefix4(tvb, o, end) ) {
2776 /* IPv4 prefixes with Path Id */
2778 i = decode_path_prefix4(subtree, hf_bgp_nlri_path_id, hf_bgp_nlri_prefix, tvb, o,
2785 /* Standard prefixes */
2787 i = decode_prefix4(subtree, hf_bgp_nlri_prefix, tvb, o, 0,
2799 * Dissect a BGP NOTIFICATION message.
2802 dissect_bgp_notification(tvbuff_t *tvb, proto_tree *tree)
2804 struct bgp_notification bgpn; /* BGP NOTIFICATION message */
2805 int hlen; /* message length */
2806 const char *p; /* string pointer */
2809 tvb_memcpy(tvb, bgpn.bgpn_marker, 0, BGP_MIN_NOTIFICATION_MSG_SIZE);
2810 hlen = g_ntohs(bgpn.bgpn_len);
2812 /* print error code */
2813 proto_tree_add_text(tree, tvb,
2814 offsetof(struct bgp_notification, bgpn_major), 1,
2815 "Error code: %s (%u)",
2816 val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
2819 /* print error subcode */
2820 if (bgpn.bgpn_major < array_length(bgpnotify_minor)
2821 && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
2822 p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
2824 } else if (bgpn.bgpn_minor == 0)
2828 proto_tree_add_text(tree, tvb,
2829 offsetof(struct bgp_notification, bgpn_minor), 1,
2830 "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
2832 /* only print if there is optional data */
2833 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
2834 proto_tree_add_text(tree, tvb, BGP_MIN_NOTIFICATION_MSG_SIZE,
2835 hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
2840 * Dissect a BGP ROUTE-REFRESH message.
2843 dissect_bgp_route_refresh(tvbuff_t *tvb, proto_tree *tree)
2845 guint16 i; /* tmp */
2846 int p; /* tvb offset counter */
2847 int pend; /* end of list of entries for one orf type */
2848 guint16 hlen; /* tvb RR msg length */
2849 proto_item *ti; /* tree item */
2850 proto_item *ti1; /* tree item */
2851 proto_tree *subtree; /* tree for orf */
2852 proto_tree *subtree1; /* tree for orf entry */
2853 guint8 orftype; /* ORF Type */
2854 guint8 orfwhen; /* ORF flag: immediate, defer */
2855 guint16 orflen; /* ORF len */
2856 guint8 entryflag; /* ORF Entry flag: action(add,del,delall) match(permit,deny) */
2857 guint32 entryseq; /* ORF Entry sequence number */
2858 int entrylen; /* ORF Entry length */
2859 guint8 pfx_ge; /* ORF PrefixList mask lower bound */
2860 guint8 pfx_le; /* ORF PrefixList mask upper bound */
2861 int advance; /* tmp */
2867 00 01 00 01 afi,safi= ipv4-unicast
2868 02 80 00 01 defer, prefix-orf, len=1
2872 00 01 00 01 afi,saif= ipv4-unicast
2873 01 80 00 0a immediate, prefix-orf, len=10
2875 00 00 00 05 seqno = 5
2878 10 07 02 prefix = 7.2.0.0/16
2880 hlen = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
2881 p = BGP_HEADER_SIZE;
2883 i = tvb_get_ntohs(tvb, p);
2884 proto_tree_add_text(tree, tvb, p, 2,
2885 "Address family identifier: %s (%u)",
2886 val_to_str(i, afn_vals, "Unknown"), i);
2889 proto_tree_add_text(tree, tvb, p, 1,
2890 "Reserved: 1 byte");
2893 i = tvb_get_guint8(tvb, p);
2894 proto_tree_add_text(tree, tvb, p, 1,
2895 "Subsequent address family identifier: %s (%u)",
2896 val_to_str(i, bgpattr_nlri_safi,
2897 i >= 128 ? "Vendor specific" : "Unknown"),
2900 if ( hlen == BGP_HEADER_SIZE + 4 )
2904 orfwhen = tvb_get_guint8(tvb, p);
2905 orftype = tvb_get_guint8(tvb, p+1);
2906 orflen = tvb_get_ntohs(tvb, p+2);
2907 ti = proto_tree_add_text(tree, tvb, p , orflen + 4 , "ORF information (%u bytes)", orflen + 4);
2908 subtree = proto_item_add_subtree(ti, ett_bgp_orf);
2909 proto_tree_add_text(subtree, tvb, p , 1, "ORF flag: %s", val_to_str(orfwhen, orf_when_vals,"UNKNOWN"));
2910 proto_tree_add_text(subtree, tvb, p+1 , 1, "ORF type: %s", val_to_str(orftype, orf_type_vals,"UNKNOWN"));
2911 proto_tree_add_text(subtree, tvb, p+2 , 2, "ORF len: %u byte%s", orflen, plurality(orflen, "", "s"));
2914 if (orftype != BGP_ORF_PREFIX_CISCO) {
2915 proto_tree_add_text(subtree, tvb, p, orflen,
2916 "ORFEntry-Unknown (%u bytes)", orflen);
2922 entryflag = tvb_get_guint8(tvb, p);
2923 if ((entryflag & BGP_ORF_ACTION) == BGP_ORF_REMOVEALL) {
2924 ti1 = proto_tree_add_text(subtree, tvb, p, 1,
2925 "ORFEntry-PrefixList (1 byte)");
2926 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2927 proto_tree_add_text(subtree1, tvb, p , 1, "RemoveAll");
2930 ti1 = proto_tree_add_text(subtree, tvb, p, -1,
2931 "ORFEntry-PrefixList");
2932 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2933 proto_tree_add_text(subtree1, tvb, p, 1,
2934 "ACTION: %s MATCH: %s",
2935 val_to_str(entryflag&BGP_ORF_ACTION,
2936 orf_entry_action_vals, "UNKNOWN"),
2937 val_to_str(entryflag&BGP_ORF_MATCH,
2938 orf_entry_match_vals, "UNKNOWN"));
2940 entryseq = tvb_get_ntohl(tvb, p);
2941 proto_tree_add_text(subtree1, tvb, p, 4,
2942 "Entry Sequence No: %u", entryseq);
2944 pfx_ge = tvb_get_guint8(tvb, p);
2945 proto_tree_add_text(subtree1, tvb, p, 1,
2946 "PrefixMask length lower bound: %u", pfx_ge);
2948 pfx_le = tvb_get_guint8(tvb, p);
2949 proto_tree_add_text(subtree1, tvb, p, 1,
2950 "PrefixMask length upper bound: %u", pfx_le);
2953 advance = decode_prefix4(subtree1, -1, tvb, p, 0, "ORF");
2956 entrylen = 7 + 1 + advance;
2958 proto_item_append_text(ti1, " (%u bytes)", entrylen);
2959 proto_item_set_len(ti1, entrylen);
2967 * Dissect a BGP CAPABILITY message.
2970 dissect_bgp_capability(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo)
2975 mend = offset + tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2976 offset += BGP_HEADER_SIZE;
2977 /* step through all of the capabilities */
2978 while (offset < mend) {
2979 offset = dissect_bgp_capability_item(tvb, tree, pinfo, offset, TRUE);
2984 dissect_bgp_pdu(tvbuff_t *volatile tvb, packet_info *pinfo, proto_tree *tree,
2987 guint16 bgp_len; /* Message length */
2988 guint8 bgp_type; /* Message type */
2989 const char *typ; /* Message type (string) */
2990 proto_item *ti; /* tree item */
2991 proto_item *ti_len; /* length item */
2992 proto_tree *bgp_tree; /* BGP packet tree */
2994 bgp_len = tvb_get_ntohs(tvb, BGP_MARKER_SIZE);
2995 bgp_type = tvb_get_guint8(tvb, BGP_MARKER_SIZE + 2);
2996 typ = val_to_str(bgp_type, bgptypevals, "Unknown message type (0x%02x)");
2999 col_add_str(pinfo->cinfo, COL_INFO, typ);
3001 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
3004 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, ENC_NA);
3005 proto_item_append_text(ti, " - %s", typ);
3007 /* add a different tree for each message type */
3010 bgp_tree = proto_item_add_subtree(ti, ett_bgp_open);
3013 bgp_tree = proto_item_add_subtree(ti, ett_bgp_update);
3015 case BGP_NOTIFICATION:
3016 bgp_tree = proto_item_add_subtree(ti, ett_bgp_notification);
3019 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
3021 case BGP_ROUTE_REFRESH_CISCO:
3022 case BGP_ROUTE_REFRESH:
3023 bgp_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
3025 case BGP_CAPABILITY:
3026 bgp_tree = proto_item_add_subtree(ti, ett_bgp_capability);
3029 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
3033 proto_tree_add_item(bgp_tree, hf_bgp_marker, tvb, 0, 16, ENC_NA);
3035 ti_len = proto_tree_add_item(bgp_tree, hf_bgp_length, tvb, 16, 2, ENC_BIG_ENDIAN);
3036 if (bgp_len < BGP_HEADER_SIZE || bgp_len > BGP_MAX_PACKET_SIZE) {
3037 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Length is invalid %u", bgp_len);
3041 proto_tree_add_item(bgp_tree, hf_bgp_type, tvb, 16 + 2, 1, ENC_BIG_ENDIAN);
3045 dissect_bgp_open(tvb, bgp_tree, pinfo);
3048 dissect_bgp_update(tvb, bgp_tree);
3050 case BGP_NOTIFICATION:
3051 dissect_bgp_notification(tvb, bgp_tree);
3054 /* no data in KEEPALIVE messages */
3056 case BGP_ROUTE_REFRESH_CISCO:
3057 case BGP_ROUTE_REFRESH:
3058 dissect_bgp_route_refresh(tvb, bgp_tree);
3060 case BGP_CAPABILITY:
3061 dissect_bgp_capability(tvb, bgp_tree, pinfo);
3070 * Dissect a BGP packet.
3073 dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3075 volatile int offset = 0; /* offset into the tvbuff */
3076 gint reported_length_remaining;
3077 guint8 bgp_marker[BGP_MARKER_SIZE]; /* Marker (should be all ones */
3078 static guchar marker[] = { /* BGP message marker */
3079 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3080 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3082 proto_item *ti; /* tree item */
3083 proto_tree *bgp_tree; /* BGP packet tree */
3084 guint16 bgp_len; /* Message length */
3086 guint length_remaining;
3088 volatile gboolean first = TRUE; /* TRUE for the first BGP message in packet */
3089 tvbuff_t *volatile next_tvb;
3092 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
3093 col_clear(pinfo->cinfo, COL_INFO);
3096 * Scan through the TCP payload looking for a BGP marker.
3098 while ((reported_length_remaining = tvb_reported_length_remaining(tvb, offset))
3101 * "reported_length_remaining" is the number of bytes of TCP payload
3102 * remaining. If it's more than the length of a BGP marker,
3103 * we check only the number of bytes in a BGP marker.
3105 if (reported_length_remaining > BGP_MARKER_SIZE)
3106 reported_length_remaining = BGP_MARKER_SIZE;
3109 * OK, is there a BGP marker starting at the specified offset -
3110 * or, at least, the beginning of a BGP marker running to the end
3111 * of the TCP payload?
3113 * This will throw an exception if the frame is short; that's what
3116 tvb_memcpy(tvb, bgp_marker, offset, reported_length_remaining);
3117 if (memcmp(bgp_marker, marker, reported_length_remaining) == 0) {
3119 * Yes - stop scanning and start processing BGP packets.
3125 * No - keep scanning through the tvbuff to try to find a marker.
3131 * If we skipped any bytes, mark it as a BGP continuation.
3134 ti = proto_tree_add_item(tree, proto_bgp, tvb, 0, -1, ENC_NA);
3135 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
3137 proto_tree_add_text(bgp_tree, tvb, 0, offset, "Continuation");
3141 * Now process the BGP packets in the TCP payload.
3143 * XXX - perhaps "tcp_dissect_pdus()" should take a starting
3144 * offset, in which case we can replace the loop below with
3145 * a call to "tcp_dissect_pdus()".
3147 while (tvb_reported_length_remaining(tvb, offset) > 0) {
3149 * This will throw an exception if we don't have any data left.
3150 * That's what we want. (See "tcp_dissect_pdus()", which is
3153 length_remaining = tvb_ensure_length_remaining(tvb, offset);
3156 * Can we do reassembly?
3158 if (bgp_desegment && pinfo->can_desegment) {
3160 * Yes - would a BGP header starting at this offset be split
3161 * across segment boundaries?
3163 if (length_remaining < BGP_HEADER_SIZE) {
3165 * Yes. Tell the TCP dissector where the data for this message
3166 * starts in the data it handed us and that we need "some more
3167 * data." Don't tell it exactly how many bytes we need because
3168 * if/when we ask for even more (after the header) that will
3171 pinfo->desegment_offset = offset;
3172 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3178 * Get the length and type from the BGP header.
3180 bgp_len = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
3181 if (bgp_len < BGP_HEADER_SIZE) {
3183 * The BGP length doesn't include the BGP header; report that
3186 show_reported_bounds_error(tvb, pinfo, tree);
3191 * Can we do reassembly?
3193 if (bgp_desegment && pinfo->can_desegment) {
3195 * Yes - is the PDU split across segment boundaries?
3197 if (length_remaining < bgp_len) {
3199 * Yes. Tell the TCP dissector where the data for this
3200 * message starts in the data it handed us, and how many
3201 * more bytes we need, and return.
3203 pinfo->desegment_offset = offset;
3204 pinfo->desegment_len = bgp_len - length_remaining;
3210 * Construct a tvbuff containing the amount of the payload we have
3211 * available. Make its reported length the amount of data in the PDU.
3213 * XXX - if reassembly isn't enabled. the subdissector will throw a
3214 * BoundsError exception, rather than a ReportedBoundsError exception.
3215 * We really want a tvbuff where the length is "length", the reported
3216 * length is "plen", and the "if the snapshot length were infinite"
3217 * length is the minimum of the reported length of the tvbuff handed
3218 * to us and "plen", with a new type of exception thrown if the offset
3219 * is within the reported length but beyond that third length, with
3220 * that exception getting the "Unreassembled Packet" error.
3222 length = length_remaining;
3223 if (length > bgp_len)
3225 next_tvb = tvb_new_subset(tvb, offset, length, bgp_len);
3230 * Catch the ReportedBoundsError exception; if this particular message
3231 * happens to get a ReportedBoundsError exception, that doesn't mean
3232 * that we should stop dissecting PDUs within this frame or chunk of
3235 * If it gets a BoundsError, we can stop, as there's nothing more to
3236 * see, so we just re-throw it.
3238 pd_save = pinfo->private_data;
3240 dissect_bgp_pdu(next_tvb, pinfo, tree, first);
3242 CATCH(BoundsError) {
3245 CATCH(ReportedBoundsError) {
3246 /* Restore the private_data structure in case one of the
3247 * called dissectors modified it (and, due to the exception,
3248 * was unable to restore it).
3250 pinfo->private_data = pd_save;
3252 show_reported_bounds_error(tvb, pinfo, tree);
3259 * Step to the next PDU.
3260 * Make sure we don't overflow.
3262 offset_before = offset;
3264 if (offset <= offset_before)
3270 * Register ourselves.
3273 proto_register_bgp(void)
3276 static hf_register_info hf[] = {
3279 { "Marker", "bgp.marker", FT_BYTES, BASE_NONE,
3280 NULL, 0x0, "Must be set to all ones (16 Bytes)", HFILL }},
3282 { "Length", "bgp.length", FT_UINT16, BASE_DEC,
3283 NULL, 0x0, "The total length of the message, including the header in octets", HFILL }},
3285 { "Type", "bgp.type", FT_UINT8, BASE_DEC,
3286 VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
3288 { &hf_bgp_open_version,
3289 { "Version", "bgp.open.version", FT_UINT8, BASE_DEC,
3290 NULL, 0x0, "The protocol version number", HFILL }},
3291 { &hf_bgp_open_myas,
3292 { "My AS", "bgp.open.myas", FT_UINT16, BASE_DEC,
3293 NULL, 0x0, "The Autonomous System number of the sender", HFILL }},
3294 { &hf_bgp_open_holdtime,
3295 { "Hold Time", "bgp.open.holdtime", FT_UINT16, BASE_DEC,
3296 NULL, 0x0, "The number of seconds the sender proposes for Hold Time", HFILL }},
3297 { &hf_bgp_open_identifier,
3298 { "BGP Identifier", "bgp.open.identifier", FT_IPv4, BASE_NONE,
3299 NULL, 0x0, "The BGP Identifier of the sender", HFILL }},
3300 { &hf_bgp_open_opt_len,
3301 { "Optional Parameters Length", "bgp.open.opt.len", FT_UINT8, BASE_DEC,
3302 NULL, 0x0, "The total length of the Optional Parameters field in octets", HFILL }},
3303 { &hf_bgp_open_opt_params,
3304 { "Optional Parameters", "bgp.open.opt", FT_NONE, BASE_NONE,
3305 NULL, 0x0, "List of optional parameters", HFILL }},
3306 { &hf_bgp_open_opt_param,
3307 { "Optional Parameter", "bgp.open.opt.param", FT_NONE, BASE_NONE,
3308 NULL, 0x0, NULL, HFILL }},
3309 { &hf_bgp_open_opt_param_type,
3310 { "Parameter Type", "bgp.open.opt.param.type", FT_UINT8, BASE_DEC,
3311 VALS(bgp_open_opt_vals), 0x0, "Unambiguously identifies individual parameters", HFILL }},
3312 { &hf_bgp_open_opt_param_len,
3313 { "Parameter Length", "bgp.open.opt.param.len", FT_UINT8, BASE_DEC,
3314 NULL, 0x0, "Length of the Parameter Value", HFILL }},
3315 { &hf_bgp_open_opt_param_auth,
3316 { "Authentification Data", "bgp.open.opt.param.auth", FT_BYTES, BASE_NONE,
3317 NULL, 0x0, "Deprecated", HFILL }},
3318 { &hf_bgp_open_opt_param_unknown,
3319 { "Unknown", "bgp.open.opt.param.unknown", FT_BYTES, BASE_NONE,
3320 NULL, 0x0, "Unknown Parameter", HFILL }},
3322 { "Capability", "bgp.cap", FT_NONE, BASE_NONE,
3323 NULL, 0x0, NULL, HFILL }},
3325 { "Type", "bgp.cap.type", FT_UINT8, BASE_DEC,
3326 VALS(capability_vals), 0x0, NULL, HFILL }},
3327 { &hf_bgp_cap_length,
3328 { "Length", "bgp.cap.length", FT_UINT8, BASE_DEC,
3329 NULL, 0x0, NULL, HFILL }},
3330 { &hf_bgp_cap_action,
3331 { "Action", "bgp.cap.action", FT_UINT8, BASE_DEC,
3332 VALS(bgpcap_action), 0x0, NULL, HFILL }},
3333 { &hf_bgp_cap_unknown,
3334 { "Unknown", "bgp.cap.unknown", FT_BYTES, BASE_NONE,
3335 NULL, 0x0, NULL, HFILL }},
3336 { &hf_bgp_cap_reserved,
3337 { "Reserved", "bgp.cap.reserved", FT_BYTES, BASE_NONE,
3338 NULL, 0x0, "Must be Zero", HFILL }},
3339 { &hf_bgp_cap_mp_afi,
3340 { "AFI", "bgp.cap.mp.afi", FT_UINT16, BASE_DEC,
3341 VALS(afn_vals), 0x0, NULL, HFILL }},
3342 { &hf_bgp_cap_mp_safi,
3343 { "SAFI", "bgp.cap.mp.safi", FT_UINT8, BASE_DEC,
3344 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
3345 { &hf_bgp_cap_gr_timers,
3346 { "Restart Timers", "bgp.cap.gr.timers", FT_UINT16, BASE_HEX,
3347 NULL, 0x0, NULL, HFILL }},
3348 { &hf_bgp_cap_gr_timers_restart_flag,
3349 { "Restart", "bgp.cap.gr.timers.restart", FT_BOOLEAN, 16,
3350 TFS(&tfs_yes_no), 0x8000, NULL, HFILL }},
3351 { &hf_bgp_cap_gr_timers_restart_time,
3352 { "Time", "bgp.cap.gr.timers.restart", FT_UINT16, BASE_DEC,
3353 NULL, 0x0FFF, "in us", HFILL }},
3354 { &hf_bgp_cap_gr_afi,
3355 { "AFI", "bgp.cap.gr.afi", FT_UINT16, BASE_DEC,
3356 VALS(afn_vals), 0x0, NULL, HFILL }},
3357 { &hf_bgp_cap_gr_safi,
3358 { "SAFI", "bgp.cap.gr.safi", FT_UINT8, BASE_DEC,
3359 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
3360 { &hf_bgp_cap_gr_flag,
3361 { "Flag", "bgp.cap.gr.flag", FT_UINT8, BASE_HEX,
3362 NULL, 0x0, NULL, HFILL }},
3363 { &hf_bgp_cap_gr_flag_pfs,
3364 { "Preserve forwarding state", "bgp.cap.gr.flag.pfs", FT_BOOLEAN, 8,
3365 TFS(&tfs_yes_no), 0x80, NULL, HFILL }},
3367 { "AS Number", "bgp.cap.4as", FT_UINT32, BASE_DEC,
3368 NULL, 0x0, NULL, HFILL }},
3370 { "Capability Dynamic", "bgp.cap.dc", FT_UINT8, BASE_DEC,
3371 VALS(capability_vals), 0x0, NULL, HFILL }},
3372 { &hf_bgp_cap_ap_afi,
3373 { "AFI", "bgp.cap.ap.afi", FT_UINT16, BASE_DEC,
3374 VALS(afn_vals), 0x0, NULL, HFILL }},
3375 { &hf_bgp_cap_ap_safi,
3376 { "SAFI", "bgp.cap.ap.safi", FT_UINT8, BASE_DEC,
3377 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
3378 { &hf_bgp_cap_ap_sendreceive,
3379 { "Send/Receive", "bgp.cap.ap.sendreceive", FT_UINT8, BASE_DEC,
3380 VALS(orf_send_recv_vals), 0x0, NULL, HFILL }},
3381 { &hf_bgp_cap_orf_afi,
3382 { "AFI", "bgp.cap.orf.afi", FT_UINT16, BASE_DEC,
3383 VALS(afn_vals), 0x0, NULL, HFILL }},
3384 { &hf_bgp_cap_orf_safi,
3385 { "SAFI", "bgp.cap.orf.safi", FT_UINT8, BASE_DEC,
3386 VALS(bgpattr_nlri_safi), 0x0, NULL, HFILL }},
3387 { &hf_bgp_cap_orf_number,
3388 { "Number", "bgp.cap.orf.number", FT_UINT8, BASE_DEC,
3389 NULL, 0x0, NULL, HFILL }},
3390 { &hf_bgp_cap_orf_type,
3391 { "Type", "bgp.cap.orf.type", FT_UINT8, BASE_DEC,
3392 VALS(orf_type_vals), 0x0, NULL, HFILL }},
3393 { &hf_bgp_cap_orf_sendreceive,
3394 { "Send Receive", "bgp.cap.orf.type", FT_UINT8, BASE_DEC,
3395 VALS(orf_send_recv_vals), 0x0, NULL, HFILL }},
3397 { &hf_bgp_aggregator_as,
3398 { "Aggregator AS", "bgp.aggregator_as", FT_UINT16, BASE_DEC,
3399 NULL, 0x0, NULL, HFILL}},
3400 { &hf_bgp_aggregator_origin,
3401 { "Aggregator origin", "bgp.aggregator_origin", FT_IPv4, BASE_NONE,
3402 NULL, 0x0, NULL, HFILL}},
3404 { "AS Path", "bgp.as_path", FT_UINT16, BASE_DEC,
3405 NULL, 0x0, NULL, HFILL}},
3406 { &hf_bgp_community_as,
3407 { "Community AS", "bgp.community_as", FT_UINT16, BASE_DEC,
3408 NULL, 0x0, NULL, HFILL}},
3409 { &hf_bgp_community_value,
3410 { "Community value", "bgp.community_value", FT_UINT16, BASE_DEC,
3411 NULL, 0x0, NULL, HFILL}},
3412 { &hf_bgp_local_pref,
3413 { "Local preference", "bgp.local_pref", FT_UINT32, BASE_DEC,
3414 NULL, 0x0, NULL, HFILL}},
3415 { &hf_bgp_mp_reach_nlri_ipv4_prefix,
3416 { "MP Reach NLRI IPv4 prefix", "bgp.mp_reach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
3417 NULL, 0x0, NULL, HFILL}},
3418 { &hf_bgp_mp_unreach_nlri_ipv4_prefix,
3419 { "MP Unreach NLRI IPv4 prefix", "bgp.mp_unreach_nlri_ipv4_prefix", FT_IPv4, BASE_NONE,
3420 NULL, 0x0, NULL, HFILL}},
3421 { &hf_bgp_mp_nlri_tnl_id,
3422 { "MP Reach NLRI Tunnel Identifier", "bgp.mp_nlri_tnl_id", FT_UINT16, BASE_HEX,
3423 NULL, 0x0, NULL, HFILL}},
3424 { &hf_bgp_multi_exit_disc,
3425 { "Multiple exit discriminator", "bgp.multi_exit_disc", FT_UINT32, BASE_DEC,
3426 NULL, 0x0, NULL, HFILL}},
3428 { "Next hop", "bgp.next_hop", FT_IPv4, BASE_NONE,
3429 NULL, 0x0, NULL, HFILL}},
3430 { &hf_bgp_nlri_prefix,
3431 { "NLRI prefix", "bgp.nlri_prefix", FT_IPv4, BASE_NONE,
3432 NULL, 0x0, NULL, HFILL}},
3433 { &hf_bgp_nlri_path_id,
3434 { "NLRI path id", "bgp.nlri_path_id", FT_UINT32, BASE_DEC,
3435 NULL, 0x0, NULL, HFILL}},
3437 { "Origin", "bgp.origin", FT_UINT8, BASE_DEC,
3438 VALS(bgpattr_origin), 0x0, NULL, HFILL}},
3439 { &hf_bgp_originator_id,
3440 { "Originator identifier", "bgp.originator_id", FT_IPv4, BASE_NONE,
3441 NULL, 0x0, NULL, HFILL}},
3443 { "Transitive bit", "bgp.ssa_t", FT_BOOLEAN, 8,
3444 NULL, 0x80, "SSA Transitive bit", HFILL}},
3446 { "SSA Type", "bgp.ssa_type", FT_UINT16, BASE_DEC,
3447 VALS(bgp_ssa_type), 0x7FFF, NULL, HFILL}},
3449 { "Length", "bgp.ssa_len", FT_UINT16, BASE_DEC,
3450 NULL, 0x0, "SSA Length", HFILL}},
3451 { &hf_bgp_ssa_value,
3452 { "Value", "bgp.ssa_value", FT_BYTES, BASE_NONE,
3453 NULL, 0x0, "SSA Value", HFILL}},
3454 { &hf_bgp_ssa_l2tpv3_pref,
3455 { "Preference", "bgp.ssa_l2tpv3_pref", FT_UINT16, BASE_DEC,
3456 NULL, 0x0, NULL, HFILL}},
3457 { &hf_bgp_ssa_l2tpv3_s,
3458 { "Sequencing bit", "bgp.ssa_l2tpv3_s", FT_BOOLEAN, 8,
3459 NULL, 0x80, "Sequencing S-bit", HFILL}},
3460 { &hf_bgp_ssa_l2tpv3_unused,
3461 { "Unused", "bgp.ssa_l2tpv3_Unused", FT_BOOLEAN, 8,
3462 NULL, 0x7F, "Unused Flags", HFILL}},
3463 { &hf_bgp_ssa_l2tpv3_cookie_len,
3464 { "Cookie Length", "bgp.ssa_l2tpv3_cookie_len", FT_UINT8, BASE_DEC,
3465 NULL, 0x0, NULL, HFILL}},
3466 { &hf_bgp_ssa_l2tpv3_session_id,
3467 { "Session ID", "bgp.ssa_l2tpv3_session_id", FT_UINT32, BASE_DEC,
3468 NULL, 0x0, NULL, HFILL}},
3469 { &hf_bgp_ssa_l2tpv3_cookie,
3470 { "Cookie", "bgp.ssa_l2tpv3_cookie", FT_BYTES, BASE_NONE,
3471 NULL, 0x0, NULL, HFILL}},
3472 { &hf_bgp_withdrawn_prefix,
3473 { "Withdrawn prefix", "bgp.withdrawn_prefix", FT_IPv4, BASE_NONE,
3474 NULL, 0x0, NULL, HFILL}},
3475 { &hf_bgp_cluster_list,
3476 { "Cluster List", "bgp.cluster_list", FT_BYTES, BASE_NONE,
3477 NULL, 0x0, NULL, HFILL}}
3480 static gint *ett[] = {
3486 &ett_bgp_attr_flags,
3488 &ett_bgp_mp_reach_nlri,
3489 &ett_bgp_mp_unreach_nlri,
3494 &ett_bgp_notification,
3495 &ett_bgp_route_refresh,
3496 &ett_bgp_capability,
3498 &ett_bgp_as_path_segments,
3499 &ett_bgp_communities,
3500 &ett_bgp_cluster_list,
3504 &ett_bgp_extended_communities,
3505 &ett_bgp_ext_com_flags,
3507 &ett_bgp_ssa_subtree,
3511 module_t *bgp_module;
3512 static enum_val_t asn_len[] = {
3513 {"auto-detect", "Auto-detect", 0},
3514 {"2", "2 octet", 2},
3515 {"4", "4 octet", 4},
3519 proto_bgp = proto_register_protocol("Border Gateway Protocol",
3521 proto_register_field_array(proto_bgp, hf, array_length(hf));
3522 proto_register_subtree_array(ett, array_length(ett));
3524 bgp_module = prefs_register_protocol(proto_bgp, NULL);
3525 prefs_register_bool_preference(bgp_module, "desegment",
3526 "Reassemble BGP messages spanning multiple TCP segments",
3527 "Whether the BGP dissector should reassemble messages spanning multiple TCP segments."
3528 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3530 prefs_register_enum_preference(bgp_module, "asn_len",
3531 "Length of the AS number",
3532 "BGP dissector detect the length of the AS number in AS_PATH attributes automatically or manually (NOTE: Automatic detection is not 100% accurate)",
3533 &bgp_asn_len, asn_len, FALSE);
3537 proto_reg_handoff_bgp(void)
3539 dissector_handle_t bgp_handle;
3541 bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
3542 dissector_add_uint("tcp.port", BGP_TCP_PORT, bgp_handle);
3545 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3550 * indent-tabs-mode: nil
3553 * ex: set shiftwidth=4 tabstop=8 expandtab:
3554 * :indentSize=4:tabSize=8:noTabs=true: