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