1 /* $OpenBSD: print-bgp.c,v 1.4 2002/09/03 12:21:12 ho Exp $ */ 2 3 /* 4 * Copyright (C) 1999 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifndef lint 33 static const char rcsid[] = 34 "@(#) $TCPDUMP: /tcpdump/master/tcpdump/print-bgp.c,v 1.27 2001/10/18 09:52:17 itojun Exp $"; 35 #endif 36 37 #include <sys/param.h> 38 #include <sys/time.h> 39 #include <sys/types.h> 40 #include <sys/socket.h> 41 42 #include <netinet/in.h> 43 44 #include <errno.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <netdb.h> 48 49 #include "interface.h" 50 #include "addrtoname.h" 51 #include "extract.h" 52 53 struct bgp { 54 u_int8_t bgp_marker[16]; 55 u_int16_t bgp_len; 56 u_int8_t bgp_type; 57 }; 58 #define BGP_SIZE 19 /* unaligned */ 59 60 #define BGP_OPEN 1 61 #define BGP_UPDATE 2 62 #define BGP_NOTIFICATION 3 63 #define BGP_KEEPALIVE 4 64 65 struct bgp_open { 66 u_int8_t bgpo_marker[16]; 67 u_int16_t bgpo_len; 68 u_int8_t bgpo_type; 69 u_int8_t bgpo_version; 70 u_int16_t bgpo_myas; 71 u_int16_t bgpo_holdtime; 72 u_int32_t bgpo_id; 73 u_int8_t bgpo_optlen; 74 /* options should follow */ 75 }; 76 #define BGP_OPEN_SIZE 29 /* unaligned */ 77 78 struct bgp_opt { 79 u_int8_t bgpopt_type; 80 u_int8_t bgpopt_len; 81 /* variable length */ 82 }; 83 #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ 84 85 struct bgp_notification { 86 u_int8_t bgpn_marker[16]; 87 u_int16_t bgpn_len; 88 u_int8_t bgpn_type; 89 u_int8_t bgpn_major; 90 u_int8_t bgpn_minor; 91 /* data should follow */ 92 }; 93 #define BGP_NOTIFICATION_SIZE 21 /* unaligned */ 94 95 struct bgp_attr { 96 u_int8_t bgpa_flags; 97 u_int8_t bgpa_type; 98 union { 99 u_int8_t len; 100 u_int16_t elen; 101 } bgpa_len; 102 #define bgp_attr_len(p) \ 103 (((p)->bgpa_flags & 0x10) ? \ 104 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len) 105 #define bgp_attr_off(p) \ 106 (((p)->bgpa_flags & 0x10) ? 4 : 3) 107 }; 108 109 #define BGPTYPE_ORIGIN 1 110 #define BGPTYPE_AS_PATH 2 111 #define BGPTYPE_NEXT_HOP 3 112 #define BGPTYPE_MULTI_EXIT_DISC 4 113 #define BGPTYPE_LOCAL_PREF 5 114 #define BGPTYPE_ATOMIC_AGGREGATE 6 115 #define BGPTYPE_AGGREGATOR 7 116 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ 117 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */ 118 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ 119 #define BGPTYPE_DPA 11 /* work in progress */ 120 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ 121 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */ 122 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ 123 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ 124 125 126 static const char *bgptype[] = { 127 NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", 128 }; 129 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) 130 131 static const char *bgpopt_type[] = { 132 NULL, "Authentication Information", "Capabilities Advertisement", 133 }; 134 #define bgp_opttype(x) \ 135 num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x)) 136 137 static const char *bgpnotify_major[] = { 138 NULL, "Message Header Error", 139 "OPEN Message Error", "UPDATE Message Error", 140 "Hold Timer Expired", "Finite State Machine Error", 141 "Cease", 142 }; 143 #define bgp_notify_major(x) \ 144 num_or_str(bgpnotify_major, \ 145 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x)) 146 147 static const char *bgpnotify_minor_1[] = { 148 NULL, "Connection Not Synchronized", 149 "Bad Message Length", "Bad Message Type", 150 }; 151 152 static const char *bgpnotify_minor_2[] = { 153 NULL, "Unsupported Version Number", 154 "Bad Peer AS", "Bad BGP Identifier", 155 "Unsupported Optional Parameter", "Authentication Failure", 156 "Unacceptable Hold Time", 157 }; 158 159 static const char *bgpnotify_minor_3[] = { 160 NULL, "Malformed Attribute List", 161 "Unrecognized Well-known Attribute", "Missing Well-known Attribute", 162 "Attribute Flags Error", "Attribute Length Error", 163 "Invalid ORIGIN Attribute", "AS Routing Loop", 164 "Invalid NEXT_HOP Attribute", "Optional Attribute Error", 165 "Invalid Network Field", "Malformed AS_PATH", 166 }; 167 168 static const char **bgpnotify_minor[] = { 169 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3, 170 }; 171 static const int bgpnotify_minor_siz[] = { 172 0, sizeof(bgpnotify_minor_1)/sizeof(bgpnotify_minor_1[0]), 173 sizeof(bgpnotify_minor_2)/sizeof(bgpnotify_minor_2[0]), 174 sizeof(bgpnotify_minor_3)/sizeof(bgpnotify_minor_3[0]), 175 }; 176 177 static const char *bgpattr_origin[] = { 178 "IGP", "EGP", "INCOMPLETE", 179 }; 180 #define bgp_attr_origin(x) \ 181 num_or_str(bgpattr_origin, \ 182 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x)) 183 184 static const char *bgpattr_type[] = { 185 NULL, "ORIGIN", "AS_PATH", "NEXT_HOP", 186 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR", 187 "COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA", 188 "ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI", 189 }; 190 #define bgp_attr_type(x) \ 191 num_or_str(bgpattr_type, \ 192 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x)) 193 194 /* Subsequent address family identifier, RFC2283 section 7 */ 195 static const char *bgpattr_nlri_safi[] = { 196 "Reserved", "Unicast", "Multicast", "Unicast+Multicast", 197 }; 198 #define bgp_attr_nlri_safi(x) \ 199 num_or_str(bgpattr_nlri_safi, \ 200 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x)) 201 202 /* well-known community */ 203 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01 204 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02 205 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 206 207 /* RFC1700 address family numbers */ 208 #define AFNUM_INET 1 209 #define AFNUM_INET6 2 210 #define AFNUM_NSAP 3 211 #define AFNUM_HDLC 4 212 #define AFNUM_BBN1822 5 213 #define AFNUM_802 6 214 #define AFNUM_E163 7 215 #define AFNUM_E164 8 216 #define AFNUM_F69 9 217 #define AFNUM_X121 10 218 #define AFNUM_IPX 11 219 #define AFNUM_ATALK 12 220 #define AFNUM_DECNET 13 221 #define AFNUM_BANYAN 14 222 #define AFNUM_E164NSAP 15 223 224 static const char *afnumber[] = { 225 "Reserved", "IPv4", "IPv6", "NSAP", "HDLC", 226 "BBN 1822", "802", "E.163", "E.164", "F.69", 227 "X.121", "IPX", "Appletalk", "Decnet IV", "Banyan Vines", 228 "E.164 with NSAP subaddress", 229 }; 230 #define af_name(x) \ 231 (((x) == 65535) ? afnumber[0] : \ 232 num_or_str(afnumber, \ 233 sizeof(afnumber)/sizeof(afnumber[0]), (x))) 234 235 236 static const char * 237 num_or_str(const char **table, size_t siz, int value) 238 { 239 static char buf[20]; 240 if (value < 0 || siz <= value || table[value] == NULL) { 241 snprintf(buf, sizeof(buf), "#%d", value); 242 return buf; 243 } else 244 return table[value]; 245 } 246 247 static const char * 248 bgp_notify_minor(int major, int minor) 249 { 250 static const char **table; 251 int siz; 252 static char buf[20]; 253 const char *p; 254 255 if (0 <= major 256 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0]) 257 && bgpnotify_minor[major]) { 258 table = bgpnotify_minor[major]; 259 siz = bgpnotify_minor_siz[major]; 260 if (0 <= minor && minor < siz && table[minor]) 261 p = table[minor]; 262 else 263 p = NULL; 264 } else 265 p = NULL; 266 if (p == NULL) { 267 snprintf(buf, sizeof(buf), "#%d", minor); 268 return buf; 269 } else 270 return p; 271 } 272 273 static int 274 decode_prefix4(const u_char *pd, char *buf, u_int buflen) 275 { 276 struct in_addr addr; 277 u_int plen; 278 279 plen = pd[0]; 280 if (plen < 0 || 32 < plen) 281 return -1; 282 283 memset(&addr, 0, sizeof(addr)); 284 memcpy(&addr, &pd[1], (plen + 7) / 8); 285 if (plen % 8) { 286 ((u_char *)&addr)[(plen + 7) / 8 - 1] &= 287 ((0xff00 >> (plen % 8)) & 0xff); 288 } 289 snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen); 290 return 1 + (plen + 7) / 8; 291 } 292 293 #ifdef INET6 294 static int 295 decode_prefix6(const u_char *pd, char *buf, u_int buflen) 296 { 297 struct in6_addr addr; 298 u_int plen; 299 300 plen = pd[0]; 301 if (plen < 0 || 128 < plen) 302 return -1; 303 304 memset(&addr, 0, sizeof(addr)); 305 memcpy(&addr, &pd[1], (plen + 7) / 8); 306 if (plen % 8) { 307 addr.s6_addr[(plen + 7) / 8 - 1] &= 308 ((0xff00 >> (plen % 8)) & 0xff); 309 } 310 snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen); 311 return 1 + (plen + 7) / 8; 312 } 313 #endif 314 315 static void 316 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len) 317 { 318 int i; 319 u_int16_t af; 320 u_int8_t safi, snpa; 321 int advance; 322 int tlen; 323 const u_char *p; 324 char buf[MAXHOSTNAMELEN + 100]; 325 326 p = dat; 327 328 switch (attr->bgpa_type) { 329 case BGPTYPE_ORIGIN: 330 if (len != 1) 331 printf(" invalid len"); 332 else 333 printf(" %s", bgp_attr_origin(p[0])); 334 break; 335 case BGPTYPE_AS_PATH: 336 if (len % 2) { 337 printf(" invalid len"); 338 break; 339 } 340 while (p < dat + len) { 341 /* 342 * under RFC1965, p[0] means: 343 * 1: AS_SET 2: AS_SEQUENCE 344 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE 345 */ 346 printf(" "); 347 if (p[0] == 3 || p[0] == 4) 348 printf("confed"); 349 printf("%s", (p[0] & 1) ? "{" : ""); 350 for (i = 0; i < p[1] * 2; i += 2) { 351 printf("%s%u", i == 0 ? "" : " ", 352 EXTRACT_16BITS(&p[2 + i])); 353 } 354 printf("%s", (p[0] & 1) ? "}" : ""); 355 p += 2 + p[1] * 2; 356 } 357 break; 358 case BGPTYPE_NEXT_HOP: 359 if (len != 4) 360 printf(" invalid len"); 361 else 362 printf(" %s", getname(p)); 363 break; 364 case BGPTYPE_MULTI_EXIT_DISC: 365 case BGPTYPE_LOCAL_PREF: 366 if (len != 4) 367 printf(" invalid len"); 368 else 369 printf(" %u", EXTRACT_32BITS(p)); 370 break; 371 case BGPTYPE_ATOMIC_AGGREGATE: 372 if (len != 0) 373 printf(" invalid len"); 374 break; 375 case BGPTYPE_AGGREGATOR: 376 if (len != 6) { 377 printf(" invalid len"); 378 break; 379 } 380 printf(" AS #%u, origin %s", EXTRACT_16BITS(p), 381 getname(p + 2)); 382 break; 383 case BGPTYPE_COMMUNITIES: 384 if (len % 4) { 385 printf(" invalid len"); 386 break; 387 } 388 for (i = 0; i < len; i += 4) { 389 u_int32_t comm; 390 comm = EXTRACT_32BITS(&p[i]); 391 switch (comm) { 392 case BGP_COMMUNITY_NO_EXPORT: 393 printf(" NO_EXPORT"); 394 break; 395 case BGP_COMMUNITY_NO_ADVERT: 396 printf(" NO_ADVERTISE"); 397 break; 398 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: 399 printf(" NO_EXPORT_SUBCONFED"); 400 break; 401 default: 402 printf(" (AS #%d value 0x%04x)", 403 (comm >> 16) & 0xffff, comm & 0xffff); 404 break; 405 } 406 } 407 break; 408 case BGPTYPE_MP_REACH_NLRI: 409 af = EXTRACT_16BITS(p); 410 safi = p[2]; 411 if (safi >= 128) 412 printf(" %s vendor specific,", af_name(af)); 413 else { 414 printf(" %s %s,", af_name(af), 415 bgp_attr_nlri_safi(safi)); 416 } 417 p += 3; 418 419 if (af == AFNUM_INET) 420 ; 421 #ifdef INET6 422 else if (af == AFNUM_INET6) 423 ; 424 #endif 425 else 426 break; 427 428 tlen = p[0]; 429 if (tlen) { 430 printf(" nexthop"); 431 i = 0; 432 while (i < tlen) { 433 switch (af) { 434 case AFNUM_INET: 435 printf(" %s", getname(p + 1 + i)); 436 i += sizeof(struct in_addr); 437 break; 438 #ifdef INET6 439 case AFNUM_INET6: 440 printf(" %s", getname6(p + 1 + i)); 441 i += sizeof(struct in6_addr); 442 break; 443 #endif 444 default: 445 printf(" (unknown af)"); 446 i = tlen; /*exit loop*/ 447 break; 448 } 449 } 450 printf(","); 451 } 452 p += 1 + tlen; 453 454 snpa = p[0]; 455 p++; 456 if (snpa) { 457 printf(" %u snpa", snpa); 458 for (/*nothing*/; snpa > 0; snpa--) { 459 printf("(%d bytes)", p[0]); 460 p += p[0] + 1; 461 } 462 printf(","); 463 } 464 465 printf(" NLRI"); 466 while (len - (p - dat) > 0) { 467 switch (af) { 468 case AFNUM_INET: 469 advance = decode_prefix4(p, buf, sizeof(buf)); 470 printf(" %s", buf); 471 break; 472 #ifdef INET6 473 case AFNUM_INET6: 474 advance = decode_prefix6(p, buf, sizeof(buf)); 475 printf(" %s", buf); 476 break; 477 #endif 478 default: 479 printf(" (unknown af)"); 480 advance = 0; 481 p = dat + len; 482 break; 483 } 484 485 p += advance; 486 } 487 488 break; 489 490 case BGPTYPE_MP_UNREACH_NLRI: 491 af = EXTRACT_16BITS(p); 492 safi = p[2]; 493 if (safi >= 128) 494 printf(" %s vendor specific,", af_name(af)); 495 else { 496 printf(" %s %s,", af_name(af), 497 bgp_attr_nlri_safi(safi)); 498 } 499 p += 3; 500 501 printf(" Withdraw"); 502 while (len - (p - dat) > 0) { 503 switch (af) { 504 case AFNUM_INET: 505 advance = decode_prefix4(p, buf, sizeof(buf)); 506 printf(" %s", buf); 507 break; 508 #ifdef INET6 509 case AFNUM_INET6: 510 advance = decode_prefix6(p, buf, sizeof(buf)); 511 printf(" %s", buf); 512 break; 513 #endif 514 default: 515 printf(" (unknown af)"); 516 advance = 0; 517 p = dat + len; 518 break; 519 } 520 521 p += advance; 522 } 523 break; 524 default: 525 break; 526 } 527 } 528 529 static void 530 bgp_open_print(const u_char *dat, int length) 531 { 532 struct bgp_open bgpo; 533 struct bgp_opt bgpopt; 534 int hlen; 535 const u_char *opt; 536 int i; 537 538 TCHECK2(dat[0], BGP_OPEN_SIZE); 539 memcpy(&bgpo, dat, BGP_OPEN_SIZE); 540 hlen = ntohs(bgpo.bgpo_len); 541 542 printf(": Version %d,", bgpo.bgpo_version); 543 printf(" AS #%u,", ntohs(bgpo.bgpo_myas)); 544 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)); 545 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id)); 546 printf(" Option length %u", bgpo.bgpo_optlen); 547 548 /* ugly! */ 549 opt = &((const struct bgp_open *)dat)->bgpo_optlen; 550 opt++; 551 552 i = 0; 553 while (i < bgpo.bgpo_optlen) { 554 TCHECK2(opt[i], BGP_OPT_SIZE); 555 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); 556 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { 557 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); 558 break; 559 } 560 561 printf(" (option %s, len=%d)", bgp_opttype(bgpopt.bgpopt_type), 562 bgpopt.bgpopt_len); 563 i += BGP_OPT_SIZE + bgpopt.bgpopt_len; 564 } 565 return; 566 trunc: 567 printf("[|BGP]"); 568 } 569 570 static void 571 bgp_update_print(const u_char *dat, int length) 572 { 573 struct bgp bgp; 574 struct bgp_attr bgpa; 575 int hlen; 576 const u_char *p; 577 int len; 578 int i; 579 int newline; 580 581 TCHECK2(dat[0], BGP_SIZE); 582 memcpy(&bgp, dat, BGP_SIZE); 583 hlen = ntohs(bgp.bgp_len); 584 p = dat + BGP_SIZE; /*XXX*/ 585 printf(":"); 586 587 /* Unfeasible routes */ 588 len = EXTRACT_16BITS(p); 589 if (len) { 590 /* 591 * Without keeping state from the original NLRI message, 592 * it's not possible to tell if this a v4 or v6 route, 593 * so only try to decode it if we're not v6 enabled. 594 */ 595 #ifdef INET6 596 printf(" (Withdrawn routes: %d bytes)", len); 597 #else 598 char buf[MAXHOSTNAMELEN + 100]; 599 600 TCHECK2(p[2], len); 601 i = 2; 602 603 printf(" (Withdrawn routes:"); 604 605 while(i < 2 + len) { 606 i += decode_prefix4(&p[i], buf, sizeof(buf)); 607 printf(" %s", buf); 608 } 609 printf(")\n"); 610 #endif 611 } 612 p += 2 + len; 613 614 TCHECK2(p[0], 2); 615 len = EXTRACT_16BITS(p); 616 if (len) { 617 /* do something more useful!*/ 618 i = 2; 619 printf(" (Path attributes:"); /* ) */ 620 newline = 0; 621 while (i < 2 + len) { 622 int alen, aoff; 623 624 TCHECK2(p[i], sizeof(bgpa)); 625 memcpy(&bgpa, &p[i], sizeof(bgpa)); 626 alen = bgp_attr_len(&bgpa); 627 aoff = bgp_attr_off(&bgpa); 628 629 if (vflag && newline) 630 printf("\n\t\t"); 631 else 632 printf(" "); 633 printf("("); /* ) */ 634 printf("%s", bgp_attr_type(bgpa.bgpa_type)); 635 if (bgpa.bgpa_flags) { 636 printf("[%s%s%s%s", 637 bgpa.bgpa_flags & 0x80 ? "O" : "", 638 bgpa.bgpa_flags & 0x40 ? "T" : "", 639 bgpa.bgpa_flags & 0x20 ? "P" : "", 640 bgpa.bgpa_flags & 0x10 ? "E" : ""); 641 if (bgpa.bgpa_flags & 0xf) 642 printf("+%x", bgpa.bgpa_flags & 0xf); 643 printf("]"); 644 } 645 646 bgp_attr_print(&bgpa, &p[i + aoff], alen); 647 newline = 1; 648 649 /* ( */ 650 printf(")"); 651 652 i += aoff + alen; 653 } 654 655 /* ( */ 656 printf(")"); 657 } 658 p += 2 + len; 659 660 if (len && dat + length > p) 661 printf("\n\t\t"); 662 if (dat + length > p) { 663 printf("(NLRI:"); /* ) */ 664 while (dat + length > p) { 665 char buf[MAXHOSTNAMELEN + 100]; 666 i = decode_prefix4(p, buf, sizeof(buf)); 667 printf(" %s", buf); 668 if (i < 0) 669 break; 670 p += i; 671 } 672 673 /* ( */ 674 printf(")"); 675 } 676 return; 677 trunc: 678 printf("[|BGP]"); 679 } 680 681 static void 682 bgp_notification_print(const u_char *dat, int length) 683 { 684 struct bgp_notification bgpn; 685 int hlen; 686 687 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); 688 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); 689 hlen = ntohs(bgpn.bgpn_len); 690 691 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)); 692 printf(" subcode %s", 693 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); 694 return; 695 trunc: 696 printf("[|BGP]"); 697 } 698 699 static void 700 bgp_header_print(const u_char *dat, int length) 701 { 702 struct bgp bgp; 703 704 TCHECK2(dat[0], BGP_SIZE); 705 memcpy(&bgp, dat, BGP_SIZE); 706 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */ 707 708 switch (bgp.bgp_type) { 709 case BGP_OPEN: 710 bgp_open_print(dat, length); 711 break; 712 case BGP_UPDATE: 713 bgp_update_print(dat, length); 714 break; 715 case BGP_NOTIFICATION: 716 bgp_notification_print(dat, length); 717 break; 718 } 719 720 /* ( */ 721 printf(")"); 722 return; 723 trunc: 724 printf("[|BGP]"); 725 } 726 727 void 728 bgp_print(const u_char *dat, int length) 729 { 730 const u_char *p; 731 const u_char *ep; 732 const u_char *start; 733 const u_char marker[] = { 734 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 735 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 736 }; 737 struct bgp bgp; 738 u_int16_t hlen; 739 int newline; 740 741 ep = dat + length; 742 if (snapend < dat + length) 743 ep = snapend; 744 745 printf(": BGP"); 746 747 p = dat; 748 newline = 0; 749 start = p; 750 while (p < snapend) { 751 if (!TTEST2(p[0], 1)) 752 break; 753 if (p[0] != 0xff) { 754 p++; 755 continue; 756 } 757 758 if (!TTEST2(p[0], sizeof(marker))) 759 break; 760 if (memcmp(p, marker, sizeof(marker)) != 0) { 761 p++; 762 continue; 763 } 764 765 /* found BGP header */ 766 TCHECK2(p[0], BGP_SIZE); /*XXX*/ 767 memcpy(&bgp, p, BGP_SIZE); 768 769 if (start != p) 770 printf(" [|BGP]"); 771 772 hlen = ntohs(bgp.bgp_len); 773 if (vflag && newline) 774 printf("\n\t"); 775 else 776 printf(" "); 777 if (TTEST2(p[0], hlen)) { 778 bgp_header_print(p, hlen); 779 newline = 1; 780 p += hlen; 781 start = p; 782 } else { 783 printf("[|BGP %s]", bgp_type(bgp.bgp_type)); 784 break; 785 } 786 } 787 788 return; 789 790 trunc: 791 printf(" [|BGP]"); 792 } 793