1 /* $OpenBSD: mrtparser.c,v 1.9 2018/07/20 12:49:49 claudio Exp $ */ 2 /* 3 * Copyright (c) 2011 Claudio Jeker <claudio@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include <sys/types.h> 18 #include <sys/socket.h> 19 #include <netinet/in.h> 20 #include <err.h> 21 #include <errno.h> 22 #include <limits.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <time.h> 27 #include <unistd.h> 28 29 #include "mrt.h" 30 #include "mrtparser.h" 31 32 void *mrt_read_msg(int, struct mrt_hdr *); 33 size_t mrt_read_buf(int, void *, size_t); 34 35 struct mrt_peer *mrt_parse_v2_peer(struct mrt_hdr *, void *); 36 struct mrt_rib *mrt_parse_v2_rib(struct mrt_hdr *, void *); 37 int mrt_parse_dump(struct mrt_hdr *, void *, struct mrt_peer **, 38 struct mrt_rib **); 39 int mrt_parse_dump_mp(struct mrt_hdr *, void *, struct mrt_peer **, 40 struct mrt_rib **); 41 int mrt_extract_attr(struct mrt_rib_entry *, u_char *, int, sa_family_t, 42 int); 43 44 void mrt_free_peers(struct mrt_peer *); 45 void mrt_free_rib(struct mrt_rib *); 46 void mrt_free_bgp_state(struct mrt_bgp_state *); 47 void mrt_free_bgp_msg(struct mrt_bgp_msg *); 48 49 u_char *mrt_aspath_inflate(void *, u_int16_t, u_int16_t *); 50 int mrt_extract_addr(void *, u_int, union mrt_addr *, sa_family_t); 51 52 struct mrt_bgp_state *mrt_parse_state(struct mrt_hdr *, void *); 53 struct mrt_bgp_msg *mrt_parse_msg(struct mrt_hdr *, void *); 54 55 void * 56 mrt_read_msg(int fd, struct mrt_hdr *hdr) 57 { 58 void *buf; 59 60 bzero(hdr, sizeof(*hdr)); 61 if (mrt_read_buf(fd, hdr, sizeof(*hdr)) != sizeof(*hdr)) 62 return (NULL); 63 64 if ((buf = malloc(ntohl(hdr->length))) == NULL) 65 err(1, "malloc(%d)", hdr->length); 66 67 if (mrt_read_buf(fd, buf, ntohl(hdr->length)) != ntohl(hdr->length)) { 68 free(buf); 69 return (NULL); 70 } 71 return (buf); 72 } 73 74 size_t 75 mrt_read_buf(int fd, void *buf, size_t len) 76 { 77 char *b = buf; 78 ssize_t n; 79 80 while (len > 0) { 81 if ((n = read(fd, b, len)) == -1) { 82 if (errno == EINTR) 83 continue; 84 err(1, "read"); 85 } 86 if (n == 0) 87 break; 88 b += n; 89 len -= n; 90 } 91 92 return (b - (char *)buf); 93 } 94 95 void 96 mrt_parse(int fd, struct mrt_parser *p, int verbose) 97 { 98 struct mrt_hdr h; 99 struct mrt_peer *pctx = NULL; 100 struct mrt_rib *r; 101 struct mrt_bgp_state *s; 102 struct mrt_bgp_msg *m; 103 void *msg; 104 105 while ((msg = mrt_read_msg(fd, &h))) { 106 switch (ntohs(h.type)) { 107 case MSG_NULL: 108 case MSG_START: 109 case MSG_DIE: 110 case MSG_I_AM_DEAD: 111 case MSG_PEER_DOWN: 112 case MSG_PROTOCOL_BGP: 113 case MSG_PROTOCOL_IDRP: 114 case MSG_PROTOCOL_BGP4PLUS: 115 case MSG_PROTOCOL_BGP4PLUS1: 116 if (verbose) 117 printf("deprecated MRT type %d\n", 118 ntohs(h.type)); 119 break; 120 case MSG_PROTOCOL_RIP: 121 case MSG_PROTOCOL_RIPNG: 122 case MSG_PROTOCOL_OSPF: 123 case MSG_PROTOCOL_ISIS_ET: 124 case MSG_PROTOCOL_ISIS: 125 case MSG_PROTOCOL_OSPFV3_ET: 126 case MSG_PROTOCOL_OSPFV3: 127 if (verbose) 128 printf("unsuported MRT type %d\n", 129 ntohs(h.type)); 130 break; 131 case MSG_TABLE_DUMP: 132 switch (ntohs(h.subtype)) { 133 case MRT_DUMP_AFI_IP: 134 case MRT_DUMP_AFI_IPv6: 135 if (p->dump == NULL) 136 break; 137 if (mrt_parse_dump(&h, msg, &pctx, &r) == 0) { 138 if (p->dump) 139 p->dump(r, pctx, p->arg); 140 mrt_free_rib(r); 141 } 142 break; 143 default: 144 if (verbose) 145 printf("unknown AFI %d in table dump\n", 146 ntohs(h.subtype)); 147 break; 148 } 149 break; 150 case MSG_TABLE_DUMP_V2: 151 switch (ntohs(h.subtype)) { 152 case MRT_DUMP_V2_PEER_INDEX_TABLE: 153 if (p->dump == NULL) 154 break; 155 if (pctx) 156 mrt_free_peers(pctx); 157 pctx = mrt_parse_v2_peer(&h, msg); 158 break; 159 case MRT_DUMP_V2_RIB_IPV4_UNICAST: 160 case MRT_DUMP_V2_RIB_IPV4_MULTICAST: 161 case MRT_DUMP_V2_RIB_IPV6_UNICAST: 162 case MRT_DUMP_V2_RIB_IPV6_MULTICAST: 163 case MRT_DUMP_V2_RIB_GENERIC: 164 if (p->dump == NULL) 165 break; 166 r = mrt_parse_v2_rib(&h, msg); 167 if (r) { 168 if (p->dump) 169 p->dump(r, pctx, p->arg); 170 mrt_free_rib(r); 171 } 172 break; 173 default: 174 if (verbose) 175 printf("unhandled BGP4MP subtype %d\n", 176 ntohs(h.subtype)); 177 break; 178 } 179 break; 180 case MSG_PROTOCOL_BGP4MP_ET: 181 case MSG_PROTOCOL_BGP4MP: 182 switch (ntohs(h.subtype)) { 183 case BGP4MP_STATE_CHANGE: 184 case BGP4MP_STATE_CHANGE_AS4: 185 if ((s = mrt_parse_state(&h, msg))) { 186 if (p->state) 187 p->state(s, p->arg); 188 free(s); 189 } 190 break; 191 case BGP4MP_MESSAGE: 192 case BGP4MP_MESSAGE_AS4: 193 case BGP4MP_MESSAGE_LOCAL: 194 case BGP4MP_MESSAGE_AS4_LOCAL: 195 if ((m = mrt_parse_msg(&h, msg))) { 196 if (p->message) 197 p->message(m, p->arg); 198 free(m->msg); 199 free(m); 200 } 201 break; 202 case BGP4MP_ENTRY: 203 if (p->dump == NULL) 204 break; 205 if (mrt_parse_dump_mp(&h, msg, &pctx, &r) == 206 0) { 207 if (p->dump) 208 p->dump(r, pctx, p->arg); 209 mrt_free_rib(r); 210 } 211 break; 212 default: 213 if (verbose) 214 printf("unhandled BGP4MP subtype %d\n", 215 ntohs(h.subtype)); 216 break; 217 } 218 break; 219 default: 220 if (verbose) 221 printf("unknown MRT type %d\n", ntohs(h.type)); 222 break; 223 } 224 free(msg); 225 } 226 if (pctx) 227 mrt_free_peers(pctx); 228 } 229 230 struct mrt_peer * 231 mrt_parse_v2_peer(struct mrt_hdr *hdr, void *msg) 232 { 233 struct mrt_peer_entry *peers = NULL; 234 struct mrt_peer *p; 235 u_int8_t *b = msg; 236 u_int32_t bid, as4; 237 u_int16_t cnt, i, as2; 238 u_int len = ntohl(hdr->length); 239 240 if (len < 8) /* min msg size */ 241 return NULL; 242 243 p = calloc(1, sizeof(struct mrt_peer)); 244 if (p == NULL) 245 err(1, "calloc"); 246 247 /* collector bgp id */ 248 memcpy(&bid, b, sizeof(bid)); 249 b += sizeof(bid); 250 len -= sizeof(bid); 251 p->bgp_id = ntohl(bid); 252 253 /* view name length */ 254 memcpy(&cnt, b, sizeof(cnt)); 255 b += sizeof(cnt); 256 len -= sizeof(cnt); 257 cnt = ntohs(cnt); 258 259 /* view name */ 260 if (cnt > len) 261 goto fail; 262 if (cnt != 0) { 263 if ((p->view = malloc(cnt + 1)) == NULL) 264 err(1, "malloc"); 265 memcpy(p->view, b, cnt); 266 p->view[cnt] = 0; 267 } else 268 if ((p->view = strdup("")) == NULL) 269 err(1, "strdup"); 270 b += cnt; 271 len -= cnt; 272 273 /* peer_count */ 274 if (len < sizeof(cnt)) 275 goto fail; 276 memcpy(&cnt, b, sizeof(cnt)); 277 b += sizeof(cnt); 278 len -= sizeof(cnt); 279 cnt = ntohs(cnt); 280 281 /* peer entries */ 282 if ((peers = calloc(cnt, sizeof(struct mrt_peer_entry))) == NULL) 283 err(1, "calloc"); 284 for (i = 0; i < cnt; i++) { 285 u_int8_t type; 286 287 if (len < sizeof(u_int8_t) + sizeof(u_int32_t)) 288 goto fail; 289 type = *b++; 290 len -= 1; 291 memcpy(&bid, b, sizeof(bid)); 292 b += sizeof(bid); 293 len -= sizeof(bid); 294 peers[i].bgp_id = ntohl(bid); 295 296 if (type & MRT_DUMP_V2_PEER_BIT_I) { 297 if (mrt_extract_addr(b, len, &peers[i].addr, 298 AF_INET6) == -1) 299 goto fail; 300 b += sizeof(struct in6_addr); 301 len -= sizeof(struct in6_addr); 302 } else { 303 if (mrt_extract_addr(b, len, &peers[i].addr, 304 AF_INET) == -1) 305 goto fail; 306 b += sizeof(struct in_addr); 307 len -= sizeof(struct in_addr); 308 } 309 310 if (type & MRT_DUMP_V2_PEER_BIT_A) { 311 memcpy(&as4, b, sizeof(as4)); 312 b += sizeof(as4); 313 len -= sizeof(as4); 314 as4 = ntohl(as4); 315 } else { 316 memcpy(&as2, b, sizeof(as2)); 317 b += sizeof(as2); 318 len -= sizeof(as2); 319 as4 = ntohs(as2); 320 } 321 peers[i].asnum = as4; 322 } 323 p->peers = peers; 324 p->npeers = cnt; 325 return (p); 326 fail: 327 mrt_free_peers(p); 328 free(peers); 329 return (NULL); 330 } 331 332 struct mrt_rib * 333 mrt_parse_v2_rib(struct mrt_hdr *hdr, void *msg) 334 { 335 struct mrt_rib_entry *entries = NULL; 336 struct mrt_rib *r; 337 u_int8_t *b = msg; 338 u_int len = ntohl(hdr->length); 339 u_int32_t snum; 340 u_int16_t cnt, i; 341 u_int8_t plen; 342 343 if (len < sizeof(snum) + 1) 344 return NULL; 345 346 r = calloc(1, sizeof(struct mrt_rib)); 347 if (r == NULL) 348 err(1, "calloc"); 349 350 /* seq_num */ 351 memcpy(&snum, b, sizeof(snum)); 352 b += sizeof(snum); 353 len -= sizeof(snum); 354 r->seqnum = ntohl(snum); 355 356 switch (ntohs(hdr->subtype)) { 357 case MRT_DUMP_V2_RIB_IPV4_UNICAST: 358 case MRT_DUMP_V2_RIB_IPV4_MULTICAST: 359 plen = *b++; 360 len -= 1; 361 if (len < MRT_PREFIX_LEN(plen)) 362 goto fail; 363 r->prefix.sin.sin_family = AF_INET; 364 r->prefix.sin.sin_len = sizeof(struct sockaddr_in); 365 memcpy(&r->prefix.sin.sin_addr, b, MRT_PREFIX_LEN(plen)); 366 b += MRT_PREFIX_LEN(plen); 367 len -= MRT_PREFIX_LEN(plen); 368 r->prefixlen = plen; 369 break; 370 case MRT_DUMP_V2_RIB_IPV6_UNICAST: 371 case MRT_DUMP_V2_RIB_IPV6_MULTICAST: 372 plen = *b++; 373 len -= 1; 374 if (len < MRT_PREFIX_LEN(plen)) 375 goto fail; 376 r->prefix.sin6.sin6_family = AF_INET6; 377 r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6); 378 memcpy(&r->prefix.sin6.sin6_addr, b, MRT_PREFIX_LEN(plen)); 379 b += MRT_PREFIX_LEN(plen); 380 len -= MRT_PREFIX_LEN(plen); 381 r->prefixlen = plen; 382 break; 383 case MRT_DUMP_V2_RIB_GENERIC: 384 /* XXX unhandled */ 385 errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented"); 386 goto fail; 387 } 388 389 /* entries count */ 390 if (len < sizeof(cnt)) 391 goto fail; 392 memcpy(&cnt, b, sizeof(cnt)); 393 b += sizeof(cnt); 394 len -= sizeof(cnt); 395 cnt = ntohs(cnt); 396 r->nentries = cnt; 397 398 /* entries */ 399 if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL) 400 err(1, "calloc"); 401 for (i = 0; i < cnt; i++) { 402 u_int32_t otm; 403 u_int16_t pix, alen; 404 if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t)) 405 goto fail; 406 /* peer index */ 407 memcpy(&pix, b, sizeof(pix)); 408 b += sizeof(pix); 409 len -= sizeof(pix); 410 entries[i].peer_idx = ntohs(pix); 411 412 /* originated */ 413 memcpy(&otm, b, sizeof(otm)); 414 b += sizeof(otm); 415 len -= sizeof(otm); 416 entries[i].originated = ntohl(otm); 417 418 /* attr_len */ 419 memcpy(&alen, b, sizeof(alen)); 420 b += sizeof(alen); 421 len -= sizeof(alen); 422 alen = ntohs(alen); 423 424 /* attr */ 425 if (len < alen) 426 goto fail; 427 if (mrt_extract_attr(&entries[i], b, alen, 428 r->prefix.sa.sa_family, 1) == -1) 429 goto fail; 430 b += alen; 431 len -= alen; 432 } 433 r->entries = entries; 434 return (r); 435 fail: 436 mrt_free_rib(r); 437 free(entries); 438 return (NULL); 439 } 440 441 int 442 mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, 443 struct mrt_rib **rp) 444 { 445 struct mrt_peer *p; 446 struct mrt_rib *r; 447 struct mrt_rib_entry *re; 448 u_int8_t *b = msg; 449 u_int len = ntohl(hdr->length); 450 u_int16_t asnum, alen; 451 452 if (*pp == NULL) { 453 *pp = calloc(1, sizeof(struct mrt_peer)); 454 if (*pp == NULL) 455 err(1, "calloc"); 456 (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); 457 if ((*pp)->peers == NULL) 458 err(1, "calloc"); 459 (*pp)->npeers = 1; 460 } 461 p = *pp; 462 463 *rp = r = calloc(1, sizeof(struct mrt_rib)); 464 if (r == NULL) 465 err(1, "calloc"); 466 re = calloc(1, sizeof(struct mrt_rib_entry)); 467 if (re == NULL) 468 err(1, "calloc"); 469 r->nentries = 1; 470 r->entries = re; 471 472 if (len < 2 * sizeof(u_int16_t)) 473 goto fail; 474 /* view */ 475 b += sizeof(u_int16_t); 476 len -= sizeof(u_int16_t); 477 /* seqnum */ 478 memcpy(&r->seqnum, b, sizeof(u_int16_t)); 479 b += sizeof(u_int16_t); 480 len -= sizeof(u_int16_t); 481 r->seqnum = ntohs(r->seqnum); 482 483 switch (ntohs(hdr->subtype)) { 484 case MRT_DUMP_AFI_IP: 485 if (mrt_extract_addr(b, len, &r->prefix, AF_INET) == -1) 486 goto fail; 487 b += sizeof(struct in_addr); 488 len -= sizeof(struct in_addr); 489 break; 490 case MRT_DUMP_AFI_IPv6: 491 if (mrt_extract_addr(b, len, &r->prefix, AF_INET6) == -1) 492 goto fail; 493 b += sizeof(struct in6_addr); 494 len -= sizeof(struct in6_addr); 495 break; 496 } 497 if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2) 498 goto fail; 499 r->prefixlen = *b++; 500 len -= 1; 501 /* status */ 502 b += 1; 503 len -= 1; 504 /* originated */ 505 memcpy(&re->originated, b, sizeof(u_int32_t)); 506 b += sizeof(u_int32_t); 507 len -= sizeof(u_int32_t); 508 re->originated = ntohl(re->originated); 509 /* peer ip */ 510 switch (ntohs(hdr->subtype)) { 511 case MRT_DUMP_AFI_IP: 512 if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1) 513 goto fail; 514 b += sizeof(struct in_addr); 515 len -= sizeof(struct in_addr); 516 break; 517 case MRT_DUMP_AFI_IPv6: 518 if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1) 519 goto fail; 520 b += sizeof(struct in6_addr); 521 len -= sizeof(struct in6_addr); 522 break; 523 } 524 memcpy(&asnum, b, sizeof(asnum)); 525 b += sizeof(asnum); 526 len -= sizeof(asnum); 527 p->peers->asnum = ntohs(asnum); 528 529 memcpy(&alen, b, sizeof(alen)); 530 b += sizeof(alen); 531 len -= sizeof(alen); 532 alen = ntohs(alen); 533 534 /* attr */ 535 if (len < alen) 536 goto fail; 537 if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1) 538 goto fail; 539 b += alen; 540 len -= alen; 541 542 return (0); 543 fail: 544 mrt_free_rib(r); 545 return (-1); 546 } 547 548 int 549 mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, 550 struct mrt_rib **rp) 551 { 552 struct mrt_peer *p; 553 struct mrt_rib *r; 554 struct mrt_rib_entry *re; 555 u_int8_t *b = msg; 556 u_int len = ntohl(hdr->length); 557 u_int16_t asnum, alen, afi; 558 u_int8_t safi, nhlen; 559 sa_family_t af; 560 561 /* just ignore the microsec field for _ET header for now */ 562 if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { 563 b = (char *)b + sizeof(u_int32_t); 564 len -= sizeof(u_int32_t); 565 } 566 567 if (*pp == NULL) { 568 *pp = calloc(1, sizeof(struct mrt_peer)); 569 if (*pp == NULL) 570 err(1, "calloc"); 571 (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); 572 if ((*pp)->peers == NULL) 573 err(1, "calloc"); 574 (*pp)->npeers = 1; 575 } 576 p = *pp; 577 578 *rp = r = calloc(1, sizeof(struct mrt_rib)); 579 if (r == NULL) 580 err(1, "calloc"); 581 re = calloc(1, sizeof(struct mrt_rib_entry)); 582 if (re == NULL) 583 err(1, "calloc"); 584 r->nentries = 1; 585 r->entries = re; 586 587 if (len < 4 * sizeof(u_int16_t)) 588 goto fail; 589 /* source AS */ 590 b += sizeof(u_int16_t); 591 len -= sizeof(u_int16_t); 592 /* dest AS */ 593 memcpy(&asnum, b, sizeof(asnum)); 594 b += sizeof(asnum); 595 len -= sizeof(asnum); 596 p->peers->asnum = ntohs(asnum); 597 /* iface index */ 598 b += sizeof(u_int16_t); 599 len -= sizeof(u_int16_t); 600 /* afi */ 601 memcpy(&afi, b, sizeof(afi)); 602 b += sizeof(afi); 603 len -= sizeof(afi); 604 afi = ntohs(afi); 605 606 /* source + dest ip */ 607 switch (afi) { 608 case MRT_DUMP_AFI_IP: 609 if (len < 2 * sizeof(struct in_addr)) 610 goto fail; 611 /* source IP */ 612 b += sizeof(struct in_addr); 613 len -= sizeof(struct in_addr); 614 /* dest IP */ 615 if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET) == -1) 616 goto fail; 617 b += sizeof(struct in_addr); 618 len -= sizeof(struct in_addr); 619 break; 620 case MRT_DUMP_AFI_IPv6: 621 if (len < 2 * sizeof(struct in6_addr)) 622 goto fail; 623 /* source IP */ 624 b += sizeof(struct in6_addr); 625 len -= sizeof(struct in6_addr); 626 /* dest IP */ 627 if (mrt_extract_addr(b, len, &p->peers->addr, AF_INET6) == -1) 628 goto fail; 629 b += sizeof(struct in6_addr); 630 len -= sizeof(struct in6_addr); 631 break; 632 } 633 634 if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t)) 635 goto fail; 636 /* view + status */ 637 b += 2 * sizeof(u_int16_t); 638 len -= 2 * sizeof(u_int16_t); 639 /* originated */ 640 memcpy(&re->originated, b, sizeof(u_int32_t)); 641 b += sizeof(u_int32_t); 642 len -= sizeof(u_int32_t); 643 re->originated = ntohl(re->originated); 644 645 /* afi */ 646 memcpy(&afi, b, sizeof(afi)); 647 b += sizeof(afi); 648 len -= sizeof(afi); 649 afi = ntohs(afi); 650 651 /* safi */ 652 safi = *b++; 653 len -= 1; 654 655 switch (afi) { 656 case MRT_DUMP_AFI_IP: 657 if (safi == 1 || safi == 2) { 658 af = AF_INET; 659 break; 660 } else if (safi == 128) { 661 af = AF_VPNv4; 662 break; 663 } 664 goto fail; 665 case MRT_DUMP_AFI_IPv6: 666 if (safi != 1 && safi != 2) 667 goto fail; 668 af = AF_INET6; 669 break; 670 default: 671 goto fail; 672 } 673 674 /* nhlen */ 675 nhlen = *b++; 676 len -= 1; 677 678 /* nexthop */ 679 if (mrt_extract_addr(b, len, &re->nexthop, af) == -1) 680 goto fail; 681 if (len < nhlen) 682 goto fail; 683 b += nhlen; 684 len -= nhlen; 685 686 if (len < 1) 687 goto fail; 688 r->prefixlen = *b++; 689 len -= 1; 690 691 /* prefix */ 692 switch (af) { 693 case AF_INET: 694 if (len < MRT_PREFIX_LEN(r->prefixlen)) 695 goto fail; 696 r->prefix.sin.sin_family = AF_INET; 697 r->prefix.sin.sin_len = sizeof(struct sockaddr_in); 698 memcpy(&r->prefix.sin.sin_addr, b, 699 MRT_PREFIX_LEN(r->prefixlen)); 700 b += MRT_PREFIX_LEN(r->prefixlen); 701 len -= MRT_PREFIX_LEN(r->prefixlen); 702 break; 703 case AF_INET6: 704 if (len < MRT_PREFIX_LEN(r->prefixlen)) 705 goto fail; 706 r->prefix.sin6.sin6_family = AF_INET6; 707 r->prefix.sin6.sin6_len = sizeof(struct sockaddr_in6); 708 memcpy(&r->prefix.sin6.sin6_addr, b, 709 MRT_PREFIX_LEN(r->prefixlen)); 710 b += MRT_PREFIX_LEN(r->prefixlen); 711 len -= MRT_PREFIX_LEN(r->prefixlen); 712 break; 713 case AF_VPNv4: 714 if (len < MRT_PREFIX_LEN(r->prefixlen)) 715 goto fail; 716 errx(1, "AF_VPNv4 handling not yet implemented"); 717 goto fail; 718 } 719 720 memcpy(&alen, b, sizeof(alen)); 721 b += sizeof(alen); 722 len -= sizeof(alen); 723 alen = ntohs(alen); 724 725 /* attr */ 726 if (len < alen) 727 goto fail; 728 if (mrt_extract_attr(re, b, alen, r->prefix.sa.sa_family, 0) == -1) 729 goto fail; 730 b += alen; 731 len -= alen; 732 733 return (0); 734 fail: 735 mrt_free_rib(r); 736 return (-1); 737 } 738 739 int 740 mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, sa_family_t af, 741 int as4) 742 { 743 struct mrt_attr *ap; 744 u_int32_t tmp; 745 u_int16_t attr_len; 746 u_int8_t type, flags, *attr; 747 748 do { 749 if (alen < 3) 750 return (-1); 751 attr = a; 752 flags = *a++; 753 alen -= 1; 754 type = *a++; 755 alen -= 1; 756 757 if (flags & MRT_ATTR_EXTLEN) { 758 if (alen < 2) 759 return (-1); 760 memcpy(&attr_len, a, sizeof(attr_len)); 761 attr_len = ntohs(attr_len); 762 a += sizeof(attr_len); 763 alen -= sizeof(attr_len); 764 } else { 765 attr_len = *a++; 766 alen -= 1; 767 } 768 switch (type) { 769 case MRT_ATTR_ORIGIN: 770 if (attr_len != 1) 771 return (-1); 772 re->origin = *a; 773 break; 774 case MRT_ATTR_ASPATH: 775 if (as4) { 776 re->aspath_len = attr_len; 777 if ((re->aspath = malloc(attr_len)) == NULL) 778 err(1, "malloc"); 779 memcpy(re->aspath, a, attr_len); 780 } else { 781 re->aspath = mrt_aspath_inflate(a, attr_len, 782 &re->aspath_len); 783 if (re->aspath == NULL) 784 return (-1); 785 } 786 break; 787 case MRT_ATTR_NEXTHOP: 788 if (attr_len != 4) 789 return (-1); 790 if (af != AF_INET) 791 break; 792 memcpy(&tmp, a, sizeof(tmp)); 793 re->nexthop.sin.sin_len = sizeof(struct sockaddr_in); 794 re->nexthop.sin.sin_family = AF_INET; 795 re->nexthop.sin.sin_addr.s_addr = tmp; 796 break; 797 case MRT_ATTR_MED: 798 if (attr_len != 4) 799 return (-1); 800 memcpy(&tmp, a, sizeof(tmp)); 801 re->med = ntohl(tmp); 802 break; 803 case MRT_ATTR_LOCALPREF: 804 if (attr_len != 4) 805 return (-1); 806 memcpy(&tmp, a, sizeof(tmp)); 807 re->local_pref = ntohl(tmp); 808 break; 809 case MRT_ATTR_MP_REACH_NLRI: 810 /* 811 * XXX horrible hack: 812 * Once again IETF and the real world differ in the 813 * implementation. In short the abbreviated MP_NLRI 814 * hack in the standard is not used in real life. 815 * Detect the two cases by looking at the first byte 816 * of the payload (either the nexthop addr length (RFC) 817 * or the high byte of the AFI (old form)). If the 818 * first byte matches the expected nexthop length it 819 * is expected to be the RFC 6396 encoding. 820 */ 821 if (*a != attr_len - 1) { 822 a += 3; 823 alen -= 3; 824 attr_len -= 3; 825 } 826 switch (af) { 827 case AF_INET6: 828 if (attr_len < sizeof(struct in6_addr) + 1) 829 return (-1); 830 re->nexthop.sin6.sin6_len = 831 sizeof(struct sockaddr_in6); 832 re->nexthop.sin6.sin6_family = AF_INET6; 833 memcpy(&re->nexthop.sin6.sin6_addr, a + 1, 834 sizeof(struct in6_addr)); 835 break; 836 case AF_VPNv4: 837 if (attr_len < sizeof(u_int64_t) + 838 sizeof(struct in_addr)) 839 return (-1); 840 re->nexthop.svpn4.sv_len = 841 sizeof(struct sockaddr_vpn4); 842 re->nexthop.svpn4.sv_family = AF_VPNv4; 843 memcpy(&tmp, a + 1 + sizeof(u_int64_t), 844 sizeof(tmp)); 845 re->nexthop.svpn4.sv_addr.s_addr = tmp; 846 break; 847 } 848 break; 849 case MRT_ATTR_AS4PATH: 850 if (!as4) { 851 free(re->aspath); 852 re->aspath_len = attr_len; 853 if ((re->aspath = malloc(attr_len)) == NULL) 854 err(1, "malloc"); 855 memcpy(re->aspath, a, attr_len); 856 break; 857 } 858 /* FALLTHROUGH */ 859 default: 860 re->nattrs++; 861 if (re->nattrs >= UCHAR_MAX) 862 err(1, "too many attributes"); 863 ap = reallocarray(re->attrs, 864 re->nattrs, sizeof(struct mrt_attr)); 865 if (ap == NULL) 866 err(1, "realloc"); 867 re->attrs = ap; 868 ap = re->attrs + re->nattrs - 1; 869 ap->attr_len = a + attr_len - attr; 870 if ((ap->attr = malloc(ap->attr_len)) == NULL) 871 err(1, "malloc"); 872 memcpy(ap->attr, attr, ap->attr_len); 873 break; 874 } 875 a += attr_len; 876 alen -= attr_len; 877 } while (alen > 0); 878 879 return (0); 880 } 881 882 void 883 mrt_free_peers(struct mrt_peer *p) 884 { 885 free(p->peers); 886 free(p->view); 887 free(p); 888 } 889 890 void 891 mrt_free_rib(struct mrt_rib *r) 892 { 893 u_int16_t i, j; 894 895 for (i = 0; i < r->nentries && r->entries; i++) { 896 for (j = 0; j < r->entries[i].nattrs; j++) 897 free(r->entries[i].attrs[j].attr); 898 free(r->entries[i].attrs); 899 free(r->entries[i].aspath); 900 } 901 902 free(r->entries); 903 free(r); 904 } 905 906 void 907 mrt_free_bgp_state(struct mrt_bgp_state *s) 908 { 909 free(s); 910 } 911 912 void 913 mrt_free_bgp_msg(struct mrt_bgp_msg *m) 914 { 915 free(m->msg); 916 free(m); 917 } 918 919 u_char * 920 mrt_aspath_inflate(void *data, u_int16_t len, u_int16_t *newlen) 921 { 922 u_int8_t *seg, *nseg, *ndata; 923 u_int16_t seg_size, olen, nlen; 924 u_int8_t seg_len; 925 926 /* first calculate the length of the aspath */ 927 seg = data; 928 nlen = 0; 929 for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) { 930 seg_len = seg[1]; 931 seg_size = 2 + sizeof(u_int16_t) * seg_len; 932 nlen += 2 + sizeof(u_int32_t) * seg_len; 933 934 if (seg_size > olen) 935 return NULL; 936 } 937 938 *newlen = nlen; 939 if ((ndata = malloc(nlen)) == NULL) 940 err(1, "malloc"); 941 942 /* then copy the aspath */ 943 seg = data; 944 for (nseg = ndata; nseg < ndata + nlen; ) { 945 *nseg++ = *seg++; 946 *nseg++ = seg_len = *seg++; 947 for (; seg_len > 0; seg_len--) { 948 *nseg++ = 0; 949 *nseg++ = 0; 950 *nseg++ = *seg++; 951 *nseg++ = *seg++; 952 } 953 } 954 955 return (ndata); 956 } 957 958 int 959 mrt_extract_addr(void *msg, u_int len, union mrt_addr *addr, sa_family_t af) 960 { 961 u_int8_t *b = msg; 962 963 switch (af) { 964 case AF_INET: 965 if (len < sizeof(struct in_addr)) 966 return (-1); 967 addr->sin.sin_family = AF_INET; 968 addr->sin.sin_len = sizeof(struct sockaddr_in); 969 memcpy(&addr->sin.sin_addr, b, sizeof(struct in_addr)); 970 return sizeof(struct in_addr); 971 case AF_INET6: 972 if (len < sizeof(struct in6_addr)) 973 return (-1); 974 addr->sin6.sin6_family = AF_INET6; 975 addr->sin6.sin6_len = sizeof(struct sockaddr_in6); 976 memcpy(&addr->sin6.sin6_addr, b, sizeof(struct in6_addr)); 977 return sizeof(struct in6_addr); 978 case AF_VPNv4: 979 if (len < sizeof(u_int64_t) + sizeof(struct in_addr)) 980 return (-1); 981 addr->svpn4.sv_len = sizeof(struct sockaddr_vpn4); 982 addr->svpn4.sv_family = AF_VPNv4; 983 memcpy(&addr->svpn4.sv_addr, b + sizeof(u_int64_t), 984 sizeof(struct in_addr)); 985 return (sizeof(u_int64_t) + sizeof(struct in_addr)); 986 default: 987 return (-1); 988 } 989 } 990 991 struct mrt_bgp_state * 992 mrt_parse_state(struct mrt_hdr *hdr, void *msg) 993 { 994 struct timespec t; 995 struct mrt_bgp_state *s; 996 u_int8_t *b = msg; 997 u_int len = ntohl(hdr->length); 998 u_int32_t sas, das, usec; 999 u_int16_t tmp16, afi; 1000 int r; 1001 sa_family_t af; 1002 1003 t.tv_sec = ntohl(hdr->timestamp); 1004 t.tv_nsec = 0; 1005 1006 /* handle the microsec field for _ET header */ 1007 if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { 1008 memcpy(&usec, b, sizeof(usec)); 1009 b += sizeof(usec); 1010 len -= sizeof(usec); 1011 t.tv_nsec = ntohl(usec) * 1000; 1012 } 1013 1014 switch (ntohs(hdr->subtype)) { 1015 case BGP4MP_STATE_CHANGE: 1016 if (len < 8) 1017 return (0); 1018 /* source as */ 1019 memcpy(&tmp16, b, sizeof(tmp16)); 1020 b += sizeof(tmp16); 1021 len -= sizeof(tmp16); 1022 sas = ntohs(tmp16); 1023 /* dest as */ 1024 memcpy(&tmp16, b, sizeof(tmp16)); 1025 b += sizeof(tmp16); 1026 len -= sizeof(tmp16); 1027 das = ntohs(tmp16); 1028 /* if_index, ignored */ 1029 b += sizeof(tmp16); 1030 len -= sizeof(tmp16); 1031 /* afi */ 1032 memcpy(&tmp16, b, sizeof(tmp16)); 1033 b += sizeof(tmp16); 1034 len -= sizeof(tmp16); 1035 afi = ntohs(tmp16); 1036 break; 1037 case BGP4MP_STATE_CHANGE_AS4: 1038 if (len < 12) 1039 return (0); 1040 /* source as */ 1041 memcpy(&sas, b, sizeof(sas)); 1042 b += sizeof(sas); 1043 len -= sizeof(sas); 1044 sas = ntohl(sas); 1045 /* dest as */ 1046 memcpy(&das, b, sizeof(das)); 1047 b += sizeof(das); 1048 len -= sizeof(das); 1049 das = ntohl(das); 1050 /* if_index, ignored */ 1051 b += sizeof(tmp16); 1052 len -= sizeof(tmp16); 1053 /* afi */ 1054 memcpy(&tmp16, b, sizeof(tmp16)); 1055 b += sizeof(tmp16); 1056 len -= sizeof(tmp16); 1057 afi = ntohs(tmp16); 1058 break; 1059 default: 1060 errx(1, "mrt_parse_state: bad subtype"); 1061 } 1062 1063 /* src & dst addr */ 1064 switch (afi) { 1065 case MRT_DUMP_AFI_IP: 1066 af = AF_INET; 1067 break; 1068 case MRT_DUMP_AFI_IPv6: 1069 af = AF_INET6; 1070 break; 1071 default: 1072 errx(1, "mrt_parse_state: bad afi"); 1073 } 1074 1075 if ((s = calloc(1, sizeof(struct mrt_bgp_state))) == NULL) 1076 err(1, "calloc"); 1077 s->time = t; 1078 s->src_as = sas; 1079 s->dst_as = das; 1080 1081 if ((r = mrt_extract_addr(b, len, &s->src, af)) == -1) 1082 goto fail; 1083 b += r; 1084 len -= r; 1085 if ((r = mrt_extract_addr(b, len, &s->dst, af)) == -1) 1086 goto fail; 1087 b += r; 1088 len -= r; 1089 1090 /* states */ 1091 memcpy(&tmp16, b, sizeof(tmp16)); 1092 b += sizeof(tmp16); 1093 len -= sizeof(tmp16); 1094 s->old_state = ntohs(tmp16); 1095 memcpy(&tmp16, b, sizeof(tmp16)); 1096 b += sizeof(tmp16); 1097 len -= sizeof(tmp16); 1098 s->new_state = ntohs(tmp16); 1099 1100 return (s); 1101 1102 fail: 1103 free(s); 1104 return (NULL); 1105 } 1106 1107 struct mrt_bgp_msg * 1108 mrt_parse_msg(struct mrt_hdr *hdr, void *msg) 1109 { 1110 struct timespec t; 1111 struct mrt_bgp_msg *m; 1112 u_int8_t *b = msg; 1113 u_int len = ntohl(hdr->length); 1114 u_int32_t sas, das, usec; 1115 u_int16_t tmp16, afi; 1116 int r; 1117 sa_family_t af; 1118 1119 t.tv_sec = ntohl(hdr->timestamp); 1120 t.tv_nsec = 0; 1121 1122 /* handle the microsec field for _ET header */ 1123 if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { 1124 memcpy(&usec, b, sizeof(usec)); 1125 b += sizeof(usec); 1126 len -= sizeof(usec); 1127 t.tv_nsec = ntohl(usec) * 1000; 1128 } 1129 1130 switch (ntohs(hdr->subtype)) { 1131 case BGP4MP_MESSAGE: 1132 if (len < 8) 1133 return (0); 1134 /* source as */ 1135 memcpy(&tmp16, b, sizeof(tmp16)); 1136 b += sizeof(tmp16); 1137 len -= sizeof(tmp16); 1138 sas = ntohs(tmp16); 1139 /* dest as */ 1140 memcpy(&tmp16, b, sizeof(tmp16)); 1141 b += sizeof(tmp16); 1142 len -= sizeof(tmp16); 1143 das = ntohs(tmp16); 1144 /* if_index, ignored */ 1145 b += sizeof(tmp16); 1146 len -= sizeof(tmp16); 1147 /* afi */ 1148 memcpy(&tmp16, b, sizeof(tmp16)); 1149 b += sizeof(tmp16); 1150 len -= sizeof(tmp16); 1151 afi = ntohs(tmp16); 1152 break; 1153 case BGP4MP_MESSAGE_AS4: 1154 if (len < 12) 1155 return (0); 1156 /* source as */ 1157 memcpy(&sas, b, sizeof(sas)); 1158 b += sizeof(sas); 1159 len -= sizeof(sas); 1160 sas = ntohl(sas); 1161 /* dest as */ 1162 memcpy(&das, b, sizeof(das)); 1163 b += sizeof(das); 1164 len -= sizeof(das); 1165 das = ntohl(das); 1166 /* if_index, ignored */ 1167 b += sizeof(tmp16); 1168 len -= sizeof(tmp16); 1169 /* afi */ 1170 memcpy(&tmp16, b, sizeof(tmp16)); 1171 b += sizeof(tmp16); 1172 len -= sizeof(tmp16); 1173 afi = ntohs(tmp16); 1174 break; 1175 default: 1176 errx(1, "mrt_parse_msg: bad subtype"); 1177 } 1178 1179 /* src & dst addr */ 1180 switch (afi) { 1181 case MRT_DUMP_AFI_IP: 1182 af = AF_INET; 1183 break; 1184 case MRT_DUMP_AFI_IPv6: 1185 af = AF_INET6; 1186 break; 1187 default: 1188 errx(1, "mrt_parse_msg: bad afi"); 1189 } 1190 1191 if ((m = calloc(1, sizeof(struct mrt_bgp_msg))) == NULL) 1192 err(1, "calloc"); 1193 m->time = t; 1194 m->src_as = sas; 1195 m->dst_as = das; 1196 1197 if ((r = mrt_extract_addr(b, len, &m->src, af)) == -1) 1198 goto fail; 1199 b += r; 1200 len -= r; 1201 if ((r = mrt_extract_addr(b, len, &m->dst, af)) == -1) 1202 goto fail; 1203 b += r; 1204 len -= r; 1205 1206 /* msg */ 1207 if (len > 0) { 1208 m->msg_len = len; 1209 if ((m->msg = malloc(len)) == NULL) 1210 err(1, "malloc"); 1211 memcpy(m->msg, b, len); 1212 } 1213 1214 return (m); 1215 1216 fail: 1217 free(m->msg); 1218 free(m); 1219 return (NULL); 1220 } 1221