]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
finally get rid of all the macros for codepoint to
[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.33 2002-07-04 09:24:43 hannes 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
46 #include <errno.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <netdb.h>
50
51 #include "interface.h"
52 #include "addrtoname.h"
53 #include "extract.h"
54
55 struct bgp {
56 u_int8_t bgp_marker[16];
57 u_int16_t bgp_len;
58 u_int8_t bgp_type;
59 };
60 #define BGP_SIZE 19 /* unaligned */
61
62 #define BGP_OPEN 1
63 #define BGP_UPDATE 2
64 #define BGP_NOTIFICATION 3
65 #define BGP_KEEPALIVE 4
66
67 static struct tok bgp_msg_values[] = {
68 { BGP_OPEN, "Open"},
69 { BGP_UPDATE, "Update"},
70 { BGP_NOTIFICATION, "Notification"},
71 { BGP_KEEPALIVE, "Keepalive"},
72 { 0, NULL}
73 };
74
75 struct bgp_open {
76 u_int8_t bgpo_marker[16];
77 u_int16_t bgpo_len;
78 u_int8_t bgpo_type;
79 u_int8_t bgpo_version;
80 u_int16_t bgpo_myas;
81 u_int16_t bgpo_holdtime;
82 u_int32_t bgpo_id;
83 u_int8_t bgpo_optlen;
84 /* options should follow */
85 };
86 #define BGP_OPEN_SIZE 29 /* unaligned */
87
88 struct bgp_opt {
89 u_int8_t bgpopt_type;
90 u_int8_t bgpopt_len;
91 /* variable length */
92 };
93 #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */
94
95 struct bgp_notification {
96 u_int8_t bgpn_marker[16];
97 u_int16_t bgpn_len;
98 u_int8_t bgpn_type;
99 u_int8_t bgpn_major;
100 u_int8_t bgpn_minor;
101 /* data should follow */
102 };
103 #define BGP_NOTIFICATION_SIZE 21 /* unaligned */
104
105 struct bgp_attr {
106 u_int8_t bgpa_flags;
107 u_int8_t bgpa_type;
108 union {
109 u_int8_t len;
110 u_int16_t elen;
111 } bgpa_len;
112 #define bgp_attr_len(p) \
113 (((p)->bgpa_flags & 0x10) ? \
114 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len)
115 #define bgp_attr_off(p) \
116 (((p)->bgpa_flags & 0x10) ? 4 : 3)
117 };
118
119 #define BGPTYPE_ORIGIN 1
120 #define BGPTYPE_AS_PATH 2
121 #define BGPTYPE_NEXT_HOP 3
122 #define BGPTYPE_MULTI_EXIT_DISC 4
123 #define BGPTYPE_LOCAL_PREF 5
124 #define BGPTYPE_ATOMIC_AGGREGATE 6
125 #define BGPTYPE_AGGREGATOR 7
126 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
127 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */
128 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */
129 #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */
130 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */
131 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */
132 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
133 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
134 #define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */
135
136 static struct tok bgp_attr_values[] = {
137 { BGPTYPE_ORIGIN, "Origin"},
138 { BGPTYPE_AS_PATH, "AS Path"},
139 { BGPTYPE_NEXT_HOP, "Next Hop"},
140 { BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"},
141 { BGPTYPE_LOCAL_PREF, "Local Preference"},
142 { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
143 { BGPTYPE_AGGREGATOR, "Aggregator"},
144 { BGPTYPE_COMMUNITIES, "Community"},
145 { BGPTYPE_ORIGINATOR_ID, "Originator ID"},
146 { BGPTYPE_CLUSTER_LIST, "Cluster List"},
147 { BGPTYPE_DPA, "DPA"},
148 { BGPTYPE_ADVERTISERS, "Advertisers"},
149 { BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"},
150 { BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"},
151 { BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"},
152 { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
153 { 255, "Reserved for development"},
154 { 0, NULL}
155 };
156
157 static struct tok bgp_opt_values[] = {
158 { 1, "Authentication Information"},
159 { 2, "Capabilities Advertisement"},
160 { 0, NULL}
161 };
162
163 #define BGP_NOTIFY_MAJOR_MSG 1
164 #define BGP_NOTIFY_MAJOR_OPEN 2
165 #define BGP_NOTIFY_MAJOR_UPDATE 3
166 #define BGP_NOTIFY_MAJOR_HOLDTIME 4
167 #define BGP_NOTIFY_MAJOR_FSM 5
168 #define BGP_NOTIFY_MAJOR_CEASE 6
169
170 static struct tok bgp_notify_major_values[] = {
171 { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"},
172 { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"},
173 { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"},
174 { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
175 { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"},
176 { BGP_NOTIFY_MAJOR_CEASE, "Cease"},
177 { 0, NULL}
178 };
179
180 static struct tok bgp_notify_minor_msg_values[] = {
181 { 1, "Connection Not Synchronized"},
182 { 2, "Bad Message Length"},
183 { 3, "Bad Message Type"},
184 { 0, NULL}
185 };
186
187 static struct tok bgp_notify_minor_open_values[] = {
188 { 1, "Unsupported Version Number"},
189 { 2, "Bad Peer AS"},
190 { 3, "Bad BGP Identifier"},
191 { 4, "Unsupported Optional Parameter"},
192 { 5, "Authentication Failure"},
193 { 6, "Unacceptable Hold Time"},
194 { 0, NULL}
195 };
196
197 static struct tok bgp_notify_minor_update_values[] = {
198 { 1, "Malformed Attribute List"},
199 { 2, "Unrecognized Well-known Attribute"},
200 { 3, "Missing Well-known Attribute"},
201 { 4, "Attribute Flags Error"},
202 { 5, "Attribute Length Error"},
203 { 6, "Invalid ORIGIN Attribute"},
204 { 7, "AS Routing Loop"},
205 { 8, "Invalid NEXT_HOP Attribute"},
206 { 9, "Optional Attribute Error"},
207 { 10, "Invalid Network Field"},
208 { 11, "Malformed AS_PATH"},
209 { 0, NULL}
210 };
211
212 static struct tok bgp_origin_values[] = {
213 { 1, "IGP"},
214 { 2, "EGP"},
215 { 3, "Incomplete"},
216 { 0, NULL}
217 };
218
219 /* Subsequent address family identifier, RFC2283 section 7 */
220 #define SAFNUM_RES 0
221 #define SAFNUM_UNICAST 1
222 #define SAFNUM_MULTICAST 2
223 #define SAFNUM_UNIMULTICAST 3
224 /* labeled BGP RFC3107 */
225 #define SAFNUM_LABUNICAST 4
226 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */
227 #define SAFNUM_VPNUNICAST 128
228 #define SAFNUM_VPNMULTICAST 129
229 #define SAFNUM_VPNUNIMULTICAST 130
230
231 static struct tok bgp_safi_values[] = {
232 { SAFNUM_RES, "Reserved"},
233 { SAFNUM_UNICAST, "Unicast"},
234 { SAFNUM_MULTICAST, "Multicast"},
235 { SAFNUM_UNIMULTICAST, "Unicast+Multicast"},
236 { SAFNUM_LABUNICAST, "labeled Unicast"},
237 { SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
238 { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
239 { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
240 { 0, NULL }
241 };
242
243 /* well-known community */
244 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01
245 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02
246 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
247
248 /* RFC1700 address family numbers */
249 #define AFNUM_INET 1
250 #define AFNUM_INET6 2
251 #define AFNUM_NSAP 3
252 #define AFNUM_HDLC 4
253 #define AFNUM_BBN1822 5
254 #define AFNUM_802 6
255 #define AFNUM_E163 7
256 #define AFNUM_E164 8
257 #define AFNUM_F69 9
258 #define AFNUM_X121 10
259 #define AFNUM_IPX 11
260 #define AFNUM_ATALK 12
261 #define AFNUM_DECNET 13
262 #define AFNUM_BANYAN 14
263 #define AFNUM_E164NSAP 15
264 /* draft-kompella-ppvpn-l2vpn */
265 #define AFNUM_L2VPN 196 /* still to be approved by IANA */
266
267 static struct tok bgp_afi_values[] = {
268 { 0, "Reserved"},
269 { AFNUM_INET, "IPv4"},
270 { AFNUM_INET6, "IPv6"},
271 { AFNUM_NSAP, "NSAP"},
272 { AFNUM_HDLC, "HDLC"},
273 { AFNUM_BBN1822, "BBN 1822"},
274 { AFNUM_802, "802"},
275 { AFNUM_E163, "E.163"},
276 { AFNUM_E164, "E.164"},
277 { AFNUM_F69, "F.69"},
278 { AFNUM_X121, "X.121"},
279 { AFNUM_IPX, "Novell IPX"},
280 { AFNUM_ATALK, "Appletalk"},
281 { AFNUM_DECNET, "Decnet IV"},
282 { AFNUM_BANYAN, "Banyan Vines"},
283 { AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
284 { AFNUM_L2VPN, "Layer-2 VPN"},
285 { 0, NULL},
286 };
287
288 static const char *
289 num_or_str(const char **table, size_t siz, int value)
290 {
291 static char buf[20];
292 if (value < 0 || siz <= value || table[value] == NULL) {
293 snprintf(buf, sizeof(buf), "#%d", value);
294 return buf;
295 } else
296 return table[value];
297 }
298
299 static int
300 decode_prefix4(const u_char *pd, char *buf, u_int buflen)
301 {
302 struct in_addr addr;
303 u_int plen;
304
305 plen = pd[0];
306 if (plen < 0 || 32 < plen)
307 return -1;
308
309 memset(&addr, 0, sizeof(addr));
310 memcpy(&addr, &pd[1], (plen + 7) / 8);
311 if (plen % 8) {
312 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
313 ((0xff00 >> (plen % 8)) & 0xff);
314 }
315 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
316 return 1 + (plen + 7) / 8;
317 }
318
319 static int
320 decode_labeled_prefix4(const u_char *pd, char *buf, u_int buflen)
321 {
322 struct in_addr addr;
323 u_int plen;
324
325 plen = pd[0]; /* get prefix length */
326
327 /* this is one of the weirdnesses of rfc3107
328 the label length (actually the label + COS bits)
329 is added of the prefix length;
330 we also do only read out just one label -
331 there is no real application for advertisment of
332 stacked labels in a a single BGP message
333 */
334
335 plen-=24; /* adjust prefixlen - labellength */
336
337 if (plen < 0 || 32 < plen)
338 return -1;
339
340 memset(&addr, 0, sizeof(addr));
341 memcpy(&addr, &pd[4], (plen + 7) / 8);
342 if (plen % 8) {
343 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
344 ((0xff00 >> (plen % 8)) & 0xff);
345 }
346 /* the label may get offsetted by 4 bits so lets shift it right */
347 snprintf(buf, buflen, "%s/%d label:%u %s",
348 getname((u_char *)&addr),
349 plen,
350 EXTRACT_24BITS(pd+1)>>4,
351 ((pd[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
352
353 return 4 + (plen + 7) / 8;
354 }
355
356 #ifdef INET6
357 static int
358 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
359 {
360 struct in6_addr addr;
361 u_int plen;
362
363 plen = pd[0];
364 if (plen < 0 || 128 < plen)
365 return -1;
366
367 memset(&addr, 0, sizeof(addr));
368 memcpy(&addr, &pd[1], (plen + 7) / 8);
369 if (plen % 8) {
370 addr.s6_addr[(plen + 7) / 8 - 1] &=
371 ((0xff00 >> (plen % 8)) & 0xff);
372 }
373 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
374 return 1 + (plen + 7) / 8;
375 }
376 #endif
377
378 static void
379 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
380 {
381 int i;
382 u_int16_t af;
383 u_int8_t safi, snpa;
384 int advance;
385 int tlen;
386 const u_char *p;
387 char buf[MAXHOSTNAMELEN + 100];
388
389 p = dat;
390
391 switch (attr->bgpa_type) {
392 case BGPTYPE_ORIGIN:
393 if (len != 1)
394 printf(" invalid len");
395 else
396 printf(" %s", tok2str(bgp_origin_values, "Unknown Origin Typecode", p[0]));
397 break;
398 case BGPTYPE_AS_PATH:
399 if (len % 2) {
400 printf(" invalid len");
401 break;
402 }
403 while (p < dat + len) {
404 /*
405 * under RFC1965, p[0] means:
406 * 1: AS_SET 2: AS_SEQUENCE
407 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
408 */
409 printf(" ");
410 if (p[0] == 3 || p[0] == 4)
411 printf("confed");
412 printf("%s", (p[0] & 1) ? "{" : "");
413 for (i = 0; i < p[1] * 2; i += 2) {
414 printf("%s%u", i == 0 ? "" : " ",
415 EXTRACT_16BITS(&p[2 + i]));
416 }
417 printf("%s", (p[0] & 1) ? "}" : "");
418 p += 2 + p[1] * 2;
419 }
420 break;
421 case BGPTYPE_NEXT_HOP:
422 if (len != 4)
423 printf(" invalid len");
424 else
425 printf(" %s", getname(p));
426 break;
427 case BGPTYPE_MULTI_EXIT_DISC:
428 case BGPTYPE_LOCAL_PREF:
429 if (len != 4)
430 printf(" invalid len");
431 else
432 printf(" %u", EXTRACT_32BITS(p));
433 break;
434 case BGPTYPE_ATOMIC_AGGREGATE:
435 if (len != 0)
436 printf(" invalid len");
437 break;
438 case BGPTYPE_AGGREGATOR:
439 if (len != 6) {
440 printf(" invalid len");
441 break;
442 }
443 printf(" AS #%u, origin %s", EXTRACT_16BITS(p),
444 getname(p + 2));
445 break;
446 case BGPTYPE_COMMUNITIES:
447 if (len % 4) {
448 printf(" invalid len");
449 break;
450 }
451 for (i = 0; i < len; i += 4) {
452 u_int32_t comm;
453 comm = EXTRACT_32BITS(&p[i]);
454 switch (comm) {
455 case BGP_COMMUNITY_NO_EXPORT:
456 printf(" NO_EXPORT");
457 break;
458 case BGP_COMMUNITY_NO_ADVERT:
459 printf(" NO_ADVERTISE");
460 break;
461 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
462 printf(" NO_EXPORT_SUBCONFED");
463 break;
464 default:
465 printf(" (AS #%d value 0x%04x)",
466 (comm >> 16) & 0xffff, comm & 0xffff);
467 break;
468 }
469 }
470 break;
471 case BGPTYPE_MP_REACH_NLRI:
472 af = EXTRACT_16BITS(p);
473 safi = p[2];
474 if (safi >= 128)
475 printf(" %s vendor specific,",
476 tok2str(bgp_afi_values, "Unknown AFI", af));
477 else {
478 printf(" AFI %s SAFI %s,",
479 tok2str(bgp_afi_values, "Unknown AFI", af),
480 tok2str(bgp_safi_values, "Unknown SAFI", safi));
481 }
482 p += 3;
483
484 if (af == AFNUM_INET)
485 ;
486 #ifdef INET6
487 else if (af == AFNUM_INET6)
488 ;
489 #endif
490 else
491 break;
492
493 tlen = p[0];
494 if (tlen) {
495 printf(" nexthop");
496 i = 0;
497 while (i < tlen) {
498 switch (af) {
499 case AFNUM_INET:
500 printf(" %s", getname(p + 1 + i));
501 i += sizeof(struct in_addr);
502 break;
503 #ifdef INET6
504 case AFNUM_INET6:
505 printf(" %s", getname6(p + 1 + i));
506 i += sizeof(struct in6_addr);
507 break;
508 #endif
509 default:
510 printf(" (unknown af)");
511 i = tlen; /*exit loop*/
512 break;
513 }
514 }
515 printf(",");
516 }
517 p += 1 + tlen;
518
519 snpa = p[0];
520 p++;
521 if (snpa) {
522 printf(" %u snpa", snpa);
523 for (/*nothing*/; snpa > 0; snpa--) {
524 printf("(%d bytes)", p[0]);
525 p += p[0] + 1;
526 }
527 printf(",");
528 } else {
529 printf(" no spna,");
530 }
531
532 printf(" NLRI");
533 while (len - (p - dat) > 0) {
534 switch (af) {
535 case AFNUM_INET:
536 if(safi==SAFNUM_LABUNICAST) {
537 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
538 } else {
539 advance = decode_prefix4(p, buf, sizeof(buf));
540 }
541 if (advance<0)
542 break;
543 printf(" %s", buf);
544 break;
545 #ifdef INET6
546 case AFNUM_INET6:
547 advance = decode_prefix6(p, buf, sizeof(buf));
548 printf(" %s", buf);
549 break;
550 #endif
551 default:
552 printf(" (unknown af)");
553 advance = 0;
554 p = dat + len;
555 break;
556 }
557
558 p += advance;
559 }
560
561 break;
562
563 case BGPTYPE_MP_UNREACH_NLRI:
564 af = EXTRACT_16BITS(p);
565 safi = p[2];
566 if (safi >= 128)
567 printf(" %s vendor specific,",
568 tok2str(bgp_afi_values, "Unknown AFI", af));
569 else {
570 printf(" AFI %s SAFI %s,",
571 tok2str(bgp_afi_values, "Unknown AFI", af),
572 tok2str(bgp_safi_values, "Unknown SAFI", safi));
573 }
574 p += 3;
575
576 printf(" Withdraw");
577 while (len - (p - dat) > 0) {
578 switch (af) {
579 case AFNUM_INET:
580 if(safi==SAFNUM_LABUNICAST) {
581 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
582 } else {
583 advance = decode_prefix4(p, buf, sizeof(buf));
584 }
585 if (advance<0)
586 break;
587 printf(" %s", buf);
588 break;
589 #ifdef INET6
590 case AFNUM_INET6:
591 advance = decode_prefix6(p, buf, sizeof(buf));
592 printf(" %s", buf);
593 break;
594 #endif
595 default:
596 printf(" (unknown af)");
597 advance = 0;
598 p = dat + len;
599 break;
600 }
601
602 p += advance;
603 }
604 break;
605 default:
606 break;
607 }
608 }
609
610 static void
611 bgp_open_print(const u_char *dat, int length)
612 {
613 struct bgp_open bgpo;
614 struct bgp_opt bgpopt;
615 int hlen;
616 const u_char *opt;
617 int i;
618
619 TCHECK2(dat[0], BGP_OPEN_SIZE);
620 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
621 hlen = ntohs(bgpo.bgpo_len);
622
623 printf(": Version %d,", bgpo.bgpo_version);
624 printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
625 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
626 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id));
627 printf(" Option length %u", bgpo.bgpo_optlen);
628
629 /* ugly! */
630 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
631 opt++;
632
633 i = 0;
634 while (i < bgpo.bgpo_optlen) {
635 TCHECK2(opt[i], BGP_OPT_SIZE);
636 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
637 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
638 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type);
639 break;
640 }
641
642 printf(" (option %s, len=%d)",
643 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
644 bgpopt.bgpopt_len);
645 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
646 }
647 return;
648 trunc:
649 printf("[|BGP]");
650 }
651
652 static void
653 bgp_update_print(const u_char *dat, int length)
654 {
655 struct bgp bgp;
656 struct bgp_attr bgpa;
657 int hlen;
658 const u_char *p;
659 int len;
660 int i;
661 int newline;
662
663 TCHECK2(dat[0], BGP_SIZE);
664 memcpy(&bgp, dat, BGP_SIZE);
665 hlen = ntohs(bgp.bgp_len);
666 p = dat + BGP_SIZE; /*XXX*/
667 printf(":");
668
669 /* Unfeasible routes */
670 len = EXTRACT_16BITS(p);
671 if (len) {
672 /*
673 * Without keeping state from the original NLRI message,
674 * it's not possible to tell if this a v4 or v6 route,
675 * so only try to decode it if we're not v6 enabled.
676 */
677 #ifdef INET6
678 printf(" (Withdrawn routes: %d bytes)", len);
679 #else
680 char buf[MAXHOSTNAMELEN + 100];
681
682 TCHECK2(p[2], len);
683 i = 2;
684
685 printf(" (Withdrawn routes:");
686
687 while(i < 2 + len) {
688 i += decode_prefix4(&p[i], buf, sizeof(buf));
689 printf(" %s", buf);
690 }
691 printf(")\n");
692 #endif
693 }
694 p += 2 + len;
695
696 TCHECK2(p[0], 2);
697 len = EXTRACT_16BITS(p);
698 if (len) {
699 /* do something more useful!*/
700 i = 2;
701 printf(" (Path attributes:"); /* ) */
702 newline = 0;
703 while (i < 2 + len) {
704 int alen, aoff;
705
706 TCHECK2(p[i], sizeof(bgpa));
707 memcpy(&bgpa, &p[i], sizeof(bgpa));
708 alen = bgp_attr_len(&bgpa);
709 aoff = bgp_attr_off(&bgpa);
710
711 if (vflag && newline)
712 printf("\n\t\t");
713 else
714 printf(" ");
715
716 printf("(%s", tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type));
717 if (bgpa.bgpa_flags) {
718 printf("[%s%s%s%s",
719 bgpa.bgpa_flags & 0x80 ? "O" : "",
720 bgpa.bgpa_flags & 0x40 ? "T" : "",
721 bgpa.bgpa_flags & 0x20 ? "P" : "",
722 bgpa.bgpa_flags & 0x10 ? "E" : "");
723 if (bgpa.bgpa_flags & 0xf)
724 printf("+%x", bgpa.bgpa_flags & 0xf);
725 printf("]");
726 }
727
728 bgp_attr_print(&bgpa, &p[i + aoff], alen);
729 newline = 1;
730
731 /* ( */
732 printf(")");
733
734 i += aoff + alen;
735 }
736
737 /* ( */
738 printf(")");
739 }
740 p += 2 + len;
741
742 if (len && dat + length > p)
743 printf("\n\t\t");
744 if (dat + length > p) {
745 printf("(NLRI:"); /* ) */
746 while (dat + length > p) {
747 char buf[MAXHOSTNAMELEN + 100];
748 i = decode_prefix4(p, buf, sizeof(buf));
749 printf(" %s", buf);
750 if (i < 0)
751 break;
752 p += i;
753 }
754
755 /* ( */
756 printf(")");
757 }
758 return;
759 trunc:
760 printf("[|BGP]");
761 }
762
763 static void
764 bgp_notification_print(const u_char *dat, int length)
765 {
766 struct bgp_notification bgpn;
767 int hlen;
768
769 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
770 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
771 hlen = ntohs(bgpn.bgpn_len);
772
773 printf(": error %s,", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
774
775 switch (bgpn.bgpn_major) {
776
777 case BGP_NOTIFY_MAJOR_MSG:
778 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
779 break;
780 case BGP_NOTIFY_MAJOR_OPEN:
781 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
782 break;
783 case BGP_NOTIFY_MAJOR_UPDATE:
784 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
785 break;
786 default:
787 break;
788 }
789
790 return;
791 trunc:
792 printf("[|BGP]");
793 }
794
795 static void
796 bgp_header_print(const u_char *dat, int length)
797 {
798 struct bgp bgp;
799
800 TCHECK2(dat[0], BGP_SIZE);
801 memcpy(&bgp, dat, BGP_SIZE);
802 printf("(%s", tok2str(bgp_msg_values, "Unknown Message Type", bgp.bgp_type));
803
804 switch (bgp.bgp_type) {
805 case BGP_OPEN:
806 bgp_open_print(dat, length);
807 break;
808 case BGP_UPDATE:
809 bgp_update_print(dat, length);
810 break;
811 case BGP_NOTIFICATION:
812 bgp_notification_print(dat, length);
813 break;
814 }
815
816 /* ( */
817 printf(")");
818 return;
819 trunc:
820 printf("[|BGP]");
821 }
822
823 void
824 bgp_print(const u_char *dat, int length)
825 {
826 const u_char *p;
827 const u_char *ep;
828 const u_char *start;
829 const u_char marker[] = {
830 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
831 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
832 };
833 struct bgp bgp;
834 u_int16_t hlen;
835 int newline;
836
837 ep = dat + length;
838 if (snapend < dat + length)
839 ep = snapend;
840
841 printf(": BGP");
842
843 p = dat;
844 newline = 0;
845 start = p;
846 while (p < snapend) {
847 if (!TTEST2(p[0], 1))
848 break;
849 if (p[0] != 0xff) {
850 p++;
851 continue;
852 }
853
854 if (!TTEST2(p[0], sizeof(marker)))
855 break;
856 if (memcmp(p, marker, sizeof(marker)) != 0) {
857 p++;
858 continue;
859 }
860
861 /* found BGP header */
862 TCHECK2(p[0], BGP_SIZE); /*XXX*/
863 memcpy(&bgp, p, BGP_SIZE);
864
865 if (start != p)
866 printf(" [|BGP]");
867
868 hlen = ntohs(bgp.bgp_len);
869 if (vflag && newline)
870 printf("\n\t");
871 else
872 printf(" ");
873 if (TTEST2(p[0], hlen)) {
874 bgp_header_print(p, hlen);
875 newline = 1;
876 p += hlen;
877 start = p;
878 } else {
879 printf("[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
880 break;
881 }
882 }
883
884 return;
885
886 trunc:
887 printf(" [|BGP]");
888 }
889
890
891
892
893
894