1 /* $OpenBSD: print-bgp.c,v 1.16 2014/01/12 11:26:48 deraadt 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 39 #include <errno.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <netdb.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[MAXHOSTNAMELEN + 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 printf(" empty"); 445 break; 446 } 447 while (p < dat + len) { 448 TCHECK(p[0]); 449 if (asn_bytes == 0) { 450 asn_bytes = (len-2)/p[1]; 451 } 452 printf("%s", 453 tok2str(bgp_as_path_segment_open_values, 454 "?", p[0])); 455 456 for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) { 457 TCHECK2(p[2 + i], asn_bytes); 458 printf("%s", i == 0 ? "" : " "); 459 if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i])) 460 printf("%u%s", 461 EXTRACT_16BITS(&p[2 + i]), 462 asn_bytes == 4 ? "." : ""); 463 if (asn_bytes == 4) 464 printf("%u", 465 EXTRACT_16BITS(&p[2 + i + 2])); 466 } 467 TCHECK(p[0]); 468 printf("%s", 469 tok2str(bgp_as_path_segment_close_values, 470 "?", p[0])); 471 TCHECK(p[1]); 472 p += 2 + p[1] * asn_bytes; 473 } 474 break; 475 case BGPTYPE_NEXT_HOP: 476 if (len != 4) 477 printf(" invalid len"); 478 else { 479 TCHECK2(p[0], 4); 480 printf(" %s", getname(p)); 481 } 482 break; 483 case BGPTYPE_MULTI_EXIT_DISC: 484 case BGPTYPE_LOCAL_PREF: 485 if (len != 4) 486 printf(" invalid len"); 487 else { 488 TCHECK2(p[0], 4); 489 printf(" %u", EXTRACT_32BITS(p)); 490 } 491 break; 492 case BGPTYPE_ATOMIC_AGGREGATE: 493 if (len != 0) 494 printf(" invalid len"); 495 break; 496 case BGPTYPE_AGGREGATOR4: 497 case BGPTYPE_AGGREGATOR: 498 /* 499 * like AS_PATH/AS4_PATH, AGGREGATOR can contain 500 * either 2-byte or 4-byte ASN, and AGGREGATOR4 501 * always contains 4-byte ASN. 502 */ 503 if (len != 6 && len != 8) { 504 printf(" invalid len"); 505 break; 506 } 507 TCHECK2(p[0], len); 508 printf(" AS #"); 509 if (len == 6 || EXTRACT_16BITS(p)) 510 printf("%u%s", EXTRACT_16BITS(p), len == 8 ? "." : ""); 511 if (len == 8) 512 printf("%u", EXTRACT_16BITS(p+2)); 513 printf(", origin %s", getname(p+len-4)); 514 break; 515 case BGPTYPE_COMMUNITIES: 516 if (len % 4) { 517 printf(" invalid len"); 518 break; 519 } 520 while (tlen>0) { 521 u_int32_t comm; 522 TCHECK2(p[0], 4); 523 comm = EXTRACT_32BITS(p); 524 switch (comm) { 525 case BGP_COMMUNITY_NO_EXPORT: 526 printf(" NO_EXPORT"); 527 break; 528 case BGP_COMMUNITY_NO_ADVERT: 529 printf(" NO_ADVERTISE"); 530 break; 531 case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: 532 printf(" NO_EXPORT_SUBCONFED"); 533 break; 534 case BGP_COMMUNITY_NO_PEER: 535 printf(" NO_PEER"); 536 break; 537 default: 538 printf(" %d:%d", 539 (comm >> 16) & 0xffff, comm & 0xffff); 540 break; 541 } 542 tlen -= 4; 543 p += 4; 544 } 545 break; 546 case BGPTYPE_ORIGINATOR_ID: 547 if (len != 4) { 548 printf(" invalid len"); 549 break; 550 } 551 TCHECK2(p[0], 4); 552 printf("%s",getname(p)); 553 break; 554 case BGPTYPE_CLUSTER_LIST: 555 if (len % 4) { 556 printf(" invalid len"); 557 break; 558 } 559 while (tlen>0) { 560 TCHECK2(p[0], 4); 561 printf(" %s%s", 562 getname(p), 563 (tlen>4) ? ", " : ""); 564 tlen -=4; 565 p +=4; 566 } 567 break; 568 case BGPTYPE_MP_REACH_NLRI: 569 TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); 570 af = EXTRACT_16BITS(p); 571 safi = p[2]; 572 if (safi >= 128) 573 printf(" %s vendor specific %u,", af_name(af), safi); 574 else { 575 printf(" %s %s,", af_name(af), 576 bgp_attr_nlri_safi(safi)); 577 } 578 p += 3; 579 580 if (af == AFNUM_INET) 581 ; 582 #ifdef INET6 583 else if (af == AFNUM_INET6) 584 ; 585 #endif 586 else 587 break; 588 589 TCHECK(p[0]); 590 tlen = p[0]; 591 if (tlen) { 592 printf(" nexthop"); 593 i = 0; 594 while (i < tlen) { 595 switch (af) { 596 case AFNUM_INET: 597 TCHECK2(p[1+i], sizeof(struct in_addr)); 598 printf(" %s", getname(p + 1 + i)); 599 i += sizeof(struct in_addr); 600 break; 601 #ifdef INET6 602 case AFNUM_INET6: 603 TCHECK2(p[1+i], sizeof(struct in6_addr)); 604 printf(" %s", getname6(p + 1 + i)); 605 i += sizeof(struct in6_addr); 606 break; 607 #endif 608 default: 609 printf(" (unknown af)"); 610 i = tlen; /*exit loop*/ 611 break; 612 } 613 } 614 printf(","); 615 } 616 p += 1 + tlen; 617 618 TCHECK(p[0]); 619 snpa = p[0]; 620 p++; 621 if (snpa) { 622 printf(" %u snpa", snpa); 623 for (/*nothing*/; snpa > 0; snpa--) { 624 TCHECK(p[0]); 625 printf("(%d bytes)", p[0]); 626 p += p[0] + 1; 627 } 628 printf(","); 629 } 630 631 printf(" NLRI"); 632 while (len - (p - dat) > 0) { 633 switch (af) { 634 case AFNUM_INET: 635 advance = decode_prefix4(p, buf, sizeof(buf)); 636 break; 637 #ifdef INET6 638 case AFNUM_INET6: 639 advance = decode_prefix6(p, buf, sizeof(buf)); 640 break; 641 #endif 642 default: 643 printf(" (unknown af)"); 644 advance = 0; 645 p = dat + len; 646 break; 647 } 648 649 if (advance <= 0) 650 break; 651 652 printf(" %s", buf); 653 p += advance; 654 } 655 656 break; 657 658 case BGPTYPE_MP_UNREACH_NLRI: 659 TCHECK2(p[0], BGP_MP_NLRI_MINSIZE); 660 af = EXTRACT_16BITS(p); 661 safi = p[2]; 662 if (safi >= 128) 663 printf(" %s vendor specific %u,", af_name(af), safi); 664 else { 665 printf(" %s %s,", af_name(af), 666 bgp_attr_nlri_safi(safi)); 667 } 668 p += 3; 669 670 printf(" Withdraw"); 671 while (len - (p - dat) > 0) { 672 switch (af) { 673 case AFNUM_INET: 674 advance = decode_prefix4(p, buf, sizeof(buf)); 675 break; 676 #ifdef INET6 677 case AFNUM_INET6: 678 advance = decode_prefix6(p, buf, sizeof(buf)); 679 break; 680 #endif 681 default: 682 printf(" (unknown af)"); 683 advance = 0; 684 p = dat + len; 685 break; 686 } 687 688 if (advance <= 0) 689 break; 690 691 printf(" %s", buf); 692 p += advance; 693 } 694 break; 695 default: 696 break; 697 } 698 return 1; 699 700 trunc: 701 return 0; 702 } 703 704 static void 705 bgp_open_capa_print(const u_char *opt, int length) 706 { 707 int i,cap_type,cap_len,tcap_len,cap_offset; 708 709 i = 0; 710 while (i < length) { 711 TCHECK2(opt[i], 2); 712 713 cap_type=opt[i]; 714 cap_len=opt[i+1]; 715 printf("%sCAP %s", i == 0 ? "(" : " ", /* ) */ 716 bgp_capcode(cap_type)); 717 718 /* can we print the capability? */ 719 TCHECK2(opt[i+2],cap_len); 720 i += 2; 721 722 switch(cap_type) { 723 case BGP_CAPCODE_MP: 724 if (cap_len != 4) { 725 printf(" BAD ENCODING"); 726 break; 727 } 728 printf(" [%s %s]", 729 af_name(EXTRACT_16BITS(opt+i)), 730 bgp_attr_nlri_safi(opt[i+3])); 731 break; 732 case BGP_CAPCODE_REFRESH: 733 if (cap_len != 0) { 734 printf(" BAD ENCODING"); 735 break; 736 } 737 break; 738 case BGP_CAPCODE_RESTART: 739 if (cap_len < 2 || (cap_len - 2) % 4) { 740 printf(" BAD ENCODING"); 741 break; 742 } 743 printf(" [%s], Time %us", 744 ((opt[i])&0x80) ? "R" : "none", 745 EXTRACT_16BITS(opt+i)&0xfff); 746 tcap_len=cap_len - 2; 747 cap_offset=2; 748 while(tcap_len>=4) { 749 printf(" (%s %s)%s", 750 af_name(EXTRACT_16BITS(opt+i+cap_offset)), 751 bgp_attr_nlri_safi(opt[i+cap_offset+2]), 752 ((opt[i+cap_offset+3])&0x80) ? 753 " forwarding state preserved" : "" ); 754 tcap_len-=4; 755 cap_offset+=4; 756 } 757 break; 758 case BGP_CAPCODE_AS4: 759 if (cap_len != 4) { 760 printf(" BAD ENCODING"); 761 break; 762 } 763 printf(" #"); 764 if (EXTRACT_16BITS(opt+i)) 765 printf("%u.", 766 EXTRACT_16BITS(opt+i)); 767 printf("%u", 768 EXTRACT_16BITS(opt+i+2)); 769 break; 770 default: 771 printf(" len %d", cap_len); 772 break; 773 } 774 i += cap_len; 775 if (i + cap_len < length) 776 printf(","); 777 } 778 /* ( */ 779 printf(")"); 780 return; 781 trunc: 782 printf("[|BGP]"); 783 } 784 785 static void 786 bgp_open_print(const u_char *dat, int length) 787 { 788 struct bgp_open bgpo; 789 struct bgp_opt bgpopt; 790 const u_char *opt; 791 int i; 792 793 TCHECK2(dat[0], BGP_OPEN_SIZE); 794 memcpy(&bgpo, dat, BGP_OPEN_SIZE); 795 796 printf(": Version %d,", bgpo.bgpo_version); 797 printf(" AS #%u,", ntohs(bgpo.bgpo_myas)); 798 printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime)); 799 printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id)); 800 printf(" Option length %u", bgpo.bgpo_optlen); 801 802 /* sanity checking */ 803 if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) || (!bgpo.bgpo_optlen)) 804 return; 805 806 /* ugly! */ 807 opt = &((const struct bgp_open *)dat)->bgpo_optlen; 808 opt++; 809 810 i = 0; 811 while (i < bgpo.bgpo_optlen) { 812 TCHECK2(opt[i], BGP_OPT_SIZE); 813 memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); 814 if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { 815 printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type); 816 break; 817 } 818 819 if (i == 0) 820 printf(" ("); /* ) */ 821 else 822 printf(" "); 823 824 switch(bgpopt.bgpopt_type) { 825 case BGP_OPT_CAP: 826 bgp_open_capa_print(opt + i + BGP_OPT_SIZE, 827 bgpopt.bgpopt_len); 828 break; 829 default: 830 printf(" (option %s, len=%u)", 831 bgp_opttype(bgpopt.bgpopt_type), 832 bgpopt.bgpopt_len); 833 break; 834 } 835 836 i += BGP_OPT_SIZE + bgpopt.bgpopt_len; 837 } 838 /* ( */ 839 printf(")"); 840 return; 841 trunc: 842 printf("[|BGP]"); 843 } 844 845 static void 846 bgp_update_print(const u_char *dat, int length) 847 { 848 struct bgp bgp; 849 struct bgp_attr bgpa; 850 const u_char *p; 851 int len; 852 int i; 853 int newline; 854 855 TCHECK2(dat[0], BGP_SIZE); 856 memcpy(&bgp, dat, BGP_SIZE); 857 p = dat + BGP_SIZE; /*XXX*/ 858 printf(":"); 859 860 /* Unfeasible routes */ 861 len = EXTRACT_16BITS(p); 862 if (len) { 863 /* 864 * Without keeping state from the original NLRI message, 865 * it's not possible to tell if this a v4 or v6 route, 866 * so only try to decode it if we're not v6 enabled. 867 */ 868 #ifdef INET6 869 printf(" (Withdrawn routes: %d bytes)", len); 870 #else 871 char buf[MAXHOSTNAMELEN + 100]; 872 int wpfx; 873 874 TCHECK2(p[2], len); 875 i = 2; 876 877 printf(" (Withdrawn routes:"); 878 879 while(i < 2 + len) { 880 wpfx = decode_prefix4(&p[i], buf, sizeof(buf)); 881 if (wpfx == -1) { 882 printf(" (illegal prefix length)"); 883 break; 884 } else if (wpfx == -2) 885 goto trunc; 886 i += wpfx; 887 printf(" %s", buf); 888 } 889 printf(")"); 890 #endif 891 } 892 p += 2 + len; 893 894 TCHECK2(p[0], 2); 895 len = EXTRACT_16BITS(p); 896 897 if (len == 0 && length == BGP_UPDATE_MINSIZE) { 898 printf(" End-of-Rib Marker (empty NLRI)"); 899 return; 900 } 901 902 if (len) { 903 /* do something more useful!*/ 904 i = 2; 905 printf(" (Path attributes:"); /* ) */ 906 newline = 0; 907 while (i < 2 + len) { 908 int alen, aoff; 909 910 TCHECK2(p[i], sizeof(bgpa)); 911 memcpy(&bgpa, &p[i], sizeof(bgpa)); 912 alen = bgp_attr_len(&bgpa); 913 aoff = bgp_attr_off(&bgpa); 914 915 if (vflag && newline) 916 printf("\n\t\t"); 917 else 918 printf(" "); 919 printf("("); /* ) */ 920 printf("%s", bgp_attr_type(bgpa.bgpa_type)); 921 if (bgpa.bgpa_flags) { 922 printf("[%s%s%s%s", 923 bgpa.bgpa_flags & 0x80 ? "O" : "", 924 bgpa.bgpa_flags & 0x40 ? "T" : "", 925 bgpa.bgpa_flags & 0x20 ? "P" : "", 926 bgpa.bgpa_flags & 0x10 ? "E" : ""); 927 if (bgpa.bgpa_flags & 0xf) 928 printf("+%x", bgpa.bgpa_flags & 0xf); 929 printf("]"); 930 } 931 932 if (!bgp_attr_print(&bgpa, &p[i + aoff], alen)) 933 goto trunc; 934 newline = 1; 935 936 /* ( */ 937 printf(")"); 938 939 i += aoff + alen; 940 } 941 942 /* ( */ 943 printf(")"); 944 } 945 p += 2 + len; 946 947 if (len && dat + length > p) 948 printf("\n\t\t"); 949 if (dat + length > p) { 950 printf("(NLRI:"); /* ) */ 951 while (dat + length > p) { 952 char buf[MAXHOSTNAMELEN + 100]; 953 i = decode_prefix4(p, buf, sizeof(buf)); 954 if (i == -1) { 955 printf(" (illegal prefix length)"); 956 break; 957 } else if (i == -2) 958 goto trunc; 959 printf(" %s", buf); 960 p += i; 961 } 962 963 /* ( */ 964 printf(")"); 965 } 966 return; 967 trunc: 968 printf("[|BGP]"); 969 } 970 971 static void 972 bgp_notification_print(const u_char *dat, int length) 973 { 974 struct bgp_notification bgpn; 975 u_int16_t af; 976 u_int8_t safi; 977 const u_char *p; 978 979 TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); 980 memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); 981 982 /* sanity checking */ 983 if (length<BGP_NOTIFICATION_SIZE) 984 return; 985 986 printf(": error %s,", bgp_notify_major(bgpn.bgpn_major)); 987 printf(" subcode %s", 988 bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor)); 989 990 if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE) { 991 /* 992 * RFC 4486: optional maxprefix subtype of 7 bytes 993 * may contain AFI, SAFI and MAXPREFIXES 994 */ 995 if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && 996 length >= BGP_NOTIFICATION_SIZE + 7) { 997 998 p = dat + BGP_NOTIFICATION_SIZE; 999 TCHECK2(*p, 7); 1000 1001 af = EXTRACT_16BITS(p); 1002 safi = p[2]; 1003 printf(" %s %s,", af_name(af), 1004 bgp_attr_nlri_safi(safi)); 1005 1006 printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3)); 1007 } 1008 } 1009 1010 return; 1011 trunc: 1012 printf("[|BGP]"); 1013 } 1014 1015 static void 1016 bgp_route_refresh_print(const u_char *dat, int length) 1017 { 1018 const struct bgp_route_refresh *bgp_route_refresh_header; 1019 1020 TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE); 1021 1022 /* sanity checking */ 1023 if (length<BGP_ROUTE_REFRESH_SIZE) 1024 return; 1025 1026 bgp_route_refresh_header = (const struct bgp_route_refresh *)dat; 1027 1028 printf(" (%s %s)", 1029 af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi)), 1030 bgp_attr_nlri_safi(bgp_route_refresh_header->safi)); 1031 1032 return; 1033 trunc: 1034 printf("[|BGP]"); 1035 } 1036 1037 static int 1038 bgp_header_print(const u_char *dat, int length) 1039 { 1040 struct bgp bgp; 1041 1042 TCHECK2(dat[0], BGP_SIZE); 1043 memcpy(&bgp, dat, BGP_SIZE); 1044 printf("(%s", bgp_type(bgp.bgp_type)); /* ) */ 1045 1046 switch (bgp.bgp_type) { 1047 case BGP_OPEN: 1048 bgp_open_print(dat, length); 1049 break; 1050 case BGP_UPDATE: 1051 bgp_update_print(dat, length); 1052 break; 1053 case BGP_NOTIFICATION: 1054 bgp_notification_print(dat, length); 1055 break; 1056 case BGP_KEEPALIVE: 1057 break; 1058 case BGP_ROUTE_REFRESH: 1059 bgp_route_refresh_print(dat, length); 1060 default: 1061 TCHECK2(*dat, length); 1062 break; 1063 } 1064 1065 /* ( */ 1066 printf(")"); 1067 return 1; 1068 trunc: 1069 printf("[|BGP]"); 1070 return 0; 1071 } 1072 1073 void 1074 bgp_print(const u_char *dat, int length) 1075 { 1076 const u_char *p; 1077 const u_char *ep; 1078 const u_char *start; 1079 const u_char marker[] = { 1080 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1081 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1082 }; 1083 struct bgp bgp; 1084 u_int16_t hlen; 1085 int newline; 1086 1087 ep = dat + length; 1088 if (snapend < dat + length) 1089 ep = snapend; 1090 1091 printf(": BGP"); 1092 1093 p = dat; 1094 newline = 0; 1095 start = p; 1096 while (p < ep) { 1097 if (!TTEST2(p[0], 1)) 1098 break; 1099 if (p[0] != 0xff) { 1100 p++; 1101 continue; 1102 } 1103 1104 if (!TTEST2(p[0], sizeof(marker))) 1105 break; 1106 if (memcmp(p, marker, sizeof(marker)) != 0) { 1107 p++; 1108 continue; 1109 } 1110 1111 /* found BGP header */ 1112 TCHECK2(p[0], BGP_SIZE); /*XXX*/ 1113 memcpy(&bgp, p, BGP_SIZE); 1114 1115 if (start != p) 1116 printf(" [|BGP]"); 1117 1118 hlen = ntohs(bgp.bgp_len); 1119 if (vflag && newline) 1120 printf("\n\t"); 1121 else 1122 printf(" "); 1123 if (hlen < BGP_SIZE) { 1124 printf("\n[|BGP Bogus header length %u < %u]", 1125 hlen, BGP_SIZE); 1126 break; 1127 } 1128 if (TTEST2(p[0], hlen)) { 1129 if (!bgp_header_print(p, hlen)) 1130 return; 1131 newline = 1; 1132 p += hlen; 1133 start = p; 1134 } else { 1135 printf("[|BGP %s]", bgp_type(bgp.bgp_type)); 1136 break; 1137 } 1138 } 1139 1140 return; 1141 1142 trunc: 1143 printf(" [|BGP]"); 1144 } 1145