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