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