rtsol.c revision 222861
1/* $KAME: rtsol.c,v 1.27 2003/10/05 00:09:36 itojun Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 2011 Hiroki Sato 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: head/usr.sbin/rtsold/rtsol.c 222861 2011-06-08 16:03:29Z hrs $ 33 */ 34 35#include <sys/param.h> 36#include <sys/socket.h> 37#include <sys/uio.h> 38#include <sys/time.h> 39#include <sys/queue.h> 40#include <sys/wait.h> 41#include <sys/stat.h> 42 43#include <net/if.h> 44#include <net/route.h> 45#include <net/if_dl.h> 46 47#define __BSD_VISIBLE 1 /* IN6ADDR_LINKLOCAL_ALLROUTERS_INIT */ 48#include <netinet/in.h> 49#undef __BSD_VISIBLE 50#include <netinet/ip6.h> 51#include <netinet6/ip6_var.h> 52#include <netinet/icmp6.h> 53 54#include <arpa/inet.h> 55 56#include <netdb.h> 57#include <time.h> 58#include <fcntl.h> 59#include <unistd.h> 60#include <stdio.h> 61#include <err.h> 62#include <errno.h> 63#include <string.h> 64#include <stdlib.h> 65#include <syslog.h> 66#include "rtsold.h" 67 68static struct msghdr rcvmhdr; 69static struct msghdr sndmhdr; 70static struct iovec rcviov[2]; 71static struct iovec sndiov[2]; 72static struct sockaddr_in6 from; 73static int rcvcmsglen; 74 75int rssock; 76struct ifinfo_head_t ifinfo_head = 77 TAILQ_HEAD_INITIALIZER(ifinfo_head); 78 79static const struct sockaddr_in6 sin6_allrouters = { 80 .sin6_len = sizeof(sin6_allrouters), 81 .sin6_family = AF_INET6, 82 .sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT, 83}; 84 85static void call_script(const int, const char *const *, void *); 86static size_t dname_labeldec(char *, size_t, const char *); 87static int safefile(const char *); 88static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t); 89 90#define _ARGS_OTHER otherconf_script, ifi->ifname 91#define _ARGS_RESADD resolvconf_script, "-a", ifi->ifname 92#define _ARGS_RESDEL resolvconf_script, "-d", ifi->ifname 93 94#define CALL_SCRIPT(name, sm_head) \ 95 do { \ 96 const char *const sarg[] = { _ARGS_##name, NULL }; \ 97 call_script(sizeof(sarg), sarg, sm_head); \ 98 } while(0) 99 100#define ELM_MALLOC(p,error_action) \ 101 do { \ 102 p = malloc(sizeof(*p)); \ 103 if (p == NULL) { \ 104 warnmsg(LOG_ERR, __func__, "malloc failed: %s", \ 105 strerror(errno)); \ 106 error_action; \ 107 } \ 108 memset(p, 0, sizeof(*p)); \ 109 } while(0) 110 111int 112sockopen(void) 113{ 114 static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL; 115 int sndcmsglen, on; 116 static u_char answer[1500]; 117 struct icmp6_filter filt; 118 119 sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 120 CMSG_SPACE(sizeof(int)); 121 if (rcvcmsgbuf == NULL && (rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) { 122 warnmsg(LOG_ERR, __func__, 123 "malloc for receive msghdr failed"); 124 return (-1); 125 } 126 if (sndcmsgbuf == NULL && (sndcmsgbuf = malloc(sndcmsglen)) == NULL) { 127 warnmsg(LOG_ERR, __func__, 128 "malloc for send msghdr failed"); 129 return (-1); 130 } 131 if ((rssock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { 132 warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno)); 133 return (-1); 134 } 135 136 /* specify to tell receiving interface */ 137 on = 1; 138 if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 139 sizeof(on)) < 0) { 140 warnmsg(LOG_ERR, __func__, "IPV6_RECVPKTINFO: %s", 141 strerror(errno)); 142 exit(1); 143 } 144 145 /* specify to tell value of hoplimit field of received IP6 hdr */ 146 on = 1; 147 if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 148 sizeof(on)) < 0) { 149 warnmsg(LOG_ERR, __func__, "IPV6_RECVHOPLIMIT: %s", 150 strerror(errno)); 151 exit(1); 152 } 153 154 /* specfiy to accept only router advertisements on the socket */ 155 ICMP6_FILTER_SETBLOCKALL(&filt); 156 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); 157 if (setsockopt(rssock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 158 sizeof(filt)) == -1) { 159 warnmsg(LOG_ERR, __func__, "setsockopt(ICMP6_FILTER): %s", 160 strerror(errno)); 161 return(-1); 162 } 163 164 /* initialize msghdr for receiving packets */ 165 rcviov[0].iov_base = (caddr_t)answer; 166 rcviov[0].iov_len = sizeof(answer); 167 rcvmhdr.msg_name = (caddr_t)&from; 168 rcvmhdr.msg_iov = rcviov; 169 rcvmhdr.msg_iovlen = 1; 170 rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 171 172 /* initialize msghdr for sending packets */ 173 sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); 174 sndmhdr.msg_iov = sndiov; 175 sndmhdr.msg_iovlen = 1; 176 sndmhdr.msg_control = (caddr_t)sndcmsgbuf; 177 sndmhdr.msg_controllen = sndcmsglen; 178 179 return (rssock); 180} 181 182void 183sendpacket(struct ifinfo *ifi) 184{ 185 struct in6_pktinfo *pi; 186 struct cmsghdr *cm; 187 int hoplimit = 255; 188 ssize_t i; 189 struct sockaddr_in6 dst; 190 191 dst = sin6_allrouters; 192 dst.sin6_scope_id = ifi->linkid; 193 194 sndmhdr.msg_name = (caddr_t)&dst; 195 sndmhdr.msg_iov[0].iov_base = (caddr_t)ifi->rs_data; 196 sndmhdr.msg_iov[0].iov_len = ifi->rs_datalen; 197 198 cm = CMSG_FIRSTHDR(&sndmhdr); 199 /* specify the outgoing interface */ 200 cm->cmsg_level = IPPROTO_IPV6; 201 cm->cmsg_type = IPV6_PKTINFO; 202 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 203 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 204 memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/ 205 pi->ipi6_ifindex = ifi->sdl->sdl_index; 206 207 /* specify the hop limit of the packet */ 208 cm = CMSG_NXTHDR(&sndmhdr, cm); 209 cm->cmsg_level = IPPROTO_IPV6; 210 cm->cmsg_type = IPV6_HOPLIMIT; 211 cm->cmsg_len = CMSG_LEN(sizeof(int)); 212 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 213 214 warnmsg(LOG_DEBUG, __func__, 215 "send RS on %s, whose state is %d", 216 ifi->ifname, ifi->state); 217 i = sendmsg(rssock, &sndmhdr, 0); 218 if (i < 0 || (size_t)i != ifi->rs_datalen) { 219 /* 220 * ENETDOWN is not so serious, especially when using several 221 * network cards on a mobile node. We ignore it. 222 */ 223 if (errno != ENETDOWN || dflag > 0) 224 warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s", 225 ifi->ifname, strerror(errno)); 226 } 227 228 /* update counter */ 229 ifi->probes++; 230} 231 232void 233rtsol_input(int s) 234{ 235 u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 236 int l, ifindex = 0, *hlimp = NULL; 237 ssize_t msglen; 238 struct in6_pktinfo *pi = NULL; 239 struct ifinfo *ifi = NULL; 240 struct ra_opt *rao = NULL; 241 struct icmp6_hdr *icp; 242 struct nd_router_advert *nd_ra; 243 struct cmsghdr *cm; 244 struct rainfo *rai; 245 char *raoptp; 246 char *p; 247 struct in6_addr *addr; 248 struct nd_opt_hdr *ndo; 249 struct nd_opt_rdnss *rdnss; 250 struct nd_opt_dnssl *dnssl; 251 size_t len; 252 char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1]; 253 char dname[NI_MAXHOST]; 254 struct timeval now; 255 struct timeval lifetime; 256 int newent_rai; 257 int newent_rao; 258 259 /* get message. namelen and controllen must always be initialized. */ 260 rcvmhdr.msg_namelen = sizeof(from); 261 rcvmhdr.msg_controllen = rcvcmsglen; 262 if ((msglen = recvmsg(s, &rcvmhdr, 0)) < 0) { 263 warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno)); 264 return; 265 } 266 267 /* extract optional information via Advanced API */ 268 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr); cm; 269 cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) { 270 if (cm->cmsg_level == IPPROTO_IPV6 && 271 cm->cmsg_type == IPV6_PKTINFO && 272 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 273 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 274 ifindex = pi->ipi6_ifindex; 275 } 276 if (cm->cmsg_level == IPPROTO_IPV6 && 277 cm->cmsg_type == IPV6_HOPLIMIT && 278 cm->cmsg_len == CMSG_LEN(sizeof(int))) 279 hlimp = (int *)CMSG_DATA(cm); 280 } 281 282 if (ifindex == 0) { 283 warnmsg(LOG_ERR, __func__, 284 "failed to get receiving interface"); 285 return; 286 } 287 if (hlimp == NULL) { 288 warnmsg(LOG_ERR, __func__, 289 "failed to get receiving hop limit"); 290 return; 291 } 292 293 if ((size_t)msglen < sizeof(struct nd_router_advert)) { 294 warnmsg(LOG_INFO, __func__, 295 "packet size(%zd) is too short", msglen); 296 return; 297 } 298 299 icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base; 300 301 if (icp->icmp6_type != ND_ROUTER_ADVERT) { 302 /* 303 * this should not happen because we configured a filter 304 * that only passes RAs on the receiving socket. 305 */ 306 warnmsg(LOG_ERR, __func__, 307 "invalid icmp type(%d) from %s on %s", icp->icmp6_type, 308 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 309 INET6_ADDRSTRLEN), 310 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 311 return; 312 } 313 314 if (icp->icmp6_code != 0) { 315 warnmsg(LOG_INFO, __func__, 316 "invalid icmp code(%d) from %s on %s", icp->icmp6_code, 317 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 318 INET6_ADDRSTRLEN), 319 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 320 return; 321 } 322 323 if (*hlimp != 255) { 324 warnmsg(LOG_INFO, __func__, 325 "invalid RA with hop limit(%d) from %s on %s", 326 *hlimp, 327 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 328 INET6_ADDRSTRLEN), 329 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 330 return; 331 } 332 333 if (pi && !IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) { 334 warnmsg(LOG_INFO, __func__, 335 "invalid RA with non link-local source from %s on %s", 336 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 337 INET6_ADDRSTRLEN), 338 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 339 return; 340 } 341 342 /* xxx: more validation? */ 343 344 if ((ifi = find_ifinfo(pi->ipi6_ifindex)) == NULL) { 345 warnmsg(LOG_INFO, __func__, 346 "received RA from %s on an unexpected IF(%s)", 347 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, 348 INET6_ADDRSTRLEN), 349 if_indextoname(pi->ipi6_ifindex, ifnamebuf)); 350 return; 351 } 352 353 warnmsg(LOG_DEBUG, __func__, 354 "received RA from %s on %s, state is %d", 355 inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, INET6_ADDRSTRLEN), 356 ifi->ifname, ifi->state); 357 358 nd_ra = (struct nd_router_advert *)icp; 359 360 /* 361 * Process the "O bit." 362 * If the value of OtherConfigFlag changes from FALSE to TRUE, the 363 * host should invoke the stateful autoconfiguration protocol, 364 * requesting information. 365 * [RFC 2462 Section 5.5.3] 366 */ 367 if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_OTHER) && 368 !ifi->otherconfig) { 369 warnmsg(LOG_DEBUG, __func__, 370 "OtherConfigFlag on %s is turned on", ifi->ifname); 371 ifi->otherconfig = 1; 372 CALL_SCRIPT(OTHER, NULL); 373 } 374 gettimeofday(&now, NULL); 375 newent_rai = 0; 376 rai = find_rainfo(ifi, &from); 377 if (rai == NULL) { 378 ELM_MALLOC(rai, exit(1)); 379 rai->rai_ifinfo = ifi; 380 TAILQ_INIT(&rai->rai_ra_opt); 381 memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr, 382 sizeof(rai->rai_saddr.sin6_addr)); 383 newent_rai = 1; 384 } 385 386#define RA_OPT_NEXT_HDR(x) (struct nd_opt_hdr *)((char *)x + \ 387 (((struct nd_opt_hdr *)x)->nd_opt_len * 8)) 388 /* Process RA options. */ 389 warnmsg(LOG_DEBUG, __func__, "Processing RA"); 390 raoptp = (char *)icp + sizeof(struct nd_router_advert); 391 while (raoptp < (char *)icp + msglen) { 392 ndo = (struct nd_opt_hdr *)raoptp; 393 warnmsg(LOG_DEBUG, __func__, "ndo = %p", raoptp); 394 warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_type = %d", 395 ndo->nd_opt_type); 396 warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d", 397 ndo->nd_opt_len); 398 399 switch (ndo->nd_opt_type) { 400 case ND_OPT_RDNSS: 401 rdnss = (struct nd_opt_rdnss *)raoptp; 402 403 /* Optlen sanity check (Section 5.3.1 in RFC 6106) */ 404 if (rdnss->nd_opt_rdnss_len < 3) { 405 warnmsg(LOG_INFO, __func__, 406 "too short RDNSS option" 407 "in RA from %s was ignored.", 408 inet_ntop(AF_INET6, &from.sin6_addr, 409 ntopbuf, INET6_ADDRSTRLEN)); 410 break; 411 } 412 413 addr = (struct in6_addr *)(raoptp + sizeof(*rdnss)); 414 while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) { 415 if (inet_ntop(AF_INET6, addr, ntopbuf, 416 INET6_ADDRSTRLEN) == NULL) { 417 warnmsg(LOG_INFO, __func__, 418 "an invalid address in RDNSS option" 419 " in RA from %s was ignored.", 420 inet_ntop(AF_INET6, &from.sin6_addr, 421 ntopbuf, INET6_ADDRSTRLEN)); 422 addr++; 423 continue; 424 } 425 if (IN6_IS_ADDR_LINKLOCAL(addr)) 426 /* XXX: % has to be escaped here */ 427 l = snprintf(nsbuf, sizeof(nsbuf), 428 "%s%c%s", ntopbuf, 429 SCOPE_DELIMITER, 430 ifi->ifname); 431 else 432 l = snprintf(nsbuf, sizeof(nsbuf), 433 "%s", ntopbuf); 434 if (l < 0 || (size_t)l >= sizeof(nsbuf)) { 435 warnmsg(LOG_ERR, __func__, 436 "address copying error in " 437 "RDNSS option: %d.", l); 438 addr++; 439 continue; 440 } 441 warnmsg(LOG_DEBUG, __func__, "nsbuf = %s", 442 nsbuf); 443 444 newent_rao = 0; 445 rao = find_raopt(rai, ndo->nd_opt_type, nsbuf, 446 strlen(nsbuf)); 447 if (rao == NULL) { 448 ELM_MALLOC(rao, break); 449 rao->rao_type = ndo->nd_opt_type; 450 rao->rao_len = strlen(nsbuf); 451 rao->rao_msg = strdup(nsbuf); 452 if (rao->rao_msg == NULL) { 453 warnmsg(LOG_ERR, __func__, 454 "strdup failed: %s", 455 strerror(errno)); 456 free(rao); 457 addr++; 458 continue; 459 } 460 newent_rao = 1; 461 } 462 /* Set expiration timer */ 463 memset(&rao->rao_expire, 0, 464 sizeof(rao->rao_expire)); 465 memset(&lifetime, 0, sizeof(lifetime)); 466 lifetime.tv_sec = 467 ntohl(rdnss->nd_opt_rdnss_lifetime); 468 timeradd(&now, &lifetime, &rao->rao_expire); 469 470 if (newent_rao) 471 TAILQ_INSERT_TAIL(&rai->rai_ra_opt, 472 rao, rao_next); 473 addr++; 474 } 475 break; 476 case ND_OPT_DNSSL: 477 dnssl = (struct nd_opt_dnssl *)raoptp; 478 479 /* Optlen sanity check (Section 5.3.1 in RFC 6106) */ 480 if (dnssl->nd_opt_dnssl_len < 2) { 481 warnmsg(LOG_INFO, __func__, 482 "too short DNSSL option" 483 "in RA from %s was ignored.", 484 inet_ntop(AF_INET6, &from.sin6_addr, 485 ntopbuf, INET6_ADDRSTRLEN)); 486 break; 487 } 488 489 /* 490 * Ensure NUL-termination in DNSSL in case of 491 * malformed field. 492 */ 493 p = (char *)RA_OPT_NEXT_HDR(raoptp); 494 *(p - 1) = '\0'; 495 496 p = raoptp + sizeof(*dnssl); 497 while (1 < (len = dname_labeldec(dname, sizeof(dname), 498 p))) { 499 /* length == 1 means empty string */ 500 warnmsg(LOG_DEBUG, __func__, "dname = %s", 501 dname); 502 503 newent_rao = 0; 504 rao = find_raopt(rai, ndo->nd_opt_type, dname, 505 strlen(dname)); 506 if (rao == NULL) { 507 ELM_MALLOC(rao, break); 508 rao->rao_type = ndo->nd_opt_type; 509 rao->rao_len = strlen(dname); 510 rao->rao_msg = strdup(dname); 511 if (rao->rao_msg == NULL) { 512 warnmsg(LOG_ERR, __func__, 513 "strdup failed: %s", 514 strerror(errno)); 515 free(rao); 516 addr++; 517 continue; 518 } 519 newent_rao = 1; 520 } 521 /* Set expiration timer */ 522 memset(&rao->rao_expire, 0, 523 sizeof(rao->rao_expire)); 524 memset(&lifetime, 0, sizeof(lifetime)); 525 lifetime.tv_sec = 526 ntohl(dnssl->nd_opt_dnssl_lifetime); 527 timeradd(&now, &lifetime, &rao->rao_expire); 528 529 if (newent_rao) 530 TAILQ_INSERT_TAIL(&rai->rai_ra_opt, 531 rao, rao_next); 532 p += len; 533 } 534 break; 535 default: 536 /* nothing to do for other options */ 537 break; 538 } 539 raoptp = (char *)RA_OPT_NEXT_HDR(raoptp); 540 } 541 if (newent_rai) 542 TAILQ_INSERT_TAIL(&ifi->ifi_rainfo, rai, rai_next); 543 544 ra_opt_handler(ifi); 545 ifi->racnt++; 546 547 switch (ifi->state) { 548 case IFS_IDLE: /* should be ignored */ 549 case IFS_DELAY: /* right? */ 550 break; 551 case IFS_PROBE: 552 ifi->state = IFS_IDLE; 553 ifi->probes = 0; 554 rtsol_timer_update(ifi); 555 break; 556 } 557} 558 559static char resstr_ns_prefix[] = "nameserver "; 560static char resstr_sh_prefix[] = "search "; 561static char resstr_nl[] = "\n"; 562static char resstr_sp[] = " "; 563 564int 565ra_opt_handler(struct ifinfo *ifi) 566{ 567 struct ra_opt *rao; 568 struct rainfo *rai; 569 struct script_msg *smp1, *smp2, *smp3; 570 struct timeval now; 571 TAILQ_HEAD(, script_msg) sm_rdnss_head = 572 TAILQ_HEAD_INITIALIZER(sm_rdnss_head); 573 TAILQ_HEAD(, script_msg) sm_dnssl_head = 574 TAILQ_HEAD_INITIALIZER(sm_dnssl_head); 575 int dcount, dlen; 576 577 dcount = 0; 578 dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl); 579 gettimeofday(&now, NULL); 580 581 /* 582 * All options from multiple RAs with the same or different 583 * source addresses on a single interface will be gathered and 584 * handled, not overridden. [RFC 4861 6.3.4] 585 */ 586 TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) { 587 TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) { 588 switch (rao->rao_type) { 589 case ND_OPT_RDNSS: 590 if (timercmp(&now, &rao->rao_expire, >)) { 591 warnmsg(LOG_INFO, __func__, 592 "expired rdnss entry: %s", 593 (char *)rao->rao_msg); 594 break; 595 } 596 ELM_MALLOC(smp1, continue); 597 ELM_MALLOC(smp2, goto free1); 598 ELM_MALLOC(smp3, goto free2); 599 smp1->sm_msg = resstr_ns_prefix; 600 TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1, 601 sm_next); 602 smp2->sm_msg = rao->rao_msg; 603 TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2, 604 sm_next); 605 smp3->sm_msg = resstr_nl; 606 TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3, 607 sm_next); 608 ifi->ifi_rdnss = IFI_DNSOPT_STATE_RECEIVED; 609 610 break; 611 case ND_OPT_DNSSL: 612 if (timercmp(&now, &rao->rao_expire, >)) { 613 warnmsg(LOG_INFO, __func__, 614 "expired dnssl entry: %s", 615 (char *)rao->rao_msg); 616 break; 617 } 618 dcount++; 619 /* Check resolv.conf(5) restrictions. */ 620 if (dcount > 6) { 621 warnmsg(LOG_INFO, __func__, 622 "dnssl entry exceeding maximum count (%d>6)" 623 ": %s", dcount, (char *)rao->rao_msg); 624 break; 625 } 626 if (256 < dlen + strlen(rao->rao_msg) + 627 strlen(resstr_sp)) { 628 warnmsg(LOG_INFO, __func__, 629 "dnssl entry exceeding maximum length " 630 "(>256): %s", (char *)rao->rao_msg); 631 break; 632 } 633 ELM_MALLOC(smp1, continue); 634 ELM_MALLOC(smp2, goto free1); 635 if (TAILQ_EMPTY(&sm_dnssl_head)) { 636 ELM_MALLOC(smp3, goto free2); 637 smp3->sm_msg = resstr_sh_prefix; 638 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3, 639 sm_next); 640 } 641 smp1->sm_msg = rao->rao_msg; 642 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, 643 sm_next); 644 smp2->sm_msg = resstr_sp; 645 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2, 646 sm_next); 647 dlen += strlen(rao->rao_msg) + 648 strlen(resstr_sp); 649 break; 650 651 ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED; 652 default: 653 break; 654 } 655 continue; 656free2: 657 free(smp2); 658free1: 659 free(smp1); 660 } 661 } 662 /* Add \n for DNSSL list. */ 663 if (!TAILQ_EMPTY(&sm_dnssl_head)) { 664 ELM_MALLOC(smp1, goto ra_opt_handler_freeit); 665 smp1->sm_msg = resstr_nl; 666 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, sm_next); 667 } 668 TAILQ_CONCAT(&sm_rdnss_head, &sm_dnssl_head, sm_next); 669 670 if (!TAILQ_EMPTY(&sm_rdnss_head)) 671 CALL_SCRIPT(RESADD, &sm_rdnss_head); 672 else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED || 673 ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) { 674 CALL_SCRIPT(RESDEL, NULL); 675 ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO; 676 ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO; 677 } 678 679ra_opt_handler_freeit: 680 /* Clear script message queue. */ 681 if (!TAILQ_EMPTY(&sm_rdnss_head)) { 682 while ((smp1 = TAILQ_FIRST(&sm_rdnss_head)) != NULL) { 683 TAILQ_REMOVE(&sm_rdnss_head, smp1, sm_next); 684 free(smp1); 685 } 686 } 687 if (!TAILQ_EMPTY(&sm_dnssl_head)) { 688 while ((smp1 = TAILQ_FIRST(&sm_dnssl_head)) != NULL) { 689 TAILQ_REMOVE(&sm_dnssl_head, smp1, sm_next); 690 free(smp1); 691 } 692 } 693 return (0); 694} 695 696static struct ra_opt * 697find_raopt(struct rainfo *rai, int type, void *msg, size_t len) 698{ 699 struct ra_opt *rao; 700 701 TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) { 702 if (rao->rao_type == type && 703 rao->rao_len == strlen(msg) && 704 memcmp(rao->rao_msg, msg, len) == 0) 705 break; 706 } 707 708 return (rao); 709} 710 711static void 712call_script(const int argc, const char *const argv[], void *head) 713{ 714 const char *scriptpath; 715 int fd[2]; 716 int error; 717 pid_t pid, wpid; 718 TAILQ_HEAD(, script_msg) *sm_head; 719 720 if ((scriptpath = argv[0]) == NULL) 721 return; 722 723 fd[0] = fd[1] = -1; 724 sm_head = head; 725 if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) { 726 error = pipe(fd); 727 if (error) { 728 warnmsg(LOG_ERR, __func__, 729 "failed to create a pipe: %s", strerror(errno)); 730 return; 731 } 732 } 733 734 /* launch the script */ 735 pid = fork(); 736 if (pid < 0) { 737 warnmsg(LOG_ERR, __func__, 738 "failed to fork: %s", strerror(errno)); 739 return; 740 } else if (pid) { /* parent */ 741 int wstatus; 742 743 if (fd[0] != -1) { /* Send message to the child if any. */ 744 ssize_t len; 745 struct script_msg *smp; 746 747 close(fd[0]); 748 TAILQ_FOREACH(smp, sm_head, sm_next) { 749 len = strlen(smp->sm_msg); 750 warnmsg(LOG_DEBUG, __func__, 751 "write to child = %s(%zd)", 752 smp->sm_msg, len); 753 if (write(fd[1], smp->sm_msg, len) != len) { 754 warnmsg(LOG_ERR, __func__, 755 "write to child failed: %s", 756 strerror(errno)); 757 break; 758 } 759 } 760 close(fd[1]); 761 } 762 do { 763 wpid = wait(&wstatus); 764 } while (wpid != pid && wpid > 0); 765 766 if (wpid < 0) 767 warnmsg(LOG_ERR, __func__, 768 "wait: %s", strerror(errno)); 769 else 770 warnmsg(LOG_DEBUG, __func__, 771 "script \"%s\" terminated", scriptpath); 772 } else { /* child */ 773 int nullfd; 774 char **_argv; 775 776 if (safefile(scriptpath)) { 777 warnmsg(LOG_ERR, __func__, 778 "script \"%s\" cannot be executed safely", 779 scriptpath); 780 exit(1); 781 } 782 nullfd = open("/dev/null", O_RDWR); 783 if (nullfd < 0) { 784 warnmsg(LOG_ERR, __func__, 785 "open /dev/null: %s", strerror(errno)); 786 exit(1); 787 } 788 if (fd[0] != -1) { /* Receive message from STDIN if any. */ 789 close(fd[1]); 790 if (fd[0] != STDIN_FILENO) { 791 /* Connect a pipe read-end to child's STDIN. */ 792 if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) { 793 warnmsg(LOG_ERR, __func__, 794 "dup2 STDIN: %s", strerror(errno)); 795 exit(1); 796 } 797 close(fd[0]); 798 } 799 } else 800 dup2(nullfd, STDIN_FILENO); 801 802 dup2(nullfd, STDOUT_FILENO); 803 dup2(nullfd, STDERR_FILENO); 804 if (nullfd > STDERR_FILENO) 805 close(nullfd); 806 807 _argv = malloc(sizeof(*_argv) * argc); 808 if (_argv == NULL) { 809 warnmsg(LOG_ERR, __func__, 810 "malloc: %s", strerror(errno)); 811 exit(1); 812 } 813 memcpy(_argv, argv, (size_t)argc); 814 execv(scriptpath, (char *const *)_argv); 815 warnmsg(LOG_ERR, __func__, "child: exec failed: %s", 816 strerror(errno)); 817 exit(1); 818 } 819 820 return; 821} 822 823static int 824safefile(const char *path) 825{ 826 struct stat s; 827 uid_t myuid; 828 829 /* no setuid */ 830 if (getuid() != geteuid()) { 831 warnmsg(LOG_NOTICE, __func__, 832 "setuid'ed execution not allowed\n"); 833 return (-1); 834 } 835 836 if (lstat(path, &s) != 0) { 837 warnmsg(LOG_NOTICE, __func__, "lstat failed: %s", 838 strerror(errno)); 839 return (-1); 840 } 841 842 /* the file must be owned by the running uid */ 843 myuid = getuid(); 844 if (s.st_uid != myuid) { 845 warnmsg(LOG_NOTICE, __func__, 846 "%s has invalid owner uid\n", path); 847 return (-1); 848 } 849 850 switch (s.st_mode & S_IFMT) { 851 case S_IFREG: 852 break; 853 default: 854 warnmsg(LOG_NOTICE, __func__, 855 "%s is an invalid file type 0x%o\n", 856 path, (s.st_mode & S_IFMT)); 857 return (-1); 858 } 859 860 return (0); 861} 862 863/* Decode domain name label encoding in RFC 1035 Section 3.1 */ 864static size_t 865dname_labeldec(char *dst, size_t dlen, const char *src) 866{ 867 size_t len; 868 const char *src_origin; 869 const char *src_last; 870 const char *dst_origin; 871 872 src_origin = src; 873 src_last = strchr(src, '\0'); 874 dst_origin = dst; 875 memset(dst, '\0', dlen); 876 while (src && (len = (uint8_t)(*src++) & 0x3f) && 877 (src + len) <= src_last) { 878 if (dst != dst_origin) 879 *dst++ = '.'; 880 warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len); 881 memcpy(dst, src, len); 882 src += len; 883 dst += len; 884 } 885 *dst = '\0'; 886 887 /* 888 * XXX validate that domain name only contains valid characters 889 * for two reasons: 1) correctness, 2) we do not want to pass 890 * possible malicious, unescaped characters like `` to a script 891 * or program that could be exploited that way. 892 */ 893 894 return (src - src_origin); 895} 896