]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
73d989b655ad4a701e433ec23b79bd257af7872d
[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.36 2002-07-14 14:14:51 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 #define BGP_OPT_AUTH 1
158 #define BGP_OPT_CAP 2
159
160
161 static struct tok bgp_opt_values[] = {
162 { BGP_OPT_AUTH, "Authentication Information"},
163 { BGP_OPT_CAP, "Capabilities Advertisement"},
164 { 0, NULL}
165 };
166
167 #define BGP_CAPCODE_MP 1
168 #define BGP_CAPCODE_RR 2
169 #define BGP_CAPCODE_RR_CISCO 128
170
171 static struct tok bgp_capcode_values[] = {
172 { BGP_CAPCODE_MP, "Multiprotocol Extensions"},
173 { BGP_CAPCODE_RR, "Route Refresh"},
174 { BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"},
175 { 0, NULL}
176 };
177
178 #define BGP_NOTIFY_MAJOR_MSG 1
179 #define BGP_NOTIFY_MAJOR_OPEN 2
180 #define BGP_NOTIFY_MAJOR_UPDATE 3
181 #define BGP_NOTIFY_MAJOR_HOLDTIME 4
182 #define BGP_NOTIFY_MAJOR_FSM 5
183 #define BGP_NOTIFY_MAJOR_CEASE 6
184
185 static struct tok bgp_notify_major_values[] = {
186 { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"},
187 { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"},
188 { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"},
189 { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
190 { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"},
191 { BGP_NOTIFY_MAJOR_CEASE, "Cease"},
192 { 0, NULL}
193 };
194
195 static struct tok bgp_notify_minor_msg_values[] = {
196 { 1, "Connection Not Synchronized"},
197 { 2, "Bad Message Length"},
198 { 3, "Bad Message Type"},
199 { 0, NULL}
200 };
201
202 static struct tok bgp_notify_minor_open_values[] = {
203 { 1, "Unsupported Version Number"},
204 { 2, "Bad Peer AS"},
205 { 3, "Bad BGP Identifier"},
206 { 4, "Unsupported Optional Parameter"},
207 { 5, "Authentication Failure"},
208 { 6, "Unacceptable Hold Time"},
209 { 0, NULL}
210 };
211
212 static struct tok bgp_notify_minor_update_values[] = {
213 { 1, "Malformed Attribute List"},
214 { 2, "Unrecognized Well-known Attribute"},
215 { 3, "Missing Well-known Attribute"},
216 { 4, "Attribute Flags Error"},
217 { 5, "Attribute Length Error"},
218 { 6, "Invalid ORIGIN Attribute"},
219 { 7, "AS Routing Loop"},
220 { 8, "Invalid NEXT_HOP Attribute"},
221 { 9, "Optional Attribute Error"},
222 { 10, "Invalid Network Field"},
223 { 11, "Malformed AS_PATH"},
224 { 0, NULL}
225 };
226
227 static struct tok bgp_origin_values[] = {
228 { 0, "IGP"},
229 { 1, "EGP"},
230 { 2, "Incomplete"},
231 { 0, NULL}
232 };
233
234 /* Subsequent address family identifier, RFC2283 section 7 */
235 #define SAFNUM_RES 0
236 #define SAFNUM_UNICAST 1
237 #define SAFNUM_MULTICAST 2
238 #define SAFNUM_UNIMULTICAST 3
239 /* labeled BGP RFC3107 */
240 #define SAFNUM_LABUNICAST 4
241 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */
242 #define SAFNUM_VPNUNICAST 128
243 #define SAFNUM_VPNMULTICAST 129
244 #define SAFNUM_VPNUNIMULTICAST 130
245
246 static struct tok bgp_safi_values[] = {
247 { SAFNUM_RES, "Reserved"},
248 { SAFNUM_UNICAST, "Unicast"},
249 { SAFNUM_MULTICAST, "Multicast"},
250 { SAFNUM_UNIMULTICAST, "Unicast+Multicast"},
251 { SAFNUM_LABUNICAST, "labeled Unicast"},
252 { SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
253 { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
254 { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
255 { 0, NULL }
256 };
257
258 /* well-known community */
259 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01
260 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02
261 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
262
263 /* RFC1700 address family numbers */
264 #define AFNUM_INET 1
265 #define AFNUM_INET6 2
266 #define AFNUM_NSAP 3
267 #define AFNUM_HDLC 4
268 #define AFNUM_BBN1822 5
269 #define AFNUM_802 6
270 #define AFNUM_E163 7
271 #define AFNUM_E164 8
272 #define AFNUM_F69 9
273 #define AFNUM_X121 10
274 #define AFNUM_IPX 11
275 #define AFNUM_ATALK 12
276 #define AFNUM_DECNET 13
277 #define AFNUM_BANYAN 14
278 #define AFNUM_E164NSAP 15
279 /* draft-kompella-ppvpn-l2vpn */
280 #define AFNUM_L2VPN 196 /* still to be approved by IANA */
281
282 static struct tok bgp_afi_values[] = {
283 { 0, "Reserved"},
284 { AFNUM_INET, "IPv4"},
285 { AFNUM_INET6, "IPv6"},
286 { AFNUM_NSAP, "NSAP"},
287 { AFNUM_HDLC, "HDLC"},
288 { AFNUM_BBN1822, "BBN 1822"},
289 { AFNUM_802, "802"},
290 { AFNUM_E163, "E.163"},
291 { AFNUM_E164, "E.164"},
292 { AFNUM_F69, "F.69"},
293 { AFNUM_X121, "X.121"},
294 { AFNUM_IPX, "Novell IPX"},
295 { AFNUM_ATALK, "Appletalk"},
296 { AFNUM_DECNET, "Decnet IV"},
297 { AFNUM_BANYAN, "Banyan Vines"},
298 { AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
299 { AFNUM_L2VPN, "Layer-2 VPN"},
300 { 0, NULL},
301 };
302
303 static int
304 decode_prefix4(const u_char *pd, char *buf, u_int buflen)
305 {
306 struct in_addr addr;
307 u_int plen;
308
309 plen = pd[0];
310 if (plen < 0 || 32 < plen)
311 return -1;
312
313 memset(&addr, 0, sizeof(addr));
314 memcpy(&addr, &pd[1], (plen + 7) / 8);
315 if (plen % 8) {
316 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
317 ((0xff00 >> (plen % 8)) & 0xff);
318 }
319 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
320 return 1 + (plen + 7) / 8;
321 }
322
323 static int
324 decode_labeled_prefix4(const u_char *pd, char *buf, u_int buflen)
325 {
326 struct in_addr addr;
327 u_int plen;
328
329 plen = pd[0]; /* get prefix length */
330
331 /* this is one of the weirdnesses of rfc3107
332 the label length (actually the label + COS bits)
333 is added of the prefix length;
334 we also do only read out just one label -
335 there is no real application for advertisment of
336 stacked labels in a a single BGP message
337 */
338
339 plen-=24; /* adjust prefixlen - labellength */
340
341 if (plen < 0 || 32 < plen)
342 return -1;
343
344 memset(&addr, 0, sizeof(addr));
345 memcpy(&addr, &pd[4], (plen + 7) / 8);
346 if (plen % 8) {
347 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
348 ((0xff00 >> (plen % 8)) & 0xff);
349 }
350 /* the label may get offsetted by 4 bits so lets shift it right */
351 snprintf(buf, buflen, "%s/%d label:%u %s",
352 getname((u_char *)&addr),
353 plen,
354 EXTRACT_24BITS(pd+1)>>4,
355 ((pd[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
356
357 return 4 + (plen + 7) / 8;
358 }
359
360 #ifdef INET6
361 static int
362 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
363 {
364 struct in6_addr addr;
365 u_int plen;
366
367 plen = pd[0];
368 if (plen < 0 || 128 < plen)
369 return -1;
370
371 memset(&addr, 0, sizeof(addr));
372 memcpy(&addr, &pd[1], (plen + 7) / 8);
373 if (plen % 8) {
374 addr.s6_addr[(plen + 7) / 8 - 1] &=
375 ((0xff00 >> (plen % 8)) & 0xff);
376 }
377 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
378 return 1 + (plen + 7) / 8;
379 }
380 #endif
381
382 static void
383 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
384 {
385 int i;
386 u_int16_t af;
387 u_int8_t safi, snpa;
388 int advance;
389 int tlen;
390 const u_char *p;
391 char buf[MAXHOSTNAMELEN + 100];
392
393 p = dat;
394 tlen=len;
395
396 switch (attr->bgpa_type) {
397 case BGPTYPE_ORIGIN:
398 if (len != 1)
399 printf("invalid len");
400 else
401 printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", p[0]));
402 break;
403 case BGPTYPE_AS_PATH:
404 if (len % 2) {
405 printf("invalid len");
406 break;
407 }
408 if (!len) {
409 printf("empty");
410 break;
411 }
412 while (p < dat + len) {
413 /*
414 * under RFC1965, p[0] means:
415 * 1: AS_SET 2: AS_SEQUENCE
416 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
417 */
418 if (p[0] == 3 || p[0] == 4)
419 printf("confed");
420 printf("%s", (p[0] & 1) ? "{" : "");
421 for (i = 0; i < p[1] * 2; i += 2) {
422 printf("%s%u", i == 0 ? "" : " ",
423 EXTRACT_16BITS(&p[2 + i]));
424 }
425 printf("%s", (p[0] & 1) ? "}" : "");
426 p += 2 + p[1] * 2;
427 }
428 break;
429 case BGPTYPE_NEXT_HOP:
430 if (len != 4)
431 printf("invalid len");
432 else
433 printf("%s", getname(p));
434 break;
435 case BGPTYPE_MULTI_EXIT_DISC:
436 case BGPTYPE_LOCAL_PREF:
437 if (len != 4)
438 printf("invalid len");
439 else
440 printf("%u", EXTRACT_32BITS(p));
441 break;
442 case BGPTYPE_ATOMIC_AGGREGATE:
443 if (len != 0)
444 printf("invalid len");
445 break;
446 case BGPTYPE_AGGREGATOR:
447 if (len != 6) {
448 printf("invalid len");
449 break;
450 }
451 printf(" AS #%u, origin %s", EXTRACT_16BITS(p),
452 getname(p + 2));
453 break;
454 case BGPTYPE_COMMUNITIES:
455 if (len % 4) {
456 printf("invalid len");
457 break;
458 }
459 while (tlen>0) {
460 u_int32_t comm;
461 comm = EXTRACT_32BITS(p);
462 switch (comm) {
463 case BGP_COMMUNITY_NO_EXPORT:
464 printf(" NO_EXPORT");
465 break;
466 case BGP_COMMUNITY_NO_ADVERT:
467 printf(" NO_ADVERTISE");
468 break;
469 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
470 printf(" NO_EXPORT_SUBCONFED");
471 break;
472 default:
473 printf("%u:%u%s",
474 (comm >> 16) & 0xffff,
475 comm & 0xffff,
476 (tlen>4) ? ", " : "");
477 break;
478 }
479 tlen -=4;
480 p +=4;
481 }
482 break;
483 case BGPTYPE_ORIGINATOR_ID:
484 if (len != 4) {
485 printf("invalid len");
486 break;
487 }
488 printf("%s",getname(p));
489 break;
490 case BGPTYPE_CLUSTER_LIST:
491 while (tlen>0) {
492 printf("%s%s",
493 getname(p),
494 (tlen>4) ? ", " : "");
495 tlen -=4;
496 p +=4;
497 }
498 break;
499 case BGPTYPE_MP_REACH_NLRI:
500 af = EXTRACT_16BITS(p);
501 safi = p[2];
502
503 printf("\n\t AFI %s (%u), %sSAFI %s (%u)",
504 tok2str(bgp_afi_values, "Unknown AFI", af),
505 af,
506 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
507 tok2str(bgp_safi_values, "Unknown SAFI", safi),
508 safi);
509
510 p += 3;
511
512 if (af == AFNUM_INET)
513 ;
514 #ifdef INET6
515 else if (af == AFNUM_INET6)
516 ;
517 #endif
518 else
519 break;
520
521 tlen = p[0];
522 if (tlen) {
523 printf("\n\t nexthop: ");
524 i = 0;
525 while (i < tlen) {
526 switch (af) {
527 case AFNUM_INET:
528 switch(safi) {
529 case SAFNUM_UNICAST:
530 case SAFNUM_MULTICAST:
531 case SAFNUM_UNIMULTICAST:
532 case SAFNUM_LABUNICAST:
533 printf("%s", getname(p + 1 + i));
534 i += sizeof(struct in_addr);
535 break;
536 default:
537 printf("no SAFI %u decoder",safi);
538 i = tlen;
539 break;
540 }
541 break;
542 #ifdef INET6
543 case AFNUM_INET6:
544 switch(safi) {
545 case SAFNUM_UNICAST:
546 case SAFNUM_MULTICAST:
547 case SAFNUM_UNIMULTICAST:
548 case SAFNUM_LABUNICAST:
549 printf("%s", getname6(p + 1 + i));
550 i += sizeof(struct in6_addr);
551 break;
552 default:
553 printf("no SAFI %u decoder",safi);
554 i = tlen;
555 break;
556 }
557 #endif
558 default:
559 printf("no AF %u decoder",af);
560 i = tlen; /*exit loop*/
561 break;
562 }
563 }
564 }
565 p += 1 + tlen;
566
567 snpa = p[0];
568 p++;
569 if (snpa) {
570 printf("\n\t %u SNPA", snpa);
571 for (/*nothing*/; snpa > 0; snpa--) {
572 printf("\n\t %d bytes", p[0]);
573 p += p[0] + 1;
574 }
575 } else {
576 printf(", no SNPA");
577 }
578
579 while (len - (p - dat) > 0) {
580 switch (af) {
581 case AFNUM_INET:
582 switch (safi) {
583 case SAFNUM_UNICAST:
584 case SAFNUM_MULTICAST:
585 case SAFNUM_UNIMULTICAST:
586 advance = decode_prefix4(p, buf, sizeof(buf));
587 printf("\n\t %s", buf);
588 break;
589 case SAFNUM_LABUNICAST:
590 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
591 printf("\n\t %s", buf);
592 break;
593 default:
594 printf("\n\t no SAFI %u decoder",safi);
595 advance = 0;
596 p = dat + len;
597 break;
598 }
599 break;
600 #ifdef INET6
601 case AFNUM_INET6:
602 switch (safi) {
603 case SAFNUM_UNICAST:
604 case SAFNUM_MULTICAST:
605 case SAFNUM_UNIMULTICAST:
606 advance = decode_prefix6(p, buf, sizeof(buf));
607 printf("\n\t %s", buf);
608 break;
609 default:
610 printf("\n\t no SAFI %u decoder ",safi);
611 advance = 0;
612 p = dat + len;
613 break;
614 }
615 break;
616 #endif
617 default:
618 printf("\n\t no AF %u decoder ",af);
619 advance = 0;
620 p = dat + len;
621 break;
622 }
623
624 p += advance;
625 }
626
627 break;
628
629 case BGPTYPE_MP_UNREACH_NLRI:
630 af = EXTRACT_16BITS(p);
631 safi = p[2];
632
633 printf("\n\t AFI %s (%u), %sSAFI %s (%u)",
634 tok2str(bgp_afi_values, "Unknown AFI", af),
635 af,
636 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
637 tok2str(bgp_safi_values, "Unknown SAFI", safi),
638 safi);
639
640 p += 3;
641
642 printf("\n\t Withdrawn routes");
643
644 while (len - (p - dat) > 0) {
645 switch (af) {
646 case AFNUM_INET:
647 switch (safi) {
648 case SAFNUM_UNICAST:
649 case SAFNUM_MULTICAST:
650 case SAFNUM_UNIMULTICAST:
651 advance = decode_prefix4(p, buf, sizeof(buf));
652 printf("\n\t %s", buf);
653 break;
654 case SAFNUM_LABUNICAST:
655 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
656 printf("\n\t %s", buf);
657 break;
658 default:
659 printf("\n\t no SAFI %u decoder",safi);
660 advance = 0;
661 p = dat + len;
662 break;
663 }
664 break;
665
666 #ifdef INET6
667 case AFNUM_INET6:
668 switch (safi) {
669 case SAFNUM_UNICAST:
670 case SAFNUM_MULTICAST:
671 case SAFNUM_UNIMULTICAST:
672 advance = decode_prefix6(p, buf, sizeof(buf));
673 printf("\n\t %s", buf);
674 break;
675 default:
676 printf("\n\t no SAFI %u decoder",safi);
677 advance = 0;
678 p = dat + len;
679 break;
680 }
681 break;
682 #endif
683 default:
684 printf("\n\t no AF %u decoder",af);
685 advance = 0;
686 p = dat + len;
687 break;
688 }
689
690 p += advance;
691 }
692 break;
693 default:
694 printf("no decoder");
695 break;
696 }
697 }
698
699 static void
700 bgp_open_print(const u_char *dat, int length)
701 {
702 struct bgp_open bgpo;
703 struct bgp_opt bgpopt;
704 int hlen;
705 const u_char *opt;
706 int i,cap_type,cap_len;
707
708 TCHECK2(dat[0], BGP_OPEN_SIZE);
709 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
710 hlen = ntohs(bgpo.bgpo_len);
711
712 printf("\n\t Version %d, ", bgpo.bgpo_version);
713 printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
714 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
715 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
716 printf("\n\t Optional parameters, length %u", bgpo.bgpo_optlen);
717
718 /* ugly! */
719 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
720 opt++;
721
722 i = 0;
723 while (i < bgpo.bgpo_optlen) {
724 TCHECK2(opt[i], BGP_OPT_SIZE);
725 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
726 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
727 printf("\n\t Option %d, length %d", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
728 break;
729 }
730
731 printf("\n\t Option %s (%u), length %d",
732 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
733 bgpopt.bgpopt_type,
734 bgpopt.bgpopt_len);
735
736 /* now lets decode the options we know*/
737 switch(bgpopt.bgpopt_type) {
738 case BGP_OPT_CAP:
739 cap_type=opt[i+BGP_OPT_SIZE];
740 cap_len=opt[i+BGP_OPT_SIZE+1];
741 printf("\n\t %s, length %u",
742 tok2str(bgp_capcode_values,"Unknown", cap_type),
743 cap_len);
744 switch(cap_type) {
745 case BGP_CAPCODE_MP:
746 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
747 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
748 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
749 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
750 opt[i+BGP_OPT_SIZE+5]);
751 break;
752 case BGP_CAPCODE_RR:
753 case BGP_CAPCODE_RR_CISCO:
754 break;
755 default:
756 printf("\n\t\tno decoder for Capability %u",
757 cap_type);
758 break;
759 }
760 break;
761 case BGP_OPT_AUTH:
762 default:
763 printf("\n\t no decoder for option %u",
764 bgpopt.bgpopt_type);
765 break;
766 }
767
768 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
769 }
770 return;
771 trunc:
772 printf("[|BGP]");
773 }
774
775 static void
776 bgp_update_print(const u_char *dat, int length)
777 {
778 struct bgp bgp;
779 struct bgp_attr bgpa;
780 int hlen;
781 const u_char *p;
782 int len;
783 int i;
784
785 TCHECK2(dat[0], BGP_SIZE);
786 memcpy(&bgp, dat, BGP_SIZE);
787 hlen = ntohs(bgp.bgp_len);
788 p = dat + BGP_SIZE; /*XXX*/
789
790 /* Unfeasible routes */
791 len = EXTRACT_16BITS(p);
792 if (len) {
793 /*
794 * Without keeping state from the original NLRI message,
795 * it's not possible to tell if this a v4 or v6 route,
796 * so only try to decode it if we're not v6 enabled.
797 */
798 #ifdef INET6
799 printf("\n\t Withdrawn routes: %d bytes", len);
800 #else
801 char buf[MAXHOSTNAMELEN + 100];
802
803 TCHECK2(p[2], len);
804 i = 2;
805
806 printf("\n\t Withdrawn routes:");
807
808 while(i < 2 + len) {
809 i += decode_prefix4(&p[i], buf, sizeof(buf));
810 printf("\n\t %s", buf);
811 }
812 #endif
813 }
814 p += 2 + len;
815
816 TCHECK2(p[0], 2);
817 len = EXTRACT_16BITS(p);
818 if (len) {
819 /* do something more useful!*/
820 i = 2;
821 while (i < 2 + len) {
822 int alen, aoff;
823
824 TCHECK2(p[i], sizeof(bgpa));
825 memcpy(&bgpa, &p[i], sizeof(bgpa));
826 alen = bgp_attr_len(&bgpa);
827 aoff = bgp_attr_off(&bgpa);
828
829 printf("\n\t %s ", tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type));
830 if (bgpa.bgpa_flags) {
831 printf("[%s%s%s%s",
832 bgpa.bgpa_flags & 0x80 ? "O" : "",
833 bgpa.bgpa_flags & 0x40 ? "T" : "",
834 bgpa.bgpa_flags & 0x20 ? "P" : "",
835 bgpa.bgpa_flags & 0x10 ? "E" : "");
836 if (bgpa.bgpa_flags & 0xf)
837 printf("+%x", bgpa.bgpa_flags & 0xf);
838 printf("]: ");
839 }
840
841 bgp_attr_print(&bgpa, &p[i + aoff], alen);
842 i += aoff + alen;
843 }
844 }
845 p += 2 + len;
846
847 if (dat + length > p) {
848 printf("\n\t Updated routes:");
849 while (dat + length > p) {
850 char buf[MAXHOSTNAMELEN + 100];
851 i = decode_prefix4(p, buf, sizeof(buf));
852 printf("\n\t %s", buf);
853 if (i < 0)
854 break;
855 p += i;
856 }
857 }
858 return;
859 trunc:
860 printf("[|BGP]");
861 }
862
863 static void
864 bgp_notification_print(const u_char *dat, int length)
865 {
866 struct bgp_notification bgpn;
867 int hlen;
868
869 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
870 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
871 hlen = ntohs(bgpn.bgpn_len);
872
873 printf(", Error - %s", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
874
875 switch (bgpn.bgpn_major) {
876
877 case BGP_NOTIFY_MAJOR_MSG:
878 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
879 break;
880 case BGP_NOTIFY_MAJOR_OPEN:
881 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
882 break;
883 case BGP_NOTIFY_MAJOR_UPDATE:
884 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
885 break;
886 default:
887 break;
888 }
889
890 return;
891 trunc:
892 printf("[|BGP]");
893 }
894
895 static void
896 bgp_header_print(const u_char *dat, int length)
897 {
898 struct bgp bgp;
899
900 TCHECK2(dat[0], BGP_SIZE);
901 memcpy(&bgp, dat, BGP_SIZE);
902 printf("\n\t%s Message", tok2str(bgp_msg_values, "Unknown Type", bgp.bgp_type));
903
904 switch (bgp.bgp_type) {
905 case BGP_OPEN:
906 bgp_open_print(dat, length);
907 break;
908 case BGP_UPDATE:
909 bgp_update_print(dat, length);
910 break;
911 case BGP_NOTIFICATION:
912 bgp_notification_print(dat, length);
913 break;
914 }
915 return;
916 trunc:
917 printf("[|BGP]");
918 }
919
920 void
921 bgp_print(const u_char *dat, int length)
922 {
923 const u_char *p;
924 const u_char *ep;
925 const u_char *start;
926 const u_char marker[] = {
927 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
928 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
929 };
930 struct bgp bgp;
931 u_int16_t hlen;
932
933 ep = dat + length;
934 if (snapend < dat + length)
935 ep = snapend;
936
937 printf(": BGP");
938
939 p = dat;
940 start = p;
941 while (p < snapend) {
942 if (!TTEST2(p[0], 1))
943 break;
944 if (p[0] != 0xff) {
945 p++;
946 continue;
947 }
948
949 if (!TTEST2(p[0], sizeof(marker)))
950 break;
951 if (memcmp(p, marker, sizeof(marker)) != 0) {
952 p++;
953 continue;
954 }
955
956 /* found BGP header */
957 TCHECK2(p[0], BGP_SIZE); /*XXX*/
958 memcpy(&bgp, p, BGP_SIZE);
959
960 if (start != p)
961 printf(" [|BGP]");
962
963 hlen = ntohs(bgp.bgp_len);
964
965 if (TTEST2(p[0], hlen)) {
966 bgp_header_print(p, hlen);
967 p += hlen;
968 start = p;
969 } else {
970 printf("[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
971 break;
972 }
973 }
974
975 return;
976
977 trunc:
978 printf(" [|BGP]");
979 }
980
981
982
983
984
985