1 /* $KAME: rtsol.c,v 1.27 2003/10/05 00:09:36 itojun Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * Copyright (C) 2011 Hiroki Sato 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the project nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $FreeBSD$ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/socket.h> 39 #include <sys/uio.h> 40 #include <sys/queue.h> 41 #include <sys/wait.h> 42 #include <sys/stat.h> 43 44 #include <net/if.h> 45 #include <net/route.h> 46 #include <net/if_dl.h> 47 48 #define __BSD_VISIBLE 1 /* IN6ADDR_LINKLOCAL_ALLROUTERS_INIT */ 49 #include <netinet/in.h> 50 #undef __BSD_VISIBLE 51 #include <netinet/ip6.h> 52 #include <netinet6/ip6_var.h> 53 #include <netinet/icmp6.h> 54 55 #include <arpa/inet.h> 56 57 #include <netdb.h> 58 #include <time.h> 59 #include <fcntl.h> 60 #include <unistd.h> 61 #include <stdio.h> 62 #include <time.h> 63 #include <err.h> 64 #include <errno.h> 65 #include <string.h> 66 #include <stdlib.h> 67 #include <syslog.h> 68 #include "rtsold.h" 69 70 static struct msghdr rcvmhdr; 71 static struct msghdr sndmhdr; 72 static struct iovec rcviov[2]; 73 static struct iovec sndiov[2]; 74 static struct sockaddr_in6 from; 75 static int rcvcmsglen; 76 77 int rssock; 78 static char rsid[IFNAMSIZ + 1 + sizeof(DNSINFO_ORIGIN_LABEL) + 1 + NI_MAXHOST]; 79 struct ifinfo_head_t ifinfo_head = 80 TAILQ_HEAD_INITIALIZER(ifinfo_head); 81 82 static const struct sockaddr_in6 sin6_allrouters = { 83 .sin6_len = sizeof(sin6_allrouters), 84 .sin6_family = AF_INET6, 85 .sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT, 86 }; 87 88 static void call_script(const int, const char *const *, 89 struct script_msg_head_t *); 90 static size_t dname_labeldec(char *, size_t, const char *); 91 static int safefile(const char *); 92 static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t); 93 static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *, 94 struct script_msg_head_t *, struct script_msg_head_t *); 95 static char *make_rsid(const char *, const char *, struct rainfo *); 96 97 #define _ARGS_OTHER otherconf_script, ifi->ifname 98 #define _ARGS_RESADD resolvconf_script, "-a", rsid 99 #define _ARGS_RESDEL resolvconf_script, "-d", rsid 100 101 #define CALL_SCRIPT(name, sm_head) do { \ 102 const char *const sarg[] = { _ARGS_##name, NULL }; \ 103 call_script(sizeof(sarg), sarg, sm_head); \ 104 } while (0) 105 106 #define ELM_MALLOC(p, error_action) 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 *)(void *)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 timespec now; 260 struct timespec 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 *)(void *)(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 *)(void *)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_DEBUG, __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 clock_gettime(CLOCK_MONOTONIC_FAST, &now); 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 *)(void *)(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 TS_ADD(&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 TS_ADD(&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 timespec 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 clock_gettime(CLOCK_MONOTONIC_FAST, &now); 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 (TS_CMP(&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 break; 618 case ND_OPT_DNSSL: 619 if (TS_CMP(&now, &rao->rao_expire, >)) { 620 warnmsg(LOG_INFO, __func__, 621 "expired dnssl entry: %s", 622 (char *)rao->rao_msg); 623 break; 624 } 625 dcount++; 626 /* Check resolv.conf(5) restrictions. */ 627 if (dcount > 6) { 628 warnmsg(LOG_INFO, __func__, 629 "dnssl entry exceeding maximum count (%d>6)" 630 ": %s", dcount, (char *)rao->rao_msg); 631 break; 632 } 633 if (256 < dlen + strlen(rao->rao_msg) + 634 strlen(resstr_sp)) { 635 warnmsg(LOG_INFO, __func__, 636 "dnssl entry exceeding maximum length " 637 "(>256): %s", (char *)rao->rao_msg); 638 break; 639 } 640 ELM_MALLOC(smp1, continue); 641 ELM_MALLOC(smp2, goto free1); 642 if (TAILQ_EMPTY(&sm_dnssl_head)) { 643 ELM_MALLOC(smp3, goto free2); 644 smp3->sm_msg = resstr_sh_prefix; 645 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3, 646 sm_next); 647 } 648 smp1->sm_msg = rao->rao_msg; 649 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, 650 sm_next); 651 smp2->sm_msg = resstr_sp; 652 TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2, 653 sm_next); 654 dlen += strlen(rao->rao_msg) + 655 strlen(resstr_sp); 656 ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED; 657 break; 658 } 659 continue; 660 free2: 661 free(smp2); 662 free1: 663 free(smp1); 664 } 665 /* Call the script for each information source. */ 666 if (uflag) 667 ra_opt_rdnss_dispatch(ifi, rai, &sm_rdnss_head, 668 &sm_dnssl_head); 669 } 670 /* Call the script for each interface. */ 671 if (!uflag) 672 ra_opt_rdnss_dispatch(ifi, NULL, &sm_rdnss_head, 673 &sm_dnssl_head); 674 return (0); 675 } 676 677 char * 678 make_rsid(const char *ifname, const char *origin, struct rainfo *rai) 679 { 680 char hbuf[NI_MAXHOST]; 681 682 if (rai == NULL) 683 sprintf(rsid, "%s:%s", ifname, origin); 684 else { 685 if (!IN6_IS_ADDR_LINKLOCAL(&rai->rai_saddr.sin6_addr)) 686 return (NULL); 687 if (getnameinfo((struct sockaddr *)&rai->rai_saddr, 688 rai->rai_saddr.sin6_len, hbuf, sizeof(hbuf), NULL, 0, 689 NI_NUMERICHOST) != 0) 690 return (NULL); 691 sprintf(rsid, "%s:%s:[%s]", ifname, origin, hbuf); 692 } 693 warnmsg(LOG_DEBUG, __func__, "rsid = [%s]", rsid); 694 return (rsid); 695 } 696 697 int 698 ra_opt_rdnss_dispatch(struct ifinfo *ifi, struct rainfo *rai, 699 struct script_msg_head_t *sm_rdnss_head, 700 struct script_msg_head_t *sm_dnssl_head) 701 { 702 struct script_msg *smp1; 703 const char *r; 704 int error; 705 706 error = 0; 707 /* Add \n for DNSSL list. */ 708 if (!TAILQ_EMPTY(sm_dnssl_head)) { 709 ELM_MALLOC(smp1, goto ra_opt_rdnss_freeit); 710 smp1->sm_msg = resstr_nl; 711 TAILQ_INSERT_TAIL(sm_dnssl_head, smp1, sm_next); 712 } 713 TAILQ_CONCAT(sm_rdnss_head, sm_dnssl_head, sm_next); 714 715 r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, uflag ? rai : NULL); 716 if (r == NULL) { 717 warnmsg(LOG_ERR, __func__, "make_rsid() failed. " 718 "Script was not invoked."); 719 error = 1; 720 goto ra_opt_rdnss_freeit; 721 } 722 if (!TAILQ_EMPTY(sm_rdnss_head)) 723 CALL_SCRIPT(RESADD, sm_rdnss_head); 724 else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED || 725 ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) { 726 CALL_SCRIPT(RESDEL, NULL); 727 ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO; 728 ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO; 729 } 730 731 ra_opt_rdnss_freeit: 732 /* Clear script message queue. */ 733 if (!TAILQ_EMPTY(sm_rdnss_head)) { 734 while ((smp1 = TAILQ_FIRST(sm_rdnss_head)) != NULL) { 735 TAILQ_REMOVE(sm_rdnss_head, smp1, sm_next); 736 free(smp1); 737 } 738 } 739 if (!TAILQ_EMPTY(sm_dnssl_head)) { 740 while ((smp1 = TAILQ_FIRST(sm_dnssl_head)) != NULL) { 741 TAILQ_REMOVE(sm_dnssl_head, smp1, sm_next); 742 free(smp1); 743 } 744 } 745 return (error); 746 } 747 748 static struct ra_opt * 749 find_raopt(struct rainfo *rai, int type, void *msg, size_t len) 750 { 751 struct ra_opt *rao; 752 753 TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) { 754 if (rao->rao_type == type && 755 rao->rao_len == strlen(msg) && 756 memcmp(rao->rao_msg, msg, len) == 0) 757 break; 758 } 759 760 return (rao); 761 } 762 763 static void 764 call_script(const int argc, const char *const argv[], 765 struct script_msg_head_t *sm_head) 766 { 767 const char *scriptpath; 768 int fd[2]; 769 int error; 770 pid_t pid, wpid; 771 772 if ((scriptpath = argv[0]) == NULL) 773 return; 774 775 fd[0] = fd[1] = -1; 776 if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) { 777 error = pipe(fd); 778 if (error) { 779 warnmsg(LOG_ERR, __func__, 780 "failed to create a pipe: %s", strerror(errno)); 781 return; 782 } 783 } 784 785 /* launch the script */ 786 pid = fork(); 787 if (pid < 0) { 788 warnmsg(LOG_ERR, __func__, 789 "failed to fork: %s", strerror(errno)); 790 return; 791 } else if (pid) { /* parent */ 792 int wstatus; 793 794 if (fd[0] != -1) { /* Send message to the child if any. */ 795 ssize_t len; 796 struct script_msg *smp; 797 798 close(fd[0]); 799 TAILQ_FOREACH(smp, sm_head, sm_next) { 800 len = strlen(smp->sm_msg); 801 warnmsg(LOG_DEBUG, __func__, 802 "write to child = %s(%zd)", 803 smp->sm_msg, len); 804 if (write(fd[1], smp->sm_msg, len) != len) { 805 warnmsg(LOG_ERR, __func__, 806 "write to child failed: %s", 807 strerror(errno)); 808 break; 809 } 810 } 811 close(fd[1]); 812 } 813 do { 814 wpid = wait(&wstatus); 815 } while (wpid != pid && wpid > 0); 816 817 if (wpid < 0) 818 warnmsg(LOG_ERR, __func__, 819 "wait: %s", strerror(errno)); 820 else 821 warnmsg(LOG_DEBUG, __func__, 822 "script \"%s\" terminated", scriptpath); 823 } else { /* child */ 824 int nullfd; 825 char **_argv; 826 827 if (safefile(scriptpath)) { 828 warnmsg(LOG_ERR, __func__, 829 "script \"%s\" cannot be executed safely", 830 scriptpath); 831 exit(1); 832 } 833 nullfd = open("/dev/null", O_RDWR); 834 if (nullfd < 0) { 835 warnmsg(LOG_ERR, __func__, 836 "open /dev/null: %s", strerror(errno)); 837 exit(1); 838 } 839 if (fd[0] != -1) { /* Receive message from STDIN if any. */ 840 close(fd[1]); 841 if (fd[0] != STDIN_FILENO) { 842 /* Connect a pipe read-end to child's STDIN. */ 843 if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) { 844 warnmsg(LOG_ERR, __func__, 845 "dup2 STDIN: %s", strerror(errno)); 846 exit(1); 847 } 848 close(fd[0]); 849 } 850 } else 851 dup2(nullfd, STDIN_FILENO); 852 853 dup2(nullfd, STDOUT_FILENO); 854 dup2(nullfd, STDERR_FILENO); 855 if (nullfd > STDERR_FILENO) 856 close(nullfd); 857 858 _argv = malloc(sizeof(*_argv) * argc); 859 if (_argv == NULL) { 860 warnmsg(LOG_ERR, __func__, 861 "malloc: %s", strerror(errno)); 862 exit(1); 863 } 864 memcpy(_argv, argv, (size_t)argc); 865 execv(scriptpath, (char *const *)_argv); 866 warnmsg(LOG_ERR, __func__, "child: exec failed: %s", 867 strerror(errno)); 868 exit(1); 869 } 870 871 return; 872 } 873 874 static int 875 safefile(const char *path) 876 { 877 struct stat s; 878 uid_t myuid; 879 880 /* no setuid */ 881 if (getuid() != geteuid()) { 882 warnmsg(LOG_NOTICE, __func__, 883 "setuid'ed execution not allowed\n"); 884 return (-1); 885 } 886 887 if (lstat(path, &s) != 0) { 888 warnmsg(LOG_NOTICE, __func__, "lstat failed: %s", 889 strerror(errno)); 890 return (-1); 891 } 892 893 /* the file must be owned by the running uid */ 894 myuid = getuid(); 895 if (s.st_uid != myuid) { 896 warnmsg(LOG_NOTICE, __func__, 897 "%s has invalid owner uid\n", path); 898 return (-1); 899 } 900 901 switch (s.st_mode & S_IFMT) { 902 case S_IFREG: 903 break; 904 default: 905 warnmsg(LOG_NOTICE, __func__, 906 "%s is an invalid file type 0x%o\n", 907 path, (s.st_mode & S_IFMT)); 908 return (-1); 909 } 910 911 return (0); 912 } 913 914 /* Decode domain name label encoding in RFC 1035 Section 3.1 */ 915 static size_t 916 dname_labeldec(char *dst, size_t dlen, const char *src) 917 { 918 size_t len; 919 const char *src_origin; 920 const char *src_last; 921 const char *dst_origin; 922 923 src_origin = src; 924 src_last = strchr(src, '\0'); 925 dst_origin = dst; 926 memset(dst, '\0', dlen); 927 while (src && (len = (uint8_t)(*src++) & 0x3f) && 928 (src + len) <= src_last && 929 (dst - dst_origin < (ssize_t)dlen)) { 930 if (dst != dst_origin) 931 *dst++ = '.'; 932 warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len); 933 memcpy(dst, src, len); 934 src += len; 935 dst += len; 936 } 937 *dst = '\0'; 938 939 /* 940 * XXX validate that domain name only contains valid characters 941 * for two reasons: 1) correctness, 2) we do not want to pass 942 * possible malicious, unescaped characters like `` to a script 943 * or program that could be exploited that way. 944 */ 945 946 return (src - src_origin); 947 } 948