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