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