]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
Add a "in_cksum_shouldbe()" to compute, given an Internet checksum field
[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.37 2002-07-18 00:39:12 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 if (af == AFNUM_INET)
511 ;
512 #ifdef INET6
513 else if (af == AFNUM_INET6)
514 ;
515 #endif
516 else {
517 printf("\n\t no AFI %u decoder",af);
518 print_unknown_data(p,"\n\t ",tlen);
519 break;
520 }
521
522 p +=3;
523 tlen = p[0];
524 if (tlen) {
525 printf("\n\t nexthop: ");
526 i = 0;
527 while (i < tlen) {
528 switch (af) {
529 case AFNUM_INET:
530 switch(safi) {
531 case SAFNUM_UNICAST:
532 case SAFNUM_MULTICAST:
533 case SAFNUM_UNIMULTICAST:
534 case SAFNUM_LABUNICAST:
535 printf("%s", getname(p + 1 + i));
536 i += sizeof(struct in_addr);
537 break;
538 default:
539 printf("no SAFI %u decoder",safi);
540 print_unknown_data(p,"\n\t ",tlen);
541 i = tlen;
542 break;
543 }
544 break;
545 #ifdef INET6
546 case AFNUM_INET6:
547 switch(safi) {
548 case SAFNUM_UNICAST:
549 case SAFNUM_MULTICAST:
550 case SAFNUM_UNIMULTICAST:
551 case SAFNUM_LABUNICAST:
552 printf("%s", getname6(p + 1 + i));
553 i += sizeof(struct in6_addr);
554 break;
555 default:
556 printf("no SAFI %u decoder",safi);
557 print_unknown_data(p,"\n\t ",tlen);
558 i = tlen;
559 break;
560 }
561 #endif
562 default:
563 printf("no AFI %u decoder",af);
564 print_unknown_data(p,"\n\t ",tlen);
565 i = tlen; /*exit loop*/
566 break;
567 }
568 }
569 }
570 p += 1 + tlen;
571
572 snpa = p[0];
573 p++;
574 if (snpa) {
575 printf("\n\t %u SNPA", snpa);
576 for (/*nothing*/; snpa > 0; snpa--) {
577 printf("\n\t %d bytes", p[0]);
578 p += p[0] + 1;
579 }
580 } else {
581 printf(", no SNPA");
582 }
583
584 while (len - (p - dat) > 0) {
585 switch (af) {
586 case AFNUM_INET:
587 switch (safi) {
588 case SAFNUM_UNICAST:
589 case SAFNUM_MULTICAST:
590 case SAFNUM_UNIMULTICAST:
591 advance = decode_prefix4(p, buf, sizeof(buf));
592 printf("\n\t %s", buf);
593 break;
594 case SAFNUM_LABUNICAST:
595 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
596 printf("\n\t %s", buf);
597 break;
598 default:
599 printf("\n\t no SAFI %u decoder",safi);
600 print_unknown_data(p-3,"\n\t ",tlen);
601 advance = 0;
602 p = dat + len;
603 break;
604 }
605 break;
606 #ifdef INET6
607 case AFNUM_INET6:
608 switch (safi) {
609 case SAFNUM_UNICAST:
610 case SAFNUM_MULTICAST:
611 case SAFNUM_UNIMULTICAST:
612 advance = decode_prefix6(p, buf, sizeof(buf));
613 printf("\n\t %s", buf);
614 break;
615 default:
616 printf("\n\t no SAFI %u decoder ",safi);
617 print_unknown_data(p-3,"\n\t ",tlen);
618 advance = 0;
619 p = dat + len;
620 break;
621 }
622 break;
623 #endif
624 default:
625 printf("\n\t no AFI %u decoder ",af);
626 print_unknown_data(p-3,"\n\t ",tlen);
627 advance = 0;
628 p = dat + len;
629 break;
630 }
631
632 p += advance;
633 }
634
635 break;
636
637 case BGPTYPE_MP_UNREACH_NLRI:
638 af = EXTRACT_16BITS(p);
639 safi = p[2];
640
641 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
642 tok2str(bgp_afi_values, "Unknown AFI", af),
643 af,
644 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
645 tok2str(bgp_safi_values, "Unknown SAFI", safi),
646 safi);
647
648 p += 3;
649
650 printf("\n\t Withdrawn routes");
651
652 while (len - (p - dat) > 0) {
653 switch (af) {
654 case AFNUM_INET:
655 switch (safi) {
656 case SAFNUM_UNICAST:
657 case SAFNUM_MULTICAST:
658 case SAFNUM_UNIMULTICAST:
659 advance = decode_prefix4(p, buf, sizeof(buf));
660 printf("\n\t %s", buf);
661 break;
662 case SAFNUM_LABUNICAST:
663 advance = decode_labeled_prefix4(p, buf, sizeof(buf));
664 printf("\n\t %s", buf);
665 break;
666 default:
667 printf("\n\t no SAFI %u decoder",safi);
668 print_unknown_data(p-3,"\n\t ",tlen);
669 advance = 0;
670 p = dat + len;
671 break;
672 }
673 break;
674
675 #ifdef INET6
676 case AFNUM_INET6:
677 switch (safi) {
678 case SAFNUM_UNICAST:
679 case SAFNUM_MULTICAST:
680 case SAFNUM_UNIMULTICAST:
681 advance = decode_prefix6(p, buf, sizeof(buf));
682 printf("\n\t %s", buf);
683 break;
684 default:
685 printf("\n\t no SAFI %u decoder",safi);
686 print_unknown_data(p-3,"\n\t ",tlen);
687 advance = 0;
688 p = dat + len;
689 break;
690 }
691 break;
692 #endif
693 default:
694 printf("\n\t no AFI %u decoder",af);
695 print_unknown_data(p-3,"\n\t ",tlen);
696 advance = 0;
697 p = dat + len;
698 break;
699 }
700
701 p += advance;
702 }
703 break;
704 default:
705 printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
706 print_unknown_data(p,"\n\t ",tlen);
707 break;
708 }
709 }
710
711 static void
712 bgp_open_print(const u_char *dat, int length)
713 {
714 struct bgp_open bgpo;
715 struct bgp_opt bgpopt;
716 int hlen;
717 const u_char *opt;
718 int i,cap_type,cap_len;
719
720 TCHECK2(dat[0], BGP_OPEN_SIZE);
721 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
722 hlen = ntohs(bgpo.bgpo_len);
723
724 printf("\n\t Version %d, ", bgpo.bgpo_version);
725 printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
726 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
727 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
728 printf("\n\t Optional parameters, length %u", bgpo.bgpo_optlen);
729
730 /* ugly! */
731 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
732 opt++;
733
734 i = 0;
735 while (i < bgpo.bgpo_optlen) {
736 TCHECK2(opt[i], BGP_OPT_SIZE);
737 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
738 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
739 printf("\n\t Option %d, length %d", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
740 break;
741 }
742
743 printf("\n\t Option %s (%u), length %d",
744 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
745 bgpopt.bgpopt_type,
746 bgpopt.bgpopt_len);
747
748 /* now lets decode the options we know*/
749 switch(bgpopt.bgpopt_type) {
750 case BGP_OPT_CAP:
751 cap_type=opt[i+BGP_OPT_SIZE];
752 cap_len=opt[i+BGP_OPT_SIZE+1];
753 printf("\n\t %s, length %u",
754 tok2str(bgp_capcode_values,"Unknown", cap_type),
755 cap_len);
756 switch(cap_type) {
757 case BGP_CAPCODE_MP:
758 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
759 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
760 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
761 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
762 opt[i+BGP_OPT_SIZE+5]);
763 break;
764 case BGP_CAPCODE_RR:
765 case BGP_CAPCODE_RR_CISCO:
766 break;
767 default:
768 printf("\n\t\tno decoder for Capability %u",
769 cap_type);
770 break;
771 }
772 break;
773 case BGP_OPT_AUTH:
774 default:
775 printf("\n\t no decoder for option %u",
776 bgpopt.bgpopt_type);
777 break;
778 }
779
780 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
781 }
782 return;
783 trunc:
784 printf("[|BGP]");
785 }
786
787 static void
788 bgp_update_print(const u_char *dat, int length)
789 {
790 struct bgp bgp;
791 struct bgp_attr bgpa;
792 int hlen;
793 const u_char *p;
794 int len;
795 int i;
796
797 TCHECK2(dat[0], BGP_SIZE);
798 memcpy(&bgp, dat, BGP_SIZE);
799 hlen = ntohs(bgp.bgp_len);
800 p = dat + BGP_SIZE; /*XXX*/
801
802 /* Unfeasible routes */
803 len = EXTRACT_16BITS(p);
804 if (len) {
805 /*
806 * Without keeping state from the original NLRI message,
807 * it's not possible to tell if this a v4 or v6 route,
808 * so only try to decode it if we're not v6 enabled.
809 */
810 #ifdef INET6
811 printf("\n\t Withdrawn routes: %d bytes", len);
812 #else
813 char buf[MAXHOSTNAMELEN + 100];
814
815 TCHECK2(p[2], len);
816 i = 2;
817
818 printf("\n\t Withdrawn routes:");
819
820 while(i < 2 + len) {
821 i += decode_prefix4(&p[i], buf, sizeof(buf));
822 printf("\n\t %s", buf);
823 }
824 #endif
825 }
826 p += 2 + len;
827
828 TCHECK2(p[0], 2);
829 len = EXTRACT_16BITS(p);
830 if (len) {
831 /* do something more useful!*/
832 i = 2;
833 while (i < 2 + len) {
834 int alen, aoff;
835
836 TCHECK2(p[i], sizeof(bgpa));
837 memcpy(&bgpa, &p[i], sizeof(bgpa));
838 alen = bgp_attr_len(&bgpa);
839 aoff = bgp_attr_off(&bgpa);
840
841 printf("\n\t %s (%u), length: %u",
842 tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
843 bgpa.bgpa_type,
844 alen);
845
846 if (bgpa.bgpa_flags) {
847 printf(", flags [%s%s%s%s",
848 bgpa.bgpa_flags & 0x80 ? "O" : "",
849 bgpa.bgpa_flags & 0x40 ? "T" : "",
850 bgpa.bgpa_flags & 0x20 ? "P" : "",
851 bgpa.bgpa_flags & 0x10 ? "E" : "");
852 if (bgpa.bgpa_flags & 0xf)
853 printf("+%x", bgpa.bgpa_flags & 0xf);
854 printf("]: ");
855 }
856 bgp_attr_print(&bgpa, &p[i + aoff], alen);
857 i += aoff + alen;
858 }
859 }
860 p += 2 + len;
861
862 if (dat + length > p) {
863 printf("\n\t Updated routes:");
864 while (dat + length > p) {
865 char buf[MAXHOSTNAMELEN + 100];
866 i = decode_prefix4(p, buf, sizeof(buf));
867 printf("\n\t %s", buf);
868 if (i < 0)
869 break;
870 p += i;
871 }
872 }
873 return;
874 trunc:
875 printf("[|BGP]");
876 }
877
878 static void
879 bgp_notification_print(const u_char *dat, int length)
880 {
881 struct bgp_notification bgpn;
882 int hlen;
883
884 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
885 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
886 hlen = ntohs(bgpn.bgpn_len);
887
888 printf(", Error - %s", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
889
890 switch (bgpn.bgpn_major) {
891
892 case BGP_NOTIFY_MAJOR_MSG:
893 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
894 break;
895 case BGP_NOTIFY_MAJOR_OPEN:
896 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
897 break;
898 case BGP_NOTIFY_MAJOR_UPDATE:
899 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
900 break;
901 default:
902 break;
903 }
904
905 return;
906 trunc:
907 printf("[|BGP]");
908 }
909
910 static void
911 bgp_header_print(const u_char *dat, int length)
912 {
913 struct bgp bgp;
914
915 TCHECK2(dat[0], BGP_SIZE);
916 memcpy(&bgp, dat, BGP_SIZE);
917 printf("\n\t%s Message (%u), length: %u ",
918 tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
919 bgp.bgp_type,
920 length);
921
922 switch (bgp.bgp_type) {
923 case BGP_OPEN:
924 bgp_open_print(dat, length);
925 break;
926 case BGP_UPDATE:
927 bgp_update_print(dat, length);
928 break;
929 case BGP_NOTIFICATION:
930 bgp_notification_print(dat, length);
931 break;
932 case BGP_KEEPALIVE:
933 break;
934 default:
935 /* we have no decoder for the BGP message */
936 printf("\n\t no Message %u decoder",bgp.bgp_type);
937 print_unknown_data(dat,"\n\t ",length);
938 break;
939 }
940 return;
941 trunc:
942 printf("[|BGP]");
943 }
944
945 void
946 bgp_print(const u_char *dat, int length)
947 {
948 const u_char *p;
949 const u_char *ep;
950 const u_char *start;
951 const u_char marker[] = {
952 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
953 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
954 };
955 struct bgp bgp;
956 u_int16_t hlen;
957
958 ep = dat + length;
959 if (snapend < dat + length)
960 ep = snapend;
961
962 printf(": BGP");
963
964 p = dat;
965 start = p;
966 while (p < snapend) {
967 if (!TTEST2(p[0], 1))
968 break;
969 if (p[0] != 0xff) {
970 p++;
971 continue;
972 }
973
974 if (!TTEST2(p[0], sizeof(marker)))
975 break;
976 if (memcmp(p, marker, sizeof(marker)) != 0) {
977 p++;
978 continue;
979 }
980
981 /* found BGP header */
982 TCHECK2(p[0], BGP_SIZE); /*XXX*/
983 memcpy(&bgp, p, BGP_SIZE);
984
985 if (start != p)
986 printf(" [|BGP]");
987
988 hlen = ntohs(bgp.bgp_len);
989
990 if (TTEST2(p[0], hlen)) {
991 bgp_header_print(p, hlen);
992 p += hlen;
993 start = p;
994 } else {
995 printf("[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
996 break;
997 }
998 }
999
1000 return;
1001
1002 trunc:
1003 printf(" [|BGP]");
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015