1 /* $OpenBSD: print-bgp.c,v 1.11 2009/01/29 09:46:32 bluhm 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 "@(#) $Id: print-bgp.c,v 1.11 2009/01/29 09:46:32 bluhm 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 #include "afnum.h" 53 54 struct bgp { 55 u_int8_t bgp_marker[16]; 56 u_int16_t bgp_len; 57 u_int8_t bgp_type; 58 }; 59 #define BGP_SIZE 19 /* unaligned */ 60 61 #define BGP_OPEN 1 62 #define BGP_UPDATE 2 63 #define BGP_NOTIFICATION 3 64 #define BGP_KEEPALIVE 4 65 66 struct bgp_open { 67 u_int8_t bgpo_marker[16]; 68 u_int16_t bgpo_len; 69 u_int8_t bgpo_type; 70 u_int8_t bgpo_version; 71 u_int16_t bgpo_myas; 72 u_int16_t bgpo_holdtime; 73 u_int32_t bgpo_id; 74 u_int8_t bgpo_optlen; 75 /* options should follow */ 76 }; 77 #define BGP_OPEN_SIZE 29 /* unaligned */ 78 79 struct bgp_opt { 80 u_int8_t bgpopt_type; 81 u_int8_t bgpopt_len; 82 /* variable length */ 83 }; 84 #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ 85 86 struct bgp_notification { 87 u_int8_t bgpn_marker[16]; 88 u_int16_t bgpn_len; 89 u_int8_t bgpn_type; 90 u_int8_t bgpn_major; 91 u_int8_t bgpn_minor; 92 /* data should follow */ 93 }; 94 #define BGP_NOTIFICATION_SIZE 21 /* unaligned */ 95 96 struct bgp_attr { 97 u_int8_t bgpa_flags; 98 u_int8_t bgpa_type; 99 union { 100 u_int8_t len; 101 u_int16_t elen; 102 } bgpa_len; 103 #define bgp_attr_len(p) \ 104 (((p)->bgpa_flags & 0x10) ? \ 105 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len) 106 #define bgp_attr_off(p) \ 107 (((p)->bgpa_flags & 0x10) ? 4 : 3) 108 }; 109 110 #define BGPTYPE_ORIGIN 1 111 #define BGPTYPE_AS_PATH 2 112 #define BGPTYPE_NEXT_HOP 3 113 #define BGPTYPE_MULTI_EXIT_DISC 4 114 #define BGPTYPE_LOCAL_PREF 5 115 #define BGPTYPE_ATOMIC_AGGREGATE 6 116 #define BGPTYPE_AGGREGATOR 7 117 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ 118 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */ 119 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ 120 #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */ 121 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ 122 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */ 123 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ 124 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ 125 126 #define BGP_MP_NLRI_MINSIZE 3 127 128 static const char *bgptype[] = { 129 NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", 130 }; 131 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) 132 133 static const char *bgpopt_type[] = { 134 NULL, "Authentication Information", "Capabilities Advertisement", 135 }; 136 #define bgp_opttype(x) \ 137 num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x)) 138 139 static const char *bgpnotify_major[] = { 140 NULL, "Message Header Error", 141 "OPEN Message Error", "UPDATE Message Error", 142 "Hold Timer Expired", "Finite State Machine Error", 143 "Cease", 144 }; 145 #define bgp_notify_major(x) \ 146 num_or_str(bgpnotify_major, \ 147 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x)) 148 149 static const char *bgpnotify_minor_1[] = { 150 NULL, "Connection Not Synchronized", 151 "Bad Message Length", "Bad Message Type", 152 }; 153 154 static const char *bgpnotify_minor_2[] = { 155 NULL, "Unsupported Version Number", 156 "Bad Peer AS", "Bad BGP Identifier", 157 "Unsupported Optional Parameter", "Authentication Failure", 158 "Unacceptable Hold Time", 159 }; 160 161 static const char *bgpnotify_minor_3[] = { 162 NULL, "Malformed Attribute List", 163 "Unrecognized Well-known Attribute", "Missing Well-known Attribute", 164 "Attribute Flags Error", "Attribute Length Error", 165 "Invalid ORIGIN Attribute", "AS Routing Loop", 166 "Invalid NEXT_HOP Attribute", "Optional Attribute Error", 167 "Invalid Network Field", "Malformed AS_PATH", 168 }; 169 170 static const char **bgpnotify_minor[] = { 171 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3, 172 }; 173 static const int bgpnotify_minor_siz[] = { 174 0, sizeof(bgpnotify_minor_1)/sizeof(bgpnotify_minor_1[0]), 175 sizeof(bgpnotify_minor_2)/sizeof(bgpnotify_minor_2[0]), 176 sizeof(bgpnotify_minor_3)/sizeof(bgpnotify_minor_3[0]), 177 }; 178 179 static const char *bgpattr_origin[] = { 180 "IGP", "EGP", "INCOMPLETE", 181 }; 182 #define bgp_attr_origin(x) \ 183 num_or_str(bgpattr_origin, \ 184 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x)) 185 186 static const char *bgpattr_type[] = { 187 NULL, "ORIGIN", "AS_PATH", "NEXT_HOP", 188 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR", 189 "COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA", 190 "ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI", 191 }; 192 #define bgp_attr_type(x) \ 193 num_or_str(bgpattr_type, \ 194 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x)) 195 196 /* Subsequent address family identifier, RFC2283 section 7 */ 197 static const char *bgpattr_nlri_safi[] = { 198 "Reserved", "Unicast", "Multicast", "Unicast+Multicast", 199 }; 200 #define bgp_attr_nlri_safi(x) \ 201 num_or_str(bgpattr_nlri_safi, \ 202 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x)) 203 204 /* well-known community */ 205 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01 206 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02 207 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 208 #define BGP_COMMUNITY_NO_PEER 0xffffff04 209 210 static const char *afnumber[] = AFNUM_NAME_STR; 211 #define af_name(x) \ 212 (((x) == 65535) ? afnumber[0] : \ 213 num_or_str(afnumber, \ 214 sizeof(afnumber)/sizeof(afnumber[0]), (x))) 215 216 217 static const char * 218 num_or_str(const char **table, size_t siz, int value) 219 { 220 static char buf[20]; 221 if (value < 0 || siz <= value || table[value] == NULL) { 222 snprintf(buf, sizeof(buf), "#%d", value); 223 return buf; 224 } else 225 return table[value]; 226 } 227 228 static const char * 229 bgp_notify_minor(int major, int minor) 230 { 231 static const char **table; 232 int siz; 233 static char buf[20]; 234 const char *p; 235 236 if (0 <= major 237 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0]) 238 && bgpnotify_minor[major]) { 239 table = bgpnotify_minor[major]; 240 siz = bgpnotify_minor_siz[major]; 241 if (0 <= minor && minor < siz && table[minor]) 242 p = table[minor]; 243 else 244 p = NULL; 245 } else 246 p = NULL; 247 if (p == NULL) { 248 snprintf(buf, sizeof(buf), "#%d", minor); 249 return buf; 250 } else 251 return p; 252 } 253 254 static int 255 decode_prefix4(const u_char *pd, char *buf, u_int buflen) 256 { 257 struct in_addr addr; 258 u_int plen; 259 int n; 260 261 TCHECK(pd[0]); 262 plen = pd[0]; /* 263 * prefix length is in bits; packet only contains 264 * enough bytes of address to contain this many bits 265 */ 266 if (plen < 0 || 32 < plen) 267 return -1; 268 memset(&addr, 0, sizeof(addr)); 269 TCHECK2(pd[1], (plen + 7) / 8); 270 memcpy(&addr, &pd[1], (plen + 7) / 8); 271 if (plen % 8) { 272 ((u_char *)&addr)[(plen + 7) / 8 - 1] &= 273 ((0xff00 >> (plen % 8)) & 0xff); 274 } 275 n = snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen); 276 if (n == -1 || n >= buflen) 277 return -1; 278 279 return 1 + (plen + 7) / 8; 280 281 trunc: 282 return -2; 283 } 284 285 #ifdef INET6 286 static int 287 decode_prefix6(const u_char *pd, char *buf, u_int buflen) 288 { 289 struct in6_addr addr; 290 u_int plen; 291 int n; 292 293 TCHECK(pd[0]); 294 plen = pd[0]; 295 if (plen < 0 || 128 < plen) 296 return -1; 297 298 memset(&addr, 0, sizeof(addr)); 299 TCHECK2(pd[1], (plen + 7) / 8); 300 memcpy(&addr, &pd[1], (plen + 7) / 8); 301 if (plen % 8) { 302 addr.s6_addr[(plen + 7) / 8 - 1] &= 303 ((0xff00 >> (plen % 8)) & 0xff); 304 } 305 306 n = snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen); 307 if (n == -1 || n >= buflen) 308 return -1; 309 310 return 1 + (plen + 7) / 8; 311 312 trunc: 313 return -2; 314 } 315 #endif 316 317 static int 318 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len) 319 { 320 int i; 321 u_int16_t af; 322 u_int8_t safi, snpa; 323 int advance; 324 int tlen; 325 const u_char *p; 326 char buf[MAXHOSTNAMELEN + 100]; 327 328 p = dat; 329 330 switch (attr->bgpa_type) { 331 case BGPTYPE_ORIGIN: 332 if (len != 1) 333 printf(" invalid len"); 334 else { 335 TCHECK(p[0]); 336 printf(" %s", bgp_attr_origin(p[0])); 337 } 338 break; 339 case BGPTYPE_AS_PATH: 340 if (len % 2) { 341 printf(" invalid len"); 342 break; 343 } 344 if (!len) { 345 printf(" empty"); 346 break; 347 } 348 while (p < dat + len) { 349 /* 350 * under RFC1965, p[0] means: 351 * 1: AS_SET 2: AS_SEQUENCE 352 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE 353 */ 354 printf(" "); 355 TCHECK(p[1]); 356 if (p[0] == 3 || p[0] == 4) 357 printf("confed"); 358 printf("%s", (p[0] & 1) ? "{" : ""); 359 for (i = 0; i < p[1] * 2; i += 2) { 360 TCHECK2(p[2 + i], 2); /* ASN is 2-bytes */ 361 printf("%s%u", i == 0 ? "" : " ", 362 EXTRACT_16BITS(&p[2 + i])); 363 } 364 printf("%s", (p[0] & 1) ? "}" : ""); 365 /* 366 * 1 byte for attr type, 1 byte for path length, 367 * plus size of ASN (2-bytes for now) * no of ASN 368 * 369 */ 370 p += 2 + p[1] * 2; 371 } 372 break; 373 case BGPTYPE_NEXT_HOP: 374 if (len != 4) 375 printf(" invalid len"); 376 else { 377 TCHECK2(p[0], 4); 378 printf(" %s", getname(p)); 379 } 380 break; 381 case BGPTYPE_MULTI_EXIT_DISC: 382 case BGPTYPE_LOCAL_PREF: 383 if (len != 4) 384 printf(" invalid len"); 385 else { 386 TCHECK2(p[0], 4); 387 printf(" %u", EXTRACT_32BITS(p)); 388 } 389 break; 390 case BGPTYPE_ATOMIC_AGGREGATE: 391 if (len != 0) 392 printf(" invalid len"); 393 break; 394 case BGPTYPE_AGGREGATOR: 395 if (len != 6) { 396 printf(" invalid len"); 397 break; 398 } 399 TCHECK2(p[0], 6); 400 printf(" AS #%u, origin %s", EXTRACT_16BITS(p), 401 getname(p + 2)); 402 break; 403 case BGPTYPE_COMMUNITIES: 404 if (len % 4) { 405 printf(" invalid len"); 406 break; 407 } 408 for (i = 0; i < len; i += 4) { 409 u_int32_t comm; 410 TCHECK2(p[i], 4); 411 comm = EXTRACT_32BITS(&p[i]); 412 switch (comm) { 413 case BGP_COMMUNITY_NO_EXPORT: 414 printf(" NO_EXPORT"); 415 break; 416 case BGP_COMMUNITY_NO_ADVERT: 417 printf(" NO_ADVERTISE"); 418 break; 419 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: 420 printf(" NO_EXPORT_SUBCONFED"); 421 break; 422 case BGP_COMMUNITY_NO_PEER: 423 printf(" NO_PEER"); 424 break; 425 default: 426 printf(" %d:%d", 427 (comm >> 16) & 0xffff, comm & 0xffff); 428 break; 429 } 430 } 431 break; 432 case BGPTYPE_MP_REACH_NLRI: 433 TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); 434 af = EXTRACT_16BITS(p); 435 safi = p[2]; 436 if (safi >= 128) 437 printf(" %s vendor specific,", af_name(af)); 438 else { 439 printf(" %s %s,", af_name(af), 440 bgp_attr_nlri_safi(safi)); 441 } 442 p += 3; 443 444 if (af == AFNUM_INET) 445 ; 446 #ifdef INET6 447 else if (af == AFNUM_INET6) 448 ; 449 #endif 450 else 451 break; 452 453 TCHECK(p[0]); 454 tlen = p[0]; 455 if (tlen) { 456 printf(" nexthop"); 457 i = 0; 458 while (i < tlen) { 459 switch (af) { 460 case AFNUM_INET: 461 TCHECK2(p[1+i], sizeof(struct in_addr)); 462 printf(" %s", getname(p + 1 + i)); 463 i += sizeof(struct in_addr); 464 break; 465 #ifdef INET6 466 case AFNUM_INET6: 467 TCHECK2(p[1+i], sizeof(struct in6_addr)); 468 printf(" %s", getname6(p + 1 + i)); 469 i += sizeof(struct in6_addr); 470 break; 471 #endif 472 default: 473 printf(" (unknown af)"); 474 i = tlen; /*exit loop*/ 475 break; 476 } 477 } 478 printf(","); 479 } 480 p += 1 + tlen; 481 482 TCHECK(p[0]); 483 snpa = p[0]; 484 p++; 485 if (snpa) { 486 printf(" %u snpa", snpa); 487 for (/*nothing*/; snpa > 0; snpa--) { 488 TCHECK(p[0]); 489 printf("(%d bytes)", p[0]); 490 p += p[0] + 1; 491 } 492 printf(","); 493 } 494 495 printf(" NLRI"); 496 while (len - (p - dat) > 0) { 497 switch (af) { 498 case AFNUM_INET: 499 advance = decode_prefix4(p, buf, sizeof(buf)); 500 break; 501 #ifdef INET6 502 case AFNUM_INET6: 503 advance = decode_prefix6(p, buf, sizeof(buf)); 504 break; 505 #endif 506 default: 507 printf(" (unknown af)"); 508 advance = 0; 509 p = dat + len; 510 break; 511 } 512 513 if (advance <= 0) 514 break; 515 516 printf(" %s", buf); 517 p += advance; 518 } 519 520 break; 521 522 case BGPTYPE_MP_UNREACH_NLRI: 523 TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); 524 af = EXTRACT_16BITS(p); 525 safi = p[2]; 526 if (safi >= 128) 527 printf(" %s vendor specific,", af_name(af)); 528 else { 529 printf(" %s %s,", af_name(af), 530 bgp_attr_nlri_safi(safi)); 531 } 532 p += 3; 533 534 printf(" Withdraw"); 535 while (len - (p - dat) > 0) { 536 switch (af) { 537 case AFNUM_INET: 538 advance = decode_prefix4(p, buf, sizeof(buf)); 539 break; 540 #ifdef INET6 541 case AFNUM_INET6: 542 advance = decode_prefix6(p, buf, sizeof(buf)); 543 break; 544 #endif 545 default: 546 printf(" (unknown af)"); 547 advance = 0; 548 p = dat + len; 549 break; 550 } 551 552 if (advance <= 0) 553 break; 554 555 printf(" %s", buf); 556 p += advance; 557 } 558 break; 559 default: 560 break; 561 } 562 return 1; 563 564 trunc: 565 return 0; 566 } 567 568 static void 569 bgp_open_print(const u_char *dat, int length) 570 { 571 struct bgp_open bgpo; 572 struct bgp_opt bgpopt; 573 const u_char *opt; 574 int i; 575 576 TCHECK2(dat[0], BGP_OPEN_SIZE); 577 memcpy(&bgpo, dat, BGP_OPEN_SIZE); 578 579 printf(": Version %d,", bgpo.bgpo_version); 580 printf(" AS #%u,", ntohs(bgpo.bgpo_myas)); 581 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)); 582 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id)); 583 printf(" Option length %u", bgpo.bgpo_optlen); 584 585 /* ugly! */ 586 opt = &((const struct bgp_open *)dat)->bgpo_optlen; 587 opt++; 588 589 i = 0; 590 while (i < bgpo.bgpo_optlen) { 591 TCHECK2(opt[i], BGP_OPT_SIZE); 592 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); 593 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { 594 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); 595 break; 596 } 597 598 printf(" (option %s, len=%d)", bgp_opttype(bgpopt.bgpopt_type), 599 bgpopt.bgpopt_len); 600 i += BGP_OPT_SIZE + bgpopt.bgpopt_len; 601 } 602 return; 603 trunc: 604 printf("[|BGP]"); 605 } 606 607 static void 608 bgp_update_print(const u_char *dat, int length) 609 { 610 struct bgp bgp; 611 struct bgp_attr bgpa; 612 const u_char *p; 613 int len; 614 int i; 615 int newline; 616 617 TCHECK2(dat[0], BGP_SIZE); 618 memcpy(&bgp, dat, BGP_SIZE); 619 p = dat + BGP_SIZE; /*XXX*/ 620 printf(":"); 621 622 /* Unfeasible routes */ 623 len = EXTRACT_16BITS(p); 624 if (len) { 625 /* 626 * Without keeping state from the original NLRI message, 627 * it's not possible to tell if this a v4 or v6 route, 628 * so only try to decode it if we're not v6 enabled. 629 */ 630 #ifdef INET6 631 printf(" (Withdrawn routes: %d bytes)", len); 632 #else 633 char buf[MAXHOSTNAMELEN + 100]; 634 int wpfx; 635 636 TCHECK2(p[2], len); 637 i = 2; 638 639 printf(" (Withdrawn routes:"); 640 641 while(i < 2 + len) { 642 wpfx = decode_prefix4(&p[i], buf, sizeof(buf)); 643 if (wpfx == -2) 644 goto trunc; 645 else if (wpfx < 0) { 646 printf(" (illegal prefix length)"); 647 break; 648 } 649 i += wpfx; 650 printf(" %s", buf); 651 } 652 printf(")"); 653 #endif 654 } 655 p += 2 + len; 656 657 TCHECK2(p[0], 2); 658 len = EXTRACT_16BITS(p); 659 660 if (len) { 661 /* do something more useful!*/ 662 i = 2; 663 printf(" (Path attributes:"); /* ) */ 664 newline = 0; 665 while (i < 2 + len) { 666 int alen, aoff; 667 668 TCHECK2(p[i], sizeof(bgpa)); 669 memcpy(&bgpa, &p[i], sizeof(bgpa)); 670 alen = bgp_attr_len(&bgpa); 671 aoff = bgp_attr_off(&bgpa); 672 673 if (vflag && newline) 674 printf("\n\t\t"); 675 else 676 printf(" "); 677 printf("("); /* ) */ 678 printf("%s", bgp_attr_type(bgpa.bgpa_type)); 679 if (bgpa.bgpa_flags) { 680 printf("[%s%s%s%s", 681 bgpa.bgpa_flags & 0x80 ? "O" : "", 682 bgpa.bgpa_flags & 0x40 ? "T" : "", 683 bgpa.bgpa_flags & 0x20 ? "P" : "", 684 bgpa.bgpa_flags & 0x10 ? "E" : ""); 685 if (bgpa.bgpa_flags & 0xf) 686 printf("+%x", bgpa.bgpa_flags & 0xf); 687 printf("]"); 688 } 689 690 if (!bgp_attr_print(&bgpa, &p[i + aoff], alen)) 691 goto trunc; 692 newline = 1; 693 694 /* ( */ 695 printf(")"); 696 697 i += aoff + alen; 698 } 699 700 /* ( */ 701 printf(")"); 702 } 703 p += 2 + len; 704 705 if (len && dat + length > p) 706 printf("\n\t\t"); 707 if (dat + length > p) { 708 printf("(NLRI:"); /* ) */ 709 while (dat + length > p) { 710 char buf[MAXHOSTNAMELEN + 100]; 711 i = decode_prefix4(p, buf, sizeof(buf)); 712 if (i == -2) 713 goto trunc; 714 else if (i < 0) { 715 printf(" (illegal prefix length)"); 716 break; 717 } 718 printf(" %s", buf); 719 p += i; 720 } 721 722 /* ( */ 723 printf(")"); 724 } 725 return; 726 trunc: 727 printf("[|BGP]"); 728 } 729 730 static void 731 bgp_notification_print(const u_char *dat, int length) 732 { 733 struct bgp_notification bgpn; 734 735 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); 736 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); 737 738 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)); 739 printf(" subcode %s", 740 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); 741 return; 742 trunc: 743 printf("[|BGP]"); 744 } 745 746 static int 747 bgp_header_print(const u_char *dat, int length) 748 { 749 struct bgp bgp; 750 751 TCHECK2(dat[0], BGP_SIZE); 752 memcpy(&bgp, dat, BGP_SIZE); 753 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */ 754 755 switch (bgp.bgp_type) { 756 case BGP_OPEN: 757 bgp_open_print(dat, length); 758 break; 759 case BGP_UPDATE: 760 bgp_update_print(dat, length); 761 break; 762 case BGP_NOTIFICATION: 763 bgp_notification_print(dat, length); 764 break; 765 } 766 767 /* ( */ 768 printf(")"); 769 return 1; 770 trunc: 771 printf("[|BGP]"); 772 return 0; 773 } 774 775 void 776 bgp_print(const u_char *dat, int length) 777 { 778 const u_char *p; 779 const u_char *ep; 780 const u_char *start; 781 const u_char marker[] = { 782 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 783 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 784 }; 785 struct bgp bgp; 786 u_int16_t hlen; 787 int newline; 788 789 ep = dat + length; 790 if (snapend < dat + length) 791 ep = snapend; 792 793 printf(": BGP"); 794 795 p = dat; 796 newline = 0; 797 start = p; 798 while (p < ep) { 799 if (!TTEST2(p[0], 1)) 800 break; 801 if (p[0] != 0xff) { 802 p++; 803 continue; 804 } 805 806 if (!TTEST2(p[0], sizeof(marker))) 807 break; 808 if (memcmp(p, marker, sizeof(marker)) != 0) { 809 p++; 810 continue; 811 } 812 813 /* found BGP header */ 814 TCHECK2(p[0], BGP_SIZE); /*XXX*/ 815 memcpy(&bgp, p, BGP_SIZE); 816 817 if (start != p) 818 printf(" [|BGP]"); 819 820 hlen = ntohs(bgp.bgp_len); 821 if (vflag && newline) 822 printf("\n\t"); 823 else 824 printf(" "); 825 if (TTEST2(p[0], hlen)) { 826 if (!bgp_header_print(p, hlen)) 827 return; 828 newline = 1; 829 p += hlen; 830 start = p; 831 } else { 832 printf("[|BGP %s]", bgp_type(bgp.bgp_type)); 833 break; 834 } 835 } 836 837 return; 838 839 trunc: 840 printf(" [|BGP]"); 841 } 842