1 /* $OpenBSD: mrtparser.c,v 1.10 2019/02/25 11:51:58 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, u_int8_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, struct bgpd_addr *, u_int8_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 DUMP_V2 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 AID_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 AID_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.aid = AID_INET; 364 memcpy(&r->prefix.v4, b, MRT_PREFIX_LEN(plen)); 365 b += MRT_PREFIX_LEN(plen); 366 len -= MRT_PREFIX_LEN(plen); 367 r->prefixlen = plen; 368 break; 369 case MRT_DUMP_V2_RIB_IPV6_UNICAST: 370 case MRT_DUMP_V2_RIB_IPV6_MULTICAST: 371 plen = *b++; 372 len -= 1; 373 if (len < MRT_PREFIX_LEN(plen)) 374 goto fail; 375 r->prefix.aid = AID_INET6; 376 memcpy(&r->prefix.v6, b, MRT_PREFIX_LEN(plen)); 377 b += MRT_PREFIX_LEN(plen); 378 len -= MRT_PREFIX_LEN(plen); 379 r->prefixlen = plen; 380 break; 381 case MRT_DUMP_V2_RIB_GENERIC: 382 /* XXX unhandled */ 383 errx(1, "MRT_DUMP_V2_RIB_GENERIC subtype not yet implemented"); 384 goto fail; 385 } 386 387 /* entries count */ 388 if (len < sizeof(cnt)) 389 goto fail; 390 memcpy(&cnt, b, sizeof(cnt)); 391 b += sizeof(cnt); 392 len -= sizeof(cnt); 393 cnt = ntohs(cnt); 394 r->nentries = cnt; 395 396 /* entries */ 397 if ((entries = calloc(cnt, sizeof(struct mrt_rib_entry))) == NULL) 398 err(1, "calloc"); 399 for (i = 0; i < cnt; i++) { 400 u_int32_t otm; 401 u_int16_t pix, alen; 402 if (len < 2 * sizeof(u_int16_t) + sizeof(u_int32_t)) 403 goto fail; 404 /* peer index */ 405 memcpy(&pix, b, sizeof(pix)); 406 b += sizeof(pix); 407 len -= sizeof(pix); 408 entries[i].peer_idx = ntohs(pix); 409 410 /* originated */ 411 memcpy(&otm, b, sizeof(otm)); 412 b += sizeof(otm); 413 len -= sizeof(otm); 414 entries[i].originated = ntohl(otm); 415 416 /* attr_len */ 417 memcpy(&alen, b, sizeof(alen)); 418 b += sizeof(alen); 419 len -= sizeof(alen); 420 alen = ntohs(alen); 421 422 /* attr */ 423 if (len < alen) 424 goto fail; 425 if (mrt_extract_attr(&entries[i], b, alen, 426 r->prefix.aid, 1) == -1) 427 goto fail; 428 b += alen; 429 len -= alen; 430 } 431 r->entries = entries; 432 return (r); 433 fail: 434 mrt_free_rib(r); 435 free(entries); 436 return (NULL); 437 } 438 439 int 440 mrt_parse_dump(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, 441 struct mrt_rib **rp) 442 { 443 struct mrt_peer *p; 444 struct mrt_rib *r; 445 struct mrt_rib_entry *re; 446 u_int8_t *b = msg; 447 u_int len = ntohl(hdr->length); 448 u_int16_t asnum, alen; 449 450 if (*pp == NULL) { 451 *pp = calloc(1, sizeof(struct mrt_peer)); 452 if (*pp == NULL) 453 err(1, "calloc"); 454 (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); 455 if ((*pp)->peers == NULL) 456 err(1, "calloc"); 457 (*pp)->npeers = 1; 458 } 459 p = *pp; 460 461 *rp = r = calloc(1, sizeof(struct mrt_rib)); 462 if (r == NULL) 463 err(1, "calloc"); 464 re = calloc(1, sizeof(struct mrt_rib_entry)); 465 if (re == NULL) 466 err(1, "calloc"); 467 r->nentries = 1; 468 r->entries = re; 469 470 if (len < 2 * sizeof(u_int16_t)) 471 goto fail; 472 /* view */ 473 b += sizeof(u_int16_t); 474 len -= sizeof(u_int16_t); 475 /* seqnum */ 476 memcpy(&r->seqnum, b, sizeof(u_int16_t)); 477 b += sizeof(u_int16_t); 478 len -= sizeof(u_int16_t); 479 r->seqnum = ntohs(r->seqnum); 480 481 switch (ntohs(hdr->subtype)) { 482 case MRT_DUMP_AFI_IP: 483 if (mrt_extract_addr(b, len, &r->prefix, AID_INET) == -1) 484 goto fail; 485 b += sizeof(struct in_addr); 486 len -= sizeof(struct in_addr); 487 break; 488 case MRT_DUMP_AFI_IPv6: 489 if (mrt_extract_addr(b, len, &r->prefix, AID_INET6) == -1) 490 goto fail; 491 b += sizeof(struct in6_addr); 492 len -= sizeof(struct in6_addr); 493 break; 494 } 495 if (len < 2 * sizeof(u_int32_t) + 2 * sizeof(u_int16_t) + 2) 496 goto fail; 497 r->prefixlen = *b++; 498 len -= 1; 499 /* status */ 500 b += 1; 501 len -= 1; 502 /* originated */ 503 memcpy(&re->originated, b, sizeof(u_int32_t)); 504 b += sizeof(u_int32_t); 505 len -= sizeof(u_int32_t); 506 re->originated = ntohl(re->originated); 507 /* peer ip */ 508 switch (ntohs(hdr->subtype)) { 509 case MRT_DUMP_AFI_IP: 510 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET) == -1) 511 goto fail; 512 b += sizeof(struct in_addr); 513 len -= sizeof(struct in_addr); 514 break; 515 case MRT_DUMP_AFI_IPv6: 516 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET6) == -1) 517 goto fail; 518 b += sizeof(struct in6_addr); 519 len -= sizeof(struct in6_addr); 520 break; 521 } 522 memcpy(&asnum, b, sizeof(asnum)); 523 b += sizeof(asnum); 524 len -= sizeof(asnum); 525 p->peers->asnum = ntohs(asnum); 526 527 memcpy(&alen, b, sizeof(alen)); 528 b += sizeof(alen); 529 len -= sizeof(alen); 530 alen = ntohs(alen); 531 532 /* attr */ 533 if (len < alen) 534 goto fail; 535 if (mrt_extract_attr(re, b, alen, r->prefix.aid, 0) == -1) 536 goto fail; 537 b += alen; 538 len -= alen; 539 540 return (0); 541 fail: 542 mrt_free_rib(r); 543 return (-1); 544 } 545 546 int 547 mrt_parse_dump_mp(struct mrt_hdr *hdr, void *msg, struct mrt_peer **pp, 548 struct mrt_rib **rp) 549 { 550 struct mrt_peer *p; 551 struct mrt_rib *r; 552 struct mrt_rib_entry *re; 553 u_int8_t *b = msg; 554 u_int len = ntohl(hdr->length); 555 u_int16_t asnum, alen, afi; 556 u_int8_t safi, nhlen, aid; 557 558 /* just ignore the microsec field for _ET header for now */ 559 if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { 560 b = (char *)b + sizeof(u_int32_t); 561 len -= sizeof(u_int32_t); 562 } 563 564 if (*pp == NULL) { 565 *pp = calloc(1, sizeof(struct mrt_peer)); 566 if (*pp == NULL) 567 err(1, "calloc"); 568 (*pp)->peers = calloc(1, sizeof(struct mrt_peer_entry)); 569 if ((*pp)->peers == NULL) 570 err(1, "calloc"); 571 (*pp)->npeers = 1; 572 } 573 p = *pp; 574 575 *rp = r = calloc(1, sizeof(struct mrt_rib)); 576 if (r == NULL) 577 err(1, "calloc"); 578 re = calloc(1, sizeof(struct mrt_rib_entry)); 579 if (re == NULL) 580 err(1, "calloc"); 581 r->nentries = 1; 582 r->entries = re; 583 584 if (len < 4 * sizeof(u_int16_t)) 585 goto fail; 586 /* source AS */ 587 b += sizeof(u_int16_t); 588 len -= sizeof(u_int16_t); 589 /* dest AS */ 590 memcpy(&asnum, b, sizeof(asnum)); 591 b += sizeof(asnum); 592 len -= sizeof(asnum); 593 p->peers->asnum = ntohs(asnum); 594 /* iface index */ 595 b += sizeof(u_int16_t); 596 len -= sizeof(u_int16_t); 597 /* afi */ 598 memcpy(&afi, b, sizeof(afi)); 599 b += sizeof(afi); 600 len -= sizeof(afi); 601 afi = ntohs(afi); 602 603 /* source + dest ip */ 604 switch (afi) { 605 case MRT_DUMP_AFI_IP: 606 if (len < 2 * sizeof(struct in_addr)) 607 goto fail; 608 /* source IP */ 609 b += sizeof(struct in_addr); 610 len -= sizeof(struct in_addr); 611 /* dest IP */ 612 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET) == -1) 613 goto fail; 614 b += sizeof(struct in_addr); 615 len -= sizeof(struct in_addr); 616 break; 617 case MRT_DUMP_AFI_IPv6: 618 if (len < 2 * sizeof(struct in6_addr)) 619 goto fail; 620 /* source IP */ 621 b += sizeof(struct in6_addr); 622 len -= sizeof(struct in6_addr); 623 /* dest IP */ 624 if (mrt_extract_addr(b, len, &p->peers->addr, AID_INET6) == -1) 625 goto fail; 626 b += sizeof(struct in6_addr); 627 len -= sizeof(struct in6_addr); 628 break; 629 } 630 631 if (len < 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t)) 632 goto fail; 633 /* view + status */ 634 b += 2 * sizeof(u_int16_t); 635 len -= 2 * sizeof(u_int16_t); 636 /* originated */ 637 memcpy(&re->originated, b, sizeof(u_int32_t)); 638 b += sizeof(u_int32_t); 639 len -= sizeof(u_int32_t); 640 re->originated = ntohl(re->originated); 641 642 /* afi */ 643 memcpy(&afi, b, sizeof(afi)); 644 b += sizeof(afi); 645 len -= sizeof(afi); 646 afi = ntohs(afi); 647 648 /* safi */ 649 safi = *b++; 650 len -= 1; 651 652 switch (afi) { 653 case MRT_DUMP_AFI_IP: 654 if (safi == 1 || safi == 2) { 655 aid = AID_INET; 656 break; 657 } else if (safi == 128) { 658 aid = AID_VPN_IPv4; 659 break; 660 } 661 goto fail; 662 case MRT_DUMP_AFI_IPv6: 663 if (safi == 1 || safi == 2) { 664 aid = AID_INET6; 665 break; 666 } else if (safi == 128) { 667 aid = AID_VPN_IPv6; 668 break; 669 } 670 goto fail; 671 default: 672 goto fail; 673 } 674 675 /* nhlen */ 676 nhlen = *b++; 677 len -= 1; 678 679 /* nexthop */ 680 if (mrt_extract_addr(b, len, &re->nexthop, aid) == -1) 681 goto fail; 682 if (len < nhlen) 683 goto fail; 684 b += nhlen; 685 len -= nhlen; 686 687 if (len < 1) 688 goto fail; 689 r->prefixlen = *b++; 690 len -= 1; 691 692 /* prefix */ 693 switch (aid) { 694 case AID_INET: 695 if (len < MRT_PREFIX_LEN(r->prefixlen)) 696 goto fail; 697 r->prefix.aid = aid; 698 memcpy(&r->prefix.v4, b, MRT_PREFIX_LEN(r->prefixlen)); 699 b += MRT_PREFIX_LEN(r->prefixlen); 700 len -= MRT_PREFIX_LEN(r->prefixlen); 701 break; 702 case AID_INET6: 703 if (len < MRT_PREFIX_LEN(r->prefixlen)) 704 goto fail; 705 r->prefix.aid = aid; 706 memcpy(&r->prefix.v6, b, MRT_PREFIX_LEN(r->prefixlen)); 707 b += MRT_PREFIX_LEN(r->prefixlen); 708 len -= MRT_PREFIX_LEN(r->prefixlen); 709 break; 710 case AID_VPN_IPv4: 711 if (len < MRT_PREFIX_LEN(r->prefixlen)) 712 goto fail; 713 errx(1, "AID_VPN_IPv4 handling not yet implemented"); 714 goto fail; 715 case AID_VPN_IPv6: 716 if (len < MRT_PREFIX_LEN(r->prefixlen)) 717 goto fail; 718 errx(1, "AID_VPN_IPv6 handling not yet implemented"); 719 goto fail; 720 } 721 722 memcpy(&alen, b, sizeof(alen)); 723 b += sizeof(alen); 724 len -= sizeof(alen); 725 alen = ntohs(alen); 726 727 /* attr */ 728 if (len < alen) 729 goto fail; 730 if (mrt_extract_attr(re, b, alen, r->prefix.aid, 0) == -1) 731 goto fail; 732 b += alen; 733 len -= alen; 734 735 return (0); 736 fail: 737 mrt_free_rib(r); 738 return (-1); 739 } 740 741 int 742 mrt_extract_attr(struct mrt_rib_entry *re, u_char *a, int alen, u_int8_t aid, 743 int as4) 744 { 745 struct mrt_attr *ap; 746 u_int32_t tmp; 747 u_int16_t attr_len; 748 u_int8_t type, flags, *attr; 749 750 do { 751 if (alen < 3) 752 return (-1); 753 attr = a; 754 flags = *a++; 755 alen -= 1; 756 type = *a++; 757 alen -= 1; 758 759 if (flags & MRT_ATTR_EXTLEN) { 760 if (alen < 2) 761 return (-1); 762 memcpy(&attr_len, a, sizeof(attr_len)); 763 attr_len = ntohs(attr_len); 764 a += sizeof(attr_len); 765 alen -= sizeof(attr_len); 766 } else { 767 attr_len = *a++; 768 alen -= 1; 769 } 770 switch (type) { 771 case MRT_ATTR_ORIGIN: 772 if (attr_len != 1) 773 return (-1); 774 re->origin = *a; 775 break; 776 case MRT_ATTR_ASPATH: 777 if (as4) { 778 re->aspath_len = attr_len; 779 if ((re->aspath = malloc(attr_len)) == NULL) 780 err(1, "malloc"); 781 memcpy(re->aspath, a, attr_len); 782 } else { 783 re->aspath = mrt_aspath_inflate(a, attr_len, 784 &re->aspath_len); 785 if (re->aspath == NULL) 786 return (-1); 787 } 788 break; 789 case MRT_ATTR_NEXTHOP: 790 if (attr_len != 4) 791 return (-1); 792 if (aid != AID_INET) 793 break; 794 memcpy(&tmp, a, sizeof(tmp)); 795 re->nexthop.aid = AID_INET; 796 re->nexthop.v4.s_addr = tmp; 797 break; 798 case MRT_ATTR_MED: 799 if (attr_len != 4) 800 return (-1); 801 memcpy(&tmp, a, sizeof(tmp)); 802 re->med = ntohl(tmp); 803 break; 804 case MRT_ATTR_LOCALPREF: 805 if (attr_len != 4) 806 return (-1); 807 memcpy(&tmp, a, sizeof(tmp)); 808 re->local_pref = ntohl(tmp); 809 break; 810 case MRT_ATTR_MP_REACH_NLRI: 811 /* 812 * XXX horrible hack: 813 * Once again IETF and the real world differ in the 814 * implementation. In short the abbreviated MP_NLRI 815 * hack in the standard is not used in real life. 816 * Detect the two cases by looking at the first byte 817 * of the payload (either the nexthop addr length (RFC) 818 * or the high byte of the AFI (old form)). If the 819 * first byte matches the expected nexthop length it 820 * is expected to be the RFC 6396 encoding. 821 */ 822 if (*a != attr_len - 1) { 823 a += 3; 824 alen -= 3; 825 attr_len -= 3; 826 } 827 switch (aid) { 828 case AID_INET6: 829 if (attr_len < sizeof(struct in6_addr) + 1) 830 return (-1); 831 re->nexthop.aid = aid; 832 memcpy(&re->nexthop.v6, a + 1, 833 sizeof(struct in6_addr)); 834 break; 835 case AID_VPN_IPv4: 836 if (attr_len < sizeof(u_int64_t) + 837 sizeof(struct in_addr)) 838 return (-1); 839 re->nexthop.aid = aid; 840 memcpy(&tmp, a + 1 + sizeof(u_int64_t), 841 sizeof(tmp)); 842 re->nexthop.vpn4.addr.s_addr = tmp; 843 break; 844 case AID_VPN_IPv6: 845 errx(1, "AID_VPN_IPv6 not yet implemented"); 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, struct bgpd_addr *addr, u_int8_t aid) 960 { 961 u_int8_t *b = msg; 962 963 memset(addr, 0, sizeof(*addr)); 964 switch (aid) { 965 case AID_INET: 966 if (len < sizeof(struct in_addr)) 967 return (-1); 968 addr->aid = aid; 969 memcpy(&addr->v4, b, sizeof(struct in_addr)); 970 return sizeof(struct in_addr); 971 case AID_INET6: 972 if (len < sizeof(struct in6_addr)) 973 return (-1); 974 addr->aid = aid; 975 memcpy(&addr->v6, b, sizeof(struct in6_addr)); 976 return sizeof(struct in6_addr); 977 case AID_VPN_IPv4: 978 if (len < sizeof(u_int64_t) + sizeof(struct in_addr)) 979 return (-1); 980 addr->aid = aid; 981 /* XXX labelstack and rd missing */ 982 memcpy(&addr->vpn4.addr, b + sizeof(u_int64_t), 983 sizeof(struct in_addr)); 984 return (sizeof(u_int64_t) + sizeof(struct in_addr)); 985 case AID_VPN_IPv6: 986 if (len < sizeof(u_int64_t) + sizeof(struct in6_addr)) 987 return (-1); 988 addr->aid = aid; 989 /* XXX labelstack and rd missing */ 990 memcpy(&addr->vpn6.addr, b + sizeof(u_int64_t), 991 sizeof(struct in6_addr)); 992 return (sizeof(u_int64_t) + sizeof(struct in6_addr)); 993 default: 994 return (-1); 995 } 996 } 997 998 struct mrt_bgp_state * 999 mrt_parse_state(struct mrt_hdr *hdr, void *msg) 1000 { 1001 struct timespec t; 1002 struct mrt_bgp_state *s; 1003 u_int8_t *b = msg; 1004 u_int len = ntohl(hdr->length); 1005 u_int32_t sas, das, usec; 1006 u_int16_t tmp16, afi; 1007 int r; 1008 u_int8_t aid; 1009 1010 t.tv_sec = ntohl(hdr->timestamp); 1011 t.tv_nsec = 0; 1012 1013 /* handle the microsec field for _ET header */ 1014 if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { 1015 memcpy(&usec, b, sizeof(usec)); 1016 b += sizeof(usec); 1017 len -= sizeof(usec); 1018 t.tv_nsec = ntohl(usec) * 1000; 1019 } 1020 1021 switch (ntohs(hdr->subtype)) { 1022 case BGP4MP_STATE_CHANGE: 1023 if (len < 8) 1024 return (0); 1025 /* source as */ 1026 memcpy(&tmp16, b, sizeof(tmp16)); 1027 b += sizeof(tmp16); 1028 len -= sizeof(tmp16); 1029 sas = ntohs(tmp16); 1030 /* dest as */ 1031 memcpy(&tmp16, b, sizeof(tmp16)); 1032 b += sizeof(tmp16); 1033 len -= sizeof(tmp16); 1034 das = ntohs(tmp16); 1035 /* if_index, ignored */ 1036 b += sizeof(tmp16); 1037 len -= sizeof(tmp16); 1038 /* afi */ 1039 memcpy(&tmp16, b, sizeof(tmp16)); 1040 b += sizeof(tmp16); 1041 len -= sizeof(tmp16); 1042 afi = ntohs(tmp16); 1043 break; 1044 case BGP4MP_STATE_CHANGE_AS4: 1045 if (len < 12) 1046 return (0); 1047 /* source as */ 1048 memcpy(&sas, b, sizeof(sas)); 1049 b += sizeof(sas); 1050 len -= sizeof(sas); 1051 sas = ntohl(sas); 1052 /* dest as */ 1053 memcpy(&das, b, sizeof(das)); 1054 b += sizeof(das); 1055 len -= sizeof(das); 1056 das = ntohl(das); 1057 /* if_index, ignored */ 1058 b += sizeof(tmp16); 1059 len -= sizeof(tmp16); 1060 /* afi */ 1061 memcpy(&tmp16, b, sizeof(tmp16)); 1062 b += sizeof(tmp16); 1063 len -= sizeof(tmp16); 1064 afi = ntohs(tmp16); 1065 break; 1066 default: 1067 errx(1, "mrt_parse_state: bad subtype"); 1068 } 1069 1070 /* src & dst addr */ 1071 switch (afi) { 1072 case MRT_DUMP_AFI_IP: 1073 aid = AID_INET; 1074 break; 1075 case MRT_DUMP_AFI_IPv6: 1076 aid = AID_INET6; 1077 break; 1078 default: 1079 errx(1, "mrt_parse_state: bad afi"); 1080 } 1081 1082 if ((s = calloc(1, sizeof(struct mrt_bgp_state))) == NULL) 1083 err(1, "calloc"); 1084 s->time = t; 1085 s->src_as = sas; 1086 s->dst_as = das; 1087 1088 if ((r = mrt_extract_addr(b, len, &s->src, aid)) == -1) 1089 goto fail; 1090 b += r; 1091 len -= r; 1092 if ((r = mrt_extract_addr(b, len, &s->dst, aid)) == -1) 1093 goto fail; 1094 b += r; 1095 len -= r; 1096 1097 /* states */ 1098 memcpy(&tmp16, b, sizeof(tmp16)); 1099 b += sizeof(tmp16); 1100 len -= sizeof(tmp16); 1101 s->old_state = ntohs(tmp16); 1102 memcpy(&tmp16, b, sizeof(tmp16)); 1103 b += sizeof(tmp16); 1104 len -= sizeof(tmp16); 1105 s->new_state = ntohs(tmp16); 1106 1107 return (s); 1108 1109 fail: 1110 free(s); 1111 return (NULL); 1112 } 1113 1114 struct mrt_bgp_msg * 1115 mrt_parse_msg(struct mrt_hdr *hdr, void *msg) 1116 { 1117 struct timespec t; 1118 struct mrt_bgp_msg *m; 1119 u_int8_t *b = msg; 1120 u_int len = ntohl(hdr->length); 1121 u_int32_t sas, das, usec; 1122 u_int16_t tmp16, afi; 1123 int r; 1124 u_int8_t aid; 1125 1126 t.tv_sec = ntohl(hdr->timestamp); 1127 t.tv_nsec = 0; 1128 1129 /* handle the microsec field for _ET header */ 1130 if (ntohs(hdr->type) == MSG_PROTOCOL_BGP4MP_ET) { 1131 memcpy(&usec, b, sizeof(usec)); 1132 b += sizeof(usec); 1133 len -= sizeof(usec); 1134 t.tv_nsec = ntohl(usec) * 1000; 1135 } 1136 1137 switch (ntohs(hdr->subtype)) { 1138 case BGP4MP_MESSAGE: 1139 if (len < 8) 1140 return (0); 1141 /* source as */ 1142 memcpy(&tmp16, b, sizeof(tmp16)); 1143 b += sizeof(tmp16); 1144 len -= sizeof(tmp16); 1145 sas = ntohs(tmp16); 1146 /* dest as */ 1147 memcpy(&tmp16, b, sizeof(tmp16)); 1148 b += sizeof(tmp16); 1149 len -= sizeof(tmp16); 1150 das = ntohs(tmp16); 1151 /* if_index, ignored */ 1152 b += sizeof(tmp16); 1153 len -= sizeof(tmp16); 1154 /* afi */ 1155 memcpy(&tmp16, b, sizeof(tmp16)); 1156 b += sizeof(tmp16); 1157 len -= sizeof(tmp16); 1158 afi = ntohs(tmp16); 1159 break; 1160 case BGP4MP_MESSAGE_AS4: 1161 if (len < 12) 1162 return (0); 1163 /* source as */ 1164 memcpy(&sas, b, sizeof(sas)); 1165 b += sizeof(sas); 1166 len -= sizeof(sas); 1167 sas = ntohl(sas); 1168 /* dest as */ 1169 memcpy(&das, b, sizeof(das)); 1170 b += sizeof(das); 1171 len -= sizeof(das); 1172 das = ntohl(das); 1173 /* if_index, ignored */ 1174 b += sizeof(tmp16); 1175 len -= sizeof(tmp16); 1176 /* afi */ 1177 memcpy(&tmp16, b, sizeof(tmp16)); 1178 b += sizeof(tmp16); 1179 len -= sizeof(tmp16); 1180 afi = ntohs(tmp16); 1181 break; 1182 default: 1183 errx(1, "mrt_parse_msg: bad subtype"); 1184 } 1185 1186 /* src & dst addr */ 1187 switch (afi) { 1188 case MRT_DUMP_AFI_IP: 1189 aid = AID_INET; 1190 break; 1191 case MRT_DUMP_AFI_IPv6: 1192 aid = AID_INET6; 1193 break; 1194 default: 1195 errx(1, "mrt_parse_msg: bad afi"); 1196 } 1197 1198 if ((m = calloc(1, sizeof(struct mrt_bgp_msg))) == NULL) 1199 err(1, "calloc"); 1200 m->time = t; 1201 m->src_as = sas; 1202 m->dst_as = das; 1203 1204 if ((r = mrt_extract_addr(b, len, &m->src, aid)) == -1) 1205 goto fail; 1206 b += r; 1207 len -= r; 1208 if ((r = mrt_extract_addr(b, len, &m->dst, aid)) == -1) 1209 goto fail; 1210 b += r; 1211 len -= r; 1212 1213 /* msg */ 1214 if (len > 0) { 1215 m->msg_len = len; 1216 if ((m->msg = malloc(len)) == NULL) 1217 err(1, "malloc"); 1218 memcpy(m->msg, b, len); 1219 } 1220 1221 return (m); 1222 1223 fail: 1224 free(m->msg); 1225 free(m); 1226 return (NULL); 1227 } 1228