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