2 * Routines for BGP packet dissection.
3 * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
5 * $Id: packet-bgp.c,v 1.74 2003/01/31 08:09:24 guy Exp $
8 * RFC1771 A Border Gateway Protocol 4 (BGP-4)
9 * RFC1965 Autonomous System Confederations for BGP
10 * RFC1997 BGP Communities Attribute
11 * RFC2547 BGP/MPLS VPNs
12 * RFC2796 BGP Route Reflection An alternative to full mesh IBGP
13 * RFC2842 Capabilities Advertisement with BGP-4
14 * RFC2858 Multiprotocol Extensions for BGP-4
15 * RFC2918 Route Refresh Capability for BGP-4
16 * RFC3107 Carrying Label Information in BGP-4
17 * Draft Ramahandra on Extended Communities Extentions
18 * draft-ietf-idr-as4bytes-06
19 * draft-ietf-idr-dynamic-cap-03
22 * Destination Preference Attribute for BGP (work in progress)
23 * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
25 * Ethereal - Network traffic analyzer
26 * By Gerald Combs <gerald@ethereal.com>
27 * Copyright 1998 Gerald Combs
29 * This program is free software; you can redistribute it and/or
30 * modify it under the terms of the GNU General Public License
31 * as published by the Free Software Foundation; either version 2
32 * of the License, or (at your option) any later version.
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
54 #ifdef NEED_SNPRINTF_H
55 # include "snprintf.h"
58 #include <epan/packet.h>
59 #include "packet-bgp.h"
60 #include "packet-ipv6.h"
64 static const value_string bgptypevals[] = {
65 { BGP_OPEN, "OPEN Message" },
66 { BGP_UPDATE, "UPDATE Message" },
67 { BGP_NOTIFICATION, "NOTIFICATION Message" },
68 { BGP_KEEPALIVE, "KEEPALIVE Message" },
69 { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
70 { BGP_CAPABILITY, "CAPABILITY Message" },
71 { BGP_ROUTE_REFRESH_CISCO, "Cisco ROUTE-REFRESH Message" },
75 static const value_string bgpnotify_major[] = {
76 { 1, "Message Header Error" },
77 { 2, "OPEN Message Error" },
78 { 3, "UPDATE Message Error" },
79 { 4, "Hold Timer Expired" },
80 { 5, "Finite State Machine Error" },
82 { 7, "CAPABILITY Message Error" },
86 static const value_string bgpnotify_minor_1[] = {
87 { 1, "Connection Not Synchronized" },
88 { 2, "Bad Message Length" },
89 { 3, "Bad Message Type" },
93 static const value_string bgpnotify_minor_2[] = {
94 { 1, "Unsupported Version Number" },
96 { 3, "Bad BGP Identifier" },
97 { 4, "Unsupported Optional Parameter" },
98 { 5, "Authentication Failure" },
99 { 6, "Unacceptable Hold Time" },
100 { 7, "Unsupported Capability" },
104 static const value_string bgpnotify_minor_3[] = {
105 { 1, "Malformed Attribute List" },
106 { 2, "Unrecognized Well-known Attribute" },
107 { 3, "Missing Well-known Attribute" },
108 { 4, "Attribute Flags Error" },
109 { 5, "Attribute Length Error" },
110 { 6, "Invalid ORIGIN Attribute" },
111 { 7, "AS Routing Loop" },
112 { 8, "Invalid NEXT_HOP Attribute" },
113 { 9, "Optional Attribute Error" },
114 { 10, "Invalid Network Field" },
115 { 11, "Malformed AS_PATH" },
119 static const value_string bgpnotify_minor_7[] = {
120 { 1, "Invalid Action Value" },
121 { 2, "Invalid Capability Length" },
122 { 3, "Malformed Capability Value" },
123 { 4, "Unsopported Capability Code" },
127 static const value_string *bgpnotify_minor[] = {
128 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3,
131 static const value_string bgpattr_origin[] = {
138 static const value_string as_segment_type[] = {
140 { 2, "AS_SEQUENCE" },
141 /* RFC1965 has the wrong values, corrected in */
142 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
143 { 4, "AS_CONFED_SET" },
144 { 3, "AS_CONFED_SEQUENCE" },
148 static const value_string bgpattr_type[] = {
149 { BGPTYPE_ORIGIN, "ORIGIN" },
150 { BGPTYPE_AS_PATH, "AS_PATH" },
151 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
152 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
153 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
154 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
155 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
156 { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
157 { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
158 { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
159 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
160 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
161 { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
162 { BGPTYPE_NEW_AS_PATH, "NEW_AS_PATH" },
163 { BGPTYPE_NEW_AGGREGATOR, "NEW_AGGREGATOR" },
167 /* Beware : See also MAX_SIZE_OF_EXT_COM_NAMES */
168 static const value_string bgpext_com_type[] = {
169 { BGP_EXT_COM_RT_0, "Route Target" },
170 { BGP_EXT_COM_RT_1, "Route Target" },
171 { BGP_EXT_COM_RO_0, "Route Origin" },
172 { BGP_EXT_COM_RO_1, "Route Origin" },
173 { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
174 { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
175 { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
176 { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
177 { BGP_EXT_COM_L2INFO, "Layer 2 Information" },
181 static const value_string bgp_l2vpn_encaps[] = {
184 { 2, "ATM AAL5 VCC transport"},
185 { 3, "ATM transparent cell transport"},
186 { 4, "Ethernet VLAN"},
191 { 9, "ATM VCC cell transport"},
192 { 10, "ATM VPC cell transport"},
195 { 64, "IP-interworking"},
199 static const value_string bgpext_ospf_rtype[] = {
200 { BGP_OSPF_RTYPE_RTR, "Router" },
201 { BGP_OSPF_RTYPE_NET, "Network" },
202 { BGP_OSPF_RTYPE_SUM, "Summary" },
203 { BGP_OSPF_RTYPE_EXT, "External" },
204 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
205 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
210 /* MUST be resized if a longer named extended community is added */
211 #define MAX_SIZE_OF_EXT_COM_NAMES 20
213 /* Subsequent address family identifier, RFC2858 */
214 static const value_string bgpattr_nlri_safi[] = {
216 { SAFNUM_UNICAST, "Unicast" },
217 { SAFNUM_MULCAST, "Multicast" },
218 { SAFNUM_UNIMULC, "Unicast+Multicast" },
219 { SAFNUM_MPLS_LABEL, "Labeled Unicast"},
220 { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" }, /* draft-rosen-rfc2547bis-03 */
221 { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
222 { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
226 /* ORF Type, draft-ietf-idr-route-filter-04.txt */
227 static const value_string orf_type_vals[] = {
228 { 2, "Communities ORF-Type" },
229 { 3, "Extended Communities ORF-Type" },
230 { 128, "Cisco PrefixList ORF-Type" },
231 { 129, "Cisco CommunityList ORF-Type" },
232 { 130, "Cisco Extended CommunityList ORF-Type" },
233 { 131, "Cisco AsPathList ORF-Type" },
237 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
238 static const value_string orf_send_recv_vals[] = {
245 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
246 static const value_string orf_when_vals[] = {
252 static const value_string orf_entry_action_vals[] = {
255 { 0x80, "RemoveAll" },
259 static const value_string orf_entry_match_vals[] = {
265 static const value_string capability_vals[] = {
266 { BGP_CAPABILITY_RESERVED, "Reserved capability" },
267 { BGP_CAPABILITY_MULTIPROTOCOL, "Multiprotocol extensions capability" },
268 { BGP_CAPABILITY_ROUTE_REFRESH, "Route refresh capability" },
269 { BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING, "Cooperative route filtering capability" },
270 { BGP_CAPABILITY_GRACEFUL_RESTART, "Graceful Restart capability" },
271 { BGP_CAPABILITY_4_OCTET_AS_NUMBER, "Support for 4-octet AS number capability" },
272 { BGP_CAPABILITY_DYNAMIC_CAPABILITY, "Support for Dynamic capability" },
273 { BGP_CAPABILITY_ROUTE_REFRESH_CISCO, "Route refresh capability" },
274 { BGP_CAPABILITY_ORF_CISCO, "Cooperative route filtering capability" },
277 /* Capability Message action code */
278 static const value_string bgpcap_action[] = {
279 { 0, "advertising a capability" },
280 { 1, "removing a capability" },
285 /* Maximal size of an IP address string */
286 #define MAX_SIZE_OF_IP_ADDR_STRING 16
288 static int proto_bgp = -1;
289 static int hf_bgp_type = -1;
291 static gint ett_bgp = -1;
292 static gint ett_bgp_unfeas = -1;
293 static gint ett_bgp_attrs = -1;
294 static gint ett_bgp_attr = -1;
295 static gint ett_bgp_attr_flags = -1;
296 static gint ett_bgp_mp_nhna = -1;
297 static gint ett_bgp_mp_reach_nlri = -1;
298 static gint ett_bgp_mp_unreach_nlri = -1;
299 static gint ett_bgp_mp_snpa = -1;
300 static gint ett_bgp_nlri = -1;
301 static gint ett_bgp_open = -1;
302 static gint ett_bgp_update = -1;
303 static gint ett_bgp_notification = -1;
304 static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
305 static gint ett_bgp_capability = -1;
306 static gint ett_bgp_as_paths = -1;
307 static gint ett_bgp_communities = -1;
308 static gint ett_bgp_cluster_list = -1; /* cluster list tree */
309 static gint ett_bgp_options = -1; /* optional parameters tree */
310 static gint ett_bgp_option = -1; /* an optional parameter tree */
311 static gint ett_bgp_extended_communities = -1 ; /* extended communities list tree */
312 static gint ett_bgp_orf = -1; /* orf (outbound route filter) tree */
313 static gint ett_bgp_orf_entry = -1; /* orf entry tree */
316 static gboolean bgp_desegment = TRUE;
318 static gint bgp_asn_len = 0;
321 * Decode an IPv4 prefix.
324 decode_prefix4(tvbuff_t *tvb, gint offset, char *buf, int buflen)
326 guint8 addr[4]; /* IP address */
327 guint8 plen; /* prefix length */
328 int length; /* number of octets needed for prefix */
331 plen = tvb_get_guint8(tvb, offset);
334 length = (plen + 7) / 8;
337 memset(addr, 0, sizeof(addr));
338 tvb_memcpy(tvb, addr, offset + 1, length);
340 addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
342 /* hand back a formatted string */
343 snprintf(buf, buflen, "%s/%u", ip_to_str(addr), plen);
348 * Decode an IPv6 prefix.
351 decode_prefix6(tvbuff_t *tvb, gint offset, char *buf, int buflen)
353 struct e_in6_addr addr; /* IPv6 address */
354 int plen; /* prefix length */
355 int length; /* number of octets needed for prefix */
358 plen = tvb_get_guint8(tvb, offset);
359 if (plen < 0 || 128 < plen)
361 length = (plen + 7) / 8;
364 memset(&addr, 0, sizeof(addr));
365 tvb_memcpy(tvb, (guint8 *)&addr, offset + 1, length);
367 addr.s6_addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
369 /* hand back a formatted string */
370 snprintf(buf, buflen, "%s/%d", ip6_to_str(&addr), plen);
377 * Decode an MPLS label stack
380 decode_MPLS_stack(tvbuff_t *tvb, gint offset, char *buf, size_t buflen)
382 guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
383 gint index; /* index for the label stack */
384 char junk_buf[256]; /* tmp */
387 label_entry = 0x000000 ;
391 while ((label_entry & 0x000001) == 0) {
393 label_entry = tvb_get_ntoh24(tvb, index) ;
395 /* withdrawn routes may contain 0 or 0x800000 in the first label */
396 if((index-offset)==0&&(label_entry==0||label_entry==0x800000)) {
397 snprintf(buf, buflen, "0 (withdrawn)");
401 snprintf(junk_buf, sizeof(junk_buf),"%u%s", (label_entry >> 4), ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
402 if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
403 strcat(buf, junk_buf);
406 if ((label_entry & 0x000001) == 0) {
407 /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
408 strcpy(junk_buf, " (BOGUS: Bottom of Stack NOT set!)");
409 if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
410 strcat(buf, junk_buf);
415 return((index - offset) / 3);
419 * Decode a multiprotocol address
423 mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *buf, int buflen)
425 int length; /* length of the address in byte */
426 guint8 ip4addr[4],ip4addr2[4]; /* IPv4 address */
427 guint16 rd_type; /* Route Distinguisher type */
428 struct e_in6_addr ip6addr; /* IPv6 address */
437 case SAFNUM_MPLS_LABEL:
439 tvb_memcpy(tvb, ip4addr, offset, sizeof(ip4addr));
440 snprintf(buf, buflen, "%s", ip_to_str(ip4addr));
442 case SAFNUM_LAB_VPNUNICAST:
443 case SAFNUM_LAB_VPNMULCAST:
444 case SAFNUM_LAB_VPNUNIMULC:
445 rd_type=tvb_get_ntohs(tvb,offset) ;
448 length = 8 + sizeof(ip4addr);
449 tvb_memcpy(tvb, ip4addr, offset + 8, sizeof(ip4addr)); /* Next Hop */
450 snprintf(buf, buflen, "Empty Label Stack RD=%u:%u IP=%s",
451 tvb_get_ntohs(tvb, offset + 2),
452 tvb_get_ntohl(tvb, offset + 4),
456 length = 8 + sizeof(ip4addr);
457 tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr)); /* IP part of the RD */
458 tvb_memcpy(tvb, ip4addr2, offset + 8, sizeof(ip4addr)); /* Next Hop */
459 snprintf(buf, buflen, "Empty Label Stack RD=%s:%u IP=%s",
461 tvb_get_ntohs(tvb, offset + 6),
462 ip_to_str(ip4addr2));
466 snprintf(buf, buflen, "Unknown (0x%04x)labeled VPN address format",rd_type);
472 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
482 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8,offset, 16);
483 snprintf(buf, buflen, "%s", ip6_to_str(&ip6addr));
485 case SAFNUM_LAB_VPNUNICAST:
486 case SAFNUM_LAB_VPNMULCAST:
487 case SAFNUM_LAB_VPNUNIMULC:
488 rd_type=tvb_get_ntohs(tvb,offset) ;
492 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, 16); /* Next Hop */
493 snprintf(buf, buflen, "Empty Label Stack RD=%u:%u IP=%s",
494 tvb_get_ntohs(tvb, offset + 2),
495 tvb_get_ntohl(tvb, offset + 4),
496 ip6_to_str(&ip6addr));
500 tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr)); /* IP part of the RD */
501 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, 16); /* Next Hop */
502 snprintf(buf, buflen, "Empty Label Stack RD=%s:%u IP=%s",
504 tvb_get_ntohs(tvb, offset + 6),
505 ip6_to_str(&ip6addr));
509 snprintf(buf, buflen, "Unknown (0x%04x)labeled VPN address format",rd_type);
515 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
521 case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
522 case SAFNUM_LAB_VPNMULCAST:
523 case SAFNUM_LAB_VPNUNIMULC:
524 length = 4; /* the next-hop is simply an ipv4 addr */
525 tvb_memcpy(tvb, ip4addr, offset + 0, 4);
526 snprintf(buf, buflen, "IP=%s",
531 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
537 snprintf(buf, buflen, "Unknown AFI (%u) value", afi);
544 * Decode a multiprotocol prefix
547 decode_prefix_MP(guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *buf, int buflen)
549 int length; /* length of the prefix in byte */
550 guint8 plen; /* length of the prefix in bit */
551 int labnum; /* number of labels */
552 int ce_id,labblk_off;
553 guint8 ip4addr[4],ip4addr2[4]; /* IPv4 address */
554 struct e_in6_addr ip6addr; /* IPv6 address */
555 guint16 rd_type; /* Route Distinguisher type */
556 char lab_stk[256]; /* label stack */
566 length = decode_prefix4(tvb, offset, buf, buflen) - 1 ;
568 case SAFNUM_MPLS_LABEL:
569 plen = tvb_get_guint8(tvb,offset) ;
570 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
572 offset += (1 + labnum * 3);
573 plen -= (labnum * 3*8);
579 length = (plen + 7) / 8;
580 memset(ip4addr, 0, sizeof(ip4addr));
581 tvb_memcpy(tvb, ip4addr, offset, length);
583 ip4addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
585 snprintf(buf,buflen, "Label Stack=%s IP=%s/%d",
589 length += (labnum*3) ;
592 case SAFNUM_LAB_VPNUNICAST:
593 case SAFNUM_LAB_VPNMULCAST:
594 case SAFNUM_LAB_VPNUNIMULC:
595 plen = tvb_get_guint8(tvb,offset) ;
597 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
599 offset += (1 + labnum * 3);
600 plen -= (labnum * 3*8);
602 rd_type=tvb_get_ntohs(tvb,offset) ;
606 case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
612 length = (plen + 7) / 8;
613 memset(ip4addr, 0, sizeof(ip4addr));
614 tvb_memcpy(tvb, ip4addr, offset + 8, length);
616 ip4addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
618 snprintf(buf,buflen, "Label Stack=%s RD=%u:%u, IP=%s/%d",
620 tvb_get_ntohs(tvb, offset + 2),
621 tvb_get_ntohl(tvb, offset + 4),
624 length += (labnum * 3 + 8) ;
626 case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
627 tvb_memcpy(tvb, ip4addr, offset + 2, 4);
634 length = (plen + 7) / 8;
635 memset(ip4addr2, 0, sizeof(ip4addr2));
636 tvb_memcpy(tvb, ip4addr2, offset + 8, length);
638 ip4addr2[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
640 snprintf(buf,buflen, "Label Stack=%s RD=%s:%u, IP=%s/%d",
643 tvb_get_ntohs(tvb, offset + 6),
646 length += (labnum * 3 + 8) ;
650 snprintf(buf,buflen, "Unknown labeled VPN address format");
656 snprintf(buf,buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
665 length = decode_prefix6(tvb, offset, buf, buflen) - 1 ;
668 case SAFNUM_LAB_VPNUNICAST:
669 case SAFNUM_LAB_VPNMULCAST:
670 case SAFNUM_LAB_VPNUNIMULC:
671 plen = tvb_get_guint8(tvb,offset) ;
673 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
675 offset += (1 + labnum * 3);
676 plen -= (labnum * 3*8);
678 rd_type=tvb_get_ntohs(tvb,offset) ;
688 length = (plen + 7) / 8;
689 memset(ip6addr.u6_addr.u6_addr8, 0, 16);
690 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, length);
692 ip6addr.u6_addr.u6_addr8[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
694 snprintf(buf,buflen, "Label Stack=%s RD=%u:%u, IP=%s/%d",
696 tvb_get_ntohs(tvb, offset + 2),
697 tvb_get_ntohl(tvb, offset + 4),
698 ip6_to_str(&ip6addr),
700 length += (labnum * 3 + 8) ;
703 tvb_memcpy(tvb, ip4addr, offset + 2, sizeof(ip4addr));
710 length = (plen + 7) / 8;
711 memset(ip6addr.u6_addr.u6_addr8, 0, 16);
712 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8, offset + 8, length);
714 ip6addr.u6_addr.u6_addr8[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
716 snprintf(buf,buflen, "Label Stack=%s RD=%s:%u, IP=%s/%d",
719 tvb_get_ntohs(tvb, offset + 6),
720 ip6_to_str(&ip6addr),
722 length += (labnum * 3 + 8) ;
726 snprintf(buf,buflen, "Unknown labeled VPN address format");
734 snprintf(buf,buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
740 case SAFNUM_LAB_VPNUNICAST:
741 case SAFNUM_LAB_VPNMULCAST:
742 case SAFNUM_LAB_VPNUNIMULC:
743 plen = tvb_get_ntohs(tvb,offset);
744 rd_type=tvb_get_ntohs(tvb,offset+2);
745 ce_id=tvb_get_ntohs(tvb,offset+10);
746 labblk_off=tvb_get_ntohs(tvb,offset+12);
747 labnum = decode_MPLS_stack(tvb, offset + 14, lab_stk, sizeof(lab_stk));
751 tvb_memcpy(tvb, ip4addr, offset + 6, 4);
752 snprintf(buf,buflen, "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
753 tvb_get_ntohs(tvb, offset + 4),
760 tvb_memcpy(tvb, ip4addr, offset + 4, 4);
761 snprintf(buf,buflen, "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
763 tvb_get_ntohs(tvb, offset + 8),
770 snprintf(buf,buflen, "Unknown labeled VPN address format");
773 /* FIXME there are subTLVs left to decode ... for now lets omit them */
774 length=plen+1; /* should be 2 but length+1 is returned at the end */
778 snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
784 snprintf(buf,buflen, "Unknown AFI (%u) value", afi);
791 * Dissect a BGP capability.
794 dissect_bgp_capability_item(tvbuff_t *tvb, int *p, proto_tree *tree, int ctype, int clen)
798 guint8 orfnum; /* number of ORFs */
799 guint8 orftype; /* ORF Type */
800 guint8 orfsendrecv; /* ORF Send/Receive */
801 int tclen; /* capability length */
804 /* check the capability type */
806 case BGP_CAPABILITY_RESERVED:
807 proto_tree_add_text(tree, tvb, *p - 2, 1,
808 "Capability code: %s (%d)", val_to_str(ctype,
809 capability_vals, "Unknown capability"), ctype);
810 proto_tree_add_text(tree, tvb, *p - 1,
811 1, "Capability length: %u %s", clen,
812 (clen == 1) ? "byte" : "bytes");
814 proto_tree_add_text(tree, tvb, *p,
815 clen, "Capability value: Unknown");
819 case BGP_CAPABILITY_MULTIPROTOCOL:
820 proto_tree_add_text(tree, tvb, *p - 2, 1,
821 "Capability code: %s (%d)", val_to_str(ctype,
822 capability_vals, "Unknown capability"), ctype);
824 proto_tree_add_text(tree, tvb, *p - 1,
825 1, "Capability length: Invalid");
826 proto_tree_add_text(tree, tvb, *p,
827 clen, "Capability value: Unknown");
830 proto_tree_add_text(tree, tvb, *p - 1,
831 1, "Capability length: %u %s", clen,
832 (clen == 1) ? "byte" : "bytes");
833 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
834 subtree = proto_item_add_subtree(ti, ett_bgp_option);
836 i = tvb_get_ntohs(tvb, *p);
837 proto_tree_add_text(subtree, tvb, *p,
838 2, "Address family identifier: %s (%u)",
839 val_to_str(i, afn_vals, "Unknown"), i);
842 proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
845 i = tvb_get_guint8(tvb, *p);
846 proto_tree_add_text(subtree, tvb, *p,
847 1, "Subsequent address family identifier: %s (%u)",
848 val_to_str(i, bgpattr_nlri_safi,
849 i >= 128 ? "Vendor specific" : "Unknown"), i);
853 case BGP_CAPABILITY_GRACEFUL_RESTART:
854 proto_tree_add_text(tree, tvb, *p - 2, 1,
855 "Capability code: %s (%d)", val_to_str(ctype,
856 capability_vals, "Unknown capability"), ctype);
858 proto_tree_add_text(tree, tvb, *p,
859 clen, "Capability value: Invalid");
862 proto_tree_add_text(tree, tvb, *p - 1,
863 1, "Capability length: %u %s", clen,
864 (clen == 1) ? "byte" : "bytes");
865 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
866 subtree = proto_item_add_subtree(ti, ett_bgp_option);
868 i = tvb_get_ntohs(tvb, *p);
869 proto_tree_add_text(subtree, tvb, *p,
870 2, "Restart Flags: [%s], Restart Time %us",
871 (i&0x8000) ? "R" : "none", i&0xfff);
875 * what follows is alist of AFI/SAFI/flag triplets
876 * read it until the TLV ends
880 i = tvb_get_ntohs(tvb, *p);
881 proto_tree_add_text(subtree, tvb, *p,
882 2, "Address family identifier: %s (%u)",
883 val_to_str(i, afn_vals, "Unknown"), i);
886 i = tvb_get_guint8(tvb, *p);
887 proto_tree_add_text(subtree, tvb, *p,
888 1, "Subsequent address family identifier: %s (%u)",
889 val_to_str(i, bgpattr_nlri_safi,
890 i >= 128 ? "Vendor specific" : "Unknown"), i);
893 i = tvb_get_guint8(tvb, *p);
894 proto_tree_add_text(subtree, tvb, *p, 1,
895 "Preserve forwarding state: %s",
896 (i&0x80) ? "yes" : "no");
903 case BGP_CAPABILITY_4_OCTET_AS_NUMBER:
904 proto_tree_add_text(tree, tvb, *p - 2, 1,
905 "Capability code: %s (%d)", val_to_str(ctype,
906 capability_vals, "Unknown capability"), ctype);
908 proto_tree_add_text(tree, tvb, *p,
909 clen, "Capability value: Invalid");
912 proto_tree_add_text(tree, tvb, *p - 1,
913 1, "Capability length: %u %s", clen,
914 (clen == 1) ? "byte" : "bytes");
915 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
916 subtree = proto_item_add_subtree(ti, ett_bgp_option);
917 proto_tree_add_text(subtree, tvb, *p, 4,
918 "AS number: %d", tvb_get_ntohl(tvb, *p));
922 case BGP_CAPABILITY_DYNAMIC_CAPABILITY:
923 proto_tree_add_text(tree, tvb, *p - 2, 1,
924 "Capability code: %s (%d)", val_to_str(ctype,
925 capability_vals, "Unknown capability"), ctype);
926 proto_tree_add_text(tree, tvb, *p - 1, 1,
927 "Capability length: %u %s", clen,
928 (clen == 1) ? "byte" : "bytes");
930 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
931 subtree = proto_item_add_subtree(ti, ett_bgp_option);
932 for (i = 0; (int)i <= clen; i++) {
933 proto_tree_add_text(subtree, tvb, *p, 1,
934 "Capability code: %s (%d)", val_to_str(ctype,
935 capability_vals, "Unknown capability"),
936 tvb_get_guint8(tvb, *p));
941 case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
942 case BGP_CAPABILITY_ROUTE_REFRESH:
943 proto_tree_add_text(tree, tvb, *p - 2, 1,
944 "Capability code: %s (%d)", val_to_str(ctype,
945 capability_vals, "Unknown capability"), ctype);
947 proto_tree_add_text(tree, tvb, *p,
948 clen, "Capability value: Invalid");
951 proto_tree_add_text(tree, tvb, *p - 1,
952 1, "Capability length: %u %s", clen,
953 (clen == 1) ? "byte" : "bytes");
957 case BGP_CAPABILITY_ORF_CISCO:
958 case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
959 proto_tree_add_text(tree, tvb, *p - 2, 1,
960 "Capability code: %s (%d)", val_to_str(ctype,
961 capability_vals, "Unknown capability"), ctype);
962 proto_tree_add_text(tree, tvb, *p - 1,
963 1, "Capability length: %u %s", clen,
964 (clen == 1) ? "byte" : "bytes");
965 ti = proto_tree_add_text(tree, tvb, *p, clen, "Capability value");
966 subtree = proto_item_add_subtree(ti, ett_bgp_option);
968 i = tvb_get_ntohs(tvb, *p);
969 proto_tree_add_text(subtree, tvb, *p,
970 2, "Address family identifier: %s (%u)",
971 val_to_str(i, afn_vals, "Unknown"), i);
974 proto_tree_add_text(subtree, tvb, *p, 1, "Reserved: 1 byte");
977 i = tvb_get_guint8(tvb, *p);
978 proto_tree_add_text(subtree, tvb, *p,
979 1, "Subsequent address family identifier: %s (%u)",
980 val_to_str(i, bgpattr_nlri_safi,
981 i >= 128 ? "Vendor specific" : "Unknown"), i);
984 orfnum = tvb_get_guint8(tvb, *p);
985 proto_tree_add_text(subtree, tvb, *p, 1, "Number of ORFs: %u", orfnum);
987 for (i=0; i<orfnum; i++) {
989 orftype = tvb_get_guint8(tvb, *p);
990 proto_tree_add_text(subtree, tvb, *p, 1, "ORF Type: %s (%u)",
991 val_to_str(orftype, orf_type_vals,"Unknown"), orftype);
994 orfsendrecv = tvb_get_guint8(tvb, *p);
995 proto_tree_add_text(subtree, tvb, *p,
996 1, "Send/Receive: %s (%u)",
997 val_to_str(orfsendrecv, orf_send_recv_vals,
998 "Uknown"), orfsendrecv);
1002 /* unknown capability */
1004 proto_tree_add_text(tree, tvb, *p - 2, 1,
1005 "Capability code: %s (%d)", val_to_str(ctype,
1006 capability_vals, "Unknown capability"), ctype);
1007 proto_tree_add_text(tree, tvb, *p - 2,
1008 1, "Capability code: %s (%d)",
1009 ctype >= 128 ? "Private use" : "Unknown", ctype);
1010 proto_tree_add_text(tree, tvb, *p - 1,
1011 1, "Capability length: %u %s", clen,
1012 (clen == 1) ? "byte" : "bytes");
1014 proto_tree_add_text(tree, tvb, *p,
1015 clen, "Capability value: Unknown");
1024 * Dissect a BGP OPEN message.
1026 static const value_string community_vals[] = {
1027 { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
1028 { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
1029 { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
1034 dissect_bgp_open(tvbuff_t *tvb, int offset, proto_tree *tree)
1036 struct bgp_open bgpo; /* BGP OPEN message */
1037 int hlen; /* message length */
1038 int ptype; /* parameter type */
1039 int plen; /* parameter length */
1040 int ctype; /* capability type */
1041 int clen; /* capability length */
1042 int cend; /* capabilities end */
1043 int ostart; /* options start */
1044 int oend; /* options end */
1045 int p; /* tvb offset counter */
1046 proto_item *ti; /* tree item */
1047 proto_tree *subtree; /* subtree for options */
1048 proto_tree *subtree1; /* subtree for an option */
1049 proto_tree *subtree2; /* subtree for an option */
1051 /* snarf OPEN message */
1052 tvb_memcpy(tvb, bgpo.bgpo_marker, offset, BGP_MIN_OPEN_MSG_SIZE);
1053 hlen = g_ntohs(bgpo.bgpo_len);
1055 proto_tree_add_text(tree, tvb,
1056 offset + offsetof(struct bgp_open, bgpo_version), 1,
1057 "Version: %u", bgpo.bgpo_version);
1058 proto_tree_add_text(tree, tvb,
1059 offset + offsetof(struct bgp_open, bgpo_myas), 2,
1060 "My AS: %u", g_ntohs(bgpo.bgpo_myas));
1061 proto_tree_add_text(tree, tvb,
1062 offset + offsetof(struct bgp_open, bgpo_holdtime), 2,
1063 "Hold time: %u", g_ntohs(bgpo.bgpo_holdtime));
1064 proto_tree_add_text(tree, tvb,
1065 offset + offsetof(struct bgp_open, bgpo_id), 4,
1066 "BGP identifier: %s", ip_to_str((guint8 *)&bgpo.bgpo_id));
1067 proto_tree_add_text(tree, tvb,
1068 offset + offsetof(struct bgp_open, bgpo_optlen), 1,
1069 "Optional parameters length: %u %s", bgpo.bgpo_optlen,
1070 (bgpo.bgpo_optlen == 1) ? "byte" : "bytes");
1072 /* optional parameters */
1073 if (bgpo.bgpo_optlen > 0) {
1074 /* add a subtree and setup some offsets */
1075 ostart = offset + BGP_MIN_OPEN_MSG_SIZE;
1076 ti = proto_tree_add_text(tree, tvb, ostart, bgpo.bgpo_optlen,
1077 "Optional parameters");
1078 subtree = proto_item_add_subtree(ti, ett_bgp_options);
1079 p = offset + ostart;
1080 oend = p + bgpo.bgpo_optlen;
1082 /* step through all of the optional parameters */
1085 /* grab the type and length */
1086 ptype = tvb_get_guint8(tvb, p++);
1087 plen = tvb_get_guint8(tvb, p++);
1089 /* check the type */
1091 case BGP_OPTION_AUTHENTICATION:
1092 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
1093 "Authentication information (%u %s)", plen,
1094 (plen == 1) ? "byte" : "bytes");
1096 case BGP_OPTION_CAPABILITY:
1097 /* grab the capability code */
1098 cend = p - 1 + plen;
1099 ctype = tvb_get_guint8(tvb, p++);
1100 clen = tvb_get_guint8(tvb, p++);
1101 ti = proto_tree_add_text(subtree, tvb, p - 4,
1102 2 + plen, "Capabilities Advertisement (%u bytes)",
1104 subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
1105 proto_tree_add_text(subtree1, tvb, p - 4,
1106 1, "Parameter type: Capabilities (2)");
1107 proto_tree_add_text(subtree1, tvb, p - 3,
1108 1, "Parameter length: %u %s", plen,
1109 (plen == 1) ? "byte" : "bytes");
1112 /* step through all of the capabilities */
1114 ctype = tvb_get_guint8(tvb, p++);
1115 clen = tvb_get_guint8(tvb, p++);
1117 ti = proto_tree_add_text(subtree1, tvb, p - 2,
1118 2 + clen, "%s (%u %s)", val_to_str(ctype,
1119 capability_vals, "Unknown capability"),
1120 2 + clen, (clen == 1) ? "byte" : "bytes");
1121 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
1122 dissect_bgp_capability_item(tvb, &p,
1123 subtree2, ctype, clen);
1127 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
1128 "Unknown optional parameter");
1136 * Dissect a BGP UPDATE message.
1139 dissect_bgp_update(tvbuff_t *tvb, int offset, proto_tree *tree)
1141 struct bgp_attr bgpa; /* path attributes */
1142 guint16 hlen; /* message length */
1143 gint o; /* packet offset */
1145 gint end; /* message end */
1146 guint16 ext_com; /* EXTENDED COMMUNITY type */
1147 guint16 len; /* tmp */
1148 int advance; /* tmp */
1149 proto_item *ti; /* tree item */
1150 proto_tree *subtree; /* subtree for attributes */
1151 proto_tree *subtree2; /* subtree for attributes */
1152 proto_tree *subtree3; /* subtree for attributes */
1153 proto_tree *subtree4; /* subtree for attributes */
1154 proto_tree *as_paths_tree; /* subtree for AS_PATHs */
1155 proto_tree *as_path_tree; /* subtree for AS_PATH */
1156 proto_tree *communities_tree; /* subtree for COMMUNITIES */
1157 proto_tree *community_tree; /* subtree for a community */
1158 proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
1160 guint8 length; /* AS_PATH length */
1161 guint8 type; /* AS_PATH type */
1162 char *as_path_str = NULL; /* AS_PATH string */
1163 char *communities_str = NULL; /* COMMUNITIES string */
1164 char *cluster_list_str = NULL; /* CLUSTER_LIST string */
1165 char junk_buf[256]; /* tmp */
1166 int junk_buf_len; /* tmp len */
1167 guint8 ipaddr[4]; /* IPv4 address */
1169 hlen = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
1170 o = offset + BGP_HEADER_SIZE;
1172 /* check for withdrawals */
1173 len = tvb_get_ntohs(tvb, o);
1174 proto_tree_add_text(tree, tvb, o, 2,
1175 "Unfeasible routes length: %u %s", len, (len == 1) ? "byte" : "bytes");
1178 /* parse unfeasible prefixes */
1180 ti = proto_tree_add_text(tree, tvb, o, len, "Withdrawn routes:");
1181 subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
1183 /* parse each prefixes */
1186 i = decode_prefix4(tvb, o, junk_buf, sizeof(junk_buf));
1187 if (i < 0 || 32 < i) {
1188 proto_tree_add_text (tree, tvb, o, len,
1189 "Invalid withdrawn route prefix length: %u",
1190 tvb_get_guint8(tvb, o) );
1194 proto_tree_add_text(subtree, tvb, o, i, "%s", junk_buf);
1199 /* check for advertisements */
1200 len = tvb_get_ntohs(tvb, o);
1201 proto_tree_add_text(tree, tvb, o, 2, "Total path attribute length: %u %s",
1202 len, (len == 1) ? "byte" : "bytes");
1204 /* path attributes */
1206 ti = proto_tree_add_text(tree, tvb, o + 2, len, "Path attributes");
1207 subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
1213 guint16 alen, tlen, aoff;
1219 tvb_memcpy(tvb, (guint8 *)&bgpa, o + i, sizeof(bgpa));
1220 /* check for the Extended Length bit */
1221 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1222 alen = tvb_get_ntohs(tvb, o + i + sizeof(bgpa));
1223 aoff = sizeof(bgpa) + 2;
1225 alen = tvb_get_guint8(tvb, o + i + sizeof(bgpa));
1226 aoff = sizeof(bgpa) + 1;
1230 /* This is kind of ugly - similar code appears twice, but it
1231 helps browsing attrs. */
1232 /* the first switch prints things in the title of the subtree */
1233 switch (bgpa.bgpa_type) {
1234 case BGPTYPE_ORIGIN:
1236 goto default_attribute_top;
1237 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
1238 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1240 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1241 msg, tlen + aoff, (tlen + aoff == 1) ? "byte" :
1244 case BGPTYPE_AS_PATH:
1245 case BGPTYPE_NEW_AS_PATH:
1247 (o + current attribute + aoff bytes to first tuple) */
1250 /* must be freed by second switch! */
1251 /* "tlen * 11" (10 digits + space) should be a good estimate
1252 of how long the AS path string could be */
1253 as_path_str = malloc((tlen + 1) * 11);
1254 if (as_path_str == NULL) break;
1255 as_path_str[0] = '\0';
1257 /* estimate the length of the AS number */
1258 if (bgpa.bgpa_type == BGPTYPE_NEW_AS_PATH)
1261 if (bgp_asn_len == 0) {
1265 length = tvb_get_guint8(tvb, k++);
1268 asn_len = (k == end) ? 2 : 4;
1271 asn_len = bgp_asn_len;
1275 /* snarf each AS path */
1277 type = tvb_get_guint8(tvb, q++);
1278 if (strlen(as_path_str) != 0 &&
1279 as_path_str[strlen(as_path_str) - 1] != ' ')
1280 strcat(as_path_str, " ");
1281 if (type == AS_SET) {
1282 strcat(as_path_str, "{");
1284 else if (type == AS_CONFED_SET) {
1285 strcat(as_path_str, "[");
1287 else if (type == AS_CONFED_SEQUENCE) {
1288 strcat(as_path_str, "(");
1290 length = tvb_get_guint8(tvb, q++);
1292 /* snarf each value in path */
1293 for (j = 0; j < length; j++) {
1294 snprintf(junk_buf, sizeof(junk_buf), "%u%s",
1296 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1297 (type == AS_SET || type == AS_CONFED_SET) ?
1299 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1303 /* cleanup end of string */
1304 if (type == AS_SET) {
1305 as_path_str[strlen(as_path_str) - 2] = '}';
1306 as_path_str[strlen(as_path_str) - 1] = '\0';
1308 else if (type == AS_CONFED_SET) {
1309 as_path_str[strlen(as_path_str) - 2] = ']';
1310 as_path_str[strlen(as_path_str) - 1] = '\0';
1312 else if (type == AS_CONFED_SEQUENCE) {
1313 as_path_str[strlen(as_path_str) - 1] = ')';
1316 as_path_str[strlen(as_path_str) - 1] = '\0';
1320 /* check for empty AS_PATH */
1322 strncpy(as_path_str, "empty", 6);
1324 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1326 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1327 as_path_str, tlen + aoff,
1328 (tlen + aoff == 1) ? "byte" : "bytes");
1330 case BGPTYPE_NEXT_HOP:
1332 goto default_attribute_top;
1333 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1334 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1336 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1337 ip_to_str(ipaddr), tlen + aoff, (tlen + aoff == 1)
1338 ? "byte" : "bytes");
1340 case BGPTYPE_MULTI_EXIT_DISC:
1342 goto default_attribute_top;
1343 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1345 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1346 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1347 (tlen + aoff == 1) ? "byte" : "bytes");
1349 case BGPTYPE_LOCAL_PREF:
1351 goto default_attribute_top;
1352 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1354 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1355 tvb_get_ntohl(tvb, o + i + aoff), tlen + aoff,
1356 (tlen + aoff == 1) ? "byte" : "bytes");
1358 case BGPTYPE_ATOMIC_AGGREGATE:
1360 goto default_attribute_top;
1361 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1363 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1364 tlen + aoff, (tlen + aoff == 1) ? "byte" : "bytes");
1366 case BGPTYPE_AGGREGATOR:
1367 if (tlen != 6 && tlen != 8)
1368 goto default_attribute_top;
1369 case BGPTYPE_NEW_AGGREGATOR:
1370 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
1371 goto default_attribute_top;
1373 tvb_memcpy(tvb, ipaddr, o + i + aoff + asn_len, 4);
1374 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1375 "%s: AS: %u origin: %s (%u %s)",
1376 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1377 (asn_len == 2) ? tvb_get_ntohs(tvb, o + i + aoff) :
1378 tvb_get_ntohl(tvb, o + i + aoff),
1379 ip_to_str(ipaddr), tlen + aoff,
1380 (tlen + aoff == 1) ? "byte" : "bytes");
1382 case BGPTYPE_COMMUNITIES:
1384 goto default_attribute_top;
1387 (o + current attribute + aoff bytes to first tuple) */
1390 /* must be freed by second switch! */
1391 /* "tlen * 12" (5 digits, a :, 5 digits + space ) should be
1392 a good estimate of how long the communities string could
1394 communities_str = malloc((tlen + 1) * 12);
1395 if (communities_str == NULL) break;
1396 communities_str[0] = '\0';
1397 memset(junk_buf, 0, sizeof(junk_buf));
1399 /* snarf each community */
1401 /* check for well-known communities */
1402 if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
1403 strncpy(junk_buf, "NO_EXPORT ", 10);
1404 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
1405 strncpy(junk_buf, "NO_ADVERTISE ", 13);
1406 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
1407 strncpy(junk_buf, "NO_EXPORT_SUBCONFED ", 20);
1409 snprintf(junk_buf, sizeof(junk_buf), "%u:%u ",
1410 tvb_get_ntohs(tvb, q),
1411 tvb_get_ntohs(tvb, q + 2));
1415 strncat(communities_str, junk_buf, sizeof(junk_buf));
1417 /* cleanup end of string */
1418 communities_str[strlen(communities_str) - 1] = '\0';
1420 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1422 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1423 communities_str, tlen + aoff,
1424 (tlen + aoff == 1) ? "byte" : "bytes");
1426 case BGPTYPE_ORIGINATOR_ID:
1428 goto default_attribute_top;
1429 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1430 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1432 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1433 ip_to_str(ipaddr), tlen + aoff, (tlen + aoff == 1)
1434 ? "byte" : "bytes");
1436 case BGPTYPE_CLUSTER_LIST:
1438 goto default_attribute_top;
1441 (o + current attribute + aoff bytes to first tuple) */
1444 /* must be freed by second switch! */
1445 /* "tlen * 16" (12 digits, 3 dots + space ) should be
1446 a good estimate of how long the cluster_list string could
1448 cluster_list_str = malloc((tlen + 1) * 16);
1449 if (cluster_list_str == NULL) break;
1450 cluster_list_str[0] = '\0';
1451 memset(junk_buf, 0, sizeof(junk_buf));
1453 /* snarf each cluster list */
1454 tvb_memcpy(tvb, ipaddr, q, 4);
1456 snprintf(junk_buf, sizeof(junk_buf), "%s ", ip_to_str(ipaddr));
1457 strncat(cluster_list_str, junk_buf, sizeof(junk_buf));
1460 /* cleanup end of string */
1461 cluster_list_str[strlen(cluster_list_str) - 1] = '\0';
1463 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1465 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1466 cluster_list_str, tlen + aoff,
1467 (tlen + aoff == 1) ? "byte" : "bytes");
1469 case BGPTYPE_EXTENDED_COMMUNITY:
1472 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
1474 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
1476 (tlen + aoff == 1) ? "byte" : "bytes");
1480 default_attribute_top:
1481 ti = proto_tree_add_text(subtree, tvb, o + i, tlen + aoff,
1483 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1484 tlen + aoff, (tlen + aoff == 1) ? "byte" : "bytes");
1485 } /* end of first switch */
1486 subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
1488 /* figure out flags */
1490 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) {
1491 strncat(junk_buf, "Optional, ", 10);
1494 strncat(junk_buf, "Well-known, ", 12);
1496 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) {
1497 strncat(junk_buf, "Transitive, ", 12);
1500 strncat(junk_buf, "Non-transitive, ", 16);
1502 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_PARTIAL) {
1503 strncat(junk_buf, "Partial, ", 9);
1506 strncat(junk_buf, "Complete, ", 10);
1508 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1509 strncat(junk_buf, "Extended Length, ", 17);
1511 /* stomp last ", " */
1512 j = strlen(junk_buf);
1513 junk_buf[j - 2] = '\0';
1514 ti = proto_tree_add_text(subtree2, tvb,
1515 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1516 "Flags: 0x%02x (%s)", bgpa.bgpa_flags, junk_buf);
1517 subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags);
1519 /* add flag bitfield subtrees */
1520 proto_tree_add_text(subtree3, tvb,
1521 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1522 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1523 BGP_ATTR_FLAG_OPTIONAL, 8, "Optional", "Well-known"));
1524 proto_tree_add_text(subtree3, tvb,
1525 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1526 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1527 BGP_ATTR_FLAG_TRANSITIVE, 8, "Transitive",
1529 proto_tree_add_text(subtree3, tvb,
1530 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1531 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1532 BGP_ATTR_FLAG_PARTIAL, 8, "Partial", "Complete"));
1533 proto_tree_add_text(subtree3, tvb,
1534 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1535 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1536 BGP_ATTR_FLAG_EXTENDED_LENGTH, 8, "Extended length",
1539 proto_tree_add_text(subtree2, tvb,
1540 o + i + offsetof(struct bgp_attr, bgpa_type), 1,
1541 "Type code: %s (%u)",
1542 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1545 proto_tree_add_text(subtree2, tvb, o + i + sizeof(bgpa),
1546 aoff - sizeof(bgpa), "Length: %d %s", tlen,
1547 (tlen == 1) ? "byte" : "bytes");
1549 /* the second switch prints things in the actual subtree of each
1551 switch (bgpa.bgpa_type) {
1552 case BGPTYPE_ORIGIN:
1554 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1555 "Origin (invalid): %u %s", tlen,
1556 (tlen == 1) ? "byte" : "bytes");
1558 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
1559 proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
1560 "Origin: %s (%u)", msg, tvb_get_guint8(tvb, o + i + aoff));
1563 case BGPTYPE_AS_PATH:
1564 case BGPTYPE_NEW_AS_PATH:
1565 /* check for empty AS_PATH */
1571 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1572 "AS path: %s", as_path_str);
1573 as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1576 (o + current attribute + aoff bytes to first tuple) */
1580 /* snarf each AS path tuple, we have to step through each one
1581 again to make a separate subtree so we can't just reuse
1582 as_path_str from above */
1584 as_path_str[0] = '\0';
1585 type = tvb_get_guint8(tvb, q++);
1586 if (type == AS_SET) {
1587 snprintf(as_path_str, 2, "{");
1589 else if (type == AS_CONFED_SET) {
1590 snprintf(as_path_str, 2, "[");
1592 else if (type == AS_CONFED_SEQUENCE) {
1593 snprintf(as_path_str, 2, "(");
1595 length = tvb_get_guint8(tvb, q++);
1597 /* snarf each value in path, we're just going to reuse
1598 as_path_str since we already have it malloced */
1599 for (j = 0; j < length; j++) {
1600 snprintf(junk_buf, sizeof(junk_buf), "%u%s",
1602 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q),
1603 (type == AS_SET || type == AS_CONFED_SET) ? ", " : " ");
1604 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1608 /* cleanup end of string */
1609 if (type == AS_SET) {
1610 as_path_str[strlen(as_path_str) - 2] = '}';
1612 else if (type == AS_CONFED_SET) {
1613 as_path_str[strlen(as_path_str) - 2] = ']';
1615 else if (type == AS_CONFED_SEQUENCE) {
1616 as_path_str[strlen(as_path_str) - 1] = ')';
1619 as_path_str[strlen(as_path_str) - 1] = '\0';
1622 /* length here means number of ASs, ie length * 2 bytes */
1623 ti = proto_tree_add_text(as_paths_tree, tvb,
1624 q - length * asn_len - 2,
1625 length * asn_len + 2, "AS path segment: %s", as_path_str);
1626 as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1627 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 2,
1628 1, "Path segment type: %s (%u)",
1629 val_to_str(type, as_segment_type, "Unknown"), type);
1630 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len - 1,
1631 1, "Path segment length: %u %s", length,
1632 (length == 1) ? "AS" : "ASs");
1634 /* backup and reprint path segment value(s) only */
1635 q -= asn_len * length;
1636 as_path_str[0] = '\0';
1637 for (j = 0; j < length; j++) {
1638 snprintf(junk_buf, sizeof(junk_buf), "%u ",
1640 tvb_get_ntohs(tvb, q) : tvb_get_ntohl(tvb, q));
1641 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1644 as_path_str[strlen(as_path_str) - 1] = '\0';
1646 proto_tree_add_text(as_path_tree, tvb, q - length * asn_len,
1647 length * asn_len, "Path segment value: %s", as_path_str);
1652 case BGPTYPE_NEXT_HOP:
1654 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1655 "Next hop (invalid): %u %s", tlen,
1656 (tlen == 1) ? "byte" : "bytes");
1658 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1659 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1660 "Next hop: %s", ip_to_str(ipaddr));
1663 case BGPTYPE_MULTI_EXIT_DISC:
1665 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1666 "Multiple exit discriminator (invalid): %u %s",
1667 tlen, (tlen == 1) ? "byte" : "bytes");
1669 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1670 "Multiple exit discriminator: %u",
1671 tvb_get_ntohl(tvb, o + i + aoff));
1674 case BGPTYPE_LOCAL_PREF:
1676 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1677 "Local preference (invalid): %u %s", tlen,
1678 (tlen == 1) ? "byte" : "bytes");
1680 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1681 "Local preference: %u", tvb_get_ntohl(tvb, o + i + aoff));
1684 case BGPTYPE_ATOMIC_AGGREGATE:
1686 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1687 "Atomic aggregate (invalid): %u %s", tlen,
1688 (tlen == 1) ? "byte" : "bytes");
1691 case BGPTYPE_AGGREGATOR:
1692 if (tlen != 6 && tlen != 8) {
1693 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1694 "Aggregator (invalid): %u %s", tlen,
1695 (tlen == 1) ? "byte" : "bytes");
1698 case BGPTYPE_NEW_AGGREGATOR:
1699 if (bgpa.bgpa_type == BGPTYPE_NEW_AGGREGATOR && tlen != 8)
1700 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1701 "Aggregator (invalid): %u %s", tlen,
1702 (tlen == 1) ? "byte" : "bytes");
1705 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1706 "Aggregator AS: %u", asn_len == 2 ?
1707 tvb_get_ntohs(tvb, o + i + aoff) :
1708 tvb_get_ntohl(tvb, o + i + aoff));
1709 tvb_memcpy(tvb, ipaddr, o + i + aoff + asn_len, 4);
1710 proto_tree_add_text(subtree2, tvb, o + i + aoff + asn_len,
1711 4, "Aggregator origin: %s", ip_to_str(ipaddr));
1714 case BGPTYPE_COMMUNITIES:
1715 if (tlen % 4 != 0) {
1716 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1717 "Communities (invalid): %u %s", tlen,
1718 (tlen == 1) ? "byte" : "bytes");
1719 free(communities_str);
1723 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1724 "Communities: %s", communities_str);
1725 communities_tree = proto_item_add_subtree(ti,
1726 ett_bgp_communities);
1729 (o + current attribute + aoff bytes to first tuple) */
1733 /* snarf each community */
1735 /* check for reserved values */
1736 guint32 community = tvb_get_ntohl(tvb, q);
1737 if ((community & 0xFFFF0000) == FOURHEX0 ||
1738 (community & 0xFFFF0000) == FOURHEXF) {
1739 proto_tree_add_text(communities_tree, tvb,
1741 "Community: %s (0x%08x)",
1742 val_to_str(community, community_vals, "(reserved)"),
1746 ti = proto_tree_add_text(communities_tree, tvb,
1747 q - 3 + aoff, 4, "Community: %u:%u",
1748 tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
1749 community_tree = proto_item_add_subtree(ti,
1750 ett_bgp_communities);
1751 proto_tree_add_text(community_tree, tvb, q - 3 + aoff,
1752 2, "Community AS: %u", tvb_get_ntohs(tvb, q));
1753 proto_tree_add_text(community_tree, tvb, q - 1 + aoff,
1754 2, "Community value: %u", tvb_get_ntohs(tvb, q + 2));
1760 free(communities_str);
1762 case BGPTYPE_ORIGINATOR_ID:
1764 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1765 "Originator identifier (invalid): %u %s", tlen,
1766 (tlen == 1) ? "byte" : "bytes");
1768 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1769 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1770 "Originator identifier: %s",
1774 case BGPTYPE_MP_REACH_NLRI:
1776 * RFC 2545 specifies that there may be more than one
1777 * address in the MP_REACH_NLRI attribute in section
1778 * 3, "Constructing the Next Hop field".
1780 * Yes, RFC 2858 says you can't do that, and, yes, RFC
1781 * 2858 obsoletes RFC 2283, which says you can do that,
1782 * but that doesn't mean we shouldn't dissect packets
1783 * that conform to RFC 2283 but not RFC 2858, as some
1784 * device on the network might implement the 2283-style
1785 * BGP extensions rather than RFC 2858-style extensions.
1787 af = tvb_get_ntohs(tvb, o + i + aoff);
1788 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1789 "Address family: %s (%u)",
1790 val_to_str(af, afn_vals, "Unknown"), af);
1791 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
1792 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
1793 "Subsequent address family identifier: %s (%u)",
1794 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
1796 if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
1798 * The addresses don't contain lengths, so if we
1799 * don't understand the address family type, we
1800 * cannot parse the subsequent addresses as we
1801 * don't know how long they are.
1803 * XXX - we should put a protocol tree item in for
1804 * this, as an unknown blob.
1808 nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
1809 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3, 1,
1810 "Next hop network address (%d %s)",
1811 nexthop_len, plurality(nexthop_len, "byte", "bytes"));
1812 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
1814 while (j < nexthop_len) {
1815 advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
1816 junk_buf, sizeof(junk_buf)) ;
1817 if (advance == 0) /* catch if this is a unknown AFI type*/
1819 if (j + advance > nexthop_len)
1821 proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
1822 advance, "Next hop: %s (%u)", junk_buf, advance);
1825 tlen -= nexthop_len + 4;
1826 aoff += nexthop_len + 4 ;
1829 snpa = tvb_get_guint8(tvb, o + i + aoff);
1830 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
1831 "Subnetwork points of attachment: %u", snpa);
1834 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
1835 for (/*nothing*/; snpa > 0; snpa--) {
1836 proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
1837 "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
1839 proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
1840 tvb_get_guint8(tvb, o + i + aoff + off - 1),
1841 "SNPA (%u %s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
1842 (tvb_get_guint8(tvb, o + i + aoff + off - 1) == 1) ? "byte" : "bytes");
1843 off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
1849 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1850 "Network layer reachability information (%u %s)",
1851 tlen, (tlen == 1) ? "byte" : "bytes");
1853 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
1856 advance = decode_prefix_MP(af, saf, tvb, o + i + aoff , junk_buf, sizeof(junk_buf)) ;
1857 proto_tree_add_text(subtree3, tvb, o + i + aoff, advance, "%s", junk_buf) ;
1863 case BGPTYPE_MP_UNREACH_NLRI:
1864 af = tvb_get_ntohs(tvb, o + i + aoff);
1865 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1866 "Address family: %s (%u)",
1867 val_to_str(af, afn_vals, "Unknown"), af);
1868 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
1869 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
1870 "Subsequent address family identifier: %s (%u)",
1871 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
1873 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
1874 tlen - 3, "Withdrawn routes (%u %s)", tlen - 3,
1875 (tlen - 3 == 1) ? "byte" : "bytes");
1880 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
1883 advance = decode_prefix_MP(af, saf, tvb, o + i + aoff , junk_buf, sizeof(junk_buf)) ;
1884 proto_tree_add_text(subtree3, tvb, o + i + aoff, advance, "%s", junk_buf) ;
1887 if (advance==1) /* catch if this is a unknown AFI type*/
1892 case BGPTYPE_CLUSTER_LIST:
1893 if (tlen % 4 != 0) {
1894 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1895 "Cluster list (invalid): %u %s", tlen,
1896 (tlen == 1) ? "byte" : "bytes");
1897 free(cluster_list_str);
1901 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
1902 "Cluster list: %s", cluster_list_str);
1903 cluster_list_tree = proto_item_add_subtree(ti,
1904 ett_bgp_cluster_list);
1907 (o + current attribute + aoff bytes to first tuple) */
1911 /* snarf each cluster identifier */
1913 tvb_memcpy(tvb, ipaddr, q, 4);
1914 ti = proto_tree_add_text(cluster_list_tree, tvb,
1915 q - 3 + aoff, 4, "Cluster identifier: %s",
1921 free(cluster_list_str);
1923 case BGPTYPE_EXTENDED_COMMUNITY:
1925 proto_tree_add_text(subtree3, tvb, o + i + aoff, tlen, "Extended community (invalid) : %u %s", tlen,
1926 (tlen == 1) ? "byte" : "bytes") ;
1929 end = o + i + aoff + tlen ;
1930 ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
1931 subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
1935 ext_com = tvb_get_ntohs(tvb,q) ;
1936 junk_buf_len=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf), "%s",
1937 val_to_str(ext_com,bgpext_com_type,"Unknown"));
1939 case BGP_EXT_COM_RT_0:
1940 case BGP_EXT_COM_RO_0:
1941 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %u%s%d",
1942 tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
1943 junk_buf[junk_buf_len]='\0';
1944 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
1946 case BGP_EXT_COM_RT_1:
1947 case BGP_EXT_COM_RO_1:
1948 tvb_memcpy(tvb,ipaddr,q+2,4);
1949 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s%s%u",
1950 ip_to_str(ipaddr),":",tvb_get_ntohs(tvb,q+6));
1951 junk_buf[junk_buf_len]='\0';
1952 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
1954 case BGP_EXT_COM_VPN_ORIGIN:
1955 case BGP_EXT_COM_OSPF_RID:
1956 tvb_memcpy(tvb,ipaddr,q+2,4);
1957 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s",
1959 junk_buf[junk_buf_len]='\0';
1960 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
1962 case BGP_EXT_COM_OSPF_RTYPE:
1963 tvb_memcpy(tvb,ipaddr,q+2,4);
1964 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": Area:%s %s",
1966 val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
1967 /* print OSPF Metric type if selected */
1968 /* always print E2 even if not external route -- receiving router should ignore */
1969 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
1970 junk_buf_len+=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf)-junk_buf_len," E2");
1971 } else if (tvb_get_guint8(tvb,q+6)==(BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA ) ) {
1972 junk_buf_len+=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf)-junk_buf_len," E1");
1974 junk_buf[junk_buf_len]='\0';
1975 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
1977 case BGP_EXT_COM_LINKBAND:
1978 tvb_memcpy(tvb,ipaddr,q+2,4); /* need to check on IEEE format on all platforms */
1979 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %.3f Mbps",
1980 ((double)*ipaddr)*8/1000000);
1981 junk_buf[junk_buf_len]='\0';
1982 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
1984 case BGP_EXT_COM_L2INFO:
1985 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len,
1986 ": %s, Control Flags: %s%s%s%s%s, MTU: %u %s",
1987 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"),
1988 tvb_get_guint8(tvb,q+3) ? "" : "none",
1989 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q" : "",
1990 tvb_get_ntohs(tvb,q+3)&0x04 ? "F" : "",
1991 tvb_get_ntohs(tvb,q+3)&0x02 ? "C" : "",
1992 tvb_get_ntohs(tvb,q+3)&0x01 ? "S" : "",
1993 tvb_get_ntohs(tvb,q+4),
1994 tvb_get_ntohs(tvb,q+4)==1 ? "byte" : "bytes");
1995 junk_buf[junk_buf_len]='\0';
1996 ti = proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
1998 subtree4 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
1999 proto_tree_add_text(subtree4,tvb,q+2,1, "Encapsulation: %s",
2000 val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"));
2001 proto_tree_add_text(subtree4,tvb,q+3,1, "Control Flags: %s%sControl Word %s required, Sequenced delivery %s required",
2002 tvb_get_ntohs(tvb,q+3)&0x08 ? "Q flag (Reserved) set" : "",
2003 tvb_get_ntohs(tvb,q+3)&0x04 ? "F flag (reserved) set" : "",
2004 tvb_get_ntohs(tvb,q+3)&0x02 ? "is" : "not",
2005 tvb_get_ntohs(tvb,q+3)&0x01 ? "is" : "not");
2006 proto_tree_add_text(subtree4,tvb,q+4,2, "MTU: %u %s",
2007 tvb_get_ntohs(tvb,q+4),
2008 tvb_get_ntohs(tvb,q+4)==1 ? "byte" : "bytes");
2011 junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, " ");
2012 junk_buf[junk_buf_len]='\0';
2013 proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
2021 proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
2022 "Unknown (%d %s)", tlen, (tlen == 1) ? "byte" :
2025 } /* end of second switch */
2033 len = offset + hlen - o;
2035 /* parse prefixes */
2037 ti = proto_tree_add_text(tree, tvb, o, len,
2038 "Network layer reachability information: %u %s", len,
2039 (len == 1) ? "byte" : "bytes");
2040 subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
2043 i = decode_prefix4(tvb, o, junk_buf, sizeof(junk_buf));
2044 if (i < 0 || 32 < i) {
2045 proto_tree_add_text (tree, tvb, o, len,
2046 "Invalid NLRI prefix length: %u",
2047 tvb_get_guint8(tvb, o) );
2051 proto_tree_add_text(subtree, tvb, o, i, "%s", junk_buf);
2059 * Dissect a BGP NOTIFICATION message.
2062 dissect_bgp_notification(tvbuff_t *tvb, int offset, proto_tree *tree)
2064 struct bgp_notification bgpn; /* BGP NOTIFICATION message */
2065 int hlen; /* message length */
2066 char *p; /* string pointer */
2069 tvb_memcpy(tvb, bgpn.bgpn_marker, offset, BGP_MIN_NOTIFICATION_MSG_SIZE);
2070 hlen = g_ntohs(bgpn.bgpn_len);
2072 /* print error code */
2073 proto_tree_add_text(tree, tvb,
2074 offset + offsetof(struct bgp_notification, bgpn_major), 1,
2075 "Error code: %s (%u)",
2076 val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
2079 /* print error subcode */
2080 if (bgpn.bgpn_major < array_length(bgpnotify_minor)
2081 && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
2082 p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
2084 } else if (bgpn.bgpn_minor == 0)
2088 proto_tree_add_text(tree, tvb,
2089 offset + offsetof(struct bgp_notification, bgpn_minor), 1,
2090 "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
2092 /* only print if there is optional data */
2093 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
2094 proto_tree_add_text(tree, tvb, offset + BGP_MIN_NOTIFICATION_MSG_SIZE,
2095 hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
2100 * Dissect a BGP ROUTE-REFRESH message.
2103 dissect_bgp_route_refresh(tvbuff_t *tvb, int offset, proto_tree *tree)
2105 guint16 i; /* tmp */
2106 int p; /* tvb offset counter */
2107 int pend; /* end of list of entries for one orf type */
2108 guint16 hlen; /* tvb RR msg length */
2109 proto_item *ti; /* tree item */
2110 proto_item *ti1; /* tree item */
2111 proto_tree *subtree; /* tree for orf */
2112 proto_tree *subtree1; /* tree for orf entry */
2113 guint8 orftype; /* ORF Type */
2114 guint8 orfwhen; /* ORF flag: immediate, defer */
2115 guint16 orflen; /* ORF len */
2116 guint8 entryflag; /* ORF Entry flag: action(add,del,delall) match(permit,deny) */
2117 guint32 entryseq; /* ORF Entry sequence number */
2118 int entrylen; /* ORF Entry length */
2119 guint8 pfx_ge; /* ORF PrefixList mask lower bound */
2120 guint8 pfx_le; /* ORF PrefixList mask upper bound */
2121 char pfxbuf[20]; /* ORF PrefixList prefix string buffer */
2122 int pfx_masklen; /* ORF PRefixList prefix mask length */
2128 00 01 00 01 afi,safi= ipv4-unicast
2129 02 80 00 01 defer, prefix-orf, len=1
2133 00 01 00 01 afi,saif= ipv4-unicast
2134 01 80 00 0a immediate, prefix-orf, len=10
2136 00 00 00 05 seqno = 5
2139 10 07 02 prefix = 7.2.0.0/16
2141 hlen = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2142 p = offset + BGP_HEADER_SIZE;
2144 i = tvb_get_ntohs(tvb, p);
2145 proto_tree_add_text(tree, tvb, p, 2,
2146 "Address family identifier: %s (%u)",
2147 val_to_str(i, afn_vals, "Unknown"), i);
2150 proto_tree_add_text(tree, tvb, p, 1,
2151 "Reserved: 1 byte");
2154 i = tvb_get_guint8(tvb, p);
2155 proto_tree_add_text(tree, tvb, p, 1,
2156 "Subsequent address family identifier: %s (%u)",
2157 val_to_str(i, bgpattr_nlri_safi,
2158 i >= 128 ? "Vendor specific" : "Unknown"),
2161 if ( hlen == BGP_HEADER_SIZE + 4 )
2163 while (p < offset + hlen) {
2165 orfwhen = tvb_get_guint8(tvb, p);
2166 orftype = tvb_get_guint8(tvb, p+1);
2167 orflen = tvb_get_ntohs(tvb, p+2);
2168 ti = proto_tree_add_text(tree, tvb, p , orflen + 4 , "ORF information (%u bytes)", orflen + 4);
2169 subtree = proto_item_add_subtree(ti, ett_bgp_orf);
2170 proto_tree_add_text(subtree, tvb, p , 1, "ORF flag: %s", val_to_str(orfwhen, orf_when_vals,"UNKNOWN"));
2171 proto_tree_add_text(subtree, tvb, p+1 , 1, "ORF type: %s", val_to_str(orftype, orf_type_vals,"UNKNOWN"));
2172 proto_tree_add_text(subtree, tvb, p+2 , 2, "ORF len: %u %s", orflen, (orflen == 1) ? "byte" : "bytes");
2175 if (orftype != BGP_ORF_PREFIX_CISCO){
2176 proto_tree_add_text(subtree, tvb, p, orflen, "ORFEntry-Unknown (%u bytes)", orflen);
2182 entryflag = tvb_get_guint8(tvb, p);
2183 if ((entryflag & BGP_ORF_ACTION) == BGP_ORF_REMOVEALL) {
2184 ti1 = proto_tree_add_text(subtree, tvb, p, 1, "ORFEntry-PrefixList (1 byte)");
2185 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2186 proto_tree_add_text(subtree1, tvb, p , 1, "RemoveAll");
2189 entryseq = tvb_get_ntohl(tvb, p+1);
2190 pfx_ge = tvb_get_guint8(tvb, p+5);
2191 pfx_le = tvb_get_guint8(tvb, p+6);
2193 decode_prefix4(tvb, p+7, pfxbuf, sizeof(pfxbuf));
2194 pfx_masklen = tvb_get_guint8(tvb, p+7);
2195 entrylen = 7+ 1 + (pfx_masklen+7)/8;
2196 ti1 = proto_tree_add_text(subtree, tvb, p, entrylen, "ORFEntry-PrefixList (%u bytes)", entrylen);
2197 subtree1 = proto_item_add_subtree(ti1, ett_bgp_orf_entry);
2198 proto_tree_add_text(subtree1, tvb, p , 1, "ACTION: %s MATCH: %s",
2199 val_to_str(entryflag&BGP_ORF_ACTION, orf_entry_action_vals,"UNKNOWN"),
2200 val_to_str(entryflag&BGP_ORF_MATCH, orf_entry_match_vals,"UNKNOWN"));
2202 proto_tree_add_text(subtree1, tvb, p , 4, "Entry Sequence No: %u", entryseq);
2204 proto_tree_add_text(subtree1, tvb, p , 1, "PrefixMask length lower bound: %u", pfx_ge);
2206 proto_tree_add_text(subtree1, tvb, p , 1, "PrefixMask length upper bound: %u", pfx_le);
2208 proto_tree_add_text(subtree1, tvb, p , 1 + (pfx_masklen+7)/8, "Prefix: %s", pfxbuf);
2209 p+= 1 + (pfx_masklen+7)/8;
2216 * Dissect a BGP CAPABILITY message.
2219 dissect_bgp_capability(tvbuff_t *tvb, int offset, proto_tree *tree)
2222 proto_tree *subtree;
2228 mend = offset + tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
2229 offset += BGP_HEADER_SIZE;
2230 /* step through all of the capabilities */
2231 while (offset < mend) {
2232 action = tvb_get_guint8(tvb, offset++);
2233 ctype = tvb_get_guint8(tvb, offset++);
2234 clen = tvb_get_guint8(tvb, offset++);
2236 ti = proto_tree_add_text(tree, tvb, offset - 2, 2 + clen,
2237 "%s (%u %s)", val_to_str(ctype, capability_vals,
2238 "Unknown capability"), 2 + clen, (clen == 1) ? "byte" : "bytes");
2239 subtree = proto_item_add_subtree(ti, ett_bgp_option);
2240 proto_tree_add_text(subtree, tvb, offset-2, 1, "Action: %d (%s)",
2241 action, val_to_str(action, bgpcap_action, "Invalid action value"));
2242 dissect_bgp_capability_item(tvb, &offset, subtree, ctype, clen);
2248 * Dissect a BGP packet.
2251 dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2253 proto_item *ti; /* tree item */
2254 proto_tree *bgp_tree; /* BGP packet tree */
2255 proto_tree *bgp1_tree; /* BGP message tree */
2257 int found; /* number of BGP messages in packet */
2258 static guchar marker[] = { /* BGP message marker */
2259 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2260 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2262 guint8 bgp_marker[BGP_MARKER_SIZE]; /* Marker (should be all ones */
2263 guint16 bgp_len; /* Message length */
2264 guint8 bgp_type; /* Message type */
2266 char *typ; /* Message type (string) */
2268 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2269 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
2270 if (check_col(pinfo->cinfo, COL_INFO))
2271 col_clear(pinfo->cinfo, COL_INFO);
2273 l = tvb_reported_length(tvb);
2276 /* run through the TCP packet looking for BGP headers */
2277 while (i + BGP_HEADER_SIZE <= l) {
2278 tvb_memcpy(tvb, bgp_marker, i, BGP_MARKER_SIZE);
2279 bgp_len = tvb_get_ntohs(tvb, i + BGP_MARKER_SIZE);
2280 bgp_type = tvb_get_guint8(tvb, i + BGP_MARKER_SIZE + 2);
2282 /* look for bgp header */
2283 if (memcmp(bgp_marker, marker, sizeof(marker)) != 0) {
2291 * Desegmentation check.
2293 if (bgp_desegment) {
2294 if (bgp_len > tvb_length_remaining(tvb, i) && pinfo->can_desegment) {
2296 * Not all of this packet is in the data we've been
2297 * handed, but we can do reassembly on it.
2299 * Tell the TCP dissector where the data for
2300 * this message starts in the data it handed
2301 * us, and how many more bytes we need, and
2304 pinfo->desegment_offset = i;
2305 pinfo->desegment_len = bgp_len - tvb_length_remaining(tvb, i);
2310 typ = val_to_str(bgp_type, bgptypevals, "Unknown Message");
2312 if (check_col(pinfo->cinfo, COL_INFO)) {
2314 col_add_fstr(pinfo->cinfo, COL_INFO, "%s", typ);
2316 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
2320 ti = proto_tree_add_item(tree, proto_bgp, tvb, i, bgp_len, FALSE);
2321 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
2323 ti = proto_tree_add_text(bgp_tree, tvb, i, bgp_len, "%s", typ);
2325 /* add a different tree for each message type */
2328 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_open);
2331 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_update);
2333 case BGP_NOTIFICATION:
2334 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_notification);
2337 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
2339 case BGP_ROUTE_REFRESH_CISCO:
2340 case BGP_ROUTE_REFRESH:
2341 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
2343 case BGP_CAPABILITY:
2344 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_capability);
2347 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
2351 proto_tree_add_text(bgp1_tree, tvb, i, BGP_MARKER_SIZE,
2352 "Marker: 16 bytes");
2354 if (bgp_len < BGP_HEADER_SIZE || bgp_len > BGP_MAX_PACKET_SIZE) {
2355 proto_tree_add_text(bgp1_tree, tvb,
2356 i + BGP_MARKER_SIZE, 2,
2357 "Length (invalid): %u %s", bgp_len,
2358 (bgp_len == 1) ? "byte" : "bytes");
2361 proto_tree_add_text(bgp1_tree, tvb,
2362 i + BGP_MARKER_SIZE, 2,
2363 "Length: %u %s", bgp_len,
2364 (bgp_len == 1) ? "byte" : "bytes");
2367 proto_tree_add_uint_format(bgp1_tree, hf_bgp_type, tvb,
2368 i + BGP_MARKER_SIZE + 2, 1,
2370 "Type: %s (%u)", typ, bgp_type);
2374 dissect_bgp_open(tvb, i, bgp1_tree);
2377 dissect_bgp_update(tvb, i, bgp1_tree);
2379 case BGP_NOTIFICATION:
2380 dissect_bgp_notification(tvb, i, bgp1_tree);
2383 /* no data in KEEPALIVE messages */
2385 case BGP_ROUTE_REFRESH_CISCO:
2386 case BGP_ROUTE_REFRESH:
2387 dissect_bgp_route_refresh(tvb, i, bgp1_tree);
2389 case BGP_CAPABILITY:
2390 dissect_bgp_capability(tvb, i, bgp1_tree);
2402 * Register ourselves.
2405 proto_register_bgp(void)
2408 static hf_register_info hf[] = {
2410 { "BGP message type", "bgp.type", FT_UINT8, BASE_HEX,
2411 VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
2414 static gint *ett[] = {
2419 &ett_bgp_attr_flags,
2421 &ett_bgp_mp_reach_nlri,
2422 &ett_bgp_mp_unreach_nlri,
2427 &ett_bgp_notification,
2428 &ett_bgp_route_refresh,
2429 &ett_bgp_capability,
2431 &ett_bgp_communities,
2432 &ett_bgp_cluster_list,
2435 &ett_bgp_extended_communities,
2439 module_t *bgp_module;
2440 static enum_val_t asn_len[] = {
2447 proto_bgp = proto_register_protocol("Border Gateway Protocol",
2449 proto_register_field_array(proto_bgp, hf, array_length(hf));
2450 proto_register_subtree_array(ett, array_length(ett));
2452 bgp_module = prefs_register_protocol(proto_bgp, NULL);
2453 prefs_register_bool_preference(bgp_module, "desegment",
2454 "Desegment all BGP messages spanning multiple TCP segments",
2455 "Whether the BGP dissector should desegment all messages spanning multiple TCP segments",
2457 prefs_register_enum_preference(bgp_module, "asn_len",
2458 "Length of the AS number",
2459 "BGP dissector detect the length of the AS number in AS_PATH attributes automatically or manually (NOTE: Automatic detection is not 100% accurate)",
2460 &bgp_asn_len, asn_len, FALSE);
2464 proto_reg_handoff_bgp(void)
2466 dissector_handle_t bgp_handle;
2468 bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
2469 dissector_add("tcp.port", BGP_TCP_PORT, bgp_handle);