1 /* $OpenBSD: print-bgp.c,v 1.18 2015/10/20 11:29:07 sthen 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/time.h> 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 36 #include <netinet/in.h> 37 38 #include <errno.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <netdb.h> 42 #include <limits.h> 43 44 #include "interface.h" 45 #include "addrtoname.h" 46 #include "extract.h" 47 #include "afnum.h" 48 49 struct bgp { 50 u_int8_t bgp_marker[16]; 51 u_int16_t bgp_len; 52 u_int8_t bgp_type; 53 }; 54 #define BGP_SIZE 19 /* unaligned */ 55 56 #define BGP_OPEN 1 57 #define BGP_UPDATE 2 58 #define BGP_NOTIFICATION 3 59 #define BGP_KEEPALIVE 4 60 #define BGP_ROUTE_REFRESH 5 61 62 struct bgp_open { 63 u_int8_t bgpo_marker[16]; 64 u_int16_t bgpo_len; 65 u_int8_t bgpo_type; 66 u_int8_t bgpo_version; 67 u_int16_t bgpo_myas; 68 u_int16_t bgpo_holdtime; 69 u_int32_t bgpo_id; 70 u_int8_t bgpo_optlen; 71 /* options should follow */ 72 }; 73 #define BGP_OPEN_SIZE 29 /* unaligned */ 74 75 struct bgp_opt { 76 u_int8_t bgpopt_type; 77 u_int8_t bgpopt_len; 78 /* variable length */ 79 }; 80 #define BGP_OPT_CAP 2 81 #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ 82 83 #define BGP_UPDATE_MINSIZE 23 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_route_refresh { 96 u_int8_t bgp_marker[16]; 97 u_int16_t len; 98 u_int8_t type; 99 u_int8_t afi[2]; /* unaligned; should be u_int16_t */ 100 u_int8_t res; 101 u_int8_t safi; 102 }; 103 #define BGP_ROUTE_REFRESH_SIZE 23 104 105 struct bgp_attr { 106 u_int8_t bgpa_flags; 107 u_int8_t bgpa_type; 108 union { 109 u_int8_t len; 110 u_int16_t elen; 111 } bgpa_len; 112 #define bgp_attr_len(p) \ 113 (((p)->bgpa_flags & 0x10) ? \ 114 ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len) 115 #define bgp_attr_off(p) \ 116 (((p)->bgpa_flags & 0x10) ? 4 : 3) 117 }; 118 119 #define BGPTYPE_ORIGIN 1 120 #define BGPTYPE_AS_PATH 2 121 #define BGPTYPE_NEXT_HOP 3 122 #define BGPTYPE_MULTI_EXIT_DISC 4 123 #define BGPTYPE_LOCAL_PREF 5 124 #define BGPTYPE_ATOMIC_AGGREGATE 6 125 #define BGPTYPE_AGGREGATOR 7 126 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ 127 #define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */ 128 #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ 129 #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */ 130 #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ 131 #define BGPTYPE_RCID_PATH 13 /* RFC1863 */ 132 #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ 133 #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ 134 #define BGPTYPE_EXTD_COMMUNITIES 16 /* RFC4360 */ 135 #define BGPTYPE_AS4_PATH 17 /* RFC4893 */ 136 #define BGPTYPE_AGGREGATOR4 18 /* RFC4893 */ 137 138 #define BGP_AS_SET 1 139 #define BGP_AS_SEQUENCE 2 140 #define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */ 141 #define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */ 142 143 static struct tok bgp_as_path_segment_open_values[] = { 144 { BGP_AS_SET, " {" }, 145 { BGP_AS_SEQUENCE, " " }, 146 { BGP_CONFED_AS_SEQUENCE, " (" }, 147 { BGP_CONFED_AS_SET, " ({" }, 148 { 0, NULL}, 149 }; 150 151 static struct tok bgp_as_path_segment_close_values[] = { 152 { BGP_AS_SET, "}" }, 153 { BGP_AS_SEQUENCE, "" }, 154 { BGP_CONFED_AS_SEQUENCE, ")" }, 155 { BGP_CONFED_AS_SET, "})" }, 156 { 0, NULL}, 157 }; 158 159 #define BGP_MP_NLRI_MINSIZE 3 160 161 static const char *bgptype[] = { 162 NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", 163 }; 164 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x)) 165 166 static const char *bgpopt_type[] = { 167 NULL, "Authentication Information", "Capabilities Advertisement", 168 }; 169 #define bgp_opttype(x) \ 170 num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x)) 171 172 #define BGP_CAPCODE_MP 1 173 #define BGP_CAPCODE_REFRESH 2 174 #define BGP_CAPCODE_RESTART 64 /* draft-ietf-idr-restart-05 */ 175 #define BGP_CAPCODE_AS4 65 /* RFC4893 */ 176 177 static const char *bgp_capcode[] = { 178 NULL, "MULTI_PROTOCOL", "ROUTE_REFRESH", 179 /* 3: RFC5291 */ "OUTBOUND_ROUTE_FILTERING", 180 /* 4: RFC3107 */ "MULTIPLE_ROUTES", 181 /* 5: RFC5549 */ "EXTENDED_NEXTHOP_ENCODING", 182 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 186 /* 64: RFC4724 */ "GRACEFUL_RESTART", 187 /* 65: RFC4893 */ "AS4", 0, 188 /* 67: [Chen] */ "DYNAMIC_CAPABILITY", 189 /* 68: [Appanna] */ "MULTISESSION", 190 /* 69: [draft-ietf-idr-add-paths] */ "ADD-PATH", 191 }; 192 193 #define bgp_capcode(x) \ 194 num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode[0]), (x)) 195 196 #define BGP_NOTIFY_MAJOR_CEASE 6 197 static const char *bgpnotify_major[] = { 198 NULL, "Message Header Error", 199 "OPEN Message Error", "UPDATE Message Error", 200 "Hold Timer Expired", "Finite State Machine Error", 201 "Cease", "Capability Message Error", 202 }; 203 #define bgp_notify_major(x) \ 204 num_or_str(bgpnotify_major, \ 205 sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x)) 206 207 static const char *bgpnotify_minor_msg[] = { 208 NULL, "Connection Not Synchronized", 209 "Bad Message Length", "Bad Message Type", 210 }; 211 212 static const char *bgpnotify_minor_open[] = { 213 NULL, "Unsupported Version Number", 214 "Bad Peer AS", "Bad BGP Identifier", 215 "Unsupported Optional Parameter", "Authentication Failure", 216 "Unacceptable Hold Time", "Unsupported Capability", 217 }; 218 219 static const char *bgpnotify_minor_update[] = { 220 NULL, "Malformed Attribute List", 221 "Unrecognized Well-known Attribute", "Missing Well-known Attribute", 222 "Attribute Flags Error", "Attribute Length Error", 223 "Invalid ORIGIN Attribute", "AS Routing Loop", 224 "Invalid NEXT_HOP Attribute", "Optional Attribute Error", 225 "Invalid Network Field", "Malformed AS_PATH", 226 }; 227 228 /* RFC 4486 */ 229 #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1 230 static const char *bgpnotify_minor_cease[] = { 231 NULL, "Maximum Number of Prefixes Reached", "Administratively Shutdown", 232 "Peer De-configured", "Administratively Reset", "Connection Rejected", 233 "Other Configuration Change", "Connection Collision Resolution", 234 "Out of Resources", 235 }; 236 237 static const char *bgpnotify_minor_cap[] = { 238 NULL, "Invalid Action Value", "Invalid Capability Length", 239 "Malformed Capability Value", "Unsupported Capability Code", 240 }; 241 242 static const char **bgpnotify_minor[] = { 243 NULL, bgpnotify_minor_msg, bgpnotify_minor_open, bgpnotify_minor_update, 244 }; 245 static const int bgpnotify_minor_siz[] = { 246 0, 247 sizeof(bgpnotify_minor_msg)/sizeof(bgpnotify_minor_msg[0]), 248 sizeof(bgpnotify_minor_open)/sizeof(bgpnotify_minor_open[0]), 249 sizeof(bgpnotify_minor_update)/sizeof(bgpnotify_minor_update[0]), 250 0, 251 0, 252 sizeof(bgpnotify_minor_cease)/sizeof(bgpnotify_minor_cease[0]), 253 sizeof(bgpnotify_minor_cap)/sizeof(bgpnotify_minor_cap[0]), 254 }; 255 256 static const char *bgpattr_origin[] = { 257 "IGP", "EGP", "INCOMPLETE", 258 }; 259 #define bgp_attr_origin(x) \ 260 num_or_str(bgpattr_origin, \ 261 sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x)) 262 263 static const char *bgpattr_type[] = { 264 NULL, "ORIGIN", "AS_PATH", "NEXT_HOP", 265 "MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR", 266 "COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA", 267 "ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI", 268 "EXTD_COMMUNITIES", "AS4_PATH", "AGGREGATOR4", 269 }; 270 #define bgp_attr_type(x) \ 271 num_or_str(bgpattr_type, \ 272 sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x)) 273 274 /* Subsequent address family identifier, RFC2283 section 7 */ 275 static const char *bgpattr_nlri_safi[] = { 276 "Reserved", "Unicast", "Multicast", "Unicast+Multicast", 277 "labeled Unicast", /* MPLS BGP RFC3107 */ 278 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 279 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 282 /* 64-66: MPLS BGP RFC3107 */ 283 "Tunnel", "VPLS", "MDT", 284 }; 285 #define bgp_attr_nlri_safi(x) \ 286 num_or_str(bgpattr_nlri_safi, \ 287 sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x)) 288 289 /* well-known community */ 290 #define BGP_COMMUNITY_NO_EXPORT 0xffffff01 291 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02 292 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 293 #define BGP_COMMUNITY_NO_PEER 0xffffff04 294 295 static const char *afnumber[] = AFNUM_NAME_STR; 296 #define af_name(x) \ 297 (((x) == 65535) ? afnumber[0] : \ 298 num_or_str(afnumber, \ 299 sizeof(afnumber)/sizeof(afnumber[0]), (x))) 300 301 302 static const char * 303 num_or_str(const char **table, size_t siz, int value) 304 { 305 static char buf[20]; 306 if (value < 0 || siz <= value || table[value] == NULL) { 307 snprintf(buf, sizeof(buf), "#%d", value); 308 return buf; 309 } else 310 return table[value]; 311 } 312 313 static const char * 314 bgp_notify_minor(int major, int minor) 315 { 316 static const char **table; 317 int siz; 318 static char buf[20]; 319 const char *p; 320 321 if (0 <= major 322 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0]) 323 && bgpnotify_minor[major]) { 324 table = bgpnotify_minor[major]; 325 siz = bgpnotify_minor_siz[major]; 326 if (0 <= minor && minor < siz && table[minor]) 327 p = table[minor]; 328 else 329 p = NULL; 330 } else 331 p = NULL; 332 if (p == NULL) { 333 snprintf(buf, sizeof(buf), "#%d", minor); 334 return buf; 335 } else 336 return p; 337 } 338 339 static int 340 decode_prefix4(const u_char *pd, char *buf, u_int buflen) 341 { 342 struct in_addr addr; 343 u_int plen; 344 int n; 345 346 TCHECK(pd[0]); 347 plen = pd[0]; /* 348 * prefix length is in bits; packet only contains 349 * enough bytes of address to contain this many bits 350 */ 351 plen = pd[0]; 352 if (plen < 0 || 32 < plen) 353 return -1; 354 memset(&addr, 0, sizeof(addr)); 355 TCHECK2(pd[1], (plen + 7) / 8); 356 memcpy(&addr, &pd[1], (plen + 7) / 8); 357 if (plen % 8) { 358 ((u_char *)&addr)[(plen + 7) / 8 - 1] &= 359 ((0xff00 >> (plen % 8)) & 0xff); 360 } 361 n = snprintf(buf, buflen, "%s/%u", getname((u_char *)&addr), plen); 362 if (n == -1 || n >= buflen) 363 return -1; 364 365 return 1 + (plen + 7) / 8; 366 367 trunc: 368 return -2; 369 } 370 371 #ifdef INET6 372 static int 373 decode_prefix6(const u_char *pd, char *buf, u_int buflen) 374 { 375 struct in6_addr addr; 376 u_int plen; 377 int n; 378 379 TCHECK(pd[0]); 380 plen = pd[0]; 381 if (plen < 0 || 128 < plen) 382 return -1; 383 384 memset(&addr, 0, sizeof(addr)); 385 TCHECK2(pd[1], (plen + 7) / 8); 386 memcpy(&addr, &pd[1], (plen + 7) / 8); 387 if (plen % 8) { 388 addr.s6_addr[(plen + 7) / 8 - 1] &= 389 ((0xff00 >> (plen % 8)) & 0xff); 390 } 391 392 n = snprintf(buf, buflen, "%s/%u", getname6((u_char *)&addr), plen); 393 if (n == -1 || n >= buflen) 394 return -1; 395 396 return 1 + (plen + 7) / 8; 397 398 trunc: 399 return -2; 400 } 401 #endif 402 403 static int 404 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len) 405 { 406 int i; 407 u_int16_t af; 408 u_int8_t safi, snpa; 409 int advance; 410 int tlen, asn_bytes; 411 const u_char *p; 412 char buf[HOST_NAME_MAX+1 + 100]; 413 414 p = dat; 415 tlen = len; 416 asn_bytes = 0; 417 418 switch (attr->bgpa_type) { 419 case BGPTYPE_ORIGIN: 420 if (len != 1) 421 printf(" invalid len"); 422 else { 423 TCHECK(p[0]); 424 printf(" %s", bgp_attr_origin(p[0])); 425 } 426 break; 427 case BGPTYPE_AS4_PATH: 428 asn_bytes = 4; 429 /* FALLTHROUGH */ 430 case BGPTYPE_AS_PATH: 431 /* 432 * 2-byte speakers will receive AS4_PATH as well AS_PATH (2-byte). 433 * 4-byte speakers will only receive AS_PATH but it will be 4-byte. 434 * To identify which is the case, compare the length of the path 435 * segment value in bytes, with the path segment length from the 436 * message (counted in # of AS) 437 */ 438 439 if (len % 2) { 440 printf(" invalid len"); 441 break; 442 } 443 if (!len) { 444 /* valid: local originated routes to IBGP peers */ 445 printf(" empty"); 446 break; 447 } 448 while (p < dat + len) { 449 TCHECK2(p[0], 2); 450 if (asn_bytes == 0) { 451 if (p[1] == 0) { 452 /* invalid: segment contains one or more AS */ 453 printf(" malformed"); 454 break; 455 } 456 asn_bytes = (len-2)/p[1]; 457 } 458 printf("%s", 459 tok2str(bgp_as_path_segment_open_values, 460 "?", p[0])); 461 for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) { 462 TCHECK2(p[2 + i], asn_bytes); 463 printf("%s", i == 0 ? "" : " "); 464 if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i])) 465 printf("%u%s", 466 EXTRACT_16BITS(&p[2 + i]), 467 asn_bytes == 4 ? "." : ""); 468 if (asn_bytes == 4) 469 printf("%u", 470 EXTRACT_16BITS(&p[2 + i + 2])); 471 } 472 printf("%s", 473 tok2str(bgp_as_path_segment_close_values, 474 "?", p[0])); 475 p += 2 + p[1] * asn_bytes; 476 } 477 break; 478 case BGPTYPE_NEXT_HOP: 479 if (len != 4) 480 printf(" invalid len"); 481 else { 482 TCHECK2(p[0], 4); 483 printf(" %s", getname(p)); 484 } 485 break; 486 case BGPTYPE_MULTI_EXIT_DISC: 487 case BGPTYPE_LOCAL_PREF: 488 if (len != 4) 489 printf(" invalid len"); 490 else { 491 TCHECK2(p[0], 4); 492 printf(" %u", EXTRACT_32BITS(p)); 493 } 494 break; 495 case BGPTYPE_ATOMIC_AGGREGATE: 496 if (len != 0) 497 printf(" invalid len"); 498 break; 499 case BGPTYPE_AGGREGATOR4: 500 case BGPTYPE_AGGREGATOR: 501 /* 502 * like AS_PATH/AS4_PATH, AGGREGATOR can contain 503 * either 2-byte or 4-byte ASN, and AGGREGATOR4 504 * always contains 4-byte ASN. 505 */ 506 if (len != 6 && len != 8) { 507 printf(" invalid len"); 508 break; 509 } 510 TCHECK2(p[0], len); 511 printf(" AS #"); 512 if (len == 6 || EXTRACT_16BITS(p)) 513 printf("%u%s", EXTRACT_16BITS(p), len == 8 ? "." : ""); 514 if (len == 8) 515 printf("%u", EXTRACT_16BITS(p+2)); 516 printf(", origin %s", getname(p+len-4)); 517 break; 518 case BGPTYPE_COMMUNITIES: 519 if (len % 4) { 520 printf(" invalid len"); 521 break; 522 } 523 while (tlen>0) { 524 u_int32_t comm; 525 TCHECK2(p[0], 4); 526 comm = EXTRACT_32BITS(p); 527 switch (comm) { 528 case BGP_COMMUNITY_NO_EXPORT: 529 printf(" NO_EXPORT"); 530 break; 531 case BGP_COMMUNITY_NO_ADVERT: 532 printf(" NO_ADVERTISE"); 533 break; 534 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: 535 printf(" NO_EXPORT_SUBCONFED"); 536 break; 537 case BGP_COMMUNITY_NO_PEER: 538 printf(" NO_PEER"); 539 break; 540 default: 541 printf(" %d:%d", 542 (comm >> 16) & 0xffff, comm & 0xffff); 543 break; 544 } 545 tlen -= 4; 546 p += 4; 547 } 548 break; 549 case BGPTYPE_ORIGINATOR_ID: 550 if (len != 4) { 551 printf(" invalid len"); 552 break; 553 } 554 TCHECK2(p[0], 4); 555 printf("%s",getname(p)); 556 break; 557 case BGPTYPE_CLUSTER_LIST: 558 if (len % 4) { 559 printf(" invalid len"); 560 break; 561 } 562 while (tlen>0) { 563 TCHECK2(p[0], 4); 564 printf(" %s%s", 565 getname(p), 566 (tlen>4) ? ", " : ""); 567 tlen -=4; 568 p +=4; 569 } 570 break; 571 case BGPTYPE_MP_REACH_NLRI: 572 TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); 573 af = EXTRACT_16BITS(p); 574 safi = p[2]; 575 if (safi >= 128) 576 printf(" %s vendor specific %u,", af_name(af), safi); 577 else { 578 printf(" %s %s,", af_name(af), 579 bgp_attr_nlri_safi(safi)); 580 } 581 p += 3; 582 583 if (af == AFNUM_INET) 584 ; 585 #ifdef INET6 586 else if (af == AFNUM_INET6) 587 ; 588 #endif 589 else 590 break; 591 592 TCHECK(p[0]); 593 tlen = p[0]; 594 if (tlen) { 595 printf(" nexthop"); 596 i = 0; 597 while (i < tlen) { 598 switch (af) { 599 case AFNUM_INET: 600 TCHECK2(p[1+i], sizeof(struct in_addr)); 601 printf(" %s", getname(p + 1 + i)); 602 i += sizeof(struct in_addr); 603 break; 604 #ifdef INET6 605 case AFNUM_INET6: 606 TCHECK2(p[1+i], sizeof(struct in6_addr)); 607 printf(" %s", getname6(p + 1 + i)); 608 i += sizeof(struct in6_addr); 609 break; 610 #endif 611 default: 612 printf(" (unknown af)"); 613 i = tlen; /*exit loop*/ 614 break; 615 } 616 } 617 printf(","); 618 } 619 p += 1 + tlen; 620 621 TCHECK(p[0]); 622 snpa = p[0]; 623 p++; 624 if (snpa) { 625 printf(" %u snpa", snpa); 626 for (/*nothing*/; snpa > 0; snpa--) { 627 TCHECK(p[0]); 628 printf("(%d bytes)", p[0]); 629 p += p[0] + 1; 630 } 631 printf(","); 632 } 633 634 printf(" NLRI"); 635 while (len - (p - dat) > 0) { 636 switch (af) { 637 case AFNUM_INET: 638 advance = decode_prefix4(p, buf, sizeof(buf)); 639 break; 640 #ifdef INET6 641 case AFNUM_INET6: 642 advance = decode_prefix6(p, buf, sizeof(buf)); 643 break; 644 #endif 645 default: 646 printf(" (unknown af)"); 647 advance = 0; 648 p = dat + len; 649 break; 650 } 651 652 if (advance <= 0) 653 break; 654 655 printf(" %s", buf); 656 p += advance; 657 } 658 659 break; 660 661 case BGPTYPE_MP_UNREACH_NLRI: 662 TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); 663 af = EXTRACT_16BITS(p); 664 safi = p[2]; 665 if (safi >= 128) 666 printf(" %s vendor specific %u,", af_name(af), safi); 667 else { 668 printf(" %s %s,", af_name(af), 669 bgp_attr_nlri_safi(safi)); 670 } 671 p += 3; 672 673 printf(" Withdraw"); 674 while (len - (p - dat) > 0) { 675 switch (af) { 676 case AFNUM_INET: 677 advance = decode_prefix4(p, buf, sizeof(buf)); 678 break; 679 #ifdef INET6 680 case AFNUM_INET6: 681 advance = decode_prefix6(p, buf, sizeof(buf)); 682 break; 683 #endif 684 default: 685 printf(" (unknown af)"); 686 advance = 0; 687 p = dat + len; 688 break; 689 } 690 691 if (advance <= 0) 692 break; 693 694 printf(" %s", buf); 695 p += advance; 696 } 697 break; 698 default: 699 break; 700 } 701 return 1; 702 703 trunc: 704 return 0; 705 } 706 707 static void 708 bgp_open_capa_print(const u_char *opt, int length) 709 { 710 int i,cap_type,cap_len,tcap_len,cap_offset; 711 712 i = 0; 713 while (i < length) { 714 TCHECK2(opt[i], 2); 715 716 cap_type=opt[i]; 717 cap_len=opt[i+1]; 718 printf("%sCAP %s", i == 0 ? "(" : " ", /* ) */ 719 bgp_capcode(cap_type)); 720 721 /* can we print the capability? */ 722 TCHECK2(opt[i+2],cap_len); 723 i += 2; 724 725 switch(cap_type) { 726 case BGP_CAPCODE_MP: 727 if (cap_len != 4) { 728 printf(" BAD ENCODING"); 729 break; 730 } 731 printf(" [%s %s]", 732 af_name(EXTRACT_16BITS(opt+i)), 733 bgp_attr_nlri_safi(opt[i+3])); 734 break; 735 case BGP_CAPCODE_REFRESH: 736 if (cap_len != 0) { 737 printf(" BAD ENCODING"); 738 break; 739 } 740 break; 741 case BGP_CAPCODE_RESTART: 742 if (cap_len < 2 || (cap_len - 2) % 4) { 743 printf(" BAD ENCODING"); 744 break; 745 } 746 printf(" [%s], Time %us", 747 ((opt[i])&0x80) ? "R" : "none", 748 EXTRACT_16BITS(opt+i)&0xfff); 749 tcap_len=cap_len - 2; 750 cap_offset=2; 751 while(tcap_len>=4) { 752 printf(" (%s %s)%s", 753 af_name(EXTRACT_16BITS(opt+i+cap_offset)), 754 bgp_attr_nlri_safi(opt[i+cap_offset+2]), 755 ((opt[i+cap_offset+3])&0x80) ? 756 " forwarding state preserved" : "" ); 757 tcap_len-=4; 758 cap_offset+=4; 759 } 760 break; 761 case BGP_CAPCODE_AS4: 762 if (cap_len != 4) { 763 printf(" BAD ENCODING"); 764 break; 765 } 766 printf(" #"); 767 if (EXTRACT_16BITS(opt+i)) 768 printf("%u.", 769 EXTRACT_16BITS(opt+i)); 770 printf("%u", 771 EXTRACT_16BITS(opt+i+2)); 772 break; 773 default: 774 printf(" len %d", cap_len); 775 break; 776 } 777 i += cap_len; 778 if (i + cap_len < length) 779 printf(","); 780 } 781 /* ( */ 782 printf(")"); 783 return; 784 trunc: 785 printf("[|BGP]"); 786 } 787 788 static void 789 bgp_open_print(const u_char *dat, int length) 790 { 791 struct bgp_open bgpo; 792 struct bgp_opt bgpopt; 793 const u_char *opt; 794 int i; 795 796 TCHECK2(dat[0], BGP_OPEN_SIZE); 797 memcpy(&bgpo, dat, BGP_OPEN_SIZE); 798 799 printf(": Version %d,", bgpo.bgpo_version); 800 printf(" AS #%u,", ntohs(bgpo.bgpo_myas)); 801 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)); 802 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id)); 803 printf(" Option length %u", bgpo.bgpo_optlen); 804 805 /* sanity checking */ 806 if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) || (!bgpo.bgpo_optlen)) 807 return; 808 809 /* ugly! */ 810 opt = &((const struct bgp_open *)dat)->bgpo_optlen; 811 opt++; 812 813 i = 0; 814 while (i < bgpo.bgpo_optlen) { 815 TCHECK2(opt[i], BGP_OPT_SIZE); 816 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); 817 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { 818 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); 819 break; 820 } 821 822 if (i == 0) 823 printf(" ("); /* ) */ 824 else 825 printf(" "); 826 827 switch(bgpopt.bgpopt_type) { 828 case BGP_OPT_CAP: 829 bgp_open_capa_print(opt + i + BGP_OPT_SIZE, 830 bgpopt.bgpopt_len); 831 break; 832 default: 833 printf(" (option %s, len=%u)", 834 bgp_opttype(bgpopt.bgpopt_type), 835 bgpopt.bgpopt_len); 836 break; 837 } 838 839 i += BGP_OPT_SIZE + bgpopt.bgpopt_len; 840 } 841 /* ( */ 842 printf(")"); 843 return; 844 trunc: 845 printf("[|BGP]"); 846 } 847 848 static void 849 bgp_update_print(const u_char *dat, int length) 850 { 851 struct bgp bgp; 852 struct bgp_attr bgpa; 853 const u_char *p; 854 int len; 855 int i; 856 int newline; 857 858 TCHECK2(dat[0], BGP_SIZE); 859 memcpy(&bgp, dat, BGP_SIZE); 860 p = dat + BGP_SIZE; /*XXX*/ 861 printf(":"); 862 863 /* Unfeasible routes */ 864 len = EXTRACT_16BITS(p); 865 if (len) { 866 /* 867 * Without keeping state from the original NLRI message, 868 * it's not possible to tell if this a v4 or v6 route, 869 * so only try to decode it if we're not v6 enabled. 870 */ 871 #ifdef INET6 872 printf(" (Withdrawn routes: %d bytes)", len); 873 #else 874 char buf[HOST_NAME_MAX+1 + 100]; 875 int wpfx; 876 877 TCHECK2(p[2], len); 878 i = 2; 879 880 printf(" (Withdrawn routes:"); 881 882 while(i < 2 + len) { 883 wpfx = decode_prefix4(&p[i], buf, sizeof(buf)); 884 if (wpfx == -1) { 885 printf(" (illegal prefix length)"); 886 break; 887 } else if (wpfx == -2) 888 goto trunc; 889 i += wpfx; 890 printf(" %s", buf); 891 } 892 printf(")"); 893 #endif 894 } 895 p += 2 + len; 896 897 TCHECK2(p[0], 2); 898 len = EXTRACT_16BITS(p); 899 900 if (len == 0 && length == BGP_UPDATE_MINSIZE) { 901 printf(" End-of-Rib Marker (empty NLRI)"); 902 return; 903 } 904 905 if (len) { 906 /* do something more useful!*/ 907 i = 2; 908 printf(" (Path attributes:"); /* ) */ 909 newline = 0; 910 while (i < 2 + len) { 911 int alen, aoff; 912 913 TCHECK2(p[i], sizeof(bgpa)); 914 memcpy(&bgpa, &p[i], sizeof(bgpa)); 915 alen = bgp_attr_len(&bgpa); 916 aoff = bgp_attr_off(&bgpa); 917 918 if (vflag && newline) 919 printf("\n\t\t"); 920 else 921 printf(" "); 922 printf("("); /* ) */ 923 printf("%s", bgp_attr_type(bgpa.bgpa_type)); 924 if (bgpa.bgpa_flags) { 925 printf("[%s%s%s%s", 926 bgpa.bgpa_flags & 0x80 ? "O" : "", 927 bgpa.bgpa_flags & 0x40 ? "T" : "", 928 bgpa.bgpa_flags & 0x20 ? "P" : "", 929 bgpa.bgpa_flags & 0x10 ? "E" : ""); 930 if (bgpa.bgpa_flags & 0xf) 931 printf("+%x", bgpa.bgpa_flags & 0xf); 932 printf("]"); 933 } 934 935 if (!bgp_attr_print(&bgpa, &p[i + aoff], alen)) 936 goto trunc; 937 newline = 1; 938 939 /* ( */ 940 printf(")"); 941 942 i += aoff + alen; 943 } 944 945 /* ( */ 946 printf(")"); 947 } 948 p += 2 + len; 949 950 if (len && dat + length > p) 951 printf("\n\t\t"); 952 if (dat + length > p) { 953 printf("(NLRI:"); /* ) */ 954 while (dat + length > p) { 955 char buf[HOST_NAME_MAX+1 + 100]; 956 i = decode_prefix4(p, buf, sizeof(buf)); 957 if (i == -1) { 958 printf(" (illegal prefix length)"); 959 break; 960 } else if (i == -2) 961 goto trunc; 962 printf(" %s", buf); 963 p += i; 964 } 965 966 /* ( */ 967 printf(")"); 968 } 969 return; 970 trunc: 971 printf("[|BGP]"); 972 } 973 974 static void 975 bgp_notification_print(const u_char *dat, int length) 976 { 977 struct bgp_notification bgpn; 978 u_int16_t af; 979 u_int8_t safi; 980 const u_char *p; 981 982 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); 983 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); 984 985 /* sanity checking */ 986 if (length<BGP_NOTIFICATION_SIZE) 987 return; 988 989 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)); 990 printf(" subcode %s", 991 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); 992 993 if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE) { 994 /* 995 * RFC 4486: optional maxprefix subtype of 7 bytes 996 * may contain AFI, SAFI and MAXPREFIXES 997 */ 998 if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && 999 length >= BGP_NOTIFICATION_SIZE + 7) { 1000 1001 p = dat + BGP_NOTIFICATION_SIZE; 1002 TCHECK2(*p, 7); 1003 1004 af = EXTRACT_16BITS(p); 1005 safi = p[2]; 1006 printf(" %s %s,", af_name(af), 1007 bgp_attr_nlri_safi(safi)); 1008 1009 printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3)); 1010 } 1011 } 1012 1013 return; 1014 trunc: 1015 printf("[|BGP]"); 1016 } 1017 1018 static void 1019 bgp_route_refresh_print(const u_char *dat, int length) 1020 { 1021 const struct bgp_route_refresh *bgp_route_refresh_header; 1022 1023 TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE); 1024 1025 /* sanity checking */ 1026 if (length<BGP_ROUTE_REFRESH_SIZE) 1027 return; 1028 1029 bgp_route_refresh_header = (const struct bgp_route_refresh *)dat; 1030 1031 printf(" (%s %s)", 1032 af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi)), 1033 bgp_attr_nlri_safi(bgp_route_refresh_header->safi)); 1034 1035 return; 1036 trunc: 1037 printf("[|BGP]"); 1038 } 1039 1040 static int 1041 bgp_header_print(const u_char *dat, int length) 1042 { 1043 struct bgp bgp; 1044 1045 TCHECK2(dat[0], BGP_SIZE); 1046 memcpy(&bgp, dat, BGP_SIZE); 1047 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */ 1048 1049 switch (bgp.bgp_type) { 1050 case BGP_OPEN: 1051 bgp_open_print(dat, length); 1052 break; 1053 case BGP_UPDATE: 1054 bgp_update_print(dat, length); 1055 break; 1056 case BGP_NOTIFICATION: 1057 bgp_notification_print(dat, length); 1058 break; 1059 case BGP_KEEPALIVE: 1060 break; 1061 case BGP_ROUTE_REFRESH: 1062 bgp_route_refresh_print(dat, length); 1063 default: 1064 TCHECK2(*dat, length); 1065 break; 1066 } 1067 1068 /* ( */ 1069 printf(")"); 1070 return 1; 1071 trunc: 1072 printf("[|BGP]"); 1073 return 0; 1074 } 1075 1076 void 1077 bgp_print(const u_char *dat, int length) 1078 { 1079 const u_char *p; 1080 const u_char *ep; 1081 const u_char *start; 1082 const u_char marker[] = { 1083 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1084 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1085 }; 1086 struct bgp bgp; 1087 u_int16_t hlen; 1088 int newline; 1089 1090 ep = dat + length; 1091 if (snapend < dat + length) 1092 ep = snapend; 1093 1094 printf(": BGP"); 1095 1096 p = dat; 1097 newline = 0; 1098 start = p; 1099 while (p < ep) { 1100 if (!TTEST2(p[0], 1)) 1101 break; 1102 if (p[0] != 0xff) { 1103 p++; 1104 continue; 1105 } 1106 1107 if (!TTEST2(p[0], sizeof(marker))) 1108 break; 1109 if (memcmp(p, marker, sizeof(marker)) != 0) { 1110 p++; 1111 continue; 1112 } 1113 1114 /* found BGP header */ 1115 TCHECK2(p[0], BGP_SIZE); /*XXX*/ 1116 memcpy(&bgp, p, BGP_SIZE); 1117 1118 if (start != p) 1119 printf(" [|BGP]"); 1120 1121 hlen = ntohs(bgp.bgp_len); 1122 if (vflag && newline) 1123 printf("\n\t"); 1124 else 1125 printf(" "); 1126 if (hlen < BGP_SIZE) { 1127 printf("\n[|BGP Bogus header length %u < %u]", 1128 hlen, BGP_SIZE); 1129 break; 1130 } 1131 if (TTEST2(p[0], hlen)) { 1132 if (!bgp_header_print(p, hlen)) 1133 return; 1134 newline = 1; 1135 p += hlen; 1136 start = p; 1137 } else { 1138 printf("[|BGP %s]", bgp_type(bgp.bgp_type)); 1139 break; 1140 } 1141 } 1142 1143 return; 1144 1145 trunc: 1146 printf(" [|BGP]"); 1147 } 1148