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