1 /* $OpenBSD: vroute.c,v 1.15 2021/12/01 16:42:13 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Tobias Heider <tobhe@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/ioctl.h> 20 21 #include <net/if.h> 22 #include <net/route.h> 23 #include <netinet/in.h> 24 #include <netinet6/in6_var.h> 25 #include <netinet6/nd6.h> 26 27 #include <event.h> 28 #include <err.h> 29 #include <errno.h> 30 #include <poll.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <unistd.h> 34 #include <netdb.h> 35 36 #include <iked.h> 37 38 #define ROUTE_SOCKET_BUF_SIZE 16384 39 #define IKED_VROUTE_PRIO 6 40 41 #define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 42 43 int vroute_setroute(struct iked *, uint8_t, struct sockaddr *, uint8_t, 44 struct sockaddr *, int); 45 int vroute_doroute(struct iked *, int, int, int, uint8_t, struct sockaddr *, 46 struct sockaddr *, struct sockaddr *, int *); 47 int vroute_doaddr(struct iked *, char *, struct sockaddr *, struct sockaddr *, int); 48 int vroute_dodns(struct iked *, struct sockaddr *, int, unsigned int); 49 void vroute_cleanup(struct iked *); 50 void vroute_rtmsg_cb(int, short, void *); 51 52 void vroute_insertaddr(struct iked *, int, struct sockaddr *, struct sockaddr *); 53 void vroute_removeaddr(struct iked *, int, struct sockaddr *, struct sockaddr *); 54 void vroute_insertdns(struct iked *, int, struct sockaddr *); 55 void vroute_removedns(struct iked *, int, struct sockaddr *); 56 void vroute_insertroute(struct iked *, int, struct sockaddr *, struct sockaddr *); 57 void vroute_removeroute(struct iked *, int, struct sockaddr *, struct sockaddr *); 58 59 struct vroute_addr { 60 int va_ifidx; 61 struct sockaddr_storage va_addr; 62 struct sockaddr_storage va_mask; 63 TAILQ_ENTRY(vroute_addr) va_entry; 64 }; 65 TAILQ_HEAD(vroute_addrs, vroute_addr); 66 67 struct vroute_route { 68 int vr_rdomain; 69 int vr_flags; 70 struct sockaddr_storage vr_dest; 71 struct sockaddr_storage vr_mask; 72 TAILQ_ENTRY(vroute_route) vr_entry; 73 }; 74 TAILQ_HEAD(vroute_routes, vroute_route); 75 76 struct vroute_dns { 77 struct sockaddr_storage vd_addr; 78 int vd_ifidx; 79 }; 80 81 struct iked_vroute_sc { 82 struct vroute_addrs ivr_addrs; 83 struct vroute_routes ivr_routes; 84 struct vroute_dns *ivr_dns; 85 struct event ivr_routeev; 86 int ivr_iosock; 87 int ivr_iosock6; 88 int ivr_rtsock; 89 int ivr_rtseq; 90 pid_t ivr_pid; 91 }; 92 93 struct vroute_msg { 94 struct rt_msghdr vm_rtm; 95 uint8_t vm_space[512]; 96 }; 97 98 int vroute_process(struct iked *, int msglen, struct vroute_msg *, 99 struct sockaddr *, struct sockaddr *, struct sockaddr *, int *); 100 101 void 102 vroute_rtmsg_cb(int fd, short events, void *arg) 103 { 104 struct iked *env = (struct iked *) arg; 105 struct iked_vroute_sc *ivr = env->sc_vroute; 106 static uint8_t *buf; 107 struct rt_msghdr *rtm; 108 ssize_t n; 109 110 if (buf == NULL) { 111 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 112 if (buf == NULL) 113 fatal("malloc"); 114 } 115 rtm = (struct rt_msghdr *)buf; 116 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 117 if (errno == EAGAIN || errno == EINTR) 118 return; 119 log_warn("%s: read error", __func__); 120 return; 121 } 122 123 if (n == 0) 124 fatal("routing socket closed"); 125 126 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 127 log_warnx("partial rtm of %zd in buffer", n); 128 return; 129 } 130 131 if (rtm->rtm_version != RTM_VERSION) 132 return; 133 134 switch(rtm->rtm_type) { 135 case RTM_PROPOSAL: 136 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) { 137 log_debug("%s: got solicit", __func__); 138 vroute_dodns(env, (struct sockaddr *)&ivr->ivr_dns->vd_addr, 1, 139 ivr->ivr_dns->vd_ifidx); 140 } 141 break; 142 default: 143 log_debug("%s: unexpected RTM: %d", __func__, rtm->rtm_type); 144 break; 145 } 146 } 147 148 void 149 vroute_init(struct iked *env) 150 { 151 struct iked_vroute_sc *ivr; 152 int rtfilter; 153 154 ivr = calloc(1, sizeof(*ivr)); 155 if (ivr == NULL) 156 fatal("%s: calloc.", __func__); 157 158 if ((ivr->ivr_iosock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 159 fatal("%s: failed to create ioctl socket", __func__); 160 161 if ((ivr->ivr_iosock6 = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) 162 fatal("%s: failed to create ioctl socket", __func__); 163 164 if ((ivr->ivr_rtsock = socket(AF_ROUTE, SOCK_RAW, AF_UNSPEC)) == -1) 165 fatal("%s: failed to create routing socket", __func__); 166 167 rtfilter = ROUTE_FILTER(RTM_GET) | ROUTE_FILTER(RTM_PROPOSAL); 168 if (setsockopt(ivr->ivr_rtsock, AF_ROUTE, ROUTE_MSGFILTER, &rtfilter, 169 sizeof(rtfilter)) == -1) 170 fatal("%s: setsockopt(ROUTE_MSGFILTER)", __func__); 171 172 TAILQ_INIT(&ivr->ivr_addrs); 173 TAILQ_INIT(&ivr->ivr_routes); 174 175 ivr->ivr_pid = getpid(); 176 177 env->sc_vroute = ivr; 178 179 event_set(&ivr->ivr_routeev, ivr->ivr_rtsock, EV_READ | EV_PERSIST, 180 vroute_rtmsg_cb, env); 181 event_add(&ivr->ivr_routeev, NULL); 182 } 183 184 void 185 vroute_cleanup(struct iked *env) 186 { 187 char ifname[IF_NAMESIZE]; 188 struct iked_vroute_sc *ivr = env->sc_vroute; 189 struct vroute_addr *addr; 190 struct vroute_route *route; 191 192 while ((addr = TAILQ_FIRST(&ivr->ivr_addrs))) { 193 if_indextoname(addr->va_ifidx, ifname); 194 vroute_doaddr(env, ifname, 195 (struct sockaddr *)&addr->va_addr, 196 (struct sockaddr *)&addr->va_mask, 0); 197 TAILQ_REMOVE(&ivr->ivr_addrs, addr, va_entry); 198 free(addr); 199 } 200 201 while ((route = TAILQ_FIRST(&ivr->ivr_routes))) { 202 vroute_doroute(env, RTF_UP | RTF_GATEWAY | RTF_STATIC, 203 route->vr_flags, route->vr_rdomain, RTM_DELETE, 204 (struct sockaddr *)&route->vr_dest, 205 (struct sockaddr *)&route->vr_mask, 206 NULL, NULL); 207 TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry); 208 free(route); 209 } 210 211 if (ivr->ivr_dns) { 212 vroute_dodns(env, (struct sockaddr *)&ivr->ivr_dns->vd_addr, 0, 213 ivr->ivr_dns->vd_ifidx); 214 free(ivr->ivr_dns); 215 } 216 } 217 218 int 219 vroute_setaddr(struct iked *env, int add, struct sockaddr *addr, 220 int mask, unsigned int ifidx) 221 { 222 struct iovec iov[4]; 223 int iovcnt; 224 struct sockaddr_in mask4; 225 struct sockaddr_in6 mask6; 226 227 iovcnt = 0; 228 iov[0].iov_base = addr; 229 iov[0].iov_len = addr->sa_len; 230 iovcnt++; 231 232 switch(addr->sa_family) { 233 case AF_INET: 234 bzero(&mask, sizeof(mask)); 235 mask4.sin_addr.s_addr = prefixlen2mask(mask ? mask : 32); 236 mask4.sin_family = AF_INET; 237 mask4.sin_len = sizeof(mask4); 238 239 iov[1].iov_base = &mask4; 240 iov[1].iov_len = sizeof(mask4); 241 iovcnt++; 242 break; 243 case AF_INET6: 244 bzero(&mask6, sizeof(mask6)); 245 prefixlen2mask6(mask ? mask : 128, 246 (uint32_t *)&mask6.sin6_addr.s6_addr); 247 mask6.sin6_family = AF_INET6; 248 mask6.sin6_len = sizeof(mask6); 249 iov[1].iov_base = &mask6; 250 iov[1].iov_len = sizeof(mask6); 251 iovcnt++; 252 break; 253 default: 254 return -1; 255 } 256 257 iov[2].iov_base = &ifidx; 258 iov[2].iov_len = sizeof(ifidx); 259 iovcnt++; 260 261 return (proc_composev(&env->sc_ps, PROC_PARENT, 262 add ? IMSG_IF_ADDADDR : IMSG_IF_DELADDR, iov, iovcnt)); 263 } 264 265 int 266 vroute_getaddr(struct iked *env, struct imsg *imsg) 267 { 268 char ifname[IF_NAMESIZE]; 269 struct sockaddr *addr, *mask; 270 uint8_t *ptr; 271 size_t left; 272 int af, add; 273 unsigned int ifidx; 274 275 ptr = imsg->data; 276 left = IMSG_DATA_SIZE(imsg); 277 278 if (left < sizeof(*addr)) 279 fatalx("bad length imsg received"); 280 281 addr = (struct sockaddr *) ptr; 282 af = addr->sa_family; 283 284 if (left < addr->sa_len) 285 fatalx("bad length imsg received"); 286 ptr += addr->sa_len; 287 left -= addr->sa_len; 288 289 if (left < sizeof(*mask)) 290 fatalx("bad length imsg received"); 291 mask = (struct sockaddr *) ptr; 292 if (mask->sa_family != af) 293 return (-1); 294 295 if (left < mask->sa_len) 296 fatalx("bad length imsg received"); 297 ptr += mask->sa_len; 298 left -= mask->sa_len; 299 300 if (left != sizeof(ifidx)) 301 fatalx("bad length imsg received"); 302 memcpy(&ifidx, ptr, sizeof(ifidx)); 303 ptr += sizeof(ifidx); 304 left -= sizeof(ifidx); 305 306 add = (imsg->hdr.type == IMSG_IF_ADDADDR); 307 /* Store address for cleanup */ 308 if (add) 309 vroute_insertaddr(env, ifidx, addr, mask); 310 else 311 vroute_removeaddr(env, ifidx, addr, mask); 312 313 if_indextoname(ifidx, ifname); 314 return (vroute_doaddr(env, ifname, addr, mask, add)); 315 } 316 317 int 318 vroute_setdns(struct iked *env, int add, struct sockaddr *addr, 319 unsigned int ifidx) 320 { 321 struct iovec iov[2]; 322 323 iov[0].iov_base = addr; 324 iov[0].iov_len = addr->sa_len; 325 326 iov[1].iov_base = &ifidx; 327 iov[1].iov_len = sizeof(ifidx); 328 329 return (proc_composev(&env->sc_ps, PROC_PARENT, 330 add ? IMSG_VDNS_ADD: IMSG_VDNS_DEL, iov, 2)); 331 } 332 333 int 334 vroute_getdns(struct iked *env, struct imsg *imsg) 335 { 336 struct iked_vroute_sc *ivr = env->sc_vroute; 337 struct sockaddr *dns; 338 uint8_t *ptr; 339 size_t left; 340 int add; 341 unsigned int ifidx; 342 343 ptr = imsg->data; 344 left = IMSG_DATA_SIZE(imsg); 345 346 if (left < sizeof(*dns)) 347 fatalx("bad length imsg received"); 348 349 dns = (struct sockaddr *) ptr; 350 if (left < dns->sa_len) 351 fatalx("bad length imsg received"); 352 ptr += dns->sa_len; 353 left -= dns->sa_len; 354 355 if (left != sizeof(ifidx)) 356 fatalx("bad length imsg received"); 357 memcpy(&ifidx, ptr, sizeof(ifidx)); 358 ptr += sizeof(ifidx); 359 left -= sizeof(ifidx); 360 361 add = (imsg->hdr.type == IMSG_VDNS_ADD); 362 if (add) { 363 if (ivr->ivr_dns != NULL) 364 return (0); 365 vroute_insertdns(env, ifidx, dns); 366 } else { 367 if (ivr->ivr_dns == NULL) 368 return (0); 369 vroute_removedns(env, ifidx, dns); 370 } 371 372 return (vroute_dodns(env, dns, add, ifidx)); 373 } 374 375 void 376 vroute_insertroute(struct iked *env, int rdomain, struct sockaddr *dest, 377 struct sockaddr *mask) 378 { 379 struct iked_vroute_sc *ivr = env->sc_vroute; 380 struct vroute_route *route; 381 382 route = calloc(1, sizeof(*route)); 383 if (route == NULL) 384 fatalx("%s: calloc.", __func__); 385 386 if (dest != NULL) { 387 route->vr_flags |= RTA_DST; 388 memcpy(&route->vr_dest, dest, dest->sa_len); 389 } 390 if (mask != NULL) { 391 route->vr_flags |= RTA_NETMASK; 392 memcpy(&route->vr_mask, mask, mask->sa_len); 393 } 394 route->vr_rdomain = rdomain; 395 396 TAILQ_INSERT_TAIL(&ivr->ivr_routes, route, vr_entry); 397 } 398 399 void 400 vroute_removeroute(struct iked *env, int rdomain, struct sockaddr *dest, 401 struct sockaddr *mask) 402 { 403 struct iked_vroute_sc *ivr = env->sc_vroute; 404 struct vroute_route *route, *troute; 405 406 TAILQ_FOREACH_SAFE(route, &ivr->ivr_routes, vr_entry, troute) { 407 if (sockaddr_cmp(dest, (struct sockaddr *)&route->vr_dest, -1)) 408 continue; 409 if (mask && !(route->vr_flags & RTA_NETMASK)) 410 continue; 411 if (mask && 412 sockaddr_cmp(mask, (struct sockaddr *)&route->vr_mask, -1)) 413 continue; 414 if (rdomain != route->vr_rdomain) 415 continue; 416 TAILQ_REMOVE(&ivr->ivr_routes, route, vr_entry); 417 free(route); 418 } 419 } 420 421 void 422 vroute_insertdns(struct iked *env, int ifidx, struct sockaddr *addr) 423 { 424 struct iked_vroute_sc *ivr = env->sc_vroute; 425 struct vroute_dns *dns; 426 427 dns = calloc(1, sizeof(*dns)); 428 if (dns == NULL) 429 fatalx("%s: calloc.", __func__); 430 431 memcpy(&dns->vd_addr, addr, addr->sa_len); 432 dns->vd_ifidx = ifidx; 433 434 ivr->ivr_dns = dns; 435 } 436 437 void 438 vroute_removedns(struct iked *env, int ifidx, struct sockaddr *addr) 439 { 440 struct iked_vroute_sc *ivr = env->sc_vroute; 441 442 if (ifidx == ivr->ivr_dns->vd_ifidx && 443 sockaddr_cmp(addr, (struct sockaddr *) 444 &ivr->ivr_dns->vd_addr, -1) == 0) { 445 free(ivr->ivr_dns); 446 ivr->ivr_dns = NULL; 447 } 448 } 449 450 void 451 vroute_insertaddr(struct iked *env, int ifidx, struct sockaddr *addr, 452 struct sockaddr *mask) 453 { 454 struct iked_vroute_sc *ivr = env->sc_vroute; 455 struct vroute_addr *vaddr; 456 457 vaddr = calloc(1, sizeof(*vaddr)); 458 if (vaddr == NULL) 459 fatalx("%s: calloc.", __func__); 460 461 memcpy(&vaddr->va_addr, addr, addr->sa_len); 462 memcpy(&vaddr->va_mask, mask, mask->sa_len); 463 vaddr->va_ifidx = ifidx; 464 465 TAILQ_INSERT_TAIL(&ivr->ivr_addrs, vaddr, va_entry); 466 } 467 468 void 469 vroute_removeaddr(struct iked *env, int ifidx, struct sockaddr *addr, 470 struct sockaddr *mask) 471 { 472 struct iked_vroute_sc *ivr = env->sc_vroute; 473 struct vroute_addr *vaddr, *tvaddr; 474 475 TAILQ_FOREACH_SAFE(vaddr, &ivr->ivr_addrs, va_entry, tvaddr) { 476 if (sockaddr_cmp(addr, (struct sockaddr *)&vaddr->va_addr, -1)) 477 continue; 478 if (sockaddr_cmp(mask, (struct sockaddr *)&vaddr->va_mask, -1)) 479 continue; 480 if (ifidx != vaddr->va_ifidx) 481 continue; 482 TAILQ_REMOVE(&ivr->ivr_addrs, vaddr, va_entry); 483 free(vaddr); 484 } 485 } 486 487 int 488 vroute_setaddroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst, 489 uint8_t mask, struct sockaddr *ifa) 490 { 491 return (vroute_setroute(env, rdomain, dst, mask, ifa, 492 IMSG_VROUTE_ADD)); 493 } 494 495 int 496 vroute_setcloneroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst, 497 uint8_t mask, struct sockaddr *addr) 498 { 499 return (vroute_setroute(env, rdomain, dst, mask, addr, 500 IMSG_VROUTE_CLONE)); 501 } 502 503 int 504 vroute_setdelroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst, 505 uint8_t mask, struct sockaddr *addr) 506 { 507 return (vroute_setroute(env, rdomain, dst, mask, addr, 508 IMSG_VROUTE_DEL)); 509 } 510 511 int 512 vroute_setroute(struct iked *env, uint8_t rdomain, struct sockaddr *dst, 513 uint8_t mask, struct sockaddr *addr, int type) 514 { 515 struct sockaddr_storage sa; 516 struct sockaddr_in *in; 517 struct sockaddr_in6 *in6; 518 struct iovec iov[5]; 519 int iovcnt = 0; 520 uint8_t af; 521 522 if (addr && dst->sa_family != addr->sa_family) 523 return (-1); 524 af = dst->sa_family; 525 526 iov[iovcnt].iov_base = &rdomain; 527 iov[iovcnt].iov_len = sizeof(rdomain); 528 iovcnt++; 529 530 iov[iovcnt].iov_base = dst; 531 iov[iovcnt].iov_len = dst->sa_len; 532 iovcnt++; 533 534 if (type != IMSG_VROUTE_CLONE && addr) { 535 bzero(&sa, sizeof(sa)); 536 switch(af) { 537 case AF_INET: 538 in = (struct sockaddr_in *)&sa; 539 in->sin_addr.s_addr = prefixlen2mask(mask); 540 in->sin_family = af; 541 in->sin_len = sizeof(*in); 542 iov[iovcnt].iov_base = in; 543 iov[iovcnt].iov_len = sizeof(*in); 544 iovcnt++; 545 break; 546 case AF_INET6: 547 in6 = (struct sockaddr_in6 *)&sa; 548 prefixlen2mask6(mask, 549 (uint32_t *)in6->sin6_addr.s6_addr); 550 in6->sin6_family = af; 551 in6->sin6_len = sizeof(*in6); 552 iov[iovcnt].iov_base = in6; 553 iov[iovcnt].iov_len = sizeof(*in6); 554 iovcnt++; 555 break; 556 } 557 558 iov[iovcnt].iov_base = addr; 559 iov[iovcnt].iov_len = addr->sa_len; 560 iovcnt++; 561 } 562 563 return (proc_composev(&env->sc_ps, PROC_PARENT, type, iov, iovcnt)); 564 } 565 566 int 567 vroute_getroute(struct iked *env, struct imsg *imsg) 568 { 569 struct sockaddr *dest, *mask = NULL, *gateway = NULL; 570 uint8_t *ptr; 571 size_t left; 572 int addrs = 0; 573 int type, flags; 574 uint8_t rdomain; 575 576 ptr = (uint8_t *)imsg->data; 577 left = IMSG_DATA_SIZE(imsg); 578 579 if (left < sizeof(rdomain)) 580 return (-1); 581 rdomain = *ptr; 582 ptr += sizeof(rdomain); 583 left -= sizeof(rdomain); 584 585 if (left < sizeof(struct sockaddr)) 586 return (-1); 587 dest = (struct sockaddr *)ptr; 588 if (left < dest->sa_len) 589 return (-1); 590 socket_setport(dest, 0); 591 ptr += dest->sa_len; 592 left -= dest->sa_len; 593 addrs |= RTA_DST; 594 595 flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 596 if (left != 0) { 597 if (left < sizeof(struct sockaddr)) 598 return (-1); 599 mask = (struct sockaddr *)ptr; 600 if (left < mask->sa_len) 601 return (-1); 602 socket_setport(mask, 0); 603 ptr += mask->sa_len; 604 left -= mask->sa_len; 605 addrs |= RTA_NETMASK; 606 607 if (left < sizeof(struct sockaddr)) 608 return (-1); 609 gateway = (struct sockaddr *)ptr; 610 if (left < gateway->sa_len) 611 return (-1); 612 socket_setport(gateway, 0); 613 ptr += gateway->sa_len; 614 left -= gateway->sa_len; 615 addrs |= RTA_GATEWAY; 616 } else { 617 flags |= RTF_HOST; 618 } 619 620 switch(imsg->hdr.type) { 621 case IMSG_VROUTE_ADD: 622 type = RTM_ADD; 623 break; 624 case IMSG_VROUTE_DEL: 625 type = RTM_DELETE; 626 break; 627 } 628 629 if (type == RTM_ADD) 630 vroute_insertroute(env, rdomain, dest, mask); 631 else 632 vroute_removeroute(env, rdomain, dest, mask); 633 return (vroute_doroute(env, flags, addrs, rdomain, type, 634 dest, mask, gateway, NULL)); 635 } 636 637 int 638 vroute_getcloneroute(struct iked *env, struct imsg *imsg) 639 { 640 struct sockaddr *dst; 641 struct sockaddr_storage dest; 642 struct sockaddr_storage mask; 643 struct sockaddr_storage addr; 644 uint8_t *ptr; 645 size_t left; 646 uint8_t rdomain; 647 int flags; 648 int addrs; 649 int need_gw; 650 651 ptr = (uint8_t *)imsg->data; 652 left = IMSG_DATA_SIZE(imsg); 653 654 if (left < sizeof(rdomain)) 655 return (-1); 656 rdomain = *ptr; 657 ptr += sizeof(rdomain); 658 left -= sizeof(rdomain); 659 660 bzero(&dest, sizeof(dest)); 661 bzero(&mask, sizeof(mask)); 662 bzero(&addr, sizeof(addr)); 663 664 if (left < sizeof(struct sockaddr)) 665 return (-1); 666 dst = (struct sockaddr *)ptr; 667 if (left < dst->sa_len) 668 return (-1); 669 memcpy(&dest, dst, dst->sa_len); 670 ptr += dst->sa_len; 671 left -= dst->sa_len; 672 673 /* Get route to peer */ 674 flags = RTF_UP | RTF_HOST | RTF_STATIC; 675 if (vroute_doroute(env, flags, RTA_DST, rdomain, RTM_GET, 676 (struct sockaddr *)&dest, (struct sockaddr *)&mask, 677 (struct sockaddr *)&addr, &need_gw)) 678 return (-1); 679 680 if (need_gw) 681 flags |= RTF_GATEWAY; 682 683 memcpy(&dest, dst, dst->sa_len); 684 socket_setport((struct sockaddr *)&dest, 0); 685 vroute_insertroute(env, rdomain, (struct sockaddr *)&dest, NULL); 686 687 /* Set explicit route to peer with gateway addr*/ 688 addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 689 return (vroute_doroute(env, flags, addrs, rdomain, RTM_ADD, 690 (struct sockaddr *)&dest, (struct sockaddr *)&mask, 691 (struct sockaddr *)&addr, NULL)); 692 } 693 694 int 695 vroute_dodns(struct iked *env, struct sockaddr *dns, int add, 696 unsigned int ifidx) 697 { 698 struct vroute_msg m_rtmsg; 699 struct sockaddr_in *in; 700 struct sockaddr_in6 *in6; 701 struct sockaddr_rtdns rtdns; 702 struct iked_vroute_sc *ivr = env->sc_vroute; 703 struct iovec iov[3]; 704 int i; 705 long pad = 0; 706 int iovcnt = 0, padlen; 707 708 bzero(&m_rtmsg, sizeof(m_rtmsg)); 709 #define rtm m_rtmsg.vm_rtm 710 rtm.rtm_version = RTM_VERSION; 711 rtm.rtm_type = RTM_PROPOSAL; 712 rtm.rtm_seq = ++ivr->ivr_rtseq; 713 rtm.rtm_priority = RTP_PROPOSAL_STATIC; 714 rtm.rtm_flags = RTF_UP; 715 rtm.rtm_addrs = RTA_DNS; 716 rtm.rtm_index = ifidx; 717 718 iov[iovcnt].iov_base = &rtm; 719 iov[iovcnt].iov_len = sizeof(rtm); 720 iovcnt++; 721 722 bzero(&rtdns, sizeof(rtdns)); 723 rtdns.sr_family = dns->sa_family; 724 rtdns.sr_len = 2; 725 if (add) { 726 switch(dns->sa_family) { 727 case AF_INET: 728 rtdns.sr_family = AF_INET; 729 rtdns.sr_len += sizeof(struct in_addr); 730 in = (struct sockaddr_in *)dns; 731 memcpy(rtdns.sr_dns, &in->sin_addr, sizeof(struct in_addr)); 732 break; 733 case AF_INET6: 734 rtdns.sr_family = AF_INET6; 735 rtdns.sr_len += sizeof(struct in6_addr); 736 in6 = (struct sockaddr_in6 *)dns; 737 memcpy(rtdns.sr_dns, &in6->sin6_addr, sizeof(struct in6_addr)); 738 break; 739 default: 740 return (-1); 741 } 742 } 743 iov[iovcnt].iov_base = &rtdns; 744 iov[iovcnt++].iov_len = sizeof(rtdns); 745 padlen = ROUNDUP(sizeof(rtdns)) - sizeof(rtdns); 746 if (padlen > 0) { 747 iov[iovcnt].iov_base = &pad; 748 iov[iovcnt++].iov_len = padlen; 749 } 750 751 for (i = 0; i < iovcnt; i++) 752 rtm.rtm_msglen += iov[i].iov_len; 753 #undef rtm 754 755 if (writev(ivr->ivr_rtsock, iov, iovcnt) == -1) 756 log_warn("failed to send route message"); 757 758 return (0); 759 } 760 761 int 762 vroute_doroute(struct iked *env, int flags, int addrs, int rdomain, uint8_t type, 763 struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr, int *need_gw) 764 { 765 struct vroute_msg m_rtmsg; 766 struct iovec iov[7]; 767 struct iked_vroute_sc *ivr = env->sc_vroute; 768 ssize_t len; 769 int iovcnt = 0; 770 int i; 771 long pad = 0; 772 size_t padlen; 773 774 bzero(&m_rtmsg, sizeof(m_rtmsg)); 775 #define rtm m_rtmsg.vm_rtm 776 rtm.rtm_version = RTM_VERSION; 777 rtm.rtm_tableid = rdomain; 778 rtm.rtm_type = type; 779 rtm.rtm_seq = ++ivr->ivr_rtseq; 780 if (type != RTM_GET) 781 rtm.rtm_priority = IKED_VROUTE_PRIO; 782 rtm.rtm_flags = flags; 783 rtm.rtm_addrs = addrs; 784 785 iov[iovcnt].iov_base = &rtm; 786 iov[iovcnt].iov_len = sizeof(rtm); 787 iovcnt++; 788 789 if (rtm.rtm_addrs & RTA_DST) { 790 iov[iovcnt].iov_base = dest; 791 iov[iovcnt].iov_len = dest->sa_len; 792 iovcnt++; 793 padlen = ROUNDUP(dest->sa_len) - dest->sa_len; 794 if (padlen > 0) { 795 iov[iovcnt].iov_base = &pad; 796 iov[iovcnt].iov_len = padlen; 797 iovcnt++; 798 } 799 } 800 801 if (rtm.rtm_addrs & RTA_GATEWAY) { 802 iov[iovcnt].iov_base = addr; 803 iov[iovcnt].iov_len = addr->sa_len; 804 iovcnt++; 805 padlen = ROUNDUP(addr->sa_len) - addr->sa_len; 806 if (padlen > 0) { 807 iov[iovcnt].iov_base = &pad; 808 iov[iovcnt].iov_len = padlen; 809 iovcnt++; 810 } 811 } 812 813 if (rtm.rtm_addrs & RTA_NETMASK) { 814 iov[iovcnt].iov_base = mask; 815 iov[iovcnt].iov_len = mask->sa_len; 816 iovcnt++; 817 padlen = ROUNDUP(mask->sa_len) - mask->sa_len; 818 if (padlen > 0) { 819 iov[iovcnt].iov_base = &pad; 820 iov[iovcnt].iov_len = padlen; 821 iovcnt++; 822 } 823 } 824 825 for (i = 0; i < iovcnt; i++) 826 rtm.rtm_msglen += iov[i].iov_len; 827 828 log_debug("%s: len: %u type: %s rdomain: %d flags %x (%s%s)" 829 " addrs %x (dst %s mask %s gw %s)", __func__, rtm.rtm_msglen, 830 type == RTM_ADD ? "RTM_ADD" : type == RTM_DELETE ? "RTM_DELETE" : 831 type == RTM_GET ? "RTM_GET" : "unknown", rdomain, 832 flags, 833 flags & RTF_HOST ? "H" : "", 834 flags & RTF_GATEWAY ? "G" : "", 835 addrs, 836 addrs & RTA_DST ? print_host(dest, NULL, 0) : "<>", 837 addrs & RTA_NETMASK ? print_host(mask, NULL, 0) : "<>", 838 addrs & RTA_GATEWAY ? print_host(addr, NULL, 0) : "<>"); 839 840 if (writev(ivr->ivr_rtsock, iov, iovcnt) == -1) { 841 if ((type == RTM_ADD && errno != EEXIST) || 842 (type == RTM_DELETE && errno != ESRCH)) { 843 log_warn("%s: write %d", __func__, rtm.rtm_errno); 844 return (0); 845 } 846 } 847 848 if (type == RTM_GET) { 849 do { 850 len = read(ivr->ivr_rtsock, &m_rtmsg, sizeof(m_rtmsg)); 851 } while(len > 0 && (rtm.rtm_version != RTM_VERSION || 852 rtm.rtm_seq != ivr->ivr_rtseq || rtm.rtm_pid != ivr->ivr_pid)); 853 return (vroute_process(env, len, &m_rtmsg, dest, mask, addr, need_gw)); 854 } 855 #undef rtm 856 857 return (0); 858 } 859 860 int 861 vroute_process(struct iked *env, int msglen, struct vroute_msg *m_rtmsg, 862 struct sockaddr *dest, struct sockaddr *mask, struct sockaddr *addr, int *need_gw) 863 { 864 struct sockaddr *sa; 865 char *cp; 866 int i; 867 868 #define rtm m_rtmsg->vm_rtm 869 if (rtm.rtm_version != RTM_VERSION) { 870 warnx("routing message version %u not understood", 871 rtm.rtm_version); 872 return (-1); 873 } 874 if (rtm.rtm_msglen > msglen) { 875 warnx("message length mismatch, in packet %u, returned %d", 876 rtm.rtm_msglen, msglen); 877 return (-1); 878 } 879 if (rtm.rtm_errno) { 880 warnx("RTM_GET: %s (errno %d)", 881 strerror(rtm.rtm_errno), rtm.rtm_errno); 882 return (-1); 883 } 884 cp = m_rtmsg->vm_space; 885 *need_gw = rtm.rtm_flags & RTF_GATEWAY; 886 if(rtm.rtm_addrs) { 887 for (i = 1; i; i <<= 1) { 888 if (i & rtm.rtm_addrs) { 889 sa = (struct sockaddr *)cp; 890 switch(i) { 891 case RTA_DST: 892 memcpy(dest, cp, sa->sa_len); 893 break; 894 case RTA_NETMASK: 895 memcpy(mask, cp, sa->sa_len); 896 break; 897 case RTA_GATEWAY: 898 memcpy(addr, cp, sa->sa_len); 899 break; 900 } 901 cp += ROUNDUP(sa->sa_len); 902 } 903 } 904 } 905 #undef rtm 906 return (0); 907 } 908 909 int 910 vroute_doaddr(struct iked *env, char *ifname, struct sockaddr *addr, 911 struct sockaddr *mask, int add) 912 { 913 struct iked_vroute_sc *ivr = env->sc_vroute; 914 struct ifaliasreq req; 915 struct in6_aliasreq req6; 916 unsigned long ioreq; 917 int af; 918 919 af = addr->sa_family; 920 switch (af) { 921 case AF_INET: 922 bzero(&req, sizeof(req)); 923 strncpy(req.ifra_name, ifname, sizeof(req.ifra_name)); 924 memcpy(&req.ifra_addr, addr, sizeof(req.ifra_addr)); 925 if (add) 926 memcpy(&req.ifra_mask, mask, sizeof(req.ifra_addr)); 927 928 log_debug("%s: %s inet %s netmask %s", __func__, 929 add ? "add" : "del", 930 print_host((struct sockaddr *)addr, NULL, 0), 931 print_host((struct sockaddr *)mask, NULL, 0)); 932 933 ioreq = add ? SIOCAIFADDR : SIOCDIFADDR; 934 if (ioctl(ivr->ivr_iosock, ioreq, &req) == -1) { 935 log_warn("%s: req: %lu", __func__, ioreq); 936 return (-1); 937 } 938 break; 939 case AF_INET6: 940 bzero(&req6, sizeof(req6)); 941 strncpy(req6.ifra_name, ifname, sizeof(req6.ifra_name)); 942 req6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 943 req6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 944 945 memcpy(&req6.ifra_addr, addr, sizeof(req6.ifra_addr)); 946 if (add) 947 memcpy(&req6.ifra_prefixmask, mask, 948 sizeof(req6.ifra_prefixmask)); 949 950 log_debug("%s: %s inet6 %s netmask %s", __func__, 951 add ? "add" : "del", 952 print_host((struct sockaddr *)addr, NULL, 0), 953 print_host((struct sockaddr *)mask, NULL, 0)); 954 955 ioreq = add ? SIOCAIFADDR_IN6 : SIOCDIFADDR_IN6; 956 if (ioctl(ivr->ivr_iosock6, ioreq, &req6) == -1) { 957 log_warn("%s: req: %lu", __func__, ioreq); 958 return (-1); 959 } 960 break; 961 default: 962 return (-1); 963 } 964 965 return (0); 966 } 967