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