]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
Bring in KAME IPv6 tcpdump. replaces esp/ah/isakmp decoder.
[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 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/ip_var.h>
39 #include <netinet/udp.h>
40 #include <netinet/udp_var.h>
41
42 #include <errno.h>
43 #include <stdio.h>
44
45 #include <netinet/ip6.h>
46
47 #include "route6d.h"
48 #include "interface.h"
49 #include "addrtoname.h"
50
51 struct bgp {
52 u_int8_t bgp_marker[16];
53 u_int16_t bgp_len;
54 u_int8_t bgp_type;
55 };
56 #define BGP_SIZE 19 /* unaligned */
57
58 #define BGP_OPEN 1
59 #define BGP_UPDATE 2
60 #define BGP_NOTIFICATION 3
61 #define BGP_KEEPALIVE 4
62
63 struct bgp_open {
64 u_int8_t bgpo_marker[16];
65 u_int16_t bgpo_len;
66 u_int8_t bgpo_type;
67 u_int8_t bgpo_version;
68 u_int16_t bgpo_myas;
69 u_int16_t bgpo_holdtime;
70 u_int32_t bgpo_id;
71 u_int8_t bgpo_optlen;
72 /* options should follow */
73 };
74
75 struct bgp_notification {
76 u_int8_t bgpn_marker[16];
77 u_int16_t bgpn_len;
78 u_int8_t bgpn_type;
79 u_int8_t bgpn_major;
80 u_int8_t bgpn_minor;
81 /* data should follow */
82 };
83
84 struct bgp_attr {
85 u_int8_t bgpa_flags;
86 u_int8_t bgpa_type;
87 union {
88 u_int8_t len;
89 u_int16_t elen;
90 } bgpa_len;
91 #define bgp_attr_len(p) \
92 (((p)->bgpa_flags & 0x10) ? \
93 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len)
94 #define bgp_attr_off(p) \
95 (((p)->bgpa_flags & 0x10) ? 4 : 3)
96 };
97
98 #define BGPTYPE_ORIGIN 1
99 #define BGPTYPE_AS_PATH 2
100 #define BGPTYPE_NEXT_HOP 3
101 #define BGPTYPE_MULTI_EXIT_DISC 4
102 #define BGPTYPE_LOCAL_PREF 5
103 #define BGPTYPE_ATOMIC_AGGREGATE 6
104 #define BGPTYPE_AGGREGATOR 7
105 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
106 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
107
108
109 static const char *bgptype[] = {
110 NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE",
111 };
112 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x))
113
114 static const char *bgpnotify_major[] = {
115 NULL, "Message Header Error",
116 "OPEN Message Error", "UPDATE Message Error",
117 "Hold Timer Expired", "Finite State Machine Error",
118 "Cease",
119 };
120 #define bgp_notify_major(x) \
121 num_or_str(bgpnotify_major, \
122 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x))
123
124 static const char *bgpnotify_minor_1[] = {
125 NULL, "Connection Not Synchronized",
126 "Bad Message Length", "Bad Message Type",
127 };
128
129 static const char *bgpnotify_minor_2[] = {
130 NULL, "Unsupported Version Number",
131 "Bad Peer AS", "Bad BGP Identifier",
132 "Unsupported Optional Parameter", "Authentication Failure",
133 "Unacceptable Hold Time",
134 };
135
136 static const char *bgpnotify_minor_3[] = {
137 NULL, "Malformed Attribute List",
138 "Unrecognized Well-known Attribute", "Missing Well-known Attribute",
139 "Attribute Flags Error", "Attribute Length Error",
140 "Invalid ORIGIN Attribute", "AS Routing Loop",
141 "Invalid NEXT_HOP Attribute", "Optional Attribute Error",
142 "Invalid Network Field", "Malformed AS_PATH",
143 };
144
145 static const char **bgpnotify_minor[] = {
146 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3,
147 };
148 static const int bgpnotify_minor_siz[] = {
149 0, sizeof(bgpnotify_minor_1)/sizeof(bgpnotify_minor_1[0]),
150 sizeof(bgpnotify_minor_2)/sizeof(bgpnotify_minor_2[0]),
151 sizeof(bgpnotify_minor_3)/sizeof(bgpnotify_minor_3[0]),
152 };
153
154 static const char *bgpattr_origin[] = {
155 "IGP", "EGP", "INCOMPLETE",
156 };
157 #define bgp_attr_origin(x) \
158 num_or_str(bgpattr_origin, \
159 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x))
160
161 static const char *bgpattr_type[] = {
162 NULL, "ORIGIN", "AS_PATH", "NEXT_HOP",
163 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR",
164 NULL, NULL, NULL, NULL,
165 NULL, NULL, "MP_REACH_NLRI", "MP_UNREACH_NLRI",
166 };
167 #define bgp_attr_type(x) \
168 num_or_str(bgpattr_type, \
169 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x))
170
171 /* Subsequent address family identifier, RFC2283 section 7 */
172 static const char *bgpattr_nlri_safi[] = {
173 "Reserved", "Unicast", "Multicast", "Unicast+Multicast",
174 };
175 #define bgp_attr_nlri_safi(x) \
176 num_or_str(bgpattr_nlri_safi, \
177 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x))
178
179 /* RFC1700 address family numbers */
180 #define AFNUM_INET 1
181 #define AFNUM_INET6 2
182 #define AFNUM_NSAP 3
183 #define AFNUM_HDLC 4
184 #define AFNUM_BBN1822 5
185 #define AFNUM_802 6
186 #define AFNUM_E163 7
187 #define AFNUM_E164 8
188 #define AFNUM_F69 9
189 #define AFNUM_X121 10
190 #define AFNUM_IPX 11
191 #define AFNUM_ATALK 12
192 #define AFNUM_DECNET 13
193 #define AFNUM_BANYAN 14
194 #define AFNUM_E164NSAP 15
195
196 static const char *afnumber[] = {
197 "Reserved", "IPv4", "IPv6", "NSAP", "HDLC",
198 "BBN 1822", "802", "E.163", "E.164", "F.69",
199 "X.121", "IPX", "Appletalk", "Decnet IV", "Banyan Vines",
200 "E.164 with NSAP subaddress",
201 };
202 #define af_name(x) \
203 (((x) == 65535) ? afnumber[0] : \
204 num_or_str(afnumber, \
205 sizeof(afnumber)/sizeof(afnumber[0]), (x)))
206
207
208 static const char *
209 num_or_str(const char **table, size_t siz, int value)
210 {
211 static char buf[20];
212 if (value < 0 || siz <= value || table[value] == NULL) {
213 snprintf(buf, sizeof(buf), "#%d", value);
214 return buf;
215 } else
216 return table[value];
217 }
218
219 static const char *
220 bgp_notify_minor(int major, int minor)
221 {
222 static const char **table;
223 int siz;
224 static char buf[20];
225 const char *p;
226
227 if (0 <= major
228 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0])
229 && bgpnotify_minor[major]) {
230 table = bgpnotify_minor[major];
231 siz = bgpnotify_minor_siz[major];
232 if (0 <= minor && minor < siz && table[minor])
233 p = table[minor];
234 else
235 p = NULL;
236 } else
237 p = NULL;
238 if (p == NULL) {
239 snprintf(buf, sizeof(buf), "#%d", minor);
240 return buf;
241 } else
242 return p;
243 }
244
245 static int
246 decode_prefix4(const u_char *pd, char *buf, int buflen)
247 {
248 struct in_addr addr;
249 int plen;
250
251 plen = pd[0];
252 if (plen < 0 || 32 < plen)
253 return -1;
254
255 memset(&addr, 0, sizeof(addr));
256 memcpy(&addr, &pd[1], (plen + 7) / 8);
257 if (plen % 8) {
258 ((u_char *)&addr)[(plen + 7) / 8 - 1] &=
259 ((0xff00 >> (plen % 8)) & 0xff);
260 }
261 snprintf(buf, buflen, "%s/%d", getname((char *)&addr), plen);
262 return 1 + (plen + 7) / 8;
263 }
264
265 #ifdef INET6
266 static int
267 decode_prefix6(const u_char *pd, char *buf, int buflen)
268 {
269 struct in6_addr addr;
270 int plen;
271
272 plen = pd[0];
273 if (plen < 0 || 128 < plen)
274 return -1;
275
276 memset(&addr, 0, sizeof(addr));
277 memcpy(&addr, &pd[1], (plen + 7) / 8);
278 if (plen % 8) {
279 addr.s6_addr[(plen + 7) / 8 - 1] &=
280 ((0xff00 >> (plen % 8)) & 0xff);
281 }
282 snprintf(buf, buflen, "%s/%d", getname6((char *)&addr), plen);
283 return 1 + (plen + 7) / 8;
284 }
285 #endif
286
287 static void
288 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
289 {
290 int i;
291 u_int16_t af;
292 u_int8_t safi, snpa;
293 int advance;
294 int tlen;
295 const char *s;
296 const u_char *p;
297 char buf[256];
298
299 p = dat;
300
301 switch (attr->bgpa_type) {
302 case BGPTYPE_ORIGIN:
303 if (len != 1)
304 printf(" invalid len");
305 else
306 printf(" %s", bgp_attr_origin(p[0]));
307 break;
308 case BGPTYPE_AS_PATH:
309 if (len % 2) {
310 printf(" invalid len");
311 break;
312 }
313 for (i = 0; i < len; i += 2)
314 printf(" %u", ntohs(*(u_int16_t *)&p[i]));
315 break;
316 case BGPTYPE_NEXT_HOP:
317 if (len != 4)
318 printf(" invalid len");
319 else
320 printf(" %s", getname(p));
321 break;
322 case BGPTYPE_MULTI_EXIT_DISC:
323 case BGPTYPE_LOCAL_PREF:
324 if (len != 4)
325 printf(" invalid len");
326 else
327 printf(" %u", (u_int32_t)ntohl(*(u_int32_t *)p));
328 break;
329 case BGPTYPE_ATOMIC_AGGREGATE:
330 if (len != 0)
331 printf(" invalid len");
332 break;
333 case BGPTYPE_AGGREGATOR:
334 if (len != 6) {
335 printf(" invalid len");
336 break;
337 }
338 printf(" AS #%u, origin %s", ntohs(*(u_int16_t *)p),
339 getname(p + 2));
340 break;
341 case BGPTYPE_MP_REACH_NLRI:
342 af = ntohs(*(u_int16_t *)p);
343 safi = p[2];
344 if (safi >= 128)
345 printf(" %s vendor specific,", af_name(af));
346 else {
347 printf(" %s %s,", af_name(af),
348 bgp_attr_nlri_safi(safi));
349 }
350 p += 3;
351
352 if (af == AFNUM_INET)
353 ;
354 #ifdef INET6
355 else if (af == AFNUM_INET6)
356 ;
357 #endif
358 else
359 break;
360
361 tlen = p[0];
362 if (tlen) {
363 printf(" nexthop");
364 if (af == AFNUM_INET)
365 advance = 4;
366 #ifdef INET6
367 else if (af == AFNUM_INET6)
368 advance = 16;
369 #endif
370
371 for (i = 0; i < tlen; i += advance) {
372 if (af == AFNUM_INET)
373 printf(" %s", getname(p + 1 + i));
374 #ifdef INET6
375 else if (af == AFNUM_INET6)
376 printf(" %s", getname6(p + 1 + i));
377 #endif
378 }
379 printf(",");
380 }
381 p += 1 + tlen;
382
383 snpa = p[0];
384 p++;
385 if (snpa) {
386 printf(" %u snpa", snpa);
387 for (/*nothing*/; snpa > 0; snpa--) {
388 printf("(%d bytes)", p[0]);
389 p += p[0] + 1;
390 }
391 printf(",");
392 }
393
394 printf(" NLRI");
395 while (len - (p - dat) > 0) {
396 if (af == AFNUM_INET)
397 advance = decode_prefix4(p, buf, sizeof(buf));
398 #ifdef INET6
399 else if (af == AFNUM_INET6)
400 advance = decode_prefix6(p, buf, sizeof(buf));
401 #endif
402 printf(" %s", buf);
403
404 p += advance;
405 }
406
407 break;
408
409 case BGPTYPE_MP_UNREACH_NLRI:
410 af = ntohs(*(u_int16_t *)p);
411 safi = p[2];
412 if (safi >= 128)
413 printf(" %s vendor specific,", af_name(af));
414 else {
415 printf(" %s %s,", af_name(af),
416 bgp_attr_nlri_safi(safi));
417 }
418 p += 3;
419
420 printf(" Withdraw");
421 while (len - (p - dat) > 0) {
422 if (af == AFNUM_INET)
423 advance = decode_prefix4(p, buf, sizeof(buf));
424 #ifdef INET6
425 else if (af == AFNUM_INET6)
426 advance = decode_prefix6(p, buf, sizeof(buf));
427 #endif
428 printf(" %s", buf);
429
430 p += advance;
431 }
432 break;
433 default:
434 break;
435 }
436 }
437
438 static void
439 bgp_open_print(const u_char *dat, int length)
440 {
441 struct bgp_open bgpo;
442 int hlen;
443
444 memcpy(&bgpo, dat, sizeof(bgpo));
445 hlen = ntohs(bgpo.bgpo_len);
446
447 printf(": Version %d,", bgpo.bgpo_version);
448 printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
449 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
450 printf(" ID %s,", getname((char *)&bgpo.bgpo_id));
451 printf(" Option length %u", bgpo.bgpo_optlen);
452 }
453
454 static void
455 bgp_update_print(const u_char *dat, int length)
456 {
457 struct bgp bgp;
458 struct bgp_attr bgpa;
459 int hlen;
460 const u_char *p;
461 int len;
462 int i, j;
463
464 memcpy(&bgp, dat, sizeof(bgp));
465 hlen = ntohs(bgp.bgp_len);
466 p = dat + BGP_SIZE; /*XXX*/
467 printf(":");
468
469 /* Unfeasible routes */
470 len = ntohs(*(u_int16_t *)p);
471 if (len) {
472 printf(" (Withdrawn routes: %d bytes)", len);
473 }
474 p += 2 + len;
475
476 len = ntohs(*(u_int16_t *)p);
477 if (len) {
478 /* do something more useful!*/
479 i = 2;
480 printf(" (Path attributes:"); /* ) */
481 while (i < 2 + len) {
482 int alen, aoff;
483
484 memcpy(&bgpa, &p[i], sizeof(bgpa));
485 alen = bgp_attr_len(&bgpa);
486 aoff = bgp_attr_off(&bgpa);
487
488 printf(" ("); /* ) */
489 printf("%s", bgp_attr_type(bgpa.bgpa_type));
490 if (bgpa.bgpa_flags) {
491 printf("[%s%s%s%s]",
492 bgpa.bgpa_flags & 0x80 ? "O" : "",
493 bgpa.bgpa_flags & 0x40 ? "T" : "",
494 bgpa.bgpa_flags & 0x20 ? "P" : "",
495 bgpa.bgpa_flags & 0x00 ? "E" : "");
496 }
497
498 bgp_attr_print(&bgpa, &p[i + aoff], alen);
499
500 #if 0
501 default:
502 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
503 "Unknown (%d bytes)", alen);
504 break;
505 }
506 #endif
507
508 /* ( */
509 printf(")");
510
511 i += aoff + alen;
512 }
513
514 /* ( */
515 printf(")");
516 }
517 p += 2 + len;
518
519 }
520
521 static void
522 bgp_notification_print(const u_char *dat, int length)
523 {
524 struct bgp_notification bgpn;
525 int hlen;
526
527 memcpy(&bgpn, dat, sizeof(bgpn));
528 hlen = ntohs(bgpn.bgpn_len);
529
530 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major));
531 printf(" subcode %s",
532 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor));
533 }
534
535 static void
536 bgp_header_print(const u_char *dat, int length, int newline)
537 {
538 struct bgp bgp;
539
540 memcpy(&bgp, dat, sizeof(bgp));
541 printf(newline ? "\n\t" : " ");
542 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */
543
544 switch (bgp.bgp_type) {
545 case BGP_OPEN:
546 bgp_open_print(dat, length);
547 break;
548 case BGP_UPDATE:
549 bgp_update_print(dat, length);
550 break;
551 case BGP_NOTIFICATION:
552 bgp_notification_print(dat, length);
553 break;
554 }
555
556 /* ( */
557 printf(")");
558 }
559
560 void
561 bgp_print(const u_char *dat, int length)
562 {
563 const u_char *p;
564 const u_char *ep;
565 const u_char marker[] = {
566 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
567 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
568 };
569 struct bgp bgp;
570 u_int16_t hlen;
571 int newline;
572
573 ep = dat + length;
574 if (snapend < dat + length)
575 ep = snapend;
576
577 printf(": BGP");
578
579 p = dat;
580 newline = 0;
581 while (p < snapend) {
582 if (!TTEST2(p[0], 1))
583 break;
584 if (p[0] != 0xff) {
585 p++;
586 continue;
587 }
588
589 if (!TTEST2(p[0], sizeof(marker)))
590 break;
591 if (memcmp(p, marker, sizeof(marker)) != 0) {
592 p++;
593 continue;
594 }
595
596 /* found BGP header */
597 TCHECK2(p[0], BGP_SIZE); /*XXX*/
598 memcpy(&bgp, p, sizeof(bgp));
599
600 hlen = ntohs(bgp.bgp_len);
601 if (TTEST2(p[0], hlen)) {
602 bgp_header_print(p, hlen, vflag ? newline : 0);
603 newline = 1;
604 p += hlen;
605 } else {
606 printf(" [|BGP %s]", bgp_type(bgp.bgp_type));
607 break;
608 }
609 }
610
611 return;
612
613 trunc:
614 printf(" [|BGP]");
615 }