]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
8d6bbe82dedb2718bc8ab86da5362d0f5fc6facc
[tcpdump] / print-bgp.c
1 /*
2 * Copyright (C) 1999 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #ifndef lint
35 static const char rcsid[] =
36 "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.16 2000-09-24 07:48:19 guy Exp $";
37 #endif
38
39 #include <sys/param.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
46
47 #include <errno.h>
48 #include <stdio.h>
49 #include <string.h>
50
51 #include "interface.h"
52 #include "addrtoname.h"
53
54 struct bgp {
55 u_int8_t bgp_marker[16];
56 u_int16_t bgp_len;
57 u_int8_t bgp_type;
58 };
59 #define BGP_SIZE 19 /* unaligned */
60
61 #define BGP_OPEN 1
62 #define BGP_UPDATE 2
63 #define BGP_NOTIFICATION 3
64 #define BGP_KEEPALIVE 4
65
66 struct bgp_open {
67 u_int8_t bgpo_marker[16];
68 u_int16_t bgpo_len;
69 u_int8_t bgpo_type;
70 u_int8_t bgpo_version;
71 u_int16_t bgpo_myas;
72 u_int16_t bgpo_holdtime;
73 u_int32_t bgpo_id;
74 u_int8_t bgpo_optlen;
75 /* options should follow */
76 };
77
78 struct bgp_opt {
79 u_int8_t bgpopt_type;
80 u_int8_t bgpopt_len;
81 /* variable length */
82 };
83
84 struct bgp_notification {
85 u_int8_t bgpn_marker[16];
86 u_int16_t bgpn_len;
87 u_int8_t bgpn_type;
88 u_int8_t bgpn_major;
89 u_int8_t bgpn_minor;
90 /* data should follow */
91 };
92
93 struct bgp_attr {
94 u_int8_t bgpa_flags;
95 u_int8_t bgpa_type;
96 union {
97 u_int8_t len;
98 u_int16_t elen;
99 } bgpa_len;
100 #define bgp_attr_len(p) \
101 (((p)->bgpa_flags & 0x10) ? \
102 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len)
103 #define bgp_attr_off(p) \
104 (((p)->bgpa_flags & 0x10) ? 4 : 3)
105 };
106
107 #define BGPTYPE_ORIGIN 1
108 #define BGPTYPE_AS_PATH 2
109 #define BGPTYPE_NEXT_HOP 3
110 #define BGPTYPE_MULTI_EXIT_DISC 4
111 #define BGPTYPE_LOCAL_PREF 5
112 #define BGPTYPE_ATOMIC_AGGREGATE 6
113 #define BGPTYPE_AGGREGATOR 7
114 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
115 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */
116 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */
117 #define BGPTYPE_DPA 11 /* work in progress */
118 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */
119 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */
120 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
121 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
122
123
124 static const char *bgptype[] = {
125 NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE",
126 };
127 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x))
128
129 static const char *bgpopt_type[] = {
130 NULL, "Authentication Information",
131 };
132 #define bgp_opttype(x) \
133 num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x))
134
135 static const char *bgpnotify_major[] = {
136 NULL, "Message Header Error",
137 "OPEN Message Error", "UPDATE Message Error",
138 "Hold Timer Expired", "Finite State Machine Error",
139 "Cease",
140 };
141 #define bgp_notify_major(x) \
142 num_or_str(bgpnotify_major, \
143 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x))
144
145 static const char *bgpnotify_minor_1[] = {
146 NULL, "Connection Not Synchronized",
147 "Bad Message Length", "Bad Message Type",
148 };
149
150 static const char *bgpnotify_minor_2[] = {
151 NULL, "Unsupported Version Number",
152 "Bad Peer AS", "Bad BGP Identifier",
153 "Unsupported Optional Parameter", "Authentication Failure",
154 "Unacceptable Hold Time",
155 };
156
157 static const char *bgpnotify_minor_3[] = {
158 NULL, "Malformed Attribute List",
159 "Unrecognized Well-known Attribute", "Missing Well-known Attribute",
160 "Attribute Flags Error", "Attribute Length Error",
161 "Invalid ORIGIN Attribute", "AS Routing Loop",
162 "Invalid NEXT_HOP Attribute", "Optional Attribute Error",
163 "Invalid Network Field", "Malformed AS_PATH",
164 };
165
166 static const char **bgpnotify_minor[] = {
167 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3,
168 };
169 static const int bgpnotify_minor_siz[] = {
170 0, sizeof(bgpnotify_minor_1)/sizeof(bgpnotify_minor_1[0]),
171 sizeof(bgpnotify_minor_2)/sizeof(bgpnotify_minor_2[0]),
172 sizeof(bgpnotify_minor_3)/sizeof(bgpnotify_minor_3[0]),
173 };
174
175 static const char *bgpattr_origin[] = {
176 "IGP", "EGP", "INCOMPLETE",
177 };
178 #define bgp_attr_origin(x) \
179 num_or_str(bgpattr_origin, \
180 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x))
181
182 static const char *bgpattr_type[] = {
183 NULL, "ORIGIN", "AS_PATH", "NEXT_HOP",
184 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR",
185 "COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA",
186 "ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI",
187 };
188 #define bgp_attr_type(x) \
189 num_or_str(bgpattr_type, \
190 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x))
191
192 /* Subsequent address family identifier, RFC2283 section 7 */
193 static const char *bgpattr_nlri_safi[] = {
194 "Reserved", "Unicast", "Multicast", "Unicast+Multicast",
195 };
196 #define bgp_attr_nlri_safi(x) \
197 num_or_str(bgpattr_nlri_safi, \
198 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x))
199
200 /* well-known community */
201 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01
202 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02
203 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
204
205 /* RFC1700 address family numbers */
206 #define AFNUM_INET 1
207 #define AFNUM_INET6 2
208 #define AFNUM_NSAP 3
209 #define AFNUM_HDLC 4
210 #define AFNUM_BBN1822 5
211 #define AFNUM_802 6
212 #define AFNUM_E163 7
213 #define AFNUM_E164 8
214 #define AFNUM_F69 9
215 #define AFNUM_X121 10
216 #define AFNUM_IPX 11
217 #define AFNUM_ATALK 12
218 #define AFNUM_DECNET 13
219 #define AFNUM_BANYAN 14
220 #define AFNUM_E164NSAP 15
221
222 static const char *afnumber[] = {
223 "Reserved", "IPv4", "IPv6", "NSAP", "HDLC",
224 "BBN 1822", "802", "E.163", "E.164", "F.69",
225 "X.121", "IPX", "Appletalk", "Decnet IV", "Banyan Vines",
226 "E.164 with NSAP subaddress",
227 };
228 #define af_name(x) \
229 (((x) == 65535) ? afnumber[0] : \
230 num_or_str(afnumber, \
231 sizeof(afnumber)/sizeof(afnumber[0]), (x)))
232
233
234 static const char *
235 num_or_str(const char **table, size_t siz, int value)
236 {
237 static char buf[20];
238 if (value < 0 || siz <= value || table[value] == NULL) {
239 snprintf(buf, sizeof(buf), "#%d", value);
240 return buf;
241 } else
242 return table[value];
243 }
244
245 static const char *
246 bgp_notify_minor(int major, int minor)
247 {
248 static const char **table;
249 int siz;
250 static char buf[20];
251 const char *p;
252
253 if (0 <= major
254 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0])
255 && bgpnotify_minor[major]) {
256 table = bgpnotify_minor[major];
257 siz = bgpnotify_minor_siz[major];
258 if (0 <= minor && minor < siz && table[minor])
259 p = table[minor];
260 else
261 p = NULL;
262 } else
263 p = NULL;
264 if (p == NULL) {
265 snprintf(buf, sizeof(buf), "#%d", minor);
266 return buf;
267 } else
268 return p;
269 }
270
271 static int
272 decode_prefix4(const u_char *pd, char *buf, int buflen)
273 {
274 struct in_addr addr;
275 int plen;
276
277 plen = pd[0];
278 if (plen < 0 || 32 < plen)
279 return -1;
280
281 memset(&addr, 0, sizeof(addr));
282 memcpy(&addr, &pd[1], (plen + 7) / 8);
283 if (plen % 8) {
284 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
285 ((0xff00 >> (plen % 8)) & 0xff);
286 }
287 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
288 return 1 + (plen + 7) / 8;
289 }
290
291 #ifdef INET6
292 static int
293 decode_prefix6(const u_char *pd, char *buf, int buflen)
294 {
295 struct in6_addr addr;
296 int plen;
297
298 plen = pd[0];
299 if (plen < 0 || 128 < plen)
300 return -1;
301
302 memset(&addr, 0, sizeof(addr));
303 memcpy(&addr, &pd[1], (plen + 7) / 8);
304 if (plen % 8) {
305 addr.s6_addr[(plen + 7) / 8 - 1] &=
306 ((0xff00 >> (plen % 8)) & 0xff);
307 }
308 snprintf(buf, buflen, "%s/%d", getname6((char *)&addr), plen);
309 return 1 + (plen + 7) / 8;
310 }
311 #endif
312
313 static void
314 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
315 {
316 int i;
317 u_int16_t af;
318 u_int8_t safi, snpa;
319 int advance;
320 int tlen;
321 const u_char *p;
322 char buf[256];
323
324 p = dat;
325
326 switch (attr->bgpa_type) {
327 case BGPTYPE_ORIGIN:
328 if (len != 1)
329 printf(" invalid len");
330 else
331 printf(" %s", bgp_attr_origin(p[0]));
332 break;
333 case BGPTYPE_AS_PATH:
334 if (len % 2) {
335 printf(" invalid len");
336 break;
337 }
338 while (p < dat + len) {
339 /*
340 * under RFC1965, p[0] means:
341 * 1: AS_SET 2: AS_SEQUENCE
342 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
343 */
344 printf(" ");
345 if (p[0] == 3 || p[0] == 4)
346 printf("confed");
347 printf("%s", (p[0] & 1) ? "{" : "");
348 for (i = 0; i < p[1]; i += 2) {
349 printf("%s%u", i == 0 ? "" : " ",
350 ntohs(*(u_int16_t *)&p[2 + i]));
351 }
352 printf("%s", (p[0] & 1) ? "}" : "");
353 p += 2 + p[1] * 2;
354 }
355 break;
356 case BGPTYPE_NEXT_HOP:
357 if (len != 4)
358 printf(" invalid len");
359 else
360 printf(" %s", getname(p));
361 break;
362 case BGPTYPE_MULTI_EXIT_DISC:
363 case BGPTYPE_LOCAL_PREF:
364 if (len != 4)
365 printf(" invalid len");
366 else
367 printf(" %u", (u_int32_t)ntohl(*(u_int32_t *)p));
368 break;
369 case BGPTYPE_ATOMIC_AGGREGATE:
370 if (len != 0)
371 printf(" invalid len");
372 break;
373 case BGPTYPE_AGGREGATOR:
374 if (len != 6) {
375 printf(" invalid len");
376 break;
377 }
378 printf(" AS #%u, origin %s", ntohs(*(u_int16_t *)p),
379 getname(p + 2));
380 break;
381 case BGPTYPE_COMMUNITIES:
382 if (len % 4) {
383 printf(" invalid len");
384 break;
385 }
386 for (i = 0; i < len; i += 4) {
387 u_int32_t comm;
388 comm = (u_int32_t)ntohl(*(u_int32_t *)&p[i]);
389 switch (comm) {
390 case BGP_COMMUNITY_NO_EXPORT:
391 printf(" NO_EXPORT");
392 break;
393 case BGP_COMMUNITY_NO_ADVERT:
394 printf(" NO_ADVERTISE");
395 break;
396 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
397 printf(" NO_EXPORT_SUBCONFED");
398 break;
399 default:
400 printf(" (AS #%d value 0x%04x)",
401 (comm >> 16) & 0xffff, comm & 0xffff);
402 break;
403 }
404 }
405 break;
406 case BGPTYPE_MP_REACH_NLRI:
407 af = ntohs(*(u_int16_t *)p);
408 safi = p[2];
409 if (safi >= 128)
410 printf(" %s vendor specific,", af_name(af));
411 else {
412 printf(" %s %s,", af_name(af),
413 bgp_attr_nlri_safi(safi));
414 }
415 p += 3;
416
417 if (af == AFNUM_INET)
418 ;
419 #ifdef INET6
420 else if (af == AFNUM_INET6)
421 ;
422 #endif
423 else
424 break;
425
426 tlen = p[0];
427 if (tlen) {
428 printf(" nexthop");
429 i = 0;
430 while (i < tlen) {
431 switch (af) {
432 case AFNUM_INET:
433 printf(" %s", getname(p + 1 + i));
434 i += sizeof(struct in_addr);
435 break;
436 #ifdef INET6
437 case AFNUM_INET6:
438 printf(" %s", getname6(p + 1 + i));
439 i += sizeof(struct in6_addr);
440 break;
441 #endif
442 default:
443 printf(" (unknown af)");
444 i = tlen; /*exit loop*/
445 break;
446 }
447 }
448 printf(",");
449 }
450 p += 1 + tlen;
451
452 snpa = p[0];
453 p++;
454 if (snpa) {
455 printf(" %u snpa", snpa);
456 for (/*nothing*/; snpa > 0; snpa--) {
457 printf("(%d bytes)", p[0]);
458 p += p[0] + 1;
459 }
460 printf(",");
461 }
462
463 printf(" NLRI");
464 while (len - (p - dat) > 0) {
465 switch (af) {
466 case AFNUM_INET:
467 advance = decode_prefix4(p, buf, sizeof(buf));
468 printf(" %s", buf);
469 break;
470 #ifdef INET6
471 case AFNUM_INET6:
472 advance = decode_prefix6(p, buf, sizeof(buf));
473 printf(" %s", buf);
474 break;
475 #endif
476 default:
477 printf(" (unknown af)");
478 advance = 0;
479 p = dat + len;
480 break;
481 }
482
483 p += advance;
484 }
485
486 break;
487
488 case BGPTYPE_MP_UNREACH_NLRI:
489 af = ntohs(*(u_int16_t *)p);
490 safi = p[2];
491 if (safi >= 128)
492 printf(" %s vendor specific,", af_name(af));
493 else {
494 printf(" %s %s,", af_name(af),
495 bgp_attr_nlri_safi(safi));
496 }
497 p += 3;
498
499 printf(" Withdraw");
500 while (len - (p - dat) > 0) {
501 switch (af) {
502 case AFNUM_INET:
503 advance = decode_prefix4(p, buf, sizeof(buf));
504 printf(" %s", buf);
505 break;
506 #ifdef INET6
507 case AFNUM_INET6:
508 advance = decode_prefix6(p, buf, sizeof(buf));
509 printf(" %s", buf);
510 break;
511 #endif
512 default:
513 printf(" (unknown af)");
514 advance = 0;
515 p = dat + len;
516 break;
517 }
518
519 p += advance;
520 }
521 break;
522 default:
523 break;
524 }
525 }
526
527 static void
528 bgp_open_print(const u_char *dat, int length)
529 {
530 struct bgp_open bgpo;
531 struct bgp_opt bgpopt;
532 int hlen;
533 const u_char *opt;
534 int i;
535
536 memcpy(&bgpo, dat, sizeof(bgpo));
537 hlen = ntohs(bgpo.bgpo_len);
538
539 printf(": Version %d,", bgpo.bgpo_version);
540 printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
541 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
542 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id));
543 printf(" Option length %u", bgpo.bgpo_optlen);
544
545 /* ugly! */
546 opt = &((struct bgp_open *)dat)->bgpo_optlen;
547 opt++;
548
549 for (i = 0; i < bgpo.bgpo_optlen; i++) {
550 memcpy(&bgpopt, &opt[i], sizeof(bgpopt));
551 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
552 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type);
553 break;
554 }
555
556 printf(" (option %s, len=%d)", bgp_opttype(bgpopt.bgpopt_type),
557 bgpopt.bgpopt_len);
558 i += sizeof(bgpopt) + bgpopt.bgpopt_len;
559 }
560 }
561
562 static void
563 bgp_update_print(const u_char *dat, int length)
564 {
565 struct bgp bgp;
566 struct bgp_attr bgpa;
567 int hlen;
568 const u_char *p;
569 int len;
570 int i;
571 int newline;
572
573 memcpy(&bgp, dat, sizeof(bgp));
574 hlen = ntohs(bgp.bgp_len);
575 p = dat + BGP_SIZE; /*XXX*/
576 printf(":");
577
578 /* Unfeasible routes */
579 len = ntohs(*(u_int16_t *)p);
580 if (len) {
581 printf(" (Withdrawn routes: %d bytes)", len);
582 }
583 p += 2 + len;
584
585 len = ntohs(*(u_int16_t *)p);
586 if (len) {
587 /* do something more useful!*/
588 i = 2;
589 printf(" (Path attributes:"); /* ) */
590 newline = 0;
591 while (i < 2 + len) {
592 int alen, aoff;
593
594 memcpy(&bgpa, &p[i], sizeof(bgpa));
595 alen = bgp_attr_len(&bgpa);
596 aoff = bgp_attr_off(&bgpa);
597
598 if (vflag && newline)
599 printf("\n\t\t");
600 else
601 printf(" ");
602 printf("("); /* ) */
603 printf("%s", bgp_attr_type(bgpa.bgpa_type));
604 if (bgpa.bgpa_flags) {
605 printf("[%s%s%s%s]",
606 bgpa.bgpa_flags & 0x80 ? "O" : "",
607 bgpa.bgpa_flags & 0x40 ? "T" : "",
608 bgpa.bgpa_flags & 0x20 ? "P" : "",
609 bgpa.bgpa_flags & 0x00 ? "E" : "");
610 }
611
612 bgp_attr_print(&bgpa, &p[i + aoff], alen);
613 newline = 1;
614
615 /* ( */
616 printf(")");
617
618 i += aoff + alen;
619 }
620
621 /* ( */
622 printf(")");
623 }
624 p += 2 + len;
625
626 if (len && dat + length > p)
627 printf("\n\t\t");
628 if (dat + length > p) {
629 printf("(NLRI:"); /* ) */
630 while (dat + length > p) {
631 char buf[256];
632 i = decode_prefix4(p, buf, sizeof(buf));
633 printf(" %s", buf);
634 if (i < 0)
635 break;
636 p += i;
637 }
638
639 /* ( */
640 printf(")");
641 }
642 }
643
644 static void
645 bgp_notification_print(const u_char *dat, int length)
646 {
647 struct bgp_notification bgpn;
648 int hlen;
649
650 memcpy(&bgpn, dat, sizeof(bgpn));
651 hlen = ntohs(bgpn.bgpn_len);
652
653 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major));
654 printf(" subcode %s",
655 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor));
656 }
657
658 static void
659 bgp_header_print(const u_char *dat, int length)
660 {
661 struct bgp bgp;
662
663 memcpy(&bgp, dat, sizeof(bgp));
664 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */
665
666 switch (bgp.bgp_type) {
667 case BGP_OPEN:
668 bgp_open_print(dat, length);
669 break;
670 case BGP_UPDATE:
671 bgp_update_print(dat, length);
672 break;
673 case BGP_NOTIFICATION:
674 bgp_notification_print(dat, length);
675 break;
676 }
677
678 /* ( */
679 printf(")");
680 }
681
682 void
683 bgp_print(const u_char *dat, int length)
684 {
685 const u_char *p;
686 const u_char *ep;
687 const u_char *start;
688 const u_char marker[] = {
689 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
690 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
691 };
692 struct bgp bgp;
693 u_int16_t hlen;
694 int newline;
695
696 ep = dat + length;
697 if (snapend < dat + length)
698 ep = snapend;
699
700 printf(": BGP");
701
702 p = dat;
703 newline = 0;
704 start = p;
705 while (p < snapend) {
706 if (!TTEST2(p[0], 1))
707 break;
708 if (p[0] != 0xff) {
709 p++;
710 continue;
711 }
712
713 if (!TTEST2(p[0], sizeof(marker)))
714 break;
715 if (memcmp(p, marker, sizeof(marker)) != 0) {
716 p++;
717 continue;
718 }
719
720 /* found BGP header */
721 TCHECK2(p[0], BGP_SIZE); /*XXX*/
722 memcpy(&bgp, p, sizeof(bgp));
723
724 if (start != p)
725 printf(" [|BGP]");
726
727 hlen = ntohs(bgp.bgp_len);
728 if (vflag && newline)
729 printf("\n\t");
730 else
731 printf(" ");
732 if (TTEST2(p[0], hlen)) {
733 bgp_header_print(p, hlen);
734 newline = 1;
735 p += hlen;
736 start = p;
737 } else {
738 printf("[|BGP %s]", bgp_type(bgp.bgp_type));
739 break;
740 }
741 }
742
743 return;
744
745 trunc:
746 printf(" [|BGP]");
747 }