]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
support for BGP route-refresh messages (BGP message code 5)
[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.42 2002-07-24 00:10:46 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 #define BGP_ROUTE_REFRESH 5
67
68 static struct tok bgp_msg_values[] = {
69 { BGP_OPEN, "Open"},
70 { BGP_UPDATE, "Update"},
71 { BGP_NOTIFICATION, "Notification"},
72 { BGP_KEEPALIVE, "Keepalive"},
73 { BGP_ROUTE_REFRESH, "Route Refresh"},
74 { 0, NULL}
75 };
76
77 struct bgp_open {
78 u_int8_t bgpo_marker[16];
79 u_int16_t bgpo_len;
80 u_int8_t bgpo_type;
81 u_int8_t bgpo_version;
82 u_int16_t bgpo_myas;
83 u_int16_t bgpo_holdtime;
84 u_int32_t bgpo_id;
85 u_int8_t bgpo_optlen;
86 /* options should follow */
87 };
88 #define BGP_OPEN_SIZE 29 /* unaligned */
89
90 struct bgp_opt {
91 u_int8_t bgpopt_type;
92 u_int8_t bgpopt_len;
93 /* variable length */
94 };
95 #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */
96
97 struct bgp_notification {
98 u_int8_t bgpn_marker[16];
99 u_int16_t bgpn_len;
100 u_int8_t bgpn_type;
101 u_int8_t bgpn_major;
102 u_int8_t bgpn_minor;
103 /* data should follow */
104 };
105 #define BGP_NOTIFICATION_SIZE 21 /* unaligned */
106
107 struct bgp_route_refresh {
108 u_int8_t bgp_marker[16];
109 u_int16_t len;
110 u_int8_t type;
111 u_int8_t afi; /* the compiler messes this structure up */
112 u_int8_t pad; /* when doing misaligned sequences of int8 and int16 */
113 u_int8_t res; /* afi should be int16 - so we have to access it using */
114 u_int8_t safi; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */
115 };
116 #define BGP_ROUTE_REFRESH_SIZE 23
117
118 struct bgp_attr {
119 u_int8_t bgpa_flags;
120 u_int8_t bgpa_type;
121 union {
122 u_int8_t len;
123 u_int16_t elen;
124 } bgpa_len;
125 #define bgp_attr_len(p) \
126 (((p)->bgpa_flags & 0x10) ? \
127 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len)
128 #define bgp_attr_off(p) \
129 (((p)->bgpa_flags & 0x10) ? 4 : 3)
130 };
131
132 #define BGPTYPE_ORIGIN 1
133 #define BGPTYPE_AS_PATH 2
134 #define BGPTYPE_NEXT_HOP 3
135 #define BGPTYPE_MULTI_EXIT_DISC 4
136 #define BGPTYPE_LOCAL_PREF 5
137 #define BGPTYPE_ATOMIC_AGGREGATE 6
138 #define BGPTYPE_AGGREGATOR 7
139 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
140 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */
141 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */
142 #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */
143 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */
144 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */
145 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
146 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
147 #define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */
148
149 static struct tok bgp_attr_values[] = {
150 { BGPTYPE_ORIGIN, "Origin"},
151 { BGPTYPE_AS_PATH, "AS Path"},
152 { BGPTYPE_NEXT_HOP, "Next Hop"},
153 { BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"},
154 { BGPTYPE_LOCAL_PREF, "Local Preference"},
155 { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
156 { BGPTYPE_AGGREGATOR, "Aggregator"},
157 { BGPTYPE_COMMUNITIES, "Community"},
158 { BGPTYPE_ORIGINATOR_ID, "Originator ID"},
159 { BGPTYPE_CLUSTER_LIST, "Cluster List"},
160 { BGPTYPE_DPA, "DPA"},
161 { BGPTYPE_ADVERTISERS, "Advertisers"},
162 { BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"},
163 { BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"},
164 { BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"},
165 { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
166 { 255, "Reserved for development"},
167 { 0, NULL}
168 };
169
170 #define BGP_OPT_AUTH 1
171 #define BGP_OPT_CAP 2
172
173
174 static struct tok bgp_opt_values[] = {
175 { BGP_OPT_AUTH, "Authentication Information"},
176 { BGP_OPT_CAP, "Capabilities Advertisement"},
177 { 0, NULL}
178 };
179
180 #define BGP_CAPCODE_MP 1
181 #define BGP_CAPCODE_RR 2
182 #define BGP_CAPCODE_RR_CISCO 128
183
184 static struct tok bgp_capcode_values[] = {
185 { BGP_CAPCODE_MP, "Multiprotocol Extensions"},
186 { BGP_CAPCODE_RR, "Route Refresh"},
187 { BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"},
188 { 0, NULL}
189 };
190
191 #define BGP_NOTIFY_MAJOR_MSG 1
192 #define BGP_NOTIFY_MAJOR_OPEN 2
193 #define BGP_NOTIFY_MAJOR_UPDATE 3
194 #define BGP_NOTIFY_MAJOR_HOLDTIME 4
195 #define BGP_NOTIFY_MAJOR_FSM 5
196 #define BGP_NOTIFY_MAJOR_CEASE 6
197
198 static struct tok bgp_notify_major_values[] = {
199 { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"},
200 { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"},
201 { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"},
202 { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
203 { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"},
204 { BGP_NOTIFY_MAJOR_CEASE, "Cease"},
205 { 0, NULL}
206 };
207
208 static struct tok bgp_notify_minor_msg_values[] = {
209 { 1, "Connection Not Synchronized"},
210 { 2, "Bad Message Length"},
211 { 3, "Bad Message Type"},
212 { 0, NULL}
213 };
214
215 static struct tok bgp_notify_minor_open_values[] = {
216 { 1, "Unsupported Version Number"},
217 { 2, "Bad Peer AS"},
218 { 3, "Bad BGP Identifier"},
219 { 4, "Unsupported Optional Parameter"},
220 { 5, "Authentication Failure"},
221 { 6, "Unacceptable Hold Time"},
222 { 0, NULL}
223 };
224
225 static struct tok bgp_notify_minor_update_values[] = {
226 { 1, "Malformed Attribute List"},
227 { 2, "Unrecognized Well-known Attribute"},
228 { 3, "Missing Well-known Attribute"},
229 { 4, "Attribute Flags Error"},
230 { 5, "Attribute Length Error"},
231 { 6, "Invalid ORIGIN Attribute"},
232 { 7, "AS Routing Loop"},
233 { 8, "Invalid NEXT_HOP Attribute"},
234 { 9, "Optional Attribute Error"},
235 { 10, "Invalid Network Field"},
236 { 11, "Malformed AS_PATH"},
237 { 0, NULL}
238 };
239
240 static struct tok bgp_origin_values[] = {
241 { 0, "IGP"},
242 { 1, "EGP"},
243 { 2, "Incomplete"},
244 { 0, NULL}
245 };
246
247 /* Subsequent address family identifier, RFC2283 section 7 */
248 #define SAFNUM_RES 0
249 #define SAFNUM_UNICAST 1
250 #define SAFNUM_MULTICAST 2
251 #define SAFNUM_UNIMULTICAST 3
252 /* labeled BGP RFC3107 */
253 #define SAFNUM_LABUNICAST 4
254 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */
255 #define SAFNUM_VPNUNICAST 128
256 #define SAFNUM_VPNMULTICAST 129
257 #define SAFNUM_VPNUNIMULTICAST 130
258
259 #define BGP_VPN_RD_LEN 8
260
261 static struct tok bgp_safi_values[] = {
262 { SAFNUM_RES, "Reserved"},
263 { SAFNUM_UNICAST, "Unicast"},
264 { SAFNUM_MULTICAST, "Multicast"},
265 { SAFNUM_UNIMULTICAST, "Unicast+Multicast"},
266 { SAFNUM_LABUNICAST, "labeled Unicast"},
267 { SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
268 { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
269 { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
270 { 0, NULL }
271 };
272
273 /* well-known community */
274 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01
275 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02
276 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
277
278 /* RFC1700 address family numbers */
279 #define AFNUM_INET 1
280 #define AFNUM_INET6 2
281 #define AFNUM_NSAP 3
282 #define AFNUM_HDLC 4
283 #define AFNUM_BBN1822 5
284 #define AFNUM_802 6
285 #define AFNUM_E163 7
286 #define AFNUM_E164 8
287 #define AFNUM_F69 9
288 #define AFNUM_X121 10
289 #define AFNUM_IPX 11
290 #define AFNUM_ATALK 12
291 #define AFNUM_DECNET 13
292 #define AFNUM_BANYAN 14
293 #define AFNUM_E164NSAP 15
294 /* draft-kompella-ppvpn-l2vpn */
295 #define AFNUM_L2VPN 196 /* still to be approved by IANA */
296
297 static struct tok bgp_afi_values[] = {
298 { 0, "Reserved"},
299 { AFNUM_INET, "IPv4"},
300 { AFNUM_INET6, "IPv6"},
301 { AFNUM_NSAP, "NSAP"},
302 { AFNUM_HDLC, "HDLC"},
303 { AFNUM_BBN1822, "BBN 1822"},
304 { AFNUM_802, "802"},
305 { AFNUM_E163, "E.163"},
306 { AFNUM_E164, "E.164"},
307 { AFNUM_F69, "F.69"},
308 { AFNUM_X121, "X.121"},
309 { AFNUM_IPX, "Novell IPX"},
310 { AFNUM_ATALK, "Appletalk"},
311 { AFNUM_DECNET, "Decnet IV"},
312 { AFNUM_BANYAN, "Banyan Vines"},
313 { AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
314 { AFNUM_L2VPN, "Layer-2 VPN"},
315 { 0, NULL},
316 };
317
318 static struct tok bgp_extd_comm_subtype_values[] = {
319 { 2, "target"},
320 { 3, "origin"},
321 { 4, "link-BW"},
322 { 0, NULL},
323 };
324
325 static int
326 decode_prefix4(const u_char *pptr, char *buf, u_int buflen)
327 {
328 struct in_addr addr;
329 u_int plen;
330
331 plen = pptr[0];
332 if (plen < 0 || 32 < plen)
333 return -1;
334
335 memset(&addr, 0, sizeof(addr));
336 memcpy(&addr, &pptr[1], (plen + 7) / 8);
337 if (plen % 8) {
338 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
339 ((0xff00 >> (plen % 8)) & 0xff);
340 }
341 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
342 return 1 + (plen + 7) / 8;
343 }
344
345 static int
346 decode_labeled_prefix4(const u_char *pptr, char *buf, u_int buflen)
347 {
348 struct in_addr addr;
349 u_int plen;
350
351 plen = pptr[0]; /* get prefix length */
352
353 /* this is one of the weirdnesses of rfc3107
354 the label length (actually the label + COS bits)
355 is added to the prefix length;
356 we also do only read out just one label -
357 there is no real application for advertisement of
358 stacked labels in a a single BGP message
359 */
360
361 plen-=24; /* adjust prefixlen - labellength */
362
363 if (plen < 0 || 32 < plen)
364 return -1;
365
366 memset(&addr, 0, sizeof(addr));
367 memcpy(&addr, &pptr[4], (plen + 7) / 8);
368 if (plen % 8) {
369 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
370 ((0xff00 >> (plen % 8)) & 0xff);
371 }
372 /* the label may get offsetted by 4 bits so lets shift it right */
373 snprintf(buf, buflen, "%s/%d, label:%u %s",
374 getname((u_char *)&addr),
375 plen,
376 EXTRACT_24BITS(pptr+1)>>4,
377 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
378
379 return 4 + (plen + 7) / 8;
380 }
381
382
383 static u_char *
384 bgp_vpn_rd_print (const u_char *pptr) {
385
386 /* allocate space for the following string
387 * xxx.xxx.xxx.xxx:xxxxx
388 * 21 bytes plus one termination byte */
389 static char rd[22];
390 char *pos = rd;
391
392 /* ok lets load the RD format */
393 switch (EXTRACT_16BITS(pptr)) {
394 /* AS:IP-address fmt*/
395 case 0:
396 pos+=sprintf(pos, "%u:%u.%u.%u.%u",
397 EXTRACT_16BITS(pptr+2),
398 *(pptr+4),
399 *(pptr+5),
400 *(pptr+6),
401 *(pptr+7));
402 break;
403 /* IP-address:AS fmt*/
404 case 1:
405 pos+=sprintf(pos, "%u.%u.%u.%u:%u",
406 *(pptr+2),
407 *(pptr+3),
408 *(pptr+4),
409 *(pptr+5),
410 EXTRACT_16BITS(pptr+6));
411 break;
412 default:
413 pos+=sprintf(pos, "unknown RD format");
414 break;
415 }
416 *(pos) = '\0';
417 return (rd);
418 }
419
420 static int
421 decode_labeled_vpn_prefix4(const u_char *pptr, char *buf, u_int buflen)
422 {
423 struct in_addr addr;
424 u_int plen;
425
426 plen = pptr[0]; /* get prefix length */
427
428 plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
429
430 if (plen < 0 || 32 < plen)
431 return -1;
432
433 memset(&addr, 0, sizeof(addr));
434 memcpy(&addr, &pptr[12], (plen + 7) / 8);
435 if (plen % 8) {
436 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
437 ((0xff00 >> (plen % 8)) & 0xff);
438 }
439 /* the label may get offsetted by 4 bits so lets shift it right */
440 snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
441 bgp_vpn_rd_print(pptr+4),
442 getname((u_char *)&addr),
443 plen,
444 EXTRACT_24BITS(pptr+1)>>4,
445 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
446
447 return 12 + (plen + 7) / 8;
448 }
449
450 #ifdef INET6
451 static int
452 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
453 {
454 struct in6_addr addr;
455 u_int plen;
456
457 plen = pd[0];
458 if (plen < 0 || 128 < plen)
459 return -1;
460
461 memset(&addr, 0, sizeof(addr));
462 memcpy(&addr, &pd[1], (plen + 7) / 8);
463 if (plen % 8) {
464 addr.s6_addr[(plen + 7) / 8 - 1] &=
465 ((0xff00 >> (plen % 8)) & 0xff);
466 }
467 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
468 return 1 + (plen + 7) / 8;
469 }
470 #endif
471
472 static void
473 bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
474 {
475 int i;
476 u_int16_t af;
477 u_int8_t safi, snpa;
478 int advance;
479 int tlen;
480 const u_char *tptr;
481 char buf[MAXHOSTNAMELEN + 100];
482
483 tptr = pptr;
484 tlen=len;
485
486 switch (attr->bgpa_type) {
487 case BGPTYPE_ORIGIN:
488 if (len != 1)
489 printf("invalid len");
490 else
491 printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
492 break;
493 case BGPTYPE_AS_PATH:
494 if (len % 2) {
495 printf("invalid len");
496 break;
497 }
498 if (!len) {
499 printf("empty");
500 break;
501 }
502 while (tptr < pptr + len) {
503 /*
504 * under RFC1965, p[0] means:
505 * 1: AS_SET 2: AS_SEQUENCE
506 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE
507 */
508 if (tptr[0] == 3 || tptr[0] == 4)
509 printf("confed");
510 printf("%s", (tptr[0] & 1) ? "{" : "");
511 for (i = 0; i < tptr[1] * 2; i += 2) {
512 printf("%s%u", i == 0 ? "" : " ",
513 EXTRACT_16BITS(&tptr[2 + i]));
514 }
515 printf("%s", (tptr[0] & 1) ? "}" : "");
516 tptr += 2 + tptr[1] * 2;
517 }
518 break;
519 case BGPTYPE_NEXT_HOP:
520 if (len != 4)
521 printf("invalid len");
522 else
523 printf("%s", getname(tptr));
524 break;
525 case BGPTYPE_MULTI_EXIT_DISC:
526 case BGPTYPE_LOCAL_PREF:
527 if (len != 4)
528 printf("invalid len");
529 else
530 printf("%u", EXTRACT_32BITS(tptr));
531 break;
532 case BGPTYPE_ATOMIC_AGGREGATE:
533 if (len != 0)
534 printf("invalid len");
535 break;
536 case BGPTYPE_AGGREGATOR:
537 if (len != 6) {
538 printf("invalid len");
539 break;
540 }
541 printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
542 getname(tptr + 2));
543 break;
544 case BGPTYPE_COMMUNITIES:
545 if (len % 4) {
546 printf("invalid len");
547 break;
548 }
549 while (tlen>0) {
550 u_int32_t comm;
551 comm = EXTRACT_32BITS(tptr);
552 switch (comm) {
553 case BGP_COMMUNITY_NO_EXPORT:
554 printf(" NO_EXPORT");
555 break;
556 case BGP_COMMUNITY_NO_ADVERT:
557 printf(" NO_ADVERTISE");
558 break;
559 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
560 printf(" NO_EXPORT_SUBCONFED");
561 break;
562 default:
563 printf("%u:%u%s",
564 (comm >> 16) & 0xffff,
565 comm & 0xffff,
566 (tlen>4) ? ", " : "");
567 break;
568 }
569 tlen -=4;
570 tptr +=4;
571 }
572 break;
573 case BGPTYPE_ORIGINATOR_ID:
574 if (len != 4) {
575 printf("invalid len");
576 break;
577 }
578 printf("%s",getname(tptr));
579 break;
580 case BGPTYPE_CLUSTER_LIST:
581 while (tlen>0) {
582 printf("%s%s",
583 getname(tptr),
584 (tlen>4) ? ", " : "");
585 tlen -=4;
586 tptr +=4;
587 }
588 break;
589 case BGPTYPE_MP_REACH_NLRI:
590 af = EXTRACT_16BITS(tptr);
591 safi = tptr[2];
592
593 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
594 tok2str(bgp_afi_values, "Unknown AFI", af),
595 af,
596 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
597 tok2str(bgp_safi_values, "Unknown SAFI", safi),
598 safi);
599
600 if (af == AFNUM_INET)
601 ;
602 #ifdef INET6
603 else if (af == AFNUM_INET6)
604 ;
605 #endif
606 else {
607 printf("\n\t no AFI %u decoder",af);
608 if (!vflag)
609 print_unknown_data(tptr,"\n\t ",tlen);
610 break;
611 }
612
613 tptr +=3;
614
615 tlen = tptr[0];
616 tptr++;
617
618 if (tlen) {
619 printf("\n\t nexthop: ");
620 while (tlen > 0) {
621 switch (af) {
622 case AFNUM_INET:
623 switch(safi) {
624 case SAFNUM_UNICAST:
625 case SAFNUM_MULTICAST:
626 case SAFNUM_UNIMULTICAST:
627 case SAFNUM_LABUNICAST:
628 printf("%s",getname(tptr));
629 tlen -= sizeof(struct in_addr);
630 tptr += sizeof(struct in_addr);
631 break;
632 case SAFNUM_VPNUNICAST:
633 case SAFNUM_VPNMULTICAST:
634 case SAFNUM_VPNUNIMULTICAST:
635 printf("RD: %s, %s",
636 bgp_vpn_rd_print(tptr),
637 getname(tptr+BGP_VPN_RD_LEN));
638 tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
639 tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
640 break;
641 default:
642 printf("no SAFI %u decoder",safi);
643 if (!vflag)
644 print_unknown_data(tptr,"\n\t ",tlen);
645 break;
646 }
647 break;
648 #ifdef INET6
649 case AFNUM_INET6:
650 switch(safi) {
651 case SAFNUM_UNICAST:
652 case SAFNUM_MULTICAST:
653 case SAFNUM_UNIMULTICAST:
654 case SAFNUM_LABUNICAST:
655 printf("%s", getname6(tptr));
656 tlen -= sizeof(struct in6_addr);
657 tptr += sizeof(struct in6_addr);
658 case SAFNUM_VPNUNICAST:
659 case SAFNUM_VPNMULTICAST:
660 case SAFNUM_VPNUNIMULTICAST:
661 printf("RD: %s, %s",
662 bgp_vpn_rd_print(tptr),
663 getname6(tptr+BGP_VPN_RD_LEN));
664 tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
665 tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
666 break; break;
667 default:
668 printf("no SAFI %u decoder",safi);
669 if (!vflag)
670 print_unknown_data(tptr,"\n\t ",tlen);
671 break;
672 }
673 #endif
674 default:
675 printf("no AFI %u decoder",af);
676 if (!vflag)
677 print_unknown_data(tptr,"\n\t ",tlen);
678 break;
679 }
680 }
681 }
682 tptr += tlen;
683
684 snpa = tptr[0];
685 tptr++;
686
687 if (snpa) {
688 printf("\n\t %u SNPA", snpa);
689 for (/*nothing*/; snpa > 0; snpa--) {
690 printf("\n\t %d bytes", tptr[0]);
691 tptr += tptr[0] + 1;
692 }
693 } else {
694 printf(", no SNPA");
695 }
696
697 while (len - (tptr - pptr) > 0) {
698 switch (af) {
699 case AFNUM_INET:
700 switch (safi) {
701 case SAFNUM_UNICAST:
702 case SAFNUM_MULTICAST:
703 case SAFNUM_UNIMULTICAST:
704 advance = decode_prefix4(tptr, buf, sizeof(buf));
705 printf("\n\t %s", buf);
706 break;
707 case SAFNUM_LABUNICAST:
708 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
709 printf("\n\t %s", buf);
710 break;
711 case SAFNUM_VPNUNICAST:
712 case SAFNUM_VPNMULTICAST:
713 case SAFNUM_VPNUNIMULTICAST:
714 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
715 printf("\n\t %s", buf);
716 break;
717 default:
718 printf("\n\t no SAFI %u decoder",safi);
719 if (!vflag)
720 print_unknown_data(tptr-3,"\n\t ",tlen);
721 advance = 0;
722 tptr = pptr + len;
723 break;
724 }
725 break;
726 #ifdef INET6
727 case AFNUM_INET6:
728 switch (safi) {
729 case SAFNUM_UNICAST:
730 case SAFNUM_MULTICAST:
731 case SAFNUM_UNIMULTICAST:
732 advance = decode_prefix6(tptr, buf, sizeof(buf));
733 printf("\n\t %s", buf);
734 break;
735 default:
736 printf("\n\t no SAFI %u decoder ",safi);
737 if (!vflag)
738 print_unknown_data(tptr-3,"\n\t ",tlen);
739 advance = 0;
740 tptr = ptr + len;
741 break;
742 }
743 break;
744 #endif
745 default:
746 printf("\n\t no AFI %u decoder ",af);
747 if (!vflag)
748 print_unknown_data(tptr-3,"\n\t ",tlen);
749 advance = 0;
750 tptr = pptr + len;
751 break;
752 }
753
754 tptr += advance;
755 }
756
757 break;
758
759 case BGPTYPE_MP_UNREACH_NLRI:
760 af = EXTRACT_16BITS(tptr);
761 safi = tptr[2];
762
763 printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
764 tok2str(bgp_afi_values, "Unknown AFI", af),
765 af,
766 (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
767 tok2str(bgp_safi_values, "Unknown SAFI", safi),
768 safi);
769
770 tptr += 3;
771
772 while (len - (tptr - pptr) > 0) {
773 switch (af) {
774 case AFNUM_INET:
775 switch (safi) {
776 case SAFNUM_UNICAST:
777 case SAFNUM_MULTICAST:
778 case SAFNUM_UNIMULTICAST:
779 advance = decode_prefix4(tptr, buf, sizeof(buf));
780 printf("\n\t %s", buf);
781 break;
782 case SAFNUM_LABUNICAST:
783 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
784 printf("\n\t %s", buf);
785 break;
786 case SAFNUM_VPNUNICAST:
787 case SAFNUM_VPNMULTICAST:
788 case SAFNUM_VPNUNIMULTICAST:
789 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
790 printf("\n\t %s", buf);
791 break;
792 default:
793 printf("\n\t no SAFI %u decoder",safi);
794 if (!vflag)
795 print_unknown_data(tptr-3,"\n\t ",tlen);
796 advance = 0;
797 tptr = pptr + len;
798 break;
799 }
800 break;
801
802 #ifdef INET6
803 case AFNUM_INET6:
804 switch (safi) {
805 case SAFNUM_UNICAST:
806 case SAFNUM_MULTICAST:
807 case SAFNUM_UNIMULTICAST:
808 advance = decode_prefix6(tptr, buf, sizeof(buf));
809 printf("\n\t %s", buf);
810 break;
811 default:
812 printf("\n\t no SAFI %u decoder",safi);
813 if (!vflag)
814 print_unknown_data(tptr-3,"\n\t ",tlen);
815 advance = 0;
816 tptr = pptr + len;
817 break;
818 }
819 break;
820 #endif
821 default:
822 printf("\n\t no AFI %u decoder",af);
823 if (!vflag)
824 print_unknown_data(tptr-3,"\n\t ",tlen);
825 advance = 0;
826 tptr = pptr + len;
827 break;
828 }
829
830 tptr += advance;
831 }
832 break;
833 case BGPTYPE_EXTD_COMMUNITIES:
834 if (len % 8) {
835 printf("invalid len");
836 break;
837 }
838 while (tlen>0) {
839 u_int8_t extd_comm,extd_comm_type,extd_comm_subtype;
840 extd_comm=*tptr;
841 extd_comm_type=extd_comm&0x3f;
842 extd_comm_subtype=*(tptr+1);
843 switch(extd_comm_type) {
844 case 0:
845 printf("%s%s%s:%u:%s%s",
846 (extd_comm&0x80) ? "vendor-specific: " : "",
847 (extd_comm&0x40) ? "non-transitive:" : "",
848 tok2str(bgp_extd_comm_subtype_values,
849 "unknown",
850 extd_comm_subtype&0x3f),
851 EXTRACT_16BITS(tptr+2),
852 getname(tptr+4),
853 (tlen>8) ? ", " : "");
854 break;
855 case 1:
856 printf("%s%s%s:%s:%u%s",
857 (extd_comm&0x80) ? "vendor-specific: " : "",
858 (extd_comm&0x40) ? "non-transitive:" : "",
859 tok2str(bgp_extd_comm_subtype_values,
860 "unknown",
861 extd_comm_subtype&0x3f),
862 getname(tptr+2),
863 EXTRACT_16BITS(tptr+6),
864 (tlen>8) ? ", " : "");
865 break;
866 case 2:
867 printf("%s%s%s:%u:%u%s",
868 (extd_comm&0x80) ? "vendor-specific: " : "",
869 (extd_comm&0x40) ? "non-transitive:" : "",
870 tok2str(bgp_extd_comm_subtype_values,
871 "unknown",
872 extd_comm_subtype&0x3f),
873 EXTRACT_32BITS(tptr+2),
874 EXTRACT_16BITS(tptr+6),
875 (tlen>8) ? ", " : "");
876 break;
877
878 default:
879 printf("\n\t no typecode %u decoder",
880 extd_comm_type);
881 print_unknown_data(tptr,"\n\t ",8);
882 break;
883 }
884 tlen -=8;
885 tptr +=8;
886 }
887 break;
888
889 default:
890 printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
891 if (!vflag)
892 print_unknown_data(pptr,"\n\t ",len);
893 break;
894 }
895 if (vflag&&len) /* omit zero length attributes*/
896 print_unknown_data(pptr,"\n\t ",len);
897 }
898
899 static void
900 bgp_open_print(const u_char *dat, int length)
901 {
902 struct bgp_open bgpo;
903 struct bgp_opt bgpopt;
904 int hlen;
905 const u_char *opt;
906 int i,cap_type,cap_len;
907
908 TCHECK2(dat[0], BGP_OPEN_SIZE);
909 memcpy(&bgpo, dat, BGP_OPEN_SIZE);
910 hlen = ntohs(bgpo.bgpo_len);
911
912 printf("\n\t Version %d, ", bgpo.bgpo_version);
913 printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
914 printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
915 printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
916 printf("\n\t Optional parameters, length: %u", bgpo.bgpo_optlen);
917
918 /* ugly! */
919 opt = &((const struct bgp_open *)dat)->bgpo_optlen;
920 opt++;
921
922 i = 0;
923 while (i < bgpo.bgpo_optlen) {
924 TCHECK2(opt[i], BGP_OPT_SIZE);
925 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
926 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
927 printf("\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
928 break;
929 }
930
931 printf("\n\t Option %s (%u), length: %u",
932 tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
933 bgpopt.bgpopt_type,
934 bgpopt.bgpopt_len);
935
936 /* now lets decode the options we know*/
937 switch(bgpopt.bgpopt_type) {
938 case BGP_OPT_CAP:
939 cap_type=opt[i+BGP_OPT_SIZE];
940 cap_len=opt[i+BGP_OPT_SIZE+1];
941 printf("\n\t %s, length: %u",
942 tok2str(bgp_capcode_values,"Unknown", cap_type),
943 cap_len);
944 switch(cap_type) {
945 case BGP_CAPCODE_MP:
946 printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
947 tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
948 EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
949 tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
950 opt[i+BGP_OPT_SIZE+5]);
951 break;
952 case BGP_CAPCODE_RR:
953 case BGP_CAPCODE_RR_CISCO:
954 break;
955 default:
956 printf("\n\t\tno decoder for Capability %u",
957 cap_type);
958 break;
959 }
960 break;
961 case BGP_OPT_AUTH:
962 default:
963 printf("\n\t no decoder for option %u",
964 bgpopt.bgpopt_type);
965 break;
966 }
967
968 i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
969 }
970 return;
971 trunc:
972 printf("[|BGP]");
973 }
974
975 static void
976 bgp_update_print(const u_char *dat, int length)
977 {
978 struct bgp bgp;
979 struct bgp_attr bgpa;
980 int hlen;
981 const u_char *p;
982 int len;
983 int i;
984
985 TCHECK2(dat[0], BGP_SIZE);
986 memcpy(&bgp, dat, BGP_SIZE);
987 hlen = ntohs(bgp.bgp_len);
988 p = dat + BGP_SIZE; /*XXX*/
989
990 /* Unfeasible routes */
991 len = EXTRACT_16BITS(p);
992 if (len) {
993 /*
994 * Without keeping state from the original NLRI message,
995 * it's not possible to tell if this a v4 or v6 route,
996 * so only try to decode it if we're not v6 enabled.
997 */
998 #ifdef INET6
999 printf("\n\t Withdrawn routes: %d bytes", len);
1000 #else
1001 char buf[MAXHOSTNAMELEN + 100];
1002
1003 TCHECK2(p[2], len);
1004 i = 2;
1005
1006 printf("\n\t Withdrawn routes:");
1007
1008 while(i < 2 + len) {
1009 i += decode_prefix4(&p[i], buf, sizeof(buf));
1010 printf("\n\t %s", buf);
1011 }
1012 #endif
1013 }
1014 p += 2 + len;
1015
1016 TCHECK2(p[0], 2);
1017 len = EXTRACT_16BITS(p);
1018 if (len) {
1019 /* do something more useful!*/
1020 i = 2;
1021 while (i < 2 + len) {
1022 int alen, aoff;
1023
1024 TCHECK2(p[i], sizeof(bgpa));
1025 memcpy(&bgpa, &p[i], sizeof(bgpa));
1026 alen = bgp_attr_len(&bgpa);
1027 aoff = bgp_attr_off(&bgpa);
1028
1029 printf("\n\t %s (%u), length: %u",
1030 tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1031 bgpa.bgpa_type,
1032 alen);
1033
1034 if (bgpa.bgpa_flags) {
1035 printf(", flags [%s%s%s%s",
1036 bgpa.bgpa_flags & 0x80 ? "O" : "",
1037 bgpa.bgpa_flags & 0x40 ? "T" : "",
1038 bgpa.bgpa_flags & 0x20 ? "P" : "",
1039 bgpa.bgpa_flags & 0x10 ? "E" : "");
1040 if (bgpa.bgpa_flags & 0xf)
1041 printf("+%x", bgpa.bgpa_flags & 0xf);
1042 printf("]: ");
1043 }
1044 bgp_attr_print(&bgpa, &p[i + aoff], alen);
1045 i += aoff + alen;
1046 }
1047 }
1048 p += 2 + len;
1049
1050 if (dat + length > p) {
1051 printf("\n\t Updated routes:");
1052 while (dat + length > p) {
1053 char buf[MAXHOSTNAMELEN + 100];
1054 i = decode_prefix4(p, buf, sizeof(buf));
1055 printf("\n\t %s", buf);
1056 if (i < 0)
1057 break;
1058 p += i;
1059 }
1060 }
1061 return;
1062 trunc:
1063 printf("[|BGP]");
1064 }
1065
1066 static void
1067 bgp_notification_print(const u_char *dat, int length)
1068 {
1069 struct bgp_notification bgpn;
1070 int hlen;
1071
1072 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1073 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1074 hlen = ntohs(bgpn.bgpn_len);
1075
1076 printf(", Error - %s", tok2str(bgp_notify_major_values, "Unknown", bgpn.bgpn_major));
1077
1078 switch (bgpn.bgpn_major) {
1079
1080 case BGP_NOTIFY_MAJOR_MSG:
1081 printf(" subcode %s", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor));
1082 break;
1083 case BGP_NOTIFY_MAJOR_OPEN:
1084 printf(" subcode %s", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor));
1085 break;
1086 case BGP_NOTIFY_MAJOR_UPDATE:
1087 printf(" subcode %s", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor));
1088 break;
1089 default:
1090 break;
1091 }
1092
1093 return;
1094 trunc:
1095 printf("[|BGP]");
1096 }
1097
1098 static void
1099 bgp_route_refresh_print(const u_char *pptr, int len) {
1100
1101 const struct bgp_route_refresh *bgp_route_refresh_header;
1102 bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
1103
1104 printf("\n\t AFI %s (%u), SAFI %s (%u)",
1105 tok2str(bgp_afi_values,"Unknown",
1106 EXTRACT_16BITS(&bgp_route_refresh_header->afi)), /* this stinks but the compiler pads the structure weird */
1107 EXTRACT_16BITS(&bgp_route_refresh_header->afi),
1108 tok2str(bgp_safi_values,"Unknown",
1109 bgp_route_refresh_header->safi),
1110 bgp_route_refresh_header->safi);
1111
1112 if (vflag)
1113 print_unknown_data(pptr,"\n\t ", len);
1114
1115 return;
1116 }
1117
1118 static void
1119 bgp_header_print(const u_char *dat, int length)
1120 {
1121 struct bgp bgp;
1122
1123 TCHECK2(dat[0], BGP_SIZE);
1124 memcpy(&bgp, dat, BGP_SIZE);
1125 printf("\n\t%s Message (%u), length: %u ",
1126 tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
1127 bgp.bgp_type,
1128 length);
1129
1130 switch (bgp.bgp_type) {
1131 case BGP_OPEN:
1132 bgp_open_print(dat, length);
1133 break;
1134 case BGP_UPDATE:
1135 bgp_update_print(dat, length);
1136 break;
1137 case BGP_NOTIFICATION:
1138 bgp_notification_print(dat, length);
1139 break;
1140 case BGP_KEEPALIVE:
1141 break;
1142 case BGP_ROUTE_REFRESH:
1143 bgp_route_refresh_print(dat, length);
1144 break;
1145 default:
1146 /* we have no decoder for the BGP message */
1147 printf("\n\t no Message %u decoder",bgp.bgp_type);
1148 print_unknown_data(dat,"\n\t ",length);
1149 break;
1150 }
1151 return;
1152 trunc:
1153 printf("[|BGP]");
1154 }
1155
1156 void
1157 bgp_print(const u_char *dat, int length)
1158 {
1159 const u_char *p;
1160 const u_char *ep;
1161 const u_char *start;
1162 const u_char marker[] = {
1163 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1164 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1165 };
1166 struct bgp bgp;
1167 u_int16_t hlen;
1168
1169 ep = dat + length;
1170 if (snapend < dat + length)
1171 ep = snapend;
1172
1173 printf(": BGP");
1174
1175 p = dat;
1176 start = p;
1177 while (p < snapend) {
1178 if (!TTEST2(p[0], 1))
1179 break;
1180 if (p[0] != 0xff) {
1181 p++;
1182 continue;
1183 }
1184
1185 if (!TTEST2(p[0], sizeof(marker)))
1186 break;
1187 if (memcmp(p, marker, sizeof(marker)) != 0) {
1188 p++;
1189 continue;
1190 }
1191
1192 /* found BGP header */
1193 TCHECK2(p[0], BGP_SIZE); /*XXX*/
1194 memcpy(&bgp, p, BGP_SIZE);
1195
1196 if (start != p)
1197 printf(" [|BGP]");
1198
1199 hlen = ntohs(bgp.bgp_len);
1200
1201 if (TTEST2(p[0], hlen)) {
1202 bgp_header_print(p, hlen);
1203 p += hlen;
1204 start = p;
1205 } else {
1206 printf("[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
1207 break;
1208 }
1209 }
1210
1211 return;
1212
1213 trunc:
1214 printf(" [|BGP]");
1215 }
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226