2 * Routines for BGP packet dissection.
3 * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
5 * $Id: packet-bgp.c,v 1.60 2002/08/02 23:35:47 jmayer 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
20 * Destination Preference Attribute for BGP (work in progress)
21 * RFC1863 A BGP/IDRP Route Server alternative to a full mesh routing
23 * Ethereal - Network traffic analyzer
24 * By Gerald Combs <gerald@ethereal.com>
25 * Copyright 1998 Gerald Combs
27 * This program is free software; you can redistribute it and/or
28 * modify it under the terms of the GNU General Public License
29 * as published by the Free Software Foundation; either version 2
30 * of the License, or (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
37 * You should have received a copy of the GNU General Public License
38 * along with this program; if not, write to the Free Software
39 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49 #ifdef HAVE_ARPA_INET_H
50 #include <arpa/inet.h>
56 #ifdef NEED_SNPRINTF_H
57 # include "snprintf.h"
60 #include <epan/packet.h>
61 #include "packet-bgp.h"
62 #include "packet-ipv6.h"
66 static const value_string bgptypevals[] = {
67 { BGP_OPEN, "OPEN Message" },
68 { BGP_UPDATE, "UPDATE Message" },
69 { BGP_NOTIFICATION, "NOTIFICATION Message" },
70 { BGP_KEEPALIVE, "KEEPALIVE Message" },
71 { BGP_ROUTE_REFRESH, "ROUTE-REFRESH Message" },
72 { BGP_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" },
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[] = {
120 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3,
123 static const value_string bgpattr_origin[] = {
130 static const value_string as_segment_type[] = {
132 { 2, "AS_SEQUENCE" },
133 /* RFC1965 has the wrong values, corrected in */
134 /* draft-ietf-idr-bgp-confed-rfc1965bis-01.txt */
135 { 4, "AS_CONFED_SET" },
136 { 3, "AS_CONFED_SEQUENCE" },
140 static const value_string bgpattr_type[] = {
141 { BGPTYPE_ORIGIN, "ORIGIN" },
142 { BGPTYPE_AS_PATH, "AS_PATH" },
143 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
144 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
145 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
146 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
147 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
148 { BGPTYPE_COMMUNITIES, "COMMUNITIES" },
149 { BGPTYPE_ORIGINATOR_ID, "ORIGINATOR_ID" },
150 { BGPTYPE_CLUSTER_LIST, "CLUSTER_LIST" },
151 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
152 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
153 { BGPTYPE_EXTENDED_COMMUNITY, "EXTENDED_COMMUNITIES" },
157 /* Beware : See also MAX_SIZE_OF_EXT_COM_NAMES */
158 static const value_string bgpext_com_type[] = {
159 { BGP_EXT_COM_RT_0, "Route Target" },
160 { BGP_EXT_COM_RT_1, "Route Target" },
161 { BGP_EXT_COM_RO_0, "Route Origin" },
162 { BGP_EXT_COM_RO_1, "Route Origin" },
163 { BGP_EXT_COM_LINKBAND, "Link Bandwidth" },
164 { BGP_EXT_COM_VPN_ORIGIN, "OSPF Domain" },
165 { BGP_EXT_COM_OSPF_RTYPE, "OSPF Route Type" },
166 { BGP_EXT_COM_OSPF_RID, "OSPF Router ID" },
170 static const value_string bgpext_ospf_rtype[] = {
171 { BGP_OSPF_RTYPE_RTR, "Router" },
172 { BGP_OSPF_RTYPE_NET, "Network" },
173 { BGP_OSPF_RTYPE_SUM, "Summary" },
174 { BGP_OSPF_RTYPE_EXT, "External" },
175 { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
176 { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
181 /* MUST be resized if a longer named extended community is added */
182 #define MAX_SIZE_OF_EXT_COM_NAMES 20
184 /* Subsequent address family identifier, RFC2858 */
185 static const value_string bgpattr_nlri_safi[] = {
187 { SAFNUM_UNICAST, "Unicast" },
188 { SAFNUM_MULCAST, "Multicast" },
189 { SAFNUM_UNIMULC, "Unicast+Multicast" },
190 { SAFNUM_MPLS_LABEL, "MPLS Labeled Prefix"},
191 { SAFNUM_LBVPNIP, "Labeled VPN-IPv4" }, /* draft-rosen-rfc2547bis-03 */
195 /* ORF Type, draft-ietf-idr-route-filter-04.txt */
196 static const value_string orf_type_vals[] = {
197 { 2, "Communities ORF-Type" },
198 { 3, "Extended Communities ORF-Type" },
202 /* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
203 static const value_string orf_send_recv_vals[] = {
210 /* Maximal size of an IP address string */
211 #define MAX_SIZE_OF_IP_ADDR_STRING 16
213 static int proto_bgp = -1;
214 static int hf_bgp_type = -1;
216 static gint ett_bgp = -1;
217 static gint ett_bgp_unfeas = -1;
218 static gint ett_bgp_attrs = -1;
219 static gint ett_bgp_attr = -1;
220 static gint ett_bgp_attr_flags = -1;
221 static gint ett_bgp_mp_nhna = -1;
222 static gint ett_bgp_mp_reach_nlri = -1;
223 static gint ett_bgp_mp_unreach_nlri = -1;
224 static gint ett_bgp_mp_snpa = -1;
225 static gint ett_bgp_nlri = -1;
226 static gint ett_bgp_open = -1;
227 static gint ett_bgp_update = -1;
228 static gint ett_bgp_notification = -1;
229 static gint ett_bgp_route_refresh = -1; /* ROUTE-REFRESH message tree */
230 static gint ett_bgp_as_paths = -1;
231 static gint ett_bgp_communities = -1;
232 static gint ett_bgp_cluster_list = -1; /* cluster list tree */
233 static gint ett_bgp_options = -1; /* optional parameters tree */
234 static gint ett_bgp_option = -1; /* an optional parameter tree */
235 static gint ett_bgp_extended_communities = -1 ; /* extended communities list tree */
238 static gboolean bgp_desegment = TRUE;
241 * Decode an IPv4 prefix.
244 decode_prefix4(tvbuff_t *tvb, gint offset, char *buf, int buflen)
246 guint8 addr[4]; /* IP address */
247 int plen; /* prefix length */
248 int length; /* number of octets needed for prefix */
251 plen = tvb_get_guint8(tvb, offset);
252 if (plen < 0 || 32 < plen)
254 length = (plen + 7) / 8;
257 memset(addr, 0, sizeof(addr));
258 tvb_memcpy(tvb, addr, offset + 1, length);
260 addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
262 /* hand back a formatted string */
263 snprintf(buf, buflen, "%s/%d", ip_to_str(addr), plen);
268 * Decode an IPv6 prefix.
271 decode_prefix6(tvbuff_t *tvb, gint offset, char *buf, int buflen)
273 struct e_in6_addr addr; /* IPv6 address */
274 int plen; /* prefix length */
275 int length; /* number of octets needed for prefix */
278 plen = tvb_get_guint8(tvb, offset);
279 if (plen < 0 || 128 < plen)
281 length = (plen + 7) / 8;
284 memset(&addr, 0, sizeof(addr));
285 tvb_memcpy(tvb, (guint8 *)&addr, offset + 1, length);
287 addr.s6_addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
289 /* hand back a formatted string */
290 snprintf(buf, buflen, "%s/%d", ip6_to_str(&addr), plen);
295 * Decode an MPLS label stack
298 decode_MPLS_stack(tvbuff_t *tvb, gint offset, char *buf, size_t buflen)
300 guint32 label_entry; /* an MPLS label enrty (label + COS field + stack bit */
301 gint index; /* index for the label stack */
302 char junk_buf[256]; /* tmp */
305 label_entry = 0x000000 ;
309 while ((label_entry & 0x000001) == 0) {
311 label_entry = tvb_get_ntoh24(tvb, index) ;
313 /* withdrawn routes may contain 0 or 0x800000 in the first label */
314 if((index-offset)==0&&(label_entry==0||label_entry==0x800000)) {
315 snprintf(buf, buflen, "0 (withdrawn)");
319 snprintf(junk_buf, sizeof(junk_buf),"%u%s", (label_entry >> 4), ((label_entry & 0x000001) == 0) ? "," : " (bottom)");
320 if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
321 strcat(buf, junk_buf);
324 if ((label_entry & 0x000001) == 0) {
325 /* real MPLS multi-label stack in BGP? - maybe later; for now, it must be a bogus packet */
326 strcpy(junk_buf, " (BOGUS: Bottom of Stack NOT set!)");
327 if (strlen(buf) + strlen(junk_buf) + 1 <= buflen)
328 strcat(buf, junk_buf);
333 return((index - offset) / 3);
337 * Decode a multiprotocol address
341 mp_addr_to_str (guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *buf, int buflen)
343 int length; /* length of the address in byte */
344 guint8 ip4addr[4],ip4addr2[4]; /* IPv4 address */
345 guint16 rd_type; /* Route Distinguisher type */
346 struct e_in6_addr ip6addr; /* IPv6 address */
355 case SAFNUM_MPLS_LABEL:
357 tvb_memcpy(tvb, ip4addr, offset, 4);
358 snprintf(buf, buflen, "%s", ip_to_str(ip4addr));
361 rd_type=tvb_get_ntohs(tvb,offset) ;
365 tvb_memcpy(tvb, ip4addr, offset + 8, 4);
366 snprintf(buf, buflen, "Empty Label Stack RD=%u:%u IP=%s",
367 tvb_get_ntohs(tvb, offset + 2),
368 tvb_get_ntohl(tvb, offset + 4),
373 tvb_memcpy(tvb, ip4addr, offset + 2, 4); /* IP part of the RD */
374 tvb_memcpy(tvb, ip4addr2, offset +6, 4); /* IP address of the VPN-IPv4 */
375 snprintf(buf, buflen, "Empty Label Stack RD=%s:%u IP=%s",
377 tvb_get_ntohs(tvb, offset + 6),
378 ip_to_str(ip4addr2));
382 snprintf(buf, buflen, "Unknown labeled VPN-IPv4 address format");
388 snprintf(buf, buflen, "Unknown SAFI value for AFI %u", afi);
394 tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8,offset, sizeof(ip6addr));
395 snprintf(buf, buflen, "%s", ip6_to_str(&ip6addr));
399 snprintf(buf, buflen, "Unknown AFI value");
406 * Decode a multiprotocol prefix
409 decode_prefix_MP(guint16 afi, guint8 safi, tvbuff_t *tvb, gint offset, char *buf, int buflen)
411 int length; /* length of the prefix in byte */
412 int plen; /* length of the prefix in bit */
413 int labnum; /* number of labels */
414 guint8 ip4addr[4],ip4addr2[4]; /* IPv4 address */
415 guint16 rd_type; /* Route Distinguisher type */
416 char lab_stk[256]; /* label stack */
426 length = decode_prefix4(tvb, offset, buf, buflen) - 1 ;
428 case SAFNUM_MPLS_LABEL:
429 plen = tvb_get_guint8(tvb,offset) ;
430 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
432 offset += (1 + labnum * 3);
433 plen -= (labnum * 3*8);
434 if (plen < 0 || 32 < plen) {
439 length = (plen + 7) / 8;
440 memset(ip4addr, 0, sizeof(ip4addr));
441 tvb_memcpy(tvb, ip4addr, offset, length);
443 ip4addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
445 snprintf(buf,buflen, "Label Stack=%s IP=%s/%d",
449 length += (labnum*3) ;
453 plen = tvb_get_guint8(tvb,offset) ;
455 labnum = decode_MPLS_stack(tvb, offset + 1, lab_stk, sizeof(lab_stk));
457 offset += (1 + labnum * 3);
458 plen -= (labnum * 3*8);
460 rd_type=tvb_get_ntohs(tvb,offset) ;
464 case FORMAT_AS2_LOC: /* Code borrowed from the decode_prefix4 function */
465 if (plen < 0 || 32 < plen) {
470 length = (plen + 7) / 8;
471 memset(ip4addr, 0, sizeof(ip4addr));
472 tvb_memcpy(tvb, ip4addr, offset + 8, length);
474 ip4addr[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
476 snprintf(buf,buflen, "Label Stack=%s RD=%u:%u, IP=%s/%d",
478 tvb_get_ntohs(tvb, offset + 2),
479 tvb_get_ntohl(tvb, offset + 4),
482 length += (labnum * 3 + 8) ;
484 case FORMAT_IP_LOC: /* Code borrowed from the decode_prefix4 function */
485 tvb_memcpy(tvb, ip4addr, offset + 2, 4);
487 if (plen < 0 || 32 < plen) {
492 length = (plen + 7) / 8;
493 memset(ip4addr2, 0, sizeof(ip4addr2));
494 tvb_memcpy(tvb, ip4addr2, offset + 8, length);
496 ip4addr2[length - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
498 snprintf(buf,buflen, "Label Stack=%s RD=%s:%u, IP=%s/%d",
501 tvb_get_ntohs(tvb, offset + 6),
504 length += (labnum * 3 + 8) ;
508 snprintf(buf,buflen, "Unkown labeled VPN-IPv4 address format");
514 snprintf(buf,buflen, "Unkown SAFI value for AFI %u", afi);
519 length = decode_prefix6(tvb, offset, buf, buflen) - 1 ;
523 snprintf(buf,buflen, "Unkown AFI value");
530 * Dissect a BGP OPEN message.
532 static const value_string community_vals[] = {
533 { BGP_COMM_NO_EXPORT, "NO_EXPORT" },
534 { BGP_COMM_NO_ADVERTISE, "NO_ADVERTISE" },
535 { BGP_COMM_NO_EXPORT_SUBCONFED, "NO_EXPORT_SUBCONFED" },
540 dissect_bgp_open(tvbuff_t *tvb, int offset, proto_tree *tree)
542 struct bgp_open bgpo; /* BGP OPEN message */
543 int hlen; /* message length */
545 int ptype; /* parameter type */
546 int plen; /* parameter length */
547 int ctype; /* capability type */
548 int clen; /* capability length */
549 int cend; /* capabilities end */
550 int ostart; /* options start */
551 int oend; /* options end */
552 int p; /* tvb offset counter */
553 proto_item *ti; /* tree item */
554 proto_tree *subtree; /* subtree for options */
555 proto_tree *subtree1; /* subtree for an option */
556 proto_tree *subtree2; /* subtree for an option */
557 proto_tree *subtree3; /* subtree for an option */
558 guint8 orfnum; /* number of ORFs */
559 guint8 orftype; /* ORF Type */
560 guint8 orfsendrecv; /* ORF Send/Receive */
562 /* snarf OPEN message */
563 tvb_memcpy(tvb, bgpo.bgpo_marker, offset, BGP_MIN_OPEN_MSG_SIZE);
564 hlen = g_ntohs(bgpo.bgpo_len);
566 proto_tree_add_text(tree, tvb,
567 offset + offsetof(struct bgp_open, bgpo_version), 1,
568 "Version: %u", bgpo.bgpo_version);
569 proto_tree_add_text(tree, tvb,
570 offset + offsetof(struct bgp_open, bgpo_myas), 2,
571 "My AS: %u", g_ntohs(bgpo.bgpo_myas));
572 proto_tree_add_text(tree, tvb,
573 offset + offsetof(struct bgp_open, bgpo_holdtime), 2,
574 "Hold time: %u", g_ntohs(bgpo.bgpo_holdtime));
575 proto_tree_add_text(tree, tvb,
576 offset + offsetof(struct bgp_open, bgpo_id), 4,
577 "BGP identifier: %s", ip_to_str((guint8 *)&bgpo.bgpo_id));
578 proto_tree_add_text(tree, tvb,
579 offset + offsetof(struct bgp_open, bgpo_optlen), 1,
580 "Optional parameters length: %u %s", bgpo.bgpo_optlen,
581 (bgpo.bgpo_optlen == 1) ? "byte" : "bytes");
583 /* optional parameters */
584 if (bgpo.bgpo_optlen > 0) {
585 /* add a subtree and setup some offsets */
586 ostart = offset + BGP_MIN_OPEN_MSG_SIZE;
587 ti = proto_tree_add_text(tree, tvb, ostart, bgpo.bgpo_optlen,
588 "Optional parameters");
589 subtree = proto_item_add_subtree(ti, ett_bgp_options);
591 oend = p + bgpo.bgpo_optlen;
593 /* step through all of the optional parameters */
596 /* grab the type and length */
597 ptype = tvb_get_guint8(tvb, p++);
598 plen = tvb_get_guint8(tvb, p++);
602 case BGP_OPTION_AUTHENTICATION:
603 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
604 "Authentication information (%u %s)", plen,
605 (plen == 1) ? "byte" : "bytes");
607 case BGP_OPTION_CAPABILITY:
608 /* grab the capability code */
610 ctype = tvb_get_guint8(tvb, p++);
611 clen = tvb_get_guint8(tvb, p++);
612 ti = proto_tree_add_text(subtree, tvb, p - 4,
613 2 + plen, "Capabilities Advertisement (%u bytes)",
615 subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
616 proto_tree_add_text(subtree1, tvb, p - 4,
617 1, "Parameter type: Capabilities (2)");
618 proto_tree_add_text(subtree1, tvb, p - 3,
619 1, "Parameter length: %u %s", plen,
620 (plen == 1) ? "byte" : "bytes");
623 /* step through all of the capabilities */
625 ctype = tvb_get_guint8(tvb, p++);
626 clen = tvb_get_guint8(tvb, p++);
628 /* check the capability type */
630 case BGP_CAPABILITY_RESERVED:
631 ti = proto_tree_add_text(subtree1, tvb, p - 2,
632 2 + clen, "Reserved capability (%u %s)", 2 + clen,
633 (clen == 1) ? "byte" : "bytes");
634 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
635 proto_tree_add_text(subtree2, tvb, p - 2,
636 1, "Capability code: Reserved (0)");
637 proto_tree_add_text(subtree2, tvb, p - 1,
638 1, "Capability length: %u %s", clen,
639 (clen == 1) ? "byte" : "bytes");
641 proto_tree_add_text(subtree2, tvb, p,
642 clen, "Capability value: Unknown");
646 case BGP_CAPABILITY_MULTIPROTOCOL:
647 ti = proto_tree_add_text(subtree1, tvb, p - 2,
649 "Multiprotocol extensions capability (%u %s)",
650 2 + clen, (clen == 1) ? "byte" : "bytes");
651 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
652 proto_tree_add_text(subtree2, tvb, p - 2,
653 1, "Capability code: Multiprotocol extensions (%d)",
656 proto_tree_add_text(subtree2, tvb, p - 1,
657 1, "Capability length: Invalid");
658 proto_tree_add_text(subtree2, tvb, p,
659 clen, "Capability value: Unknown");
662 proto_tree_add_text(subtree2, tvb, p - 1,
663 1, "Capability length: %u %s", clen,
664 (clen == 1) ? "byte" : "bytes");
665 ti = proto_tree_add_text(subtree2, tvb, p,
666 clen, "Capability value");
667 subtree3 = proto_item_add_subtree(ti,
670 i = tvb_get_ntohs(tvb, p);
671 proto_tree_add_text(subtree3, tvb, p,
672 2, "Address family identifier: %s (%u)",
673 val_to_str(i, afn_vals, "Unknown"), i);
676 proto_tree_add_text(subtree3, tvb, p,
677 1, "Reserved: 1 byte");
680 i = tvb_get_guint8(tvb, p);
681 proto_tree_add_text(subtree3, tvb, p,
682 1, "Subsequent address family identifier: %s (%u)",
683 val_to_str(i, bgpattr_nlri_safi,
684 i >= 128 ? "Vendor specific" : "Unknown"), i);
688 case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
689 case BGP_CAPABILITY_ROUTE_REFRESH:
690 ti = proto_tree_add_text(subtree1, tvb, p - 2,
691 2 + clen, "Route refresh capability (%u %s)", 2 + clen,
692 (clen == 1) ? "byte" : "bytes");
693 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
694 proto_tree_add_text(subtree2, tvb, p - 2,
695 1, "Capability code: Route refresh (%d)", ctype);
697 proto_tree_add_text(subtree2, tvb, p,
698 clen, "Capability value: Invalid");
701 proto_tree_add_text(subtree2, tvb, p - 1,
702 1, "Capability length: %u %s", clen,
703 (clen == 1) ? "byte" : "bytes");
707 case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
708 ti = proto_tree_add_text(subtree1, tvb, p - 2,
710 "Cooperative route filtering capability (%u %s)",
711 2 + clen, (clen == 1) ? "byte" : "bytes");
712 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
713 proto_tree_add_text(subtree2, tvb, p - 2,
714 1, "Capability code: Cooperative route filtering (%d)",
716 proto_tree_add_text(subtree2, tvb, p - 1,
717 1, "Capability length: %u %s", clen,
718 (clen == 1) ? "byte" : "bytes");
719 ti = proto_tree_add_text(subtree2, tvb, p,
720 clen, "Capability value");
721 subtree3 = proto_item_add_subtree(ti, ett_bgp_option);
723 i = tvb_get_ntohs(tvb, p);
724 proto_tree_add_text(subtree3, tvb, p,
725 2, "Address family identifier: %s (%u)",
726 val_to_str(i, afn_vals, "Unknown"), i);
729 proto_tree_add_text(subtree3, tvb, p,
730 1, "Reserved: 1 byte");
733 i = tvb_get_guint8(tvb, p);
734 proto_tree_add_text(subtree3, tvb, p,
735 1, "Subsequent address family identifier: %s (%u)",
736 val_to_str(i, bgpattr_nlri_safi,
737 i >= 128 ? "Vendor specific" : "Unknown"), i);
740 orfnum = tvb_get_guint8(tvb, p);
741 proto_tree_add_text(subtree3, tvb, p,
742 1, "Number of ORFs: %u", orfnum);
744 for (i=0; i<orfnum; i++) {
746 orftype = tvb_get_guint8(tvb, p);
747 proto_tree_add_text(subtree3, tvb, p,
748 1, "ORF Type: %s (%u)",
749 val_to_str(orftype, orf_type_vals,"Unknown"),
753 orfsendrecv = tvb_get_guint8(tvb, p);
754 proto_tree_add_text(subtree3, tvb, p,
755 1, "Send/Receive: %s (%u)",
756 val_to_str(orfsendrecv, orf_send_recv_vals,
757 "Uknown"), orfsendrecv);
761 /* unknown capability */
763 ti = proto_tree_add_text(subtree, tvb, p - 2,
764 2 + clen, "Unknown capability (%u %s)", 2 + clen,
765 (clen == 1) ? "byte" : "bytes");
766 subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
767 proto_tree_add_text(subtree2, tvb, p - 2,
768 1, "Capability code: %s (%d)",
769 ctype >= 128 ? "Private use" : "Unknown", ctype);
770 proto_tree_add_text(subtree2, tvb, p - 1,
771 1, "Capability length: %u %s", clen,
772 (clen == 1) ? "byte" : "bytes");
774 proto_tree_add_text(subtree2, tvb, p,
775 clen, "Capability value: Unknown");
783 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
784 "Unknown optional parameter");
792 * Dissect a BGP UPDATE message.
795 dissect_bgp_update(tvbuff_t *tvb, int offset, proto_tree *tree)
797 struct bgp_attr bgpa; /* path attributes */
798 int hlen; /* message length */
799 gint o; /* packet offset */
801 gint end; /* message end */
802 gint ext_com; /* EXTENDED COMMUNITY type */
804 int advance; /* tmp */
805 proto_item *ti; /* tree item */
806 proto_tree *subtree; /* subtree for attributes */
807 proto_tree *subtree2; /* subtree for attributes */
808 proto_tree *subtree3; /* subtree for attributes */
809 proto_tree *as_paths_tree; /* subtree for AS_PATHs */
810 proto_tree *as_path_tree; /* subtree for AS_PATH */
811 proto_tree *communities_tree; /* subtree for COMMUNITIES */
812 proto_tree *community_tree; /* subtree for a community */
813 proto_tree *cluster_list_tree; /* subtree for CLUSTER_LIST */
815 guint8 length; /* AS_PATH length */
816 guint8 type; /* AS_PATH type */
817 char *as_path_str = NULL; /* AS_PATH string */
818 char *communities_str = NULL; /* COMMUNITIES string */
819 char *cluster_list_str = NULL; /* CLUSTER_LIST string */
820 char *ext_com_str = NULL; /* EXTENDED COMMUNITY list */
821 char junk_buf[256]; /* tmp */
822 guint8 ipaddr[4]; /* IPv4 address */
824 hlen = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
825 o = offset + BGP_HEADER_SIZE;
827 /* check for withdrawals */
828 len = tvb_get_ntohs(tvb, o);
829 proto_tree_add_text(tree, tvb, o, 2,
830 "Unfeasible routes length: %u %s", len, (len == 1) ? "byte" : "bytes");
833 /* parse unfeasible prefixes */
835 ti = proto_tree_add_text(tree, tvb, o, len, "Withdrawn routes:");
836 subtree = proto_item_add_subtree(ti, ett_bgp_unfeas);
838 /* parse each prefixes */
841 i = decode_prefix4(tvb, o, junk_buf, sizeof(junk_buf));
842 proto_tree_add_text(subtree, tvb, o, i, "%s", junk_buf);
849 /* check for advertisements */
850 len = tvb_get_ntohs(tvb, o);
851 proto_tree_add_text(tree, tvb, o, 2, "Total path attribute length: %u %s",
852 len, (len == 1) ? "byte" : "bytes");
854 /* path attributes */
856 ti = proto_tree_add_text(tree, tvb, o + 2, len, "Path attributes");
857 subtree = proto_item_add_subtree(ti, ett_bgp_attrs);
867 tvb_memcpy(tvb, (guint8 *)&bgpa, o + i, sizeof(bgpa));
868 /* check for the Extended Length bit */
869 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
870 alen = tvb_get_ntohs(tvb, o + i + sizeof(bgpa));
871 aoff = sizeof(bgpa) + 2;
873 alen = tvb_get_guint8(tvb, o + i + sizeof(bgpa));
874 aoff = sizeof(bgpa) + 1;
877 /* This is kind of ugly - similar code appears twice, but it
878 helps browsing attrs. */
879 /* the first switch prints things in the title of the subtree */
880 switch (bgpa.bgpa_type) {
883 goto default_attribute_top;
884 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
885 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
887 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
888 msg, alen + aoff, (alen + aoff == 1) ? "byte" :
891 case BGPTYPE_AS_PATH:
893 (o + current attribute + aoff bytes to first tuple) */
896 /* must be freed by second switch! */
897 /* "alen * 6" (5 digits + space) should be a good estimate
898 of how long the AS path string could be */
899 as_path_str = malloc((alen + 1) * 6);
900 if (as_path_str == NULL) break;
901 as_path_str[0] = '\0';
903 /* snarf each AS path */
905 type = tvb_get_guint8(tvb, q++);
906 if (type == AS_SET) {
907 snprintf(as_path_str, 2, "{");
909 else if (type == AS_CONFED_SET) {
910 snprintf(as_path_str, 2, "[");
912 else if (type == AS_CONFED_SEQUENCE) {
913 snprintf(as_path_str, 2, "(");
915 length = tvb_get_guint8(tvb, q++);
917 /* snarf each value in path */
918 for (j = 0; j < length; j++) {
919 snprintf(junk_buf, sizeof(junk_buf), "%u%s", tvb_get_ntohs(tvb, q),
920 (type == AS_SET || type == AS_CONFED_SET)
922 strncat(as_path_str, junk_buf, sizeof(junk_buf));
926 /* cleanup end of string */
927 if (type == AS_SET) {
928 as_path_str[strlen(as_path_str) - 2] = '}';
930 else if (type == AS_CONFED_SET) {
931 as_path_str[strlen(as_path_str) - 2] = ']';
933 else if (type == AS_CONFED_SEQUENCE) {
934 as_path_str[strlen(as_path_str) - 1] = ')';
937 as_path_str[strlen(as_path_str) - 1] = '\0';
941 /* check for empty AS_PATH */
943 strncpy(as_path_str, "empty", 6);
945 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
947 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
948 as_path_str, alen + aoff,
949 (alen + aoff == 1) ? "byte" : "bytes");
951 case BGPTYPE_NEXT_HOP:
953 goto default_attribute_top;
954 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
955 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
957 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
958 ip_to_str(ipaddr), alen + aoff, (alen + aoff == 1)
961 case BGPTYPE_MULTI_EXIT_DISC:
963 goto default_attribute_top;
964 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
966 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
967 tvb_get_ntohl(tvb, o + i + aoff), alen + aoff,
968 (alen + aoff == 1) ? "byte" : "bytes");
970 case BGPTYPE_LOCAL_PREF:
972 goto default_attribute_top;
973 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
975 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
976 tvb_get_ntohl(tvb, o + i + aoff), alen + aoff,
977 (alen + aoff == 1) ? "byte" : "bytes");
979 case BGPTYPE_ATOMIC_AGGREGATE:
981 goto default_attribute_top;
982 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
984 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
985 alen + aoff, (alen + aoff == 1) ? "byte" : "bytes");
987 case BGPTYPE_AGGREGATOR:
989 goto default_attribute_top;
990 tvb_memcpy(tvb, ipaddr, o + i + aoff + 2, 4);
991 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
992 "%s: AS: %u origin: %s (%u %s)",
993 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
994 tvb_get_ntohs(tvb, o + i + aoff),
995 ip_to_str(ipaddr), alen + aoff,
996 (alen + aoff == 1) ? "byte" : "bytes");
998 case BGPTYPE_COMMUNITIES:
1000 goto default_attribute_top;
1003 (o + current attribute + aoff bytes to first tuple) */
1006 /* must be freed by second switch! */
1007 /* "alen * 12" (5 digits, a :, 5 digits + space ) should be
1008 a good estimate of how long the communities string could
1010 communities_str = malloc((alen + 1) * 12);
1011 if (communities_str == NULL) break;
1012 communities_str[0] = '\0';
1013 memset(junk_buf, 0, sizeof(junk_buf));
1015 /* snarf each community */
1017 /* check for well-known communities */
1018 if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT)
1019 strncpy(junk_buf, "NO_EXPORT ", 10);
1020 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_ADVERTISE)
1021 strncpy(junk_buf, "NO_ADVERTISE ", 13);
1022 else if (tvb_get_ntohl(tvb, q) == BGP_COMM_NO_EXPORT_SUBCONFED)
1023 strncpy(junk_buf, "NO_EXPORT_SUBCONFED ", 20);
1025 snprintf(junk_buf, sizeof(junk_buf), "%u:%u ",
1026 tvb_get_ntohs(tvb, q),
1027 tvb_get_ntohs(tvb, q + 2));
1031 strncat(communities_str, junk_buf, sizeof(junk_buf));
1033 /* cleanup end of string */
1034 communities_str[strlen(communities_str) - 1] = '\0';
1036 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
1038 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1039 communities_str, alen + aoff,
1040 (alen + aoff == 1) ? "byte" : "bytes");
1042 case BGPTYPE_ORIGINATOR_ID:
1044 goto default_attribute_top;
1045 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1046 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
1048 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1049 ip_to_str(ipaddr), alen + aoff, (alen + aoff == 1)
1050 ? "byte" : "bytes");
1052 case BGPTYPE_CLUSTER_LIST:
1054 goto default_attribute_top;
1057 (o + current attribute + aoff bytes to first tuple) */
1060 /* must be freed by second switch! */
1061 /* "alen * 16" (12 digits, 3 dots + space ) should be
1062 a good estimate of how long the cluster_list string could
1064 cluster_list_str = malloc((alen + 1) * 16);
1065 if (cluster_list_str == NULL) break;
1066 cluster_list_str[0] = '\0';
1067 memset(junk_buf, 0, sizeof(junk_buf));
1069 /* snarf each cluster list */
1070 tvb_memcpy(tvb, ipaddr, q, 4);
1072 snprintf(junk_buf, sizeof(junk_buf), "%s ", ip_to_str(ipaddr));
1073 strncat(cluster_list_str, junk_buf, sizeof(junk_buf));
1076 /* cleanup end of string */
1077 cluster_list_str[strlen(cluster_list_str) - 1] = '\0';
1079 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
1081 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1082 cluster_list_str, alen + aoff,
1083 (alen + aoff == 1) ? "byte" : "bytes");
1085 case BGPTYPE_EXTENDED_COMMUNITY:
1087 goto default_attribute_top;
1090 (o + current attribute + aoff bytes to first tuple) */
1093 ext_com_str = malloc((alen / 8)*MAX_SIZE_OF_EXT_COM_NAMES);
1094 if (ext_com_str == NULL) break;
1095 ext_com_str[0] = '\0';
1097 ext_com = tvb_get_ntohs(tvb, q);
1098 snprintf(junk_buf, sizeof(junk_buf), "%s", val_to_str(ext_com,bgpext_com_type,"Unknown"));
1099 strncat(ext_com_str, junk_buf, sizeof(junk_buf));
1101 if (q < end) strncat(ext_com_str, ",", 1);
1103 ti = proto_tree_add_text(subtree,tvb,o+i,alen+aoff,
1105 val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
1106 ext_com_str, alen + aoff,
1107 (alen + aoff == 1) ? "byte" : "bytes");
1112 default_attribute_top:
1113 ti = proto_tree_add_text(subtree, tvb, o + i, alen + aoff,
1115 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1116 alen + aoff, (alen + aoff == 1) ? "byte" : "bytes");
1117 } /* end of first switch */
1118 subtree2 = proto_item_add_subtree(ti, ett_bgp_attr);
1120 /* figure out flags */
1122 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_OPTIONAL) {
1123 strncat(junk_buf, "Optional, ", 10);
1126 strncat(junk_buf, "Well-known, ", 12);
1128 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_TRANSITIVE) {
1129 strncat(junk_buf, "Transitive, ", 12);
1132 strncat(junk_buf, "Non-transitive, ", 16);
1134 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_PARTIAL) {
1135 strncat(junk_buf, "Partial, ", 9);
1138 strncat(junk_buf, "Complete, ", 10);
1140 if (bgpa.bgpa_flags & BGP_ATTR_FLAG_EXTENDED_LENGTH) {
1141 strncat(junk_buf, "Extended Length, ", 17);
1143 /* stomp last ", " */
1144 j = strlen(junk_buf);
1145 junk_buf[j - 2] = '\0';
1146 ti = proto_tree_add_text(subtree2, tvb,
1147 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1148 "Flags: 0x%02x (%s)", bgpa.bgpa_flags, junk_buf);
1149 subtree3 = proto_item_add_subtree(ti, ett_bgp_attr_flags);
1151 /* add flag bitfield subtrees */
1152 proto_tree_add_text(subtree3, tvb,
1153 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1154 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1155 BGP_ATTR_FLAG_OPTIONAL, 8, "Optional", "Well-known"));
1156 proto_tree_add_text(subtree3, tvb,
1157 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1158 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1159 BGP_ATTR_FLAG_TRANSITIVE, 8, "Transitive",
1161 proto_tree_add_text(subtree3, tvb,
1162 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1163 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1164 BGP_ATTR_FLAG_PARTIAL, 8, "Partial", "Complete"));
1165 proto_tree_add_text(subtree3, tvb,
1166 o + i + offsetof(struct bgp_attr, bgpa_flags), 1,
1167 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
1168 BGP_ATTR_FLAG_EXTENDED_LENGTH, 8, "Extended length",
1171 proto_tree_add_text(subtree2, tvb,
1172 o + i + offsetof(struct bgp_attr, bgpa_type), 1,
1173 "Type code: %s (%u)",
1174 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
1177 proto_tree_add_text(subtree2, tvb, o + i + sizeof(bgpa),
1178 aoff - sizeof(bgpa), "Length: %d %s", alen,
1179 (alen == 1) ? "byte" : "bytes");
1181 /* the second switch prints things in the actual subtree of each
1183 switch (bgpa.bgpa_type) {
1184 case BGPTYPE_ORIGIN:
1186 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1187 "Origin (invalid): %u %s", alen,
1188 (alen == 1) ? "byte" : "bytes");
1190 msg = val_to_str(tvb_get_guint8(tvb, o + i + aoff), bgpattr_origin, "Unknown");
1191 proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
1192 "Origin: %s (%u)", msg, tvb_get_guint8(tvb, o + i + aoff));
1195 case BGPTYPE_AS_PATH:
1196 /* check for empty AS_PATH */
1202 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1203 "AS path: %s", as_path_str);
1204 as_paths_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1207 (o + current attribute + aoff bytes to first tuple) */
1211 /* snarf each AS path tuple, we have to step through each one
1212 again to make a separate subtree so we can't just reuse
1213 as_path_str from above */
1215 as_path_str[0] = '\0';
1216 type = tvb_get_guint8(tvb, q++);
1217 if (type == AS_SET) {
1218 snprintf(as_path_str, 2, "{");
1220 else if (type == AS_CONFED_SET) {
1221 snprintf(as_path_str, 2, "[");
1223 else if (type == AS_CONFED_SEQUENCE) {
1224 snprintf(as_path_str, 2, "(");
1226 length = tvb_get_guint8(tvb, q++);
1228 /* snarf each value in path, we're just going to reuse
1229 as_path_str since we already have it malloced */
1230 for (j = 0; j < length; j++) {
1231 snprintf(junk_buf, sizeof(junk_buf), "%u%s", tvb_get_ntohs(tvb, q),
1232 (type == AS_SET || type == AS_CONFED_SET)
1234 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1238 /* cleanup end of string */
1239 if (type == AS_SET) {
1240 as_path_str[strlen(as_path_str) - 2] = '}';
1242 else if (type == AS_CONFED_SET) {
1243 as_path_str[strlen(as_path_str) - 2] = ']';
1245 else if (type == AS_CONFED_SEQUENCE) {
1246 as_path_str[strlen(as_path_str) - 1] = ')';
1249 as_path_str[strlen(as_path_str) - 1] = '\0';
1252 /* length here means number of ASs, ie length * 2 bytes */
1253 ti = proto_tree_add_text(as_paths_tree, tvb,
1255 length * 2 + 2, "AS path segment: %s", as_path_str);
1256 as_path_tree = proto_item_add_subtree(ti, ett_bgp_as_paths);
1257 proto_tree_add_text(as_path_tree, tvb, q - length * 2 - 2,
1258 1, "Path segment type: %s (%u)",
1259 val_to_str(type, as_segment_type, "Unknown"), type);
1260 proto_tree_add_text(as_path_tree, tvb, q - length * 2 - 1,
1261 1, "Path segment length: %u %s", length,
1262 (length == 1) ? "AS" : "ASs");
1264 /* backup and reprint path segment value(s) only */
1266 as_path_str[0] = '\0';
1267 for (j = 0; j < length; j++) {
1268 snprintf(junk_buf, sizeof(junk_buf), "%u ", tvb_get_ntohs(tvb, q));
1269 strncat(as_path_str, junk_buf, sizeof(junk_buf));
1272 as_path_str[strlen(as_path_str) - 1] = '\0';
1274 proto_tree_add_text(as_path_tree, tvb, q - length * 2,
1275 length * 2, "Path segment value: %s", as_path_str);
1280 case BGPTYPE_NEXT_HOP:
1282 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1283 "Next hop (invalid): %u %s", alen,
1284 (alen == 1) ? "byte" : "bytes");
1286 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1287 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1288 "Next hop: %s", ip_to_str(ipaddr));
1291 case BGPTYPE_MULTI_EXIT_DISC:
1293 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1294 "Multiple exit discriminator (invalid): %u %s",
1295 alen, (alen == 1) ? "byte" : "bytes");
1297 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1298 "Multiple exit discriminator: %u",
1299 tvb_get_ntohl(tvb, o + i + aoff));
1302 case BGPTYPE_LOCAL_PREF:
1304 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1305 "Local preference (invalid): %u %s", alen,
1306 (alen == 1) ? "byte" : "bytes");
1308 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1309 "Local preference: %u", tvb_get_ntohl(tvb, o + i + aoff));
1312 case BGPTYPE_ATOMIC_AGGREGATE:
1314 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1315 "Atomic aggregate (invalid): %u %s", alen,
1316 (alen == 1) ? "byte" : "bytes");
1319 case BGPTYPE_AGGREGATOR:
1321 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1322 "Aggregator (invalid): %u %s", alen,
1323 (alen == 1) ? "byte" : "bytes");
1325 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1326 "Aggregator AS: %u", tvb_get_ntohs(tvb, o + i + aoff));
1327 tvb_memcpy(tvb, ipaddr, o + i + aoff + 2, 4);
1328 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 4,
1329 "Aggregator origin: %s",
1333 case BGPTYPE_COMMUNITIES:
1334 if (alen % 4 != 0) {
1335 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1336 "Communities (invalid): %u %s", alen,
1337 (alen == 1) ? "byte" : "bytes");
1338 free(communities_str);
1342 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1343 "Communities: %s", communities_str);
1344 communities_tree = proto_item_add_subtree(ti,
1345 ett_bgp_communities);
1348 (o + current attribute + aoff bytes to first tuple) */
1352 /* snarf each community */
1354 /* check for reserved values */
1355 guint32 community = tvb_get_ntohl(tvb, q);
1356 if ((community & 0xFFFF0000) == FOURHEX0 ||
1357 (community & 0xFFFF0000) == FOURHEXF) {
1358 proto_tree_add_text(communities_tree, tvb,
1360 "Community: %s (0x%08x)",
1361 val_to_str(community, community_vals, "(reserved)"),
1365 ti = proto_tree_add_text(communities_tree, tvb,
1366 q - 3 + aoff, 4, "Community: %u:%u",
1367 tvb_get_ntohs(tvb, q), tvb_get_ntohs(tvb, q + 2));
1368 community_tree = proto_item_add_subtree(ti,
1369 ett_bgp_communities);
1370 proto_tree_add_text(community_tree, tvb, q - 3 + aoff,
1371 2, "Community AS: %u", tvb_get_ntohs(tvb, q));
1372 proto_tree_add_text(community_tree, tvb, q - 1 + aoff,
1373 2, "Community value: %u", tvb_get_ntohs(tvb, q + 2));
1379 free(communities_str);
1381 case BGPTYPE_ORIGINATOR_ID:
1383 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1384 "Originator identifier (invalid): %u %s", alen,
1385 (alen == 1) ? "byte" : "bytes");
1387 tvb_memcpy(tvb, ipaddr, o + i + aoff, 4);
1388 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1389 "Originator identifier: %s",
1393 case BGPTYPE_MP_REACH_NLRI:
1395 * RFC 2545 specifies that there may be more than one
1396 * address in the MP_REACH_NLRI attribute in section
1397 * 3, "Constructing the Next Hop field".
1399 * Yes, RFC 2858 says you can't do that, and, yes, RFC
1400 * 2858 obsoletes RFC 2283, which says you can do that,
1401 * but that doesn't mean we shouldn't dissect packets
1402 * that conform to RFC 2283 but not RFC 2858, as some
1403 * device on the network might implement the 2283-style
1404 * BGP extensions rather than RFC 2858-style extensions.
1406 af = tvb_get_ntohs(tvb, o + i + aoff);
1407 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1408 "Address family: %s (%u)",
1409 val_to_str(af, afn_vals, "Unknown"), af);
1410 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
1411 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
1412 "Subsequent address family identifier: %s (%u)",
1413 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
1415 nexthop_len = tvb_get_guint8(tvb, o + i + aoff + 3);
1416 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3, 1,
1417 "Next hop network address (%d %s)",
1418 nexthop_len, plurality(nexthop_len, "byte", "bytes"));
1419 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_nhna);
1421 while (j < nexthop_len) {
1422 advance = mp_addr_to_str(af, saf, tvb, o + i + aoff + 4 + j,
1423 junk_buf, sizeof(junk_buf)) ;
1424 if (j + advance > nexthop_len)
1426 proto_tree_add_text(subtree3, tvb,o + i + aoff + 4 + j,
1427 advance, "Next hop: %s (%u)", junk_buf, advance);
1430 alen -= nexthop_len + 4;
1431 aoff += nexthop_len + 4 ;
1434 snpa = tvb_get_guint8(tvb, o + i + aoff);
1435 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, 1,
1436 "Subnetwork points of attachment: %u", snpa);
1439 subtree3 = proto_item_add_subtree(ti, ett_bgp_mp_snpa);
1440 for (/*nothing*/; snpa > 0; snpa--) {
1441 proto_tree_add_text(subtree3, tvb, o + i + aoff + off, 1,
1442 "SNPA length: %u", tvb_get_guint8(tvb, o + i + aoff + off));
1444 proto_tree_add_text(subtree3, tvb, o + i + aoff + off,
1445 tvb_get_guint8(tvb, o + i + aoff + off - 1),
1446 "SNPA (%u %s)", tvb_get_guint8(tvb, o + i + aoff + off - 1),
1447 (tvb_get_guint8(tvb, o + i + aoff + off - 1) == 1) ? "byte" : "bytes");
1448 off += tvb_get_guint8(tvb, o + i + aoff + off - 1);
1454 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1455 "Network layer reachability information (%u %s)",
1456 alen, (alen == 1) ? "byte" : "bytes");
1458 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_reach_nlri);
1461 advance = decode_prefix_MP(af, saf, tvb, o + i + aoff , junk_buf, sizeof(junk_buf)) ;
1462 proto_tree_add_text(subtree3, tvb, o + i + aoff, advance, "%s", junk_buf) ;
1468 case BGPTYPE_MP_UNREACH_NLRI:
1469 af = tvb_get_ntohs(tvb, o + i + aoff);
1470 proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
1471 "Address family: %s (%u)",
1472 val_to_str(af, afn_vals, "Unknown"), af);
1473 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
1474 proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
1475 "Subsequent address family identifier: %s (%u)",
1476 val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
1478 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff + 3,
1479 alen - 3, "Withdrawn routes (%u %s)", alen - 3,
1480 (alen - 3 == 1) ? "byte" : "bytes");
1485 subtree3 = proto_item_add_subtree(ti,ett_bgp_mp_unreach_nlri);
1488 advance = decode_prefix_MP(af, saf, tvb, o + i + aoff , junk_buf, sizeof(junk_buf)) ;
1490 proto_tree_add_text(subtree3, tvb, o + i + aoff, advance, "%s", junk_buf) ;
1496 case BGPTYPE_CLUSTER_LIST:
1497 if (alen % 4 != 0) {
1498 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1499 "Cluster list (invalid): %u %s", alen,
1500 (alen == 1) ? "byte" : "bytes");
1501 free(cluster_list_str);
1505 ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1506 "Cluster list: %s", cluster_list_str);
1507 cluster_list_tree = proto_item_add_subtree(ti,
1508 ett_bgp_cluster_list);
1511 (o + current attribute + aoff bytes to first tuple) */
1515 /* snarf each cluster identifier */
1517 tvb_memcpy(tvb, ipaddr, q, 4);
1518 ti = proto_tree_add_text(cluster_list_tree, tvb,
1519 q - 3 + aoff, 4, "Cluster identifier: %s",
1525 free(cluster_list_str);
1527 case BGPTYPE_EXTENDED_COMMUNITY:
1529 proto_tree_add_text(subtree3, tvb, o + i + aoff, alen, "Extended community (invalid) : %u %s", alen,
1530 (alen == 1) ? "byte" : "bytes") ;
1533 end = o + i + aoff + alen ;
1534 ext_com_str = malloc(MAX_SIZE_OF_EXT_COM_NAMES+MAX_SIZE_OF_IP_ADDR_STRING*2+1) ;
1535 if (ext_com_str == NULL) break ;
1536 ti = proto_tree_add_text(subtree2,tvb,q,alen, "Carried Extended communities");
1537 subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
1540 ext_com_str[0] = '\0' ;
1541 ext_com = tvb_get_ntohs(tvb,q) ;
1542 snprintf(junk_buf, sizeof(junk_buf), "%s", val_to_str(ext_com,bgpext_com_type,"Unknown"));
1543 strncat(ext_com_str,junk_buf,sizeof(junk_buf));
1545 case BGP_EXT_COM_RT_0:
1546 case BGP_EXT_COM_RO_0:
1547 snprintf(junk_buf, sizeof(junk_buf), ": %u%s%d",tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
1549 case BGP_EXT_COM_RT_1:
1550 case BGP_EXT_COM_RO_1:
1551 tvb_memcpy(tvb,ipaddr,q+2,4);
1552 snprintf(junk_buf, sizeof(junk_buf), ": %s%s%u",ip_to_str(ipaddr),":",tvb_get_ntohs(tvb,q+6));
1554 case BGP_EXT_COM_VPN_ORIGIN:
1555 case BGP_EXT_COM_OSPF_RID:
1556 tvb_memcpy(tvb,ipaddr,q+2,4);
1557 snprintf(junk_buf, sizeof(junk_buf), ": %s",ip_to_str(ipaddr));
1559 case BGP_EXT_COM_OSPF_RTYPE:
1560 tvb_memcpy(tvb,ipaddr,q+2,4);
1561 snprintf(junk_buf, sizeof(junk_buf), ": Area:%s %s",ip_to_str(ipaddr),val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
1562 /* print OSPF Metric type if selected */
1563 /* always print E2 even if not external route -- receiving router should ignore */
1564 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) {
1565 strcat(junk_buf," E2");
1566 } else if (tvb_get_guint8(tvb,q+6)==(BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA ) ) {
1567 strcat(junk_buf, " E1");
1570 case BGP_EXT_COM_LINKBAND:
1571 tvb_memcpy(tvb,ipaddr,q+2,4); /* need to check on IEEE format on all platforms */
1572 snprintf(junk_buf, sizeof(junk_buf), ": %f bytes per second",(double)*ipaddr);
1575 snprintf(junk_buf, sizeof(junk_buf), " ");
1578 strncat(ext_com_str,junk_buf,sizeof(junk_buf));
1579 proto_tree_add_text(subtree3,tvb,q,8, "%s",ext_com_str);
1586 proto_tree_add_text(subtree2, tvb, o + i + aoff, alen,
1587 "Unknown (%d %s)", alen, (alen == 1) ? "byte" :
1590 } /* end of second switch */
1598 len = offset + hlen - o;
1600 /* parse prefixes */
1602 ti = proto_tree_add_text(tree, tvb, o, len,
1603 "Network layer reachability information: %u %s", len,
1604 (len == 1) ? "byte" : "bytes");
1605 subtree = proto_item_add_subtree(ti, ett_bgp_nlri);
1608 i = decode_prefix4(tvb, o, junk_buf, sizeof(junk_buf));
1609 proto_tree_add_text(subtree, tvb, o, i, "%s", junk_buf);
1617 * Dissect a BGP NOTIFICATION message.
1620 dissect_bgp_notification(tvbuff_t *tvb, int offset, proto_tree *tree)
1622 struct bgp_notification bgpn; /* BGP NOTIFICATION message */
1623 int hlen; /* message length */
1624 char *p; /* string pointer */
1627 tvb_memcpy(tvb, bgpn.bgpn_marker, offset, BGP_MIN_NOTIFICATION_MSG_SIZE);
1628 hlen = g_ntohs(bgpn.bgpn_len);
1630 /* print error code */
1631 proto_tree_add_text(tree, tvb,
1632 offset + offsetof(struct bgp_notification, bgpn_major), 1,
1633 "Error code: %s (%u)",
1634 val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
1637 /* print error subcode */
1638 if (bgpn.bgpn_major < array_length(bgpnotify_minor)
1639 && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
1640 p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
1642 } else if (bgpn.bgpn_minor == 0)
1646 proto_tree_add_text(tree, tvb,
1647 offset + offsetof(struct bgp_notification, bgpn_minor), 1,
1648 "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
1650 /* only print if there is optional data */
1651 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
1652 proto_tree_add_text(tree, tvb, offset + BGP_MIN_NOTIFICATION_MSG_SIZE,
1653 hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
1658 * Dissect a BGP ROUTE-REFRESH message.
1661 dissect_bgp_route_refresh(tvbuff_t *tvb, int offset, proto_tree *tree)
1666 i = tvb_get_ntohs(tvb, offset + BGP_HEADER_SIZE);
1667 proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 2,
1668 "Address family identifier: %s (%u)",
1669 val_to_str(i, afn_vals, "Unknown"), i);
1672 proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 1,
1673 "Reserved: 1 byte");
1676 i = tvb_get_guint8(tvb, offset + BGP_HEADER_SIZE);
1677 proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 1,
1678 "Subsequent address family identifier: %s (%u)",
1679 val_to_str(i, bgpattr_nlri_safi,
1680 i >= 128 ? "Vendor specific" : "Unknown"),
1685 * Dissect a BGP packet.
1688 dissect_bgp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1690 proto_item *ti; /* tree item */
1691 proto_tree *bgp_tree; /* BGP packet tree */
1692 proto_tree *bgp1_tree; /* BGP message tree */
1694 int found; /* number of BGP messages in packet */
1695 static guchar marker[] = { /* BGP message marker */
1696 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1697 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1699 struct bgp bgp; /* BGP header */
1700 int hlen; /* BGP header length */
1701 char *typ; /* BGP message type */
1703 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1704 col_set_str(pinfo->cinfo, COL_PROTOCOL, "BGP");
1705 if (check_col(pinfo->cinfo, COL_INFO))
1706 col_clear(pinfo->cinfo, COL_INFO);
1708 l = tvb_reported_length(tvb);
1711 /* run through the TCP packet looking for BGP headers */
1712 while (i + BGP_HEADER_SIZE <= l) {
1713 tvb_memcpy(tvb, bgp.bgp_marker, i, BGP_HEADER_SIZE);
1715 /* look for bgp header */
1716 if (memcmp(bgp.bgp_marker, marker, sizeof(marker)) != 0) {
1722 hlen = g_ntohs(bgp.bgp_len);
1725 * Desegmentation check.
1727 if (bgp_desegment) {
1728 if (hlen > tvb_length_remaining(tvb, i) && pinfo->can_desegment) {
1730 * Not all of this packet is in the data we've been
1731 * handed, but we can do reassembly on it.
1733 * Tell the TCP dissector where the data for
1734 * this message starts in the data it handed
1735 * us, and how many more bytes we need, and
1738 pinfo->desegment_offset = i;
1739 pinfo->desegment_len = hlen - tvb_length_remaining(tvb, i);
1744 typ = val_to_str(bgp.bgp_type, bgptypevals, "Unknown Message");
1746 if (check_col(pinfo->cinfo, COL_INFO)) {
1748 col_add_fstr(pinfo->cinfo, COL_INFO, "%s", typ);
1750 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", typ);
1754 ti = proto_tree_add_item(tree, proto_bgp, tvb, i, hlen, FALSE);
1755 bgp_tree = proto_item_add_subtree(ti, ett_bgp);
1757 ti = proto_tree_add_text(bgp_tree, tvb, i, hlen, "%s", typ);
1759 /* add a different tree for each message type */
1760 switch (bgp.bgp_type) {
1762 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_open);
1765 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_update);
1767 case BGP_NOTIFICATION:
1768 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_notification);
1771 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
1773 case BGP_ROUTE_REFRESH_CISCO:
1774 case BGP_ROUTE_REFRESH:
1775 bgp1_tree = proto_item_add_subtree(ti, ett_bgp_route_refresh);
1778 bgp1_tree = proto_item_add_subtree(ti, ett_bgp);
1782 proto_tree_add_text(bgp1_tree, tvb, i, BGP_MARKER_SIZE,
1783 "Marker: 16 bytes");
1785 if (hlen < BGP_HEADER_SIZE || hlen > BGP_MAX_PACKET_SIZE) {
1786 proto_tree_add_text(bgp1_tree, tvb,
1787 i + offsetof(struct bgp, bgp_len), 2,
1788 "Length (invalid): %u %s", hlen,
1789 (hlen == 1) ? "byte" : "bytes");
1791 proto_tree_add_text(bgp1_tree, tvb,
1792 i + offsetof(struct bgp, bgp_len), 2,
1793 "Length: %u %s", hlen,
1794 (hlen == 1) ? "byte" : "bytes");
1797 proto_tree_add_uint_format(bgp1_tree, hf_bgp_type, tvb,
1798 i + offsetof(struct bgp, bgp_type), 1,
1800 "Type: %s (%u)", typ, bgp.bgp_type);
1802 switch (bgp.bgp_type) {
1804 dissect_bgp_open(tvb, i, bgp1_tree);
1807 dissect_bgp_update(tvb, i, bgp1_tree);
1809 case BGP_NOTIFICATION:
1810 dissect_bgp_notification(tvb, i, bgp1_tree);
1813 /* no data in KEEPALIVE messages */
1815 case BGP_ROUTE_REFRESH_CISCO:
1816 case BGP_ROUTE_REFRESH:
1817 dissect_bgp_route_refresh(tvb, i, bgp1_tree);
1829 * Register ourselves.
1832 proto_register_bgp(void)
1835 static hf_register_info hf[] = {
1837 { "BGP message type", "bgp.type", FT_UINT8, BASE_HEX,
1838 VALS(bgptypevals), 0x0, "BGP message type", HFILL }},
1841 static gint *ett[] = {
1846 &ett_bgp_attr_flags,
1848 &ett_bgp_mp_reach_nlri,
1849 &ett_bgp_mp_unreach_nlri,
1854 &ett_bgp_notification,
1855 &ett_bgp_route_refresh,
1857 &ett_bgp_communities,
1858 &ett_bgp_cluster_list,
1861 &ett_bgp_extended_communities
1863 module_t *bgp_module;
1865 proto_bgp = proto_register_protocol("Border Gateway Protocol",
1867 proto_register_field_array(proto_bgp, hf, array_length(hf));
1868 proto_register_subtree_array(ett, array_length(ett));
1870 bgp_module = prefs_register_protocol(proto_bgp, NULL);
1871 prefs_register_bool_preference(bgp_module, "desegment",
1872 "Desegment all BGP messages spanning multiple TCP segments",
1873 "Whether the BGP dissector should desegment all messages spanning multiple TCP segments",
1878 proto_reg_handoff_bgp(void)
1880 dissector_handle_t bgp_handle;
1882 bgp_handle = create_dissector_handle(dissect_bgp, proto_bgp);
1883 dissector_add("tcp.port", BGP_TCP_PORT, bgp_handle);