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