1 /* $OpenBSD: print-bgp.c,v 1.3 2000/10/03 14:15:55 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 #include <sys/param.h> 33 #include <sys/time.h> 34 #include <sys/types.h> 35 #include <sys/socket.h> 36 37 #include <netinet/in.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/ip.h> 40 #include <netinet/ip_var.h> 41 #include <netinet/udp.h> 42 #include <netinet/udp_var.h> 43 #include <arpa/inet.h> 44 45 #include <errno.h> 46 #include <stdio.h> 47 #include <string.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_opt { 77 u_int8_t bgpopt_type; 78 u_int8_t bgpopt_len; 79 /* variable length */ 80 }; 81 82 struct bgp_notification { 83 u_int8_t bgpn_marker[16]; 84 u_int16_t bgpn_len; 85 u_int8_t bgpn_type; 86 u_int8_t bgpn_major; 87 u_int8_t bgpn_minor; 88 /* data should follow */ 89 }; 90 91 struct bgp_attr { 92 u_int8_t bgpa_flags; 93 u_int8_t bgpa_type; 94 union { 95 u_int8_t len; 96 u_int16_t elen; 97 } bgpa_len; 98 #define bgp_attr_len(p) \ 99 (((p)->bgpa_flags & 0x10) ? \ 100 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len) 101 #define bgp_attr_off(p) \ 102 (((p)->bgpa_flags & 0x10) ? 4 : 3) 103 }; 104 105 #define BGPTYPE_ORIGIN 1 106 #define BGPTYPE_AS_PATH 2 107 #define BGPTYPE_NEXT_HOP 3 108 #define BGPTYPE_MULTI_EXIT_DISC 4 109 #define BGPTYPE_LOCAL_PREF 5 110 #define BGPTYPE_ATOMIC_AGGREGATE 6 111 #define BGPTYPE_AGGREGATOR 7 112 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ 113 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */ 114 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ 115 #define BGPTYPE_DPA 11 /* work in progress */ 116 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ 117 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */ 118 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ 119 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ 120 121 122 static const char *bgptype[] = { 123 NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", 124 }; 125 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) 126 127 static const char *bgpopt_type[] = { 128 NULL, "Authentication Information", 129 }; 130 #define bgp_opttype(x) \ 131 num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x)) 132 133 static const char *bgpnotify_major[] = { 134 NULL, "Message Header Error", 135 "OPEN Message Error", "UPDATE Message Error", 136 "Hold Timer Expired", "Finite State Machine Error", 137 "Cease", 138 }; 139 #define bgp_notify_major(x) \ 140 num_or_str(bgpnotify_major, \ 141 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x)) 142 143 static const char *bgpnotify_minor_1[] = { 144 NULL, "Connection Not Synchronized", 145 "Bad Message Length", "Bad Message Type", 146 }; 147 148 static const char *bgpnotify_minor_2[] = { 149 NULL, "Unsupported Version Number", 150 "Bad Peer AS", "Bad BGP Identifier", 151 "Unsupported Optional Parameter", "Authentication Failure", 152 "Unacceptable Hold Time", 153 }; 154 155 static const char *bgpnotify_minor_3[] = { 156 NULL, "Malformed Attribute List", 157 "Unrecognized Well-known Attribute", "Missing Well-known Attribute", 158 "Attribute Flags Error", "Attribute Length Error", 159 "Invalid ORIGIN Attribute", "AS Routing Loop", 160 "Invalid NEXT_HOP Attribute", "Optional Attribute Error", 161 "Invalid Network Field", "Malformed AS_PATH", 162 }; 163 164 static const char **bgpnotify_minor[] = { 165 NULL, bgpnotify_minor_1, bgpnotify_minor_2, bgpnotify_minor_3, 166 }; 167 static const int bgpnotify_minor_siz[] = { 168 0, sizeof(bgpnotify_minor_1)/sizeof(bgpnotify_minor_1[0]), 169 sizeof(bgpnotify_minor_2)/sizeof(bgpnotify_minor_2[0]), 170 sizeof(bgpnotify_minor_3)/sizeof(bgpnotify_minor_3[0]), 171 }; 172 173 static const char *bgpattr_origin[] = { 174 "IGP", "EGP", "INCOMPLETE", 175 }; 176 #define bgp_attr_origin(x) \ 177 num_or_str(bgpattr_origin, \ 178 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x)) 179 180 static const char *bgpattr_type[] = { 181 NULL, "ORIGIN", "AS_PATH", "NEXT_HOP", 182 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR", 183 "COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA", 184 "ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI", 185 }; 186 #define bgp_attr_type(x) \ 187 num_or_str(bgpattr_type, \ 188 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x)) 189 190 /* Subsequent address family identifier, RFC2283 section 7 */ 191 static const char *bgpattr_nlri_safi[] = { 192 "Reserved", "Unicast", "Multicast", "Unicast+Multicast", 193 }; 194 #define bgp_attr_nlri_safi(x) \ 195 num_or_str(bgpattr_nlri_safi, \ 196 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x)) 197 198 /* well-known community */ 199 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01 200 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02 201 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 202 203 /* RFC1700 address family numbers */ 204 #define AFNUM_INET 1 205 #define AFNUM_INET6 2 206 #define AFNUM_NSAP 3 207 #define AFNUM_HDLC 4 208 #define AFNUM_BBN1822 5 209 #define AFNUM_802 6 210 #define AFNUM_E163 7 211 #define AFNUM_E164 8 212 #define AFNUM_F69 9 213 #define AFNUM_X121 10 214 #define AFNUM_IPX 11 215 #define AFNUM_ATALK 12 216 #define AFNUM_DECNET 13 217 #define AFNUM_BANYAN 14 218 #define AFNUM_E164NSAP 15 219 220 static const char *afnumber[] = { 221 "Reserved", "IPv4", "IPv6", "NSAP", "HDLC", 222 "BBN 1822", "802", "E.163", "E.164", "F.69", 223 "X.121", "IPX", "Appletalk", "Decnet IV", "Banyan Vines", 224 "E.164 with NSAP subaddress", 225 }; 226 #define af_name(x) \ 227 (((x) == 65535) ? afnumber[0] : \ 228 num_or_str(afnumber, \ 229 sizeof(afnumber)/sizeof(afnumber[0]), (x))) 230 231 232 static const char * 233 num_or_str(const char **table, size_t siz, int value) 234 { 235 static char buf[20]; 236 if (value < 0 || siz <= value || table[value] == NULL) { 237 snprintf(buf, sizeof(buf), "#%d", value); 238 return buf; 239 } else 240 return table[value]; 241 } 242 243 static const char * 244 bgp_notify_minor(int major, int minor) 245 { 246 static const char **table; 247 int siz; 248 static char buf[20]; 249 const char *p; 250 251 if (0 <= major 252 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0]) 253 && bgpnotify_minor[major]) { 254 table = bgpnotify_minor[major]; 255 siz = bgpnotify_minor_siz[major]; 256 if (0 <= minor && minor < siz && table[minor]) 257 p = table[minor]; 258 else 259 p = NULL; 260 } else 261 p = NULL; 262 if (p == NULL) { 263 snprintf(buf, sizeof(buf), "#%d", minor); 264 return buf; 265 } else 266 return p; 267 } 268 269 static int 270 decode_prefix4(const u_char *pd, char *buf, int buflen) 271 { 272 struct in_addr addr; 273 int plen; 274 275 plen = pd[0]; 276 if (plen < 0 || 32 < plen) 277 return -1; 278 279 memset(&addr, 0, sizeof(addr)); 280 memcpy(&addr, &pd[1], (plen + 7) / 8); 281 if (plen % 8) { 282 ((u_char *)&addr)[(plen + 7) / 8 - 1] &= 283 ((0xff00 >> (plen % 8)) & 0xff); 284 } 285 snprintf(buf, buflen, "%s/%d", inet_ntoa(addr), plen); 286 return 1 + (plen + 7) / 8; 287 } 288 289 #ifdef INET6 290 static int 291 decode_prefix6(const u_char *pd, char *buf, int buflen) 292 { 293 struct in6_addr addr; 294 int plen; 295 296 plen = pd[0]; 297 if (plen < 0 || 128 < plen) 298 return -1; 299 300 memset(&addr, 0, sizeof(addr)); 301 memcpy(&addr, &pd[1], (plen + 7) / 8); 302 if (plen % 8) { 303 addr.s6_addr[(plen + 7) / 8 - 1] &= 304 ((0xff00 >> (plen % 8)) & 0xff); 305 } 306 snprintf(buf, buflen, "%s/%d", getname6((char *)&addr), plen); 307 return 1 + (plen + 7) / 8; 308 } 309 #endif 310 311 static void 312 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len) 313 { 314 int i; 315 u_int16_t af; 316 u_int8_t safi, snpa; 317 int advance; 318 int tlen; 319 const u_char *p; 320 char buf[256]; 321 u_int16_t ss; 322 u_int32_t ll; 323 struct in_addr aa; 324 325 p = dat; 326 327 switch (attr->bgpa_type) { 328 case BGPTYPE_ORIGIN: 329 if (len != 1) 330 printf(" invalid len"); 331 else 332 printf(" %s", bgp_attr_origin(p[0])); 333 break; 334 case BGPTYPE_AS_PATH: 335 if (len % 2) { 336 printf(" invalid len"); 337 break; 338 } 339 while (p < dat + len) { 340 /* 341 * under RFC1965, p[0] means: 342 * 1: AS_SET 2: AS_SEQUENCE 343 * 3: AS_CONFED_SET 4: AS_CONFED_SEQUENCE 344 */ 345 printf(" "); 346 if (p[0] == 3 || p[0] == 4) 347 printf("confed"); 348 printf("%s", (p[0] & 1) ? "{" : ""); 349 for (i = 0; i < p[1]; i += 2) { 350 memcpy((void *)&ss, (void *)&p[2+i], sizeof(ss)); 351 printf("%s%u", i == 0 ? "" : " ", 352 ntohs(ss)); 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 memcpy((void *)&aa.s_addr, (void *)&p[0], sizeof(aa.s_addr)); 363 printf(" %s", inet_ntoa(aa)); 364 } 365 break; 366 case BGPTYPE_MULTI_EXIT_DISC: 367 case BGPTYPE_LOCAL_PREF: 368 if (len != 4) 369 printf(" invalid len"); 370 else { 371 memcpy((void *)&ll, (void *)&p[0], sizeof(ll)); 372 printf(" %u", (u_int32_t)ntohl(ll)); 373 } 374 break; 375 case BGPTYPE_ATOMIC_AGGREGATE: 376 if (len != 0) 377 printf(" invalid len"); 378 break; 379 case BGPTYPE_AGGREGATOR: 380 if (len != 6) { 381 printf(" invalid len"); 382 break; 383 } 384 memcpy((void *)&ss, (void *)&p[0], sizeof(ss)); 385 memcpy((void *)&aa.s_addr, (void *)&p[2], sizeof(aa.s_addr)); 386 printf(" AS #%u, origin %s", ntohs(ss), inet_ntoa(aa)); 387 break; 388 case BGPTYPE_COMMUNITIES: 389 if (len % 4) { 390 printf(" invalid len"); 391 break; 392 } 393 for (i = 0; i < len; i += 4) { 394 u_int32_t comm; 395 memcpy((void *)&ll,(void *)&p[0+i],sizeof(ll)); 396 comm = (u_int32_t)ntohl(ll); 397 switch (comm) { 398 case BGP_COMMUNITY_NO_EXPORT: 399 printf(" NO_EXPORT"); 400 break; 401 case BGP_COMMUNITY_NO_ADVERT: 402 printf(" NO_ADVERTISE"); 403 break; 404 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: 405 printf(" NO_EXPORT_SUBCONFED"); 406 break; 407 default: 408 printf(" (AS #%d value 0x%04x)", 409 (comm >> 16) & 0xffff, comm & 0xffff); 410 break; 411 } 412 } 413 break; 414 case BGPTYPE_MP_REACH_NLRI: 415 memcpy((void *)&ss, (void *)&p[0], sizeof(ss)); 416 af = ntohs(ss); 417 safi = p[2]; 418 if (safi >= 128) 419 printf(" %s vendor specific,", af_name(af)); 420 else { 421 printf(" %s %s,", af_name(af), 422 bgp_attr_nlri_safi(safi)); 423 } 424 p += 3; 425 426 if (af == AFNUM_INET) 427 ; 428 #ifdef INET6 429 else if (af == AFNUM_INET6) 430 ; 431 #endif 432 else 433 break; 434 435 tlen = p[0]; 436 if (tlen) { 437 printf(" nexthop"); 438 #ifdef INET6 439 if (af == AFNUM_INET6) 440 advance = 16; 441 else 442 #endif 443 advance = 4; /* AFNUM_INET */ 444 445 for (i = 0; i < tlen; i += advance) { 446 if (af == AFNUM_INET) { 447 memcpy((void *)&aa.s_addr, (void *)&p[1+i], sizeof(aa.s_addr)); 448 printf(" %s", inet_ntoa(aa)); 449 } 450 #ifdef INET6 451 else if (af == AFNUM_INET6) 452 printf(" %s", getname6(p + 1 + i)); 453 #endif 454 } 455 printf(","); 456 } 457 p += 1 + tlen; 458 459 snpa = p[0]; 460 p++; 461 if (snpa) { 462 printf(" %u snpa", snpa); 463 for (/*nothing*/; snpa > 0; snpa--) { 464 printf("(%d bytes)", p[0]); 465 p += p[0] + 1; 466 } 467 printf(","); 468 } 469 470 printf(" NLRI"); 471 while (len - (p - dat) > 0) { 472 #ifdef INET6 473 if (af == AFNUM_INET6) 474 advance = decode_prefix6(p, buf, sizeof(buf)); 475 else 476 #endif 477 advance = decode_prefix4(p, buf, sizeof(buf)); 478 printf(" %s", buf); 479 480 p += advance; 481 } 482 483 break; 484 485 case BGPTYPE_MP_UNREACH_NLRI: 486 memcpy((void *)&ss, (void *)&p[0], sizeof(ss)); 487 af = ntohs(ss); 488 safi = p[2]; 489 if (safi >= 128) 490 printf(" %s vendor specific,", af_name(af)); 491 else { 492 printf(" %s %s,", af_name(af), 493 bgp_attr_nlri_safi(safi)); 494 } 495 p += 3; 496 497 printf(" Withdraw"); 498 while (len - (p - dat) > 0) { 499 #ifdef INET6 500 if (af == AFNUM_INET6) 501 advance = decode_prefix6(p, buf, sizeof(buf)); 502 else 503 #endif 504 advance = decode_prefix4(p, buf, sizeof(buf)); 505 506 printf(" %s", buf); 507 508 p += advance; 509 } 510 break; 511 default: 512 break; 513 } 514 } 515 516 static void 517 bgp_open_print(const u_char *dat, int length) 518 { 519 struct bgp_open bgpo; 520 struct bgp_opt bgpopt; 521 int hlen; 522 const u_char *opt; 523 int i; 524 525 memcpy(&bgpo, dat, sizeof(bgpo)); 526 hlen = ntohs(bgpo.bgpo_len); 527 528 printf(": Version %d,", bgpo.bgpo_version); 529 printf(" AS #%u,", ntohs(bgpo.bgpo_myas)); 530 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)); 531 printf(" ID %s,", getname((const u_char *)&bgpo.bgpo_id)); 532 printf(" Option length %u", bgpo.bgpo_optlen); 533 534 /* ugly! */ 535 opt = &((struct bgp_open *)dat)->bgpo_optlen; 536 opt++; 537 538 for (i = 0; i < bgpo.bgpo_optlen; i++) { 539 memcpy(&bgpopt, &opt[i], sizeof(bgpopt)); 540 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { 541 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); 542 break; 543 } 544 545 printf(" (option %s, len=%d)", bgp_opttype(bgpopt.bgpopt_type), 546 bgpopt.bgpopt_len); 547 i += sizeof(bgpopt) + bgpopt.bgpopt_len; 548 } 549 } 550 551 static void 552 bgp_update_print(const u_char *dat, int length) 553 { 554 struct bgp bgp; 555 struct bgp_attr bgpa; 556 int hlen; 557 const u_char *p; 558 int len; 559 int i; 560 int newline; 561 u_int16_t ss; 562 563 memcpy(&bgp, dat, sizeof(bgp)); 564 hlen = ntohs(bgp.bgp_len); 565 p = dat + BGP_SIZE; /*XXX*/ 566 printf(":"); 567 568 /* Unfeasible routes */ 569 memcpy((void *)&ss, (void *)&p[0], sizeof(ss)); 570 len = ntohs(ss); 571 if (len) { 572 printf(" (Withdrawn routes: %d bytes)", len); 573 } 574 p += 2 + len; 575 576 memcpy((void *)&ss, (void *)&p[0], sizeof(ss)); 577 len = ntohs(ss); 578 if (len) { 579 /* do something more useful!*/ 580 i = 2; 581 printf(" (Path attributes:"); /* ) */ 582 newline = 0; 583 while (i < 2 + len) { 584 int alen, aoff; 585 586 memcpy(&bgpa, &p[i], sizeof(bgpa)); 587 alen = bgp_attr_len(&bgpa); 588 aoff = bgp_attr_off(&bgpa); 589 590 if (vflag && newline) 591 printf("\n\t\t"); 592 else 593 printf(" "); 594 printf("("); /* ) */ 595 printf("%s", bgp_attr_type(bgpa.bgpa_type)); 596 if (bgpa.bgpa_flags) { 597 printf("[%s%s%s%s]", 598 bgpa.bgpa_flags & 0x80 ? "O" : "", 599 bgpa.bgpa_flags & 0x40 ? "T" : "", 600 bgpa.bgpa_flags & 0x20 ? "P" : "", 601 bgpa.bgpa_flags & 0x00 ? "E" : ""); 602 } 603 604 bgp_attr_print(&bgpa, &p[i + aoff], alen); 605 newline = 1; 606 607 /* ( */ 608 printf(")"); 609 610 i += aoff + alen; 611 } 612 613 /* ( */ 614 printf(")"); 615 } 616 p += 2 + len; 617 618 if (len && dat + length > p) 619 printf("\n\t\t"); 620 if (dat + length > p) { 621 printf("(NLRI:"); /* ) */ 622 while (dat + length > p) { 623 char buf[256]; 624 i = decode_prefix4(p, buf, sizeof(buf)); 625 printf(" %s", buf); 626 if (i < 0) 627 break; 628 p += i; 629 } 630 631 /* ( */ 632 printf(")"); 633 } 634 } 635 636 static void 637 bgp_notification_print(const u_char *dat, int length) 638 { 639 struct bgp_notification bgpn; 640 int hlen; 641 642 memcpy(&bgpn, dat, sizeof(bgpn)); 643 hlen = ntohs(bgpn.bgpn_len); 644 645 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)); 646 printf(" subcode %s", 647 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); 648 } 649 650 static void 651 bgp_header_print(const u_char *dat, int length) 652 { 653 struct bgp bgp; 654 655 memcpy(&bgp, dat, sizeof(bgp)); 656 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */ 657 658 switch (bgp.bgp_type) { 659 case BGP_OPEN: 660 bgp_open_print(dat, length); 661 break; 662 case BGP_UPDATE: 663 bgp_update_print(dat, length); 664 break; 665 case BGP_NOTIFICATION: 666 bgp_notification_print(dat, length); 667 break; 668 } 669 670 /* ( */ 671 printf(")"); 672 } 673 674 void 675 bgp_print(const u_char *dat, int length) 676 { 677 const u_char *p; 678 const u_char *ep; 679 const u_char *start; 680 const u_char marker[] = { 681 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 682 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 683 }; 684 struct bgp bgp; 685 u_int16_t hlen; 686 int newline; 687 688 ep = dat + length; 689 if (snapend < dat + length) 690 ep = snapend; 691 692 printf(": BGP"); 693 694 p = dat; 695 newline = 0; 696 start = p; 697 while (p < snapend) { 698 if (!TTEST2(p[0], 1)) 699 break; 700 if (p[0] != 0xff) { 701 p++; 702 continue; 703 } 704 705 if (!TTEST2(p[0], sizeof(marker))) 706 break; 707 if (memcmp(p, marker, sizeof(marker)) != 0) { 708 p++; 709 continue; 710 } 711 712 /* found BGP header */ 713 TCHECK2(p[0], BGP_SIZE); /*XXX*/ 714 memcpy(&bgp, p, sizeof(bgp)); 715 716 if (start != p) 717 printf(" [|BGP]"); 718 719 hlen = ntohs(bgp.bgp_len); 720 if (vflag && newline) 721 printf("\n\t"); 722 else 723 printf(" "); 724 if (TTEST2(p[0], hlen)) { 725 bgp_header_print(p, hlen); 726 newline = 1; 727 p += hlen; 728 start = p; 729 } else { 730 printf("[|BGP %s]", bgp_type(bgp.bgp_type)); 731 break; 732 } 733 } 734 735 return; 736 737 trunc: 738 printf(" [|BGP]"); 739 } 740