2 * Routines for BGP packet dissection
3 * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
5 * $Id: packet-bgp.c,v 1.7 1999/11/02 00:11:58 itojun Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
41 #ifdef NEED_SNPRINTF_H
47 # include "snprintf.h"
53 #include "packet-bgp.h"
54 #include "packet-ipv6.h"
56 static const value_string bgptypevals[] = {
57 { BGP_OPEN, "OPEN Message" },
58 { BGP_UPDATE, "UPDATE Message" },
59 { BGP_NOTIFICATION, "NOTIFICATION Message" },
60 { BGP_KEEPALIVE, "KEEPALIVE Message" },
64 static const value_string bgpnotify_major[] = {
65 { 1, "Message Header Error" },
66 { 2, "OPEN Message Error" },
67 { 3, "UPDATE Message Error" },
68 { 4, "Hold Timer Expired" },
69 { 5, "Finite State Machine Error" },
74 static const value_string bgpnotify_minor_1[] = {
75 { 1, "Connection Not Synchronized" },
76 { 2, "Bad Message Length" },
77 { 3, "Bad Message Type" },
81 static const value_string bgpnotify_minor_2[] = {
82 { 1, "Unsupported Version Number" },
84 { 3, "Bad BGP Identifier" },
85 { 4, "Unsupported Optional Parameter" },
86 { 5, "Authentication Failure" },
87 { 6, "Unacceptable Hold Time" },
91 static const value_string bgpnotify_minor_3[] = {
92 { 1, "Malformed Attribute List" },
93 { 2, "Unrecognized Well-known Attribute" },
94 { 3, "Missing Well-known Attribute" },
95 { 4, "Attribute Flags Error" },
96 { 5, "Attribute Length Error" },
97 { 6, "Invalid ORIGIN Attribute" },
98 { 7, "AS Routing Loop" },
99 { 8, "Invalid NEXT_HOP Attribute" },
100 { 9, "Optional Attribute Error" },
101 { 10, "Invalid Network Field" },
102 { 11, "Malformed AS_PATH" },
106 static const value_string *bgpnotify_minor[] = {
107 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3,
110 static const value_string bgpattr_flags[] = {
111 { 0x80, "Optional" },
112 { 0x40, "Transitive" },
114 { 0x10, "Extended length" },
118 static const value_string bgpattr_origin[] = {
125 static const value_string bgpattr_type[] = {
126 { BGPTYPE_ORIGIN, "ORIGIN" },
127 { BGPTYPE_AS_PATH, "AS_PATH" },
128 { BGPTYPE_NEXT_HOP, "NEXT_HOP" },
129 { BGPTYPE_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" },
130 { BGPTYPE_LOCAL_PREF, "LOCAL_PREF" },
131 { BGPTYPE_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" },
132 { BGPTYPE_AGGREGATOR, "AGGREGATOR" },
133 { BGPTYPE_MP_REACH_NLRI, "MP_REACH_NLRI" },
134 { BGPTYPE_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" },
138 /* Subsequent address family identifier, RFC2283 section 7 */
139 static const value_string bgpattr_nlri_safi[] = {
143 { 3, "Unicast+Multicast" },
147 static const value_string afnumber[] = {
149 { AFNUM_INET, "IPv4" },
150 { AFNUM_INET6, "IPv6" },
151 { AFNUM_NSAP, "NSAP" },
152 { AFNUM_HDLC, "HDLC" },
153 { AFNUM_BBN1822, "BBN 1822" },
154 { AFNUM_802, "802" },
155 { AFNUM_E163, "E.163" },
156 { AFNUM_E164, "E.164" },
157 { AFNUM_F69, "F.69" },
158 { AFNUM_X121, "X.121" },
159 { AFNUM_IPX, "IPX" },
160 { AFNUM_ATALK, "Appletalk" },
161 { AFNUM_DECNET, "Decnet IV" },
162 { AFNUM_BANYAN, "Banyan Vines" },
163 { AFNUM_E164NSAP, "E.164 with NSAP subaddress" },
164 { 65535, "Reserved" },
168 static int proto_bgp = -1;
171 decode_prefix4(const u_char *pd, char *buf, int buflen)
177 if (plen < 0 || 32 < plen)
180 memset(addr, 0, sizeof(addr));
181 memcpy(addr, &pd[1], (plen + 7) / 8);
183 addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
184 snprintf(buf, buflen, "%s/%d", ip_to_str(addr), plen);
185 return 1 + (plen + 7) / 8;
189 decode_prefix6(const u_char *pd, char *buf, int buflen)
191 struct e_in6_addr addr;
195 if (plen < 0 || 128 < plen)
198 memset(&addr, 0, sizeof(addr));
199 memcpy(&addr, &pd[1], (plen + 7) / 8);
201 addr.s6_addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
202 snprintf(buf, buflen, "%s/%d", ip6_to_str(&addr), plen);
203 return 1 + (plen + 7) / 8;
207 dissect_bgp_open(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
209 struct bgp_open bgpo;
212 memcpy(&bgpo, &pd[offset], sizeof(bgpo));
213 hlen = ntohs(bgpo.bgpo_len);
215 proto_tree_add_text(tree,
216 offset + offsetof(struct bgp_open, bgpo_version), 1,
217 "Version: %u", bgpo.bgpo_version);
218 proto_tree_add_text(tree,
219 offset + offsetof(struct bgp_open, bgpo_myas), 2,
220 "My AS: %u", ntohs(bgpo.bgpo_myas));
221 proto_tree_add_text(tree,
222 offset + offsetof(struct bgp_open, bgpo_holdtime), 2,
223 "Holdtime: %u", ntohs(bgpo.bgpo_holdtime));
224 proto_tree_add_text(tree,
225 offset + offsetof(struct bgp_open, bgpo_id), 4,
226 "ID: %s", ip_to_str((guint8 *)&bgpo.bgpo_id));
227 proto_tree_add_text(tree,
228 offset + offsetof(struct bgp_open, bgpo_optlen), 1,
229 "Option length: %u", bgpo.bgpo_optlen);
230 if (hlen > sizeof(struct bgp_open)) {
231 proto_tree_add_text(tree,
232 offset + sizeof(struct bgp_open), hlen - sizeof(struct bgp_open),
237 /* NOTE: caller needs to free() the returned value. */
239 dissect_bgp_aspath(const u_char *pd, int len)
247 msg = malloc(len / 2 * 6 + 10);
252 for (j = 0; j < len; j += 2) {
253 n = sprintf(q, "%u ", ntohs(*(guint16 *)&pd[j]));
257 /* remove the last blank */
265 dissect_bgp_update(const u_char *pd, int offset, frame_data *fd,
269 struct bgp_attr bgpa;
274 proto_tree *subtree, *subtree2, *subtree3;
277 memcpy(&bgp, &pd[offset], sizeof(bgp));
278 hlen = ntohs(bgp.bgp_len);
280 p = &pd[offset + BGP_HEADER_SIZE]; /*XXX*/
281 proto_tree_add_text(tree, p - pd, 2,
282 "Unfeasible routes length: %d", len = ntohs(*(guint16 *)p));
283 ti = proto_tree_add_text(tree, p - pd, len,
284 "Withdrawn routes (%u bytes)", len);
286 subtree = proto_item_add_subtree(ti, ETT_BGP);
289 proto_tree_add_text(tree, p - pd, 2,
290 "Total path attribute length: %d", len = ntohs(*(guint16 *)p));
291 ti = proto_tree_add_text(tree, p - pd + 2, len,
292 "Path attributes (%u bytes)", len);
294 subtree = proto_item_add_subtree(ti, ETT_BGP);
302 memcpy(&bgpa, &p[i], sizeof(bgpa));
303 if (bgpa.bgpa_flags & 0x10) {
304 alen = ntohs(*(guint16 *)&p[i + sizeof(bgpa)]);
305 aoff = sizeof(bgpa) + 2;
307 alen = p[i + sizeof(bgpa)];
308 aoff = sizeof(bgpa) + 1;
312 * This is kind of ugly - similar code appears twice,
313 * but it helps browsing attrs.
315 switch (bgpa.bgpa_type) {
318 goto default_attribute_top;
319 msg = val_to_str(p[i + aoff], bgpattr_origin, "Unknown");
320 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
321 "Attribute: %s: %s (%u bytes)",
322 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
325 case BGPTYPE_AS_PATH:
327 goto default_attribute_top;
328 msg = dissect_bgp_aspath(p + i + aoff, alen);
330 goto default_attribute_top;
331 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
332 "Attribute: %s: %s (%u bytes)",
333 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
337 case BGPTYPE_NEXT_HOP:
339 goto default_attribute_top;
340 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
341 "Attribute: %s: %s (%u bytes)",
342 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
343 ip_to_str(&p[i + aoff]), alen + aoff);
345 case BGPTYPE_MULTI_EXIT_DISC:
347 goto default_attribute_top;
348 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
349 "Attribute: %s: %u (%u bytes)",
350 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
351 ntohl(*(guint32 *)&p[i + aoff]),
354 case BGPTYPE_LOCAL_PREF:
356 goto default_attribute_top;
357 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
358 "Attribute: %s: %u (%u bytes)",
359 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
360 ntohl(*(guint32 *)&p[i + aoff]),
363 case BGPTYPE_AGGREGATOR:
365 goto default_attribute_top;
366 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
367 "Attribute: %s: AS %u, origin %s (%u bytes)",
368 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
369 ntohs(*(guint16 *)&p[i + aoff]),
370 ip_to_str(&p[i + aoff + 2]), alen + aoff);
373 default_attribute_top:
374 ti = proto_tree_add_text(subtree, p - pd + i, alen + aoff,
375 "Attribute: %s (%u bytes)",
376 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
379 subtree2 = proto_item_add_subtree(ti, ETT_BGP);
381 ti = proto_tree_add_text(subtree2,
382 p - pd + i + offsetof(struct bgp_attr, bgpa_flags), 1,
383 "Flags: 0x%02x", bgpa.bgpa_flags);
384 subtree3 = proto_item_add_subtree(ti, ETT_BGP);
385 proto_tree_add_text(subtree3,
386 p - pd + i + offsetof(struct bgp_attr, bgpa_flags), 1,
387 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
388 0x80, 8, "Optional", "not Optional"));
389 proto_tree_add_text(subtree3,
390 p - pd + i + offsetof(struct bgp_attr, bgpa_flags), 1,
391 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
392 0x40, 8, "Transitive", "not Transitive"));
393 proto_tree_add_text(subtree3,
394 p - pd + i + offsetof(struct bgp_attr, bgpa_flags), 1,
395 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
396 0x20, 8, "Partial", "not Partial"));
397 proto_tree_add_text(subtree3,
398 p - pd + i + offsetof(struct bgp_attr, bgpa_flags), 1,
399 "%s", decode_boolean_bitfield(bgpa.bgpa_flags,
400 0x10, 8, "Extended length", "not Extended length"));
402 proto_tree_add_text(subtree2,
403 p - pd + i + offsetof(struct bgp_attr, bgpa_type), 1,
404 "Type code: %s (0x%02x)",
405 val_to_str(bgpa.bgpa_type, bgpattr_type, "Unknown"),
408 if (bgpa.bgpa_flags & 0x10) {
409 proto_tree_add_text(subtree2,
410 p - pd + i + sizeof(bgpa), aoff - sizeof(bgpa),
411 "Attribute length: %d", alen);
413 proto_tree_add_text(subtree2,
414 p - pd + i + sizeof(bgpa), aoff - sizeof(bgpa),
415 "Attribute length: %d", alen);
418 switch (bgpa.bgpa_type) {
421 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
422 "Origin: Invalid (%d bytes)", alen);
424 msg = val_to_str(p[i + aoff], bgpattr_origin, "Unknown");
425 proto_tree_add_text(subtree2, p - pd + i + aoff, 1,
426 "Origin: %s (0x%02x)", msg, p[i + aoff]);
429 case BGPTYPE_AS_PATH:
431 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
432 "AS path: Invalid (%d bytes)", alen);
434 msg = dissect_bgp_aspath(p + i + aoff, alen);
436 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
437 "AS path (%d bytes)", alen);
439 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
440 "AS path: %s (%d ASes, %d bytes)",
441 msg, alen / 2, alen);
446 case BGPTYPE_NEXT_HOP:
448 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
449 "Next hop: Invalid (%d bytes)", alen);
451 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
452 "Next hop: %s", ip_to_str(&p[i + aoff]));
455 case BGPTYPE_MULTI_EXIT_DISC:
457 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
458 "Multi exit discriminator: Invalid (%d bytes)",
461 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
462 "Multi exit discriminator: %u",
463 ntohl(*(guint32 *)&p[i + aoff]));
466 case BGPTYPE_LOCAL_PREF:
468 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
469 "Local preference: Invalid (%d bytes)", alen);
471 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
472 "Local preference: %u",
473 ntohl(*(guint32 *)&p[i + aoff]));
476 case BGPTYPE_ATOMIC_AGGREGATE:
478 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
479 "Atomic aggregate: Invalid (%d bytes)", alen);
481 proto_tree_add_text(subtree2, p - pd + i + aoff, 0,
485 case BGPTYPE_AGGREGATOR:
487 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
488 "Aggregator: Invalid (%d bytes)", alen);
490 proto_tree_add_text(subtree2, p - pd + i + aoff, 2,
492 ntohs(*(guint16 *)&p[i + aoff]));
493 proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 4,
494 "Aggregator origin: %s",
495 ip_to_str(&p[i + aoff + 2]));
498 case BGPTYPE_MP_REACH_NLRI:
499 af = ntohs(*(guint16 *)&p[i + aoff]);
500 proto_tree_add_text(subtree2, p - pd + i + aoff, 2,
501 "Address family: %s (%u)",
502 val_to_str(af, afnumber, "Unknown"), af);
503 proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 1,
504 "Subsequent address family identifier: %s (%u)",
505 val_to_str(p[i + aoff + 2], bgpattr_nlri_safi,
506 p[i + aoff + 2] >= 128 ? "Vendor specific" : "Unknown"),
508 ti = proto_tree_add_text(subtree2, p - pd + i + aoff + 3, 1,
509 "Next hop network address (%d bytes)",
511 if (af == AFNUM_INET || af == AFNUM_INET6) {
515 subtree3 = proto_item_add_subtree(ti, ETT_BGP);
518 while (j < p[i + aoff + 3]) {
519 if (af == AFNUM_INET)
521 else if (af == AFNUM_INET6)
525 if (j + advance > p[i + aoff + 3])
528 if (af == AFNUM_INET)
529 s = ip_to_str(&p[i + aoff + 4 + j]);
531 s = ip6_to_str((struct e_in6_addr *)
532 &p[i + aoff + 4 + j]);
534 proto_tree_add_text(subtree3,
535 p - pd + i + aoff + 4 + j, advance,
541 alen -= (p[i + aoff + 3] + 4);
542 aoff += (p[i + aoff + 3] + 4);
545 ti = proto_tree_add_text(subtree2, p - pd + i + aoff, 1,
546 "Subnetwork points of attachment: %u", snpa);
549 subtree3 = proto_item_add_subtree(ti, ETT_BGP);
550 for (/*nothing*/; snpa > 0; snpa--) {
551 proto_tree_add_text(subtree3, p - pd + i + aoff + off, 1,
552 "SNPA length: ", p[i + aoff + off]);
554 proto_tree_add_text(subtree3, p - pd + i + aoff + off,
555 p[i + aoff + off - 1],
556 "SNPA (%u bytes)", p[i + aoff + off - 1]);
557 off += p[i + aoff + off - 1];
562 ti = proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
563 "Network Layer Reachability Information (%u bytes)",
566 subtree3 = proto_item_add_subtree(ti, ETT_BGP);
571 if (af == AFNUM_INET) {
572 advance = decode_prefix4(&p[i + aoff], buf,
574 } else if (af == AFNUM_INET6) {
575 advance = decode_prefix6(&p[i + aoff], buf,
583 proto_tree_add_text(subtree3, p - pd + i + aoff, advance,
584 "Network Layer Reachability Information: %s", buf);
591 case BGPTYPE_MP_UNREACH_NLRI:
592 af = ntohs(*(guint16 *)&p[i + aoff]);
593 proto_tree_add_text(subtree2, p - pd + i + aoff, 2,
594 "Address family: %s (%u)",
595 val_to_str(af, afnumber, "Unknown"), af);
596 proto_tree_add_text(subtree2, p - pd + i + aoff + 2, 1,
597 "Subsequent address family identifier: %s (%u)",
598 val_to_str(p[i + aoff + 2], bgpattr_nlri_safi,
599 p[i + aoff + 2] >= 128 ? "Vendor specific" : "Unknown"),
601 ti = proto_tree_add_text(subtree2, p - pd + i + aoff + 3,
602 alen - 3, "Withdrawn Routes (%u bytes)", alen - 3);
607 subtree3 = proto_item_add_subtree(ti, ETT_BGP);
612 if (af == AFNUM_INET) {
613 advance = decode_prefix4(&p[i + aoff], buf,
615 } else if (af == AFNUM_INET6) {
616 advance = decode_prefix6(&p[i + aoff], buf,
624 proto_tree_add_text(subtree3, p - pd + i + aoff, advance,
625 "Withdrawn route: %s", buf);
633 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
634 "Unknown (%d bytes)", alen);
642 len = hlen - (p - &pd[offset]);
643 ti = proto_tree_add_text(tree, p - pd, len,
644 "Network layer reachability information (%d bytes)", len);
646 subtree = proto_item_add_subtree(ti, ETT_BGP);
651 * Dissect a BGP NOTIFICATION message.
654 dissect_bgp_notification(const u_char *pd, int offset, frame_data *fd,
657 struct bgp_notification bgpn;
662 memcpy(&bgpn, &pd[offset], sizeof(bgpn));
663 hlen = ntohs(bgpn.bgpn_len);
665 /* print error code */
666 proto_tree_add_text(tree,
667 offset + offsetof(struct bgp_notification, bgpn_major), 1,
668 "Error code: %s (%u)",
669 val_to_str(bgpn.bgpn_major, bgpnotify_major, "Unknown"),
672 /* print error subcode */
673 if (bgpn.bgpn_major < array_length(bgpnotify_minor)
674 && bgpnotify_minor[bgpn.bgpn_major] != NULL) {
675 p = val_to_str(bgpn.bgpn_minor, bgpnotify_minor[bgpn.bgpn_major],
677 } else if (bgpn.bgpn_minor == 0)
681 proto_tree_add_text(tree,
682 offset + offsetof(struct bgp_notification, bgpn_minor), 1,
683 "Error subcode: %s (%u)", p, bgpn.bgpn_minor);
685 /* only print if there is optional data */
686 if (hlen > BGP_MIN_NOTIFICATION_MSG_SIZE) {
687 proto_tree_add_text(tree, offset + BGP_MIN_NOTIFICATION_MSG_SIZE,
688 hlen - BGP_MIN_NOTIFICATION_MSG_SIZE, "Data");
693 * Dissect a BGP packet.
696 dissect_bgp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
699 proto_tree *bgp_tree;
700 proto_tree *bgp1_tree;
704 static u_char marker[] = {
705 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
706 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
712 if (check_col(fd, COL_PROTOCOL))
713 col_add_str(fd, COL_PROTOCOL, "BGP");
719 /* run through the TCP packet looking for BGP headers */
720 /* this is done twice, but this way each message type can be
721 printed in the COL_INFO field */
723 /* look for bgp header */
728 CHECK_SIZE(i, sizeof(marker), l);
729 if (memcmp(&p[i], marker, sizeof(marker)) != 0) {
734 memcpy(&bgp, &p[i], sizeof(bgp));
736 hlen = ntohs(bgp.bgp_len);
737 typ = val_to_str(bgp.bgp_type, bgptypevals, "Unknown Message");
739 if (check_col(fd, COL_INFO)) {
741 col_add_fstr(fd, COL_INFO, "%s", typ);
743 col_append_fstr(fd, COL_INFO, ", %s", typ);
750 ti = proto_tree_add_text(tree, offset, END_OF_FRAME,
751 "Border Gateway Protocol");
752 bgp_tree = proto_item_add_subtree(ti, ETT_BGP);
757 /* now, run through the TCP packet again, this time dissect */
758 /* each message that we find */
760 /* look for bgp header */
765 CHECK_SIZE(i, sizeof(marker), l);
766 if (memcmp(&p[i], marker, sizeof(marker)) != 0) {
771 memcpy(&bgp, &p[i], sizeof(bgp));
772 hlen = ntohs(bgp.bgp_len);
773 typ = val_to_str(bgp.bgp_type, bgptypevals, "Unknown Message");
774 if (END_OF_FRAME < hlen) {
775 ti = proto_tree_add_text(bgp_tree, offset + i, END_OF_FRAME,
776 "%s (truncated)", typ);
778 ti = proto_tree_add_text(bgp_tree, offset + i, hlen,
781 bgp1_tree = proto_item_add_subtree(ti, ETT_BGP);
783 proto_tree_add_text(bgp1_tree, offset + i, BGP_MARKER_SIZE,
786 if (hlen < BGP_HEADER_SIZE || hlen > BGP_MAX_PACKET_SIZE) {
787 proto_tree_add_text(bgp1_tree,
788 offset + i + offsetof(struct bgp, bgp_len), 2,
789 "Length (invalid): %u %s", hlen,
790 (hlen == 1) ? "byte" : "bytes");
792 proto_tree_add_text(bgp1_tree,
793 offset + i + offsetof(struct bgp, bgp_len), 2,
794 "Length: %u %s", hlen,
795 (hlen == 1) ? "byte" : "bytes");
798 proto_tree_add_text(bgp1_tree,
799 offset + i + offsetof(struct bgp, bgp_type), 1,
800 "Type: %s (%u)", typ, bgp.bgp_type);
802 CHECK_SIZE(i, hlen, l);
804 /* handle each message type */
805 switch (bgp.bgp_type) {
807 dissect_bgp_open(pd, offset + i, fd, bgp1_tree);
810 dissect_bgp_update(pd, offset + i, fd, bgp1_tree);
812 case BGP_NOTIFICATION:
813 dissect_bgp_notification(pd, offset + i, fd, bgp1_tree);
816 /* no data in KEEPALIVE messages */
828 * Register ourselves.
831 proto_register_bgp(void)
833 proto_bgp = proto_register_protocol("Border Gateway Protocol", "bgp");