]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
Get rid of no-longer-used "num_or_str()" function.
[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.34 2002-07-07 20:55:16 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
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 int
289 decode_prefix4(const u_char *pd, char *buf, u_int buflen)
290 {
291 struct in_addr addr;
292 u_int plen;
293
294 plen = pd[0];
295 if (plen < 0 || 32 < plen)
296 return -1;
297
298 memset(&addr, 0, sizeof(addr));
299 memcpy(&addr, &pd[1], (plen + 7) / 8);
300 if (plen % 8) {
301 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
302 ((0xff00 >> (plen % 8)) & 0xff);
303 }
304 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
305 return 1 + (plen + 7) / 8;
306 }
307
308 static int
309 decode_labeled_prefix4(const u_char *pd, char *buf, u_int buflen)
310 {
311 struct in_addr addr;
312 u_int plen;
313
314 plen = pd[0]; /* get prefix length */
315
316 /* this is one of the weirdnesses of rfc3107
317 the label length (actually the label + COS bits)
318 is added of the prefix length;
319 we also do only read out just one label -
320 there is no real application for advertisment of
321 stacked labels in a a single BGP message
322 */
323
324 plen-=24; /* adjust prefixlen - labellength */
325
326 if (plen < 0 || 32 < plen)
327 return -1;
328
329 memset(&addr, 0, sizeof(addr));
330 memcpy(&addr, &pd[4], (plen + 7) / 8);
331 if (plen % 8) {
332 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
333 ((0xff00 >> (plen % 8)) & 0xff);
334 }
335 /* the label may get offsetted by 4 bits so lets shift it right */
336 snprintf(buf, buflen, "%s/%d label:%u %s",
337 getname((u_char *)&addr),
338 plen,
339 EXTRACT_24BITS(pd+1)>>4,
340 ((pd[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
341
342 return 4 + (plen + 7) / 8;
343 }
344
345 #ifdef INET6
346 static int
347 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
348 {
349 struct in6_addr addr;
350 u_int plen;
351
352 plen = pd[0];
353 if (plen < 0 || 128 < plen)
354 return -1;
355
356 memset(&addr, 0, sizeof(addr));
357 memcpy(&addr, &pd[1], (plen + 7) / 8);
358 if (plen % 8) {
359 addr.s6_addr[(plen + 7) / 8 - 1] &=
360 ((0xff00 >> (plen % 8)) & 0xff);
361 }
362 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
363 return 1 + (plen + 7) / 8;
364 }
365 #endif
366
367 static void
368 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
369 {
370 int i;
371 u_int16_t af;
372 u_int8_t safi, snpa;
373 int advance;
374 int tlen;
375 const u_char *p;
376 char buf[MAXHOSTNAMELEN + 100];
377
378 p = dat;
379
380 switch (attr->bgpa_type) {
381 case BGPTYPE_ORIGIN:
382 if (len != 1)
383 printf(" invalid len");
384 else
385 printf(" %s", tok2str(bgp_origin_values, "Unknown Origin Typecode", p[0]));
386 break;
387 case BGPTYPE_AS_PATH:
388 if (len % 2) {
389 printf(" invalid len");
390 break;
391 }
392 while (p < dat + len) {
393 /*
394 * under RFC1965, p[0] means:
395 * 1: AS_SET 2: AS_SEQUENCE
396 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
397 */
398 printf(" ");
399 if (p[0] == 3 || p[0] == 4)
400 printf("confed");
401 printf("%s", (p[0] & 1) ? "{" : "");
402 for (i = 0; i < p[1] * 2; i += 2) {
403 printf("%s%u", i == 0 ? "" : " ",
404 EXTRACT_16BITS(&p[2 + i]));
405 }
406 printf("%s", (p[0] & 1) ? "}" : "");
407 p += 2 + p[1] * 2;
408 }
409 break;
410 case BGPTYPE_NEXT_HOP:
411 if (len != 4)
412 printf(" invalid len");
413 else
414 printf(" %s", getname(p));
415 break;
416 case BGPTYPE_MULTI_EXIT_DISC:
417 case BGPTYPE_LOCAL_PREF:
418 if (len != 4)
419 printf(" invalid len");
420 else
421 printf(" %u", EXTRACT_32BITS(p));
422 break;
423 case BGPTYPE_ATOMIC_AGGREGATE:
424 if (len != 0)
425 printf(" invalid len");
426 break;
427 case BGPTYPE_AGGREGATOR:
428 if (len != 6) {
429 printf(" invalid len");
430 break;
431 }
432 printf(" AS #%u, origin %s", EXTRACT_16BITS(p),
433 getname(p + 2));
434 break;
435 case BGPTYPE_COMMUNITIES:
436 if (len % 4) {
437 printf(" invalid len");
438 break;
439 }
440 for (i = 0; i < len; i += 4) {
441 u_int32_t comm;
442 comm = EXTRACT_32BITS(&p[i]);
443 switch (comm) {
444 case BGP_COMMUNITY_NO_EXPORT:
445 printf(" NO_EXPORT");
446 break;
447 case BGP_COMMUNITY_NO_ADVERT:
448 printf(" NO_ADVERTISE");
449 break;
450 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
451 printf(" NO_EXPORT_SUBCONFED");
452 break;
453 default:
454 printf(" (AS #%d value 0x%04x)",
455 (comm >> 16) & 0xffff, comm & 0xffff);
456 break;
457 }
458 }
459 break;
460 case BGPTYPE_MP_REACH_NLRI:
461 af = EXTRACT_16BITS(p);
462 safi = p[2];
463 if (safi >= 128)
464 printf(" %s vendor specific,",
465 tok2str(bgp_afi_values, "Unknown AFI", af));
466 else {
467 printf(" AFI %s SAFI %s,",
468 tok2str(bgp_afi_values, "Unknown AFI", af),
469 tok2str(bgp_safi_values, "Unknown SAFI", safi));
470 }
471 p += 3;
472
473 if (af == AFNUM_INET)
474 ;
475 #ifdef INET6
476 else if (af == AFNUM_INET6)
477 ;
478 #endif
479 else
480 break;
481
482 tlen = p[0];
483 if (tlen) {
484 printf(" nexthop");
485 i = 0;
486 while (i < tlen) {
487 switch (af) {
488 case AFNUM_INET:
489 printf(" %s", getname(p + 1 + i));
490 i += sizeof(struct in_addr);
491 break;
492 #ifdef INET6
493 case AFNUM_INET6:
494 printf(" %s", getname6(p + 1 + i));
495 i += sizeof(struct in6_addr);
496 break;
497 #endif
498 default:
499 printf(" (unknown af)");
500 i = tlen; /*exit loop*/
501 break;
502 }
503 }
504 printf(",");
505 }
506 p += 1 + tlen;
507
508 snpa = p[0];
509 p++;
510 if (snpa) {
511 printf(" %u snpa", snpa);
512 for (/*nothing*/; snpa > 0; snpa--) {
513 printf("(%d bytes)", p[0]);
514 p += p[0] + 1;
515 }
516 printf(",");
517 } else {
518 printf(" no spna,");
519 }
520
521 printf(" NLRI");
522 while (len - (p - dat) > 0) {
523 switch (af) {
524 case AFNUM_INET:
525 if(safi==SAFNUM_LABUNICAST) {
526 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
527 } else {
528 advance = decode_prefix4(p, buf, sizeof(buf));
529 }
530 if (advance<0)
531 break;
532 printf(" %s", buf);
533 break;
534 #ifdef INET6
535 case AFNUM_INET6:
536 advance = decode_prefix6(p, buf, sizeof(buf));
537 printf(" %s", buf);
538 break;
539 #endif
540 default:
541 printf(" (unknown af)");
542 advance = 0;
543 p = dat + len;
544 break;
545 }
546
547 p += advance;
548 }
549
550 break;
551
552 case BGPTYPE_MP_UNREACH_NLRI:
553 af = EXTRACT_16BITS(p);
554 safi = p[2];
555 if (safi >= 128)
556 printf(" %s vendor specific,",
557 tok2str(bgp_afi_values, "Unknown AFI", af));
558 else {
559 printf(" AFI %s SAFI %s,",
560 tok2str(bgp_afi_values, "Unknown AFI", af),
561 tok2str(bgp_safi_values, "Unknown SAFI", safi));
562 }
563 p += 3;
564
565 printf(" Withdraw");
566 while (len - (p - dat) > 0) {
567 switch (af) {
568 case AFNUM_INET:
569 if(safi==SAFNUM_LABUNICAST) {
570 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
571 } else {
572 advance = decode_prefix4(p, buf, sizeof(buf));
573 }
574 if (advance<0)
575 break;
576 printf(" %s", buf);
577 break;
578 #ifdef INET6
579 case AFNUM_INET6:
580 advance = decode_prefix6(p, buf, sizeof(buf));
581 printf(" %s", buf);
582 break;
583 #endif
584 default:
585 printf(" (unknown af)");
586 advance = 0;
587 p = dat + len;
588 break;
589 }
590
591 p += advance;
592 }
593 break;
594 default:
595 break;
596 }
597 }
598
599 static void
600 bgp_open_print(const u_char *dat, int length)
601 {
602 struct bgp_open bgpo;
603 struct bgp_opt bgpopt;
604 int hlen;
605 const u_char *opt;
606 int i;
607
608 TCHECK2(dat[0], BGP_OPEN_SIZE);
609 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
610 hlen = ntohs(bgpo.bgpo_len);
611
612 printf(": Version %d,", bgpo.bgpo_version);
613 printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
614 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
615 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id));
616 printf(" Option length %u", bgpo.bgpo_optlen);
617
618 /* ugly! */
619 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
620 opt++;
621
622 i = 0;
623 while (i < bgpo.bgpo_optlen) {
624 TCHECK2(opt[i], BGP_OPT_SIZE);
625 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
626 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
627 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type);
628 break;
629 }
630
631 printf(" (option %s, len=%d)",
632 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
633 bgpopt.bgpopt_len);
634 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
635 }
636 return;
637 trunc:
638 printf("[|BGP]");
639 }
640
641 static void
642 bgp_update_print(const u_char *dat, int length)
643 {
644 struct bgp bgp;
645 struct bgp_attr bgpa;
646 int hlen;
647 const u_char *p;
648 int len;
649 int i;
650 int newline;
651
652 TCHECK2(dat[0], BGP_SIZE);
653 memcpy(&bgp, dat, BGP_SIZE);
654 hlen = ntohs(bgp.bgp_len);
655 p = dat + BGP_SIZE; /*XXX*/
656 printf(":");
657
658 /* Unfeasible routes */
659 len = EXTRACT_16BITS(p);
660 if (len) {
661 /*
662 * Without keeping state from the original NLRI message,
663 * it's not possible to tell if this a v4 or v6 route,
664 * so only try to decode it if we're not v6 enabled.
665 */
666 #ifdef INET6
667 printf(" (Withdrawn routes: %d bytes)", len);
668 #else
669 char buf[MAXHOSTNAMELEN + 100];
670
671 TCHECK2(p[2], len);
672 i = 2;
673
674 printf(" (Withdrawn routes:");
675
676 while(i < 2 + len) {
677 i += decode_prefix4(&p[i], buf, sizeof(buf));
678 printf(" %s", buf);
679 }
680 printf(")\n");
681 #endif
682 }
683 p += 2 + len;
684
685 TCHECK2(p[0], 2);
686 len = EXTRACT_16BITS(p);
687 if (len) {
688 /* do something more useful!*/
689 i = 2;
690 printf(" (Path attributes:"); /* ) */
691 newline = 0;
692 while (i < 2 + len) {
693 int alen, aoff;
694
695 TCHECK2(p[i], sizeof(bgpa));
696 memcpy(&bgpa, &p[i], sizeof(bgpa));
697 alen = bgp_attr_len(&bgpa);
698 aoff = bgp_attr_off(&bgpa);
699
700 if (vflag && newline)
701 printf("\n\t\t");
702 else
703 printf(" ");
704
705 printf("(%s", tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type));
706 if (bgpa.bgpa_flags) {
707 printf("[%s%s%s%s",
708 bgpa.bgpa_flags & 0x80 ? "O" : "",
709 bgpa.bgpa_flags & 0x40 ? "T" : "",
710 bgpa.bgpa_flags & 0x20 ? "P" : "",
711 bgpa.bgpa_flags & 0x10 ? "E" : "");
712 if (bgpa.bgpa_flags & 0xf)
713 printf("+%x", bgpa.bgpa_flags & 0xf);
714 printf("]");
715 }
716
717 bgp_attr_print(&bgpa, &p[i + aoff], alen);
718 newline = 1;
719
720 /* ( */
721 printf(")");
722
723 i += aoff + alen;
724 }
725
726 /* ( */
727 printf(")");
728 }
729 p += 2 + len;
730
731 if (len && dat + length > p)
732 printf("\n\t\t");
733 if (dat + length > p) {
734 printf("(NLRI:"); /* ) */
735 while (dat + length > p) {
736 char buf[MAXHOSTNAMELEN + 100];
737 i = decode_prefix4(p, buf, sizeof(buf));
738 printf(" %s", buf);
739 if (i < 0)
740 break;
741 p += i;
742 }
743
744 /* ( */
745 printf(")");
746 }
747 return;
748 trunc:
749 printf("[|BGP]");
750 }
751
752 static void
753 bgp_notification_print(const u_char *dat, int length)
754 {
755 struct bgp_notification bgpn;
756 int hlen;
757
758 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
759 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
760 hlen = ntohs(bgpn.bgpn_len);
761
762 printf(": error %s,", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
763
764 switch (bgpn.bgpn_major) {
765
766 case BGP_NOTIFY_MAJOR_MSG:
767 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
768 break;
769 case BGP_NOTIFY_MAJOR_OPEN:
770 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
771 break;
772 case BGP_NOTIFY_MAJOR_UPDATE:
773 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
774 break;
775 default:
776 break;
777 }
778
779 return;
780 trunc:
781 printf("[|BGP]");
782 }
783
784 static void
785 bgp_header_print(const u_char *dat, int length)
786 {
787 struct bgp bgp;
788
789 TCHECK2(dat[0], BGP_SIZE);
790 memcpy(&bgp, dat, BGP_SIZE);
791 printf("(%s", tok2str(bgp_msg_values, "Unknown Message Type", bgp.bgp_type));
792
793 switch (bgp.bgp_type) {
794 case BGP_OPEN:
795 bgp_open_print(dat, length);
796 break;
797 case BGP_UPDATE:
798 bgp_update_print(dat, length);
799 break;
800 case BGP_NOTIFICATION:
801 bgp_notification_print(dat, length);
802 break;
803 }
804
805 /* ( */
806 printf(")");
807 return;
808 trunc:
809 printf("[|BGP]");
810 }
811
812 void
813 bgp_print(const u_char *dat, int length)
814 {
815 const u_char *p;
816 const u_char *ep;
817 const u_char *start;
818 const u_char marker[] = {
819 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
820 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
821 };
822 struct bgp bgp;
823 u_int16_t hlen;
824 int newline;
825
826 ep = dat + length;
827 if (snapend < dat + length)
828 ep = snapend;
829
830 printf(": BGP");
831
832 p = dat;
833 newline = 0;
834 start = p;
835 while (p < snapend) {
836 if (!TTEST2(p[0], 1))
837 break;
838 if (p[0] != 0xff) {
839 p++;
840 continue;
841 }
842
843 if (!TTEST2(p[0], sizeof(marker)))
844 break;
845 if (memcmp(p, marker, sizeof(marker)) != 0) {
846 p++;
847 continue;
848 }
849
850 /* found BGP header */
851 TCHECK2(p[0], BGP_SIZE); /*XXX*/
852 memcpy(&bgp, p, BGP_SIZE);
853
854 if (start != p)
855 printf(" [|BGP]");
856
857 hlen = ntohs(bgp.bgp_len);
858 if (vflag && newline)
859 printf("\n\t");
860 else
861 printf(" ");
862 if (TTEST2(p[0], hlen)) {
863 bgp_header_print(p, hlen);
864 newline = 1;
865 p += hlen;
866 start = p;
867 } else {
868 printf("[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
869 break;
870 }
871 }
872
873 return;
874
875 trunc:
876 printf(" [|BGP]");
877 }
878
879
880
881
882
883