]> The Tcpdump Group git mirrors - tcpdump/blob - print-bgp.c
HP-UX 10.20 build fix <http://www.sics.se/~assar/tcpdump_patches/13>
[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 #ifdef INET6
46 #include <netinet/ip6.h>
47 #endif
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
465 memcpy(&bgp, dat, sizeof(bgp));
466 hlen = ntohs(bgp.bgp_len);
467 p = dat + BGP_SIZE; /*XXX*/
468 printf(":");
469
470 /* Unfeasible routes */
471 len = ntohs(*(u_int16_t *)p);
472 if (len) {
473 printf(" (Withdrawn routes: %d bytes)", len);
474 }
475 p += 2 + len;
476
477 len = ntohs(*(u_int16_t *)p);
478 if (len) {
479 /* do something more useful!*/
480 i = 2;
481 printf(" (Path attributes:"); /* ) */
482 while (i < 2 + len) {
483 int alen, aoff;
484
485 memcpy(&bgpa, &p[i], sizeof(bgpa));
486 alen = bgp_attr_len(&bgpa);
487 aoff = bgp_attr_off(&bgpa);
488
489 printf(" ("); /* ) */
490 printf("%s", bgp_attr_type(bgpa.bgpa_type));
491 if (bgpa.bgpa_flags) {
492 printf("[%s%s%s%s]",
493 bgpa.bgpa_flags & 0x80 ? "O" : "",
494 bgpa.bgpa_flags & 0x40 ? "T" : "",
495 bgpa.bgpa_flags & 0x20 ? "P" : "",
496 bgpa.bgpa_flags & 0x00 ? "E" : "");
497 }
498
499 bgp_attr_print(&bgpa, &p[i + aoff], alen);
500
501 #if 0
502 default:
503 proto_tree_add_text(subtree2, p - pd + i + aoff, alen,
504 "Unknown (%d bytes)", alen);
505 break;
506 }
507 #endif
508
509 /* ( */
510 printf(")");
511
512 i += aoff + alen;
513 }
514
515 /* ( */
516 printf(")");
517 }
518 p += 2 + len;
519
520 }
521
522 static void
523 bgp_notification_print(const u_char *dat, int length)
524 {
525 struct bgp_notification bgpn;
526 int hlen;
527
528 memcpy(&bgpn, dat, sizeof(bgpn));
529 hlen = ntohs(bgpn.bgpn_len);
530
531 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major));
532 printf(" subcode %s",
533 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor));
534 }
535
536 static void
537 bgp_header_print(const u_char *dat, int length, int newline)
538 {
539 struct bgp bgp;
540
541 memcpy(&bgp, dat, sizeof(bgp));
542 printf(newline ? "\n\t" : " ");
543 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */
544
545 switch (bgp.bgp_type) {
546 case BGP_OPEN:
547 bgp_open_print(dat, length);
548 break;
549 case BGP_UPDATE:
550 bgp_update_print(dat, length);
551 break;
552 case BGP_NOTIFICATION:
553 bgp_notification_print(dat, length);
554 break;
555 }
556
557 /* ( */
558 printf(")");
559 }
560
561 void
562 bgp_print(const u_char *dat, int length)
563 {
564 const u_char *p;
565 const u_char *ep;
566 const u_char marker[] = {
567 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
568 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
569 };
570 struct bgp bgp;
571 u_int16_t hlen;
572 int newline;
573
574 ep = dat + length;
575 if (snapend < dat + length)
576 ep = snapend;
577
578 printf(": BGP");
579
580 p = dat;
581 newline = 0;
582 while (p < snapend) {
583 if (!TTEST2(p[0], 1))
584 break;
585 if (p[0] != 0xff) {
586 p++;
587 continue;
588 }
589
590 if (!TTEST2(p[0], sizeof(marker)))
591 break;
592 if (memcmp(p, marker, sizeof(marker)) != 0) {
593 p++;
594 continue;
595 }
596
597 /* found BGP header */
598 TCHECK2(p[0], BGP_SIZE); /*XXX*/
599 memcpy(&bgp, p, sizeof(bgp));
600
601 hlen = ntohs(bgp.bgp_len);
602 if (TTEST2(p[0], hlen)) {
603 bgp_header_print(p, hlen, vflag ? newline : 0);
604 newline = 1;
605 p += hlen;
606 } else {
607 printf(" [|BGP %s]", bgp_type(bgp.bgp_type));
608 break;
609 }
610 }
611
612 return;
613
614 trunc:
615 printf(" [|BGP]");
616 }