1 /* $NetBSD: faithd.c,v 1.25 2002/05/09 14:24:03 itojun Exp $ */ 2 /* $KAME: faithd.c,v 1.50 2002/05/09 14:06:52 itojun Exp $ */ 3 4 /* 5 * Copyright (C) 1997 and 1998 WIDE Project. 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 33 /* 34 * User level translator from IPv6 to IPv4. 35 * 36 * Usage: faithd [<port> <progpath> <arg1(progname)> <arg2> ...] 37 * e.g. faithd telnet /usr/local/v6/sbin/telnetd telnetd 38 */ 39 40 #include <sys/param.h> 41 #include <sys/types.h> 42 #include <sys/sysctl.h> 43 #include <sys/socket.h> 44 #include <sys/wait.h> 45 #include <sys/stat.h> 46 #include <sys/time.h> 47 #include <sys/ioctl.h> 48 #ifdef __FreeBSD__ 49 #include <libutil.h> 50 #endif 51 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <stdarg.h> 55 #include <string.h> 56 #include <syslog.h> 57 #include <unistd.h> 58 #include <errno.h> 59 #include <signal.h> 60 #include <fcntl.h> 61 #include <termios.h> 62 63 #include <net/if_types.h> 64 #ifdef IFT_FAITH 65 # define USE_ROUTE 66 # include <net/if.h> 67 # include <net/route.h> 68 # include <net/if_dl.h> 69 #endif 70 71 #include <netinet/in.h> 72 #include <arpa/inet.h> 73 #include <netdb.h> 74 #include <ifaddrs.h> 75 76 #ifdef FAITH4 77 #include <resolv.h> 78 #include <arpa/nameser.h> 79 #ifndef FAITH_NS 80 #define FAITH_NS "FAITH_NS" 81 #endif 82 #endif 83 84 #include "faithd.h" 85 #include "prefix.h" 86 87 char *serverpath = NULL; 88 char *serverarg[MAXARGV + 1]; 89 static char *faithdname = NULL; 90 char logname[BUFSIZ]; 91 char procname[BUFSIZ]; 92 struct myaddrs { 93 struct myaddrs *next; 94 struct sockaddr *addr; 95 }; 96 struct myaddrs *myaddrs = NULL; 97 static const char *service; 98 #ifdef USE_ROUTE 99 static int sockfd = 0; 100 #endif 101 int dflag = 0; 102 static int pflag = 0; 103 static int inetd = 0; 104 static char *configfile = NULL; 105 106 int main __P((int, char **)); 107 static int inetd_main __P((int, char **)); 108 static int daemon_main __P((int, char **)); 109 static void play_service __P((int)); 110 static void play_child __P((int, struct sockaddr *)); 111 static int faith_prefix __P((struct sockaddr *)); 112 static int map6to4 __P((struct sockaddr_in6 *, struct sockaddr_in *)); 113 #ifdef FAITH4 114 static int map4to6 __P((struct sockaddr_in *, struct sockaddr_in6 *)); 115 #endif 116 static void sig_child __P((int)); 117 static void sig_terminate __P((int)); 118 static void start_daemon __P((void)); 119 static void exit_stderr __P((const char *, ...)) 120 __attribute__((__format__(__printf__, 1, 2))); 121 static void grab_myaddrs __P((void)); 122 static void free_myaddrs __P((void)); 123 static void update_myaddrs __P((void)); 124 static void usage __P((void)); 125 126 int 127 main(int argc, char **argv) 128 { 129 130 /* 131 * Initializing stuff 132 */ 133 134 faithdname = strrchr(argv[0], '/'); 135 if (faithdname) 136 faithdname++; 137 else 138 faithdname = argv[0]; 139 140 if (strcmp(faithdname, "faithd") != 0) { 141 inetd = 1; 142 return inetd_main(argc, argv); 143 } else 144 return daemon_main(argc, argv); 145 } 146 147 static int 148 inetd_main(int argc, char **argv) 149 { 150 char path[MAXPATHLEN]; 151 struct sockaddr_storage me; 152 struct sockaddr_storage from; 153 int melen, fromlen; 154 int i; 155 int error; 156 const int on = 1; 157 char sbuf[NI_MAXSERV], snum[NI_MAXSERV]; 158 159 if (config_load(configfile) < 0 && configfile) { 160 exit_failure("could not load config file"); 161 /*NOTREACHED*/ 162 } 163 164 if (strrchr(argv[0], '/') == NULL) 165 snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]); 166 else 167 snprintf(path, sizeof(path), "%s", argv[0]); 168 169 #ifdef USE_ROUTE 170 grab_myaddrs(); 171 172 sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); 173 if (sockfd < 0) { 174 exit_failure("socket(PF_ROUTE): %s", strerror(errno)); 175 /*NOTREACHED*/ 176 } 177 #endif 178 179 melen = sizeof(me); 180 if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0) { 181 exit_failure("getsockname: %s", strerror(errno)); 182 /*NOTREACHED*/ 183 } 184 fromlen = sizeof(from); 185 if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) { 186 exit_failure("getpeername: %s", strerror(errno)); 187 /*NOTREACHED*/ 188 } 189 if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0, 190 sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0) 191 service = sbuf; 192 else 193 service = DEFAULT_PORT_NAME; 194 if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0, 195 snum, sizeof(snum), NI_NUMERICHOST) != 0) 196 snprintf(snum, sizeof(snum), "?"); 197 198 snprintf(logname, sizeof(logname), "faithd %s", snum); 199 snprintf(procname, sizeof(procname), "accepting port %s", snum); 200 openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 201 202 if (argc >= MAXARGV) { 203 exit_failure("too many arguments"); 204 /*NOTREACHED*/ 205 } 206 serverarg[0] = serverpath = path; 207 for (i = 1; i < argc; i++) 208 serverarg[i] = argv[i]; 209 serverarg[i] = NULL; 210 211 error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on, 212 sizeof(on)); 213 if (error < 0) { 214 exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); 215 /*NOTREACHED*/ 216 } 217 218 play_child(STDIN_FILENO, (struct sockaddr *)&from); 219 exit_failure("should not reach here"); 220 return 0; /*dummy!*/ 221 } 222 223 static int 224 daemon_main(int argc, char **argv) 225 { 226 struct addrinfo hints, *res; 227 int s_wld, error, i, serverargc, on = 1; 228 int family = AF_INET6; 229 int c; 230 #ifdef FAITH_NS 231 char *ns; 232 #endif /* FAITH_NS */ 233 234 while ((c = getopt(argc, argv, "df:p46")) != -1) { 235 switch (c) { 236 case 'd': 237 dflag++; 238 break; 239 case 'f': 240 configfile = optarg; 241 break; 242 case 'p': 243 pflag++; 244 break; 245 #ifdef FAITH4 246 case '4': 247 family = AF_INET; 248 break; 249 case '6': 250 family = AF_INET6; 251 break; 252 #endif 253 default: 254 usage(); 255 /*NOTREACHED*/ 256 } 257 } 258 argc -= optind; 259 argv += optind; 260 261 if (config_load(configfile) < 0 && configfile) { 262 exit_failure("could not load config file"); 263 /*NOTREACHED*/ 264 } 265 266 #ifdef FAITH_NS 267 if ((ns = getenv(FAITH_NS)) != NULL) { 268 struct sockaddr_storage ss; 269 struct addrinfo hints, *res; 270 char serv[NI_MAXSERV]; 271 272 memset(&ss, 0, sizeof(ss)); 273 memset(&hints, 0, sizeof(hints)); 274 snprintf(serv, sizeof(serv), "%u", NAMESERVER_PORT); 275 hints.ai_flags = AI_NUMERICHOST; 276 if (getaddrinfo(ns, serv, &hints, &res) == 0) { 277 res_init(); 278 memcpy(&_res_ext.nsaddr, res->ai_addr, res->ai_addrlen); 279 _res.nscount = 1; 280 } 281 } 282 #endif /* FAITH_NS */ 283 284 #ifdef USE_ROUTE 285 grab_myaddrs(); 286 #endif 287 288 switch (argc) { 289 case 0: 290 usage(); 291 /*NOTREACHED*/ 292 default: 293 serverargc = argc - NUMARG; 294 if (serverargc >= MAXARGV) 295 exit_stderr("too many arguments"); 296 297 serverpath = malloc(strlen(argv[NUMPRG]) + 1); 298 if (!serverpath) 299 exit_stderr("not enough core"); 300 strcpy(serverpath, argv[NUMPRG]); 301 for (i = 0; i < serverargc; i++) { 302 serverarg[i] = malloc(strlen(argv[i + NUMARG]) + 1); 303 if (!serverarg[i]) 304 exit_stderr("not enough core"); 305 strcpy(serverarg[i], argv[i + NUMARG]); 306 } 307 serverarg[i] = NULL; 308 /* fall throuth */ 309 case 1: /* no local service */ 310 service = argv[NUMPRT]; 311 break; 312 } 313 314 start_daemon(); 315 316 /* 317 * Opening wild card socket for this service. 318 */ 319 320 memset(&hints, 0, sizeof(hints)); 321 hints.ai_flags = AI_PASSIVE; 322 hints.ai_family = family; 323 hints.ai_socktype = SOCK_STREAM; 324 hints.ai_protocol = 0; 325 error = getaddrinfo(NULL, service, &hints, &res); 326 if (error) 327 exit_failure("getaddrinfo: %s", gai_strerror(error)); 328 329 s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 330 if (s_wld == -1) 331 exit_failure("socket: %s", strerror(errno)); 332 333 #ifdef IPV6_FAITH 334 if (res->ai_family == AF_INET6) { 335 error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on)); 336 if (error == -1) 337 exit_failure("setsockopt(IPV6_FAITH): %s", 338 strerror(errno)); 339 } 340 #endif 341 #ifdef FAITH4 342 #ifdef IP_FAITH 343 if (res->ai_family == AF_INET) { 344 error = setsockopt(s_wld, IPPROTO_IP, IP_FAITH, &on, sizeof(on)); 345 if (error == -1) 346 exit_failure("setsockopt(IP_FAITH): %s", 347 strerror(errno)); 348 } 349 #endif 350 #endif /* FAITH4 */ 351 352 error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 353 if (error == -1) 354 exit_failure("setsockopt(SO_REUSEADDR): %s", strerror(errno)); 355 356 error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)); 357 if (error == -1) 358 exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); 359 360 error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen); 361 if (error == -1) 362 exit_failure("bind: %s", strerror(errno)); 363 364 error = listen(s_wld, 5); 365 if (error == -1) 366 exit_failure("listen: %s", strerror(errno)); 367 368 #ifdef USE_ROUTE 369 sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); 370 if (sockfd < 0) { 371 exit_failure("socket(PF_ROUTE): %s", strerror(errno)); 372 /*NOTREACHED*/ 373 } 374 #endif 375 376 /* 377 * Everything is OK. 378 */ 379 380 snprintf(logname, sizeof(logname), "faithd %s", service); 381 snprintf(procname, sizeof(procname), "accepting port %s", service); 382 openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 383 syslog(LOG_INFO, "Staring faith daemon for %s port", service); 384 385 play_service(s_wld); 386 /* NOTREACHED */ 387 exit(1); /*pacify gcc*/ 388 } 389 390 static void 391 play_service(int s_wld) 392 { 393 struct sockaddr_storage srcaddr; 394 int len; 395 int s_src; 396 pid_t child_pid; 397 fd_set rfds; 398 int error; 399 int maxfd; 400 401 /* 402 * Wait, accept, fork, faith.... 403 */ 404 again: 405 setproctitle("%s", procname); 406 407 FD_ZERO(&rfds); 408 FD_SET(s_wld, &rfds); 409 maxfd = s_wld; 410 #ifdef USE_ROUTE 411 if (sockfd) { 412 FD_SET(sockfd, &rfds); 413 maxfd = (maxfd < sockfd) ? sockfd : maxfd; 414 } 415 #endif 416 417 error = select(maxfd + 1, &rfds, NULL, NULL, NULL); 418 if (error < 0) { 419 if (errno == EINTR) 420 goto again; 421 exit_failure("select: %s", strerror(errno)); 422 /*NOTREACHED*/ 423 } 424 425 #ifdef USE_ROUTE 426 if (FD_ISSET(sockfd, &rfds)) { 427 update_myaddrs(); 428 } 429 #endif 430 if (FD_ISSET(s_wld, &rfds)) { 431 len = sizeof(srcaddr); 432 s_src = accept(s_wld, (struct sockaddr *)&srcaddr, 433 &len); 434 if (s_src < 0) { 435 if (errno == ECONNABORTED) 436 goto again; 437 exit_failure("socket: %s", strerror(errno)); 438 /*NOTREACHED*/ 439 } 440 441 child_pid = fork(); 442 443 if (child_pid == 0) { 444 /* child process */ 445 close(s_wld); 446 closelog(); 447 openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 448 play_child(s_src, (struct sockaddr *)&srcaddr); 449 exit_failure("should never reach here"); 450 /*NOTREACHED*/ 451 } else { 452 /* parent process */ 453 close(s_src); 454 if (child_pid == -1) 455 syslog(LOG_ERR, "can't fork"); 456 } 457 } 458 goto again; 459 } 460 461 static void 462 play_child(int s_src, struct sockaddr *srcaddr) 463 { 464 struct sockaddr_storage dstaddr6; 465 struct sockaddr_storage dstaddr4; 466 char src[NI_MAXHOST]; 467 char dst6[NI_MAXHOST]; 468 char dst4[NI_MAXHOST]; 469 int len = sizeof(dstaddr6); 470 int s_dst, error, hport, nresvport, on = 1; 471 struct timeval tv; 472 struct sockaddr *sa4; 473 const struct config *conf; 474 475 tv.tv_sec = 1; 476 tv.tv_usec = 0; 477 478 getnameinfo(srcaddr, srcaddr->sa_len, 479 src, sizeof(src), NULL, 0, NI_NUMERICHOST); 480 syslog(LOG_INFO, "accepted a client from %s", src); 481 482 error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len); 483 if (error == -1) { 484 exit_failure("getsockname: %s", strerror(errno)); 485 /*NOTREACHED*/ 486 } 487 488 getnameinfo((struct sockaddr *)&dstaddr6, len, 489 dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST); 490 syslog(LOG_INFO, "the client is connecting to %s", dst6); 491 492 if (!faith_prefix((struct sockaddr *)&dstaddr6)) { 493 if (serverpath) { 494 /* 495 * Local service 496 */ 497 syslog(LOG_INFO, "executing local %s", serverpath); 498 if (!inetd) { 499 dup2(s_src, 0); 500 close(s_src); 501 dup2(0, 1); 502 dup2(0, 2); 503 } 504 execv(serverpath, serverarg); 505 syslog(LOG_ERR, "execv %s: %s", serverpath, 506 strerror(errno)); 507 _exit(EXIT_FAILURE); 508 } else { 509 close(s_src); 510 exit_success("no local service for %s", service); 511 } 512 } 513 514 /* 515 * Act as a translator 516 */ 517 518 switch (((struct sockaddr *)&dstaddr6)->sa_family) { 519 case AF_INET6: 520 if (!map6to4((struct sockaddr_in6 *)&dstaddr6, 521 (struct sockaddr_in *)&dstaddr4)) { 522 close(s_src); 523 exit_failure("map6to4 failed"); 524 /*NOTREACHED*/ 525 } 526 syslog(LOG_INFO, "translating from v6 to v4"); 527 break; 528 #ifdef FAITH4 529 case AF_INET: 530 if (!map4to6((struct sockaddr_in *)&dstaddr6, 531 (struct sockaddr_in6 *)&dstaddr4)) { 532 close(s_src); 533 exit_failure("map4to6 failed"); 534 /*NOTREACHED*/ 535 } 536 syslog(LOG_INFO, "translating from v4 to v6"); 537 break; 538 #endif 539 default: 540 close(s_src); 541 exit_failure("family not supported"); 542 /*NOTREACHED*/ 543 } 544 545 sa4 = (struct sockaddr *)&dstaddr4; 546 getnameinfo(sa4, sa4->sa_len, 547 dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST); 548 549 conf = config_match(srcaddr, sa4); 550 if (!conf || !conf->permit) { 551 close(s_src); 552 if (conf) { 553 exit_failure("translation to %s not permitted for %s", 554 dst4, prefix_string(&conf->match)); 555 /*NOTREACHED*/ 556 } else { 557 exit_failure("translation to %s not permitted", dst4); 558 /*NOTREACHED*/ 559 } 560 } 561 562 syslog(LOG_INFO, "the translator is connecting to %s", dst4); 563 564 setproctitle("port %s, %s -> %s", service, src, dst4); 565 566 if (sa4->sa_family == AF_INET6) 567 hport = ntohs(((struct sockaddr_in6 *)&dstaddr4)->sin6_port); 568 else /* AF_INET */ 569 hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port); 570 571 if (pflag) 572 s_dst = rresvport_af(&nresvport, sa4->sa_family); 573 else 574 s_dst = socket(sa4->sa_family, SOCK_STREAM, 0); 575 if (s_dst < 0) { 576 exit_failure("socket: %s", strerror(errno)); 577 /*NOTREACHED*/ 578 } 579 580 if (conf->src.a.ss_family) { 581 if (bind(s_dst, (const struct sockaddr *)&conf->src.a, 582 conf->src.a.ss_len) < 0) { 583 exit_failure("bind: %s", strerror(errno)); 584 /*NOTREACHED*/ 585 } 586 } 587 588 error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)); 589 if (error < 0) { 590 exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); 591 /*NOTREACHED*/ 592 } 593 594 error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 595 if (error < 0) { 596 exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno)); 597 /*NOTREACHED*/ 598 } 599 error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 600 if (error < 0) { 601 exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno)); 602 /*NOTREACHED*/ 603 } 604 605 error = connect(s_dst, sa4, sa4->sa_len); 606 if (error < 0) { 607 exit_failure("connect: %s", strerror(errno)); 608 /*NOTREACHED*/ 609 } 610 611 switch (hport) { 612 case FTP_PORT: 613 ftp_relay(s_src, s_dst); 614 break; 615 default: 616 tcp_relay(s_src, s_dst, service); 617 break; 618 } 619 620 /* NOTREACHED */ 621 } 622 623 /* 0: non faith, 1: faith */ 624 static int 625 faith_prefix(struct sockaddr *dst) 626 { 627 #ifndef USE_ROUTE 628 int mib[4], size; 629 struct in6_addr faith_prefix; 630 struct sockaddr_in6 *dst6 = (struct sockaddr_in *)dst; 631 632 if (dst->sa_family != AF_INET6) 633 return 0; 634 635 mib[0] = CTL_NET; 636 mib[1] = PF_INET6; 637 mib[2] = IPPROTO_IPV6; 638 mib[3] = IPV6CTL_FAITH_PREFIX; 639 size = sizeof(struct in6_addr); 640 if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0) { 641 exit_failure("sysctl: %s", strerror(errno)); 642 /*NOTREACHED*/ 643 } 644 645 if (memcmp(dst, &faith_prefix, 646 sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) { 647 return 1; 648 } 649 return 0; 650 #else 651 struct myaddrs *p; 652 struct sockaddr_in6 *sin6; 653 struct sockaddr_in *sin4; 654 struct sockaddr_in6 *dst6; 655 struct sockaddr_in *dst4; 656 struct sockaddr_in dstmap; 657 658 dst6 = (struct sockaddr_in6 *)dst; 659 if (dst->sa_family == AF_INET6 660 && IN6_IS_ADDR_V4MAPPED(&dst6->sin6_addr)) { 661 /* ugly... */ 662 memset(&dstmap, 0, sizeof(dstmap)); 663 dstmap.sin_family = AF_INET; 664 dstmap.sin_len = sizeof(dstmap); 665 memcpy(&dstmap.sin_addr, &dst6->sin6_addr.s6_addr[12], 666 sizeof(dstmap.sin_addr)); 667 dst = (struct sockaddr *)&dstmap; 668 } 669 670 dst6 = (struct sockaddr_in6 *)dst; 671 dst4 = (struct sockaddr_in *)dst; 672 673 for (p = myaddrs; p; p = p->next) { 674 sin6 = (struct sockaddr_in6 *)p->addr; 675 sin4 = (struct sockaddr_in *)p->addr; 676 677 if (p->addr->sa_len != dst->sa_len 678 || p->addr->sa_family != dst->sa_family) 679 continue; 680 681 switch (dst->sa_family) { 682 case AF_INET6: 683 if (sin6->sin6_scope_id == dst6->sin6_scope_id 684 && IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &dst6->sin6_addr)) 685 return 0; 686 break; 687 case AF_INET: 688 if (sin4->sin_addr.s_addr == dst4->sin_addr.s_addr) 689 return 0; 690 break; 691 } 692 } 693 return 1; 694 #endif 695 } 696 697 /* 0: non faith, 1: faith */ 698 static int 699 map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4) 700 { 701 memset(dst4, 0, sizeof(*dst4)); 702 dst4->sin_len = sizeof(*dst4); 703 dst4->sin_family = AF_INET; 704 dst4->sin_port = dst6->sin6_port; 705 memcpy(&dst4->sin_addr, &dst6->sin6_addr.s6_addr[12], 706 sizeof(dst4->sin_addr)); 707 708 if (dst4->sin_addr.s_addr == INADDR_ANY 709 || dst4->sin_addr.s_addr == INADDR_BROADCAST 710 || IN_MULTICAST(ntohl(dst4->sin_addr.s_addr))) 711 return 0; 712 713 return 1; 714 } 715 716 #ifdef FAITH4 717 /* 0: non faith, 1: faith */ 718 static int 719 map4to6(struct sockaddr_in *dst4, struct sockaddr_in6 *dst6) 720 { 721 char host[NI_MAXHOST]; 722 char serv[NI_MAXSERV]; 723 struct addrinfo hints, *res; 724 int ai_errno; 725 726 if (getnameinfo((struct sockaddr *)dst4, dst4->sin_len, host, sizeof(host), 727 serv, sizeof(serv), NI_NAMEREQD|NI_NUMERICSERV) != 0) 728 return 0; 729 730 memset(&hints, 0, sizeof(hints)); 731 hints.ai_flags = 0; 732 hints.ai_family = AF_INET6; 733 hints.ai_socktype = SOCK_STREAM; 734 hints.ai_protocol = 0; 735 736 if ((ai_errno = getaddrinfo(host, serv, &hints, &res)) != 0) { 737 syslog(LOG_INFO, "%s %s: %s", host, serv, 738 gai_strerror(ai_errno)); 739 return 0; 740 } 741 742 memcpy(dst6, res->ai_addr, res->ai_addrlen); 743 744 freeaddrinfo(res); 745 746 return 1; 747 } 748 #endif /* FAITH4 */ 749 750 static void 751 sig_child(int sig) 752 { 753 int status; 754 pid_t pid; 755 756 while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) 757 if (WEXITSTATUS(status)) 758 syslog(LOG_WARNING, "child %d exit status 0x%x", 759 pid, status); 760 } 761 762 void 763 sig_terminate(int sig) 764 { 765 syslog(LOG_INFO, "Terminating faith daemon"); 766 exit(EXIT_SUCCESS); 767 } 768 769 static void 770 start_daemon(void) 771 { 772 #ifdef SA_NOCLDWAIT 773 struct sigaction sa; 774 #endif 775 776 if (daemon(0, 0) == -1) 777 exit_stderr("daemon: %s", strerror(errno)); 778 779 #ifdef SA_NOCLDWAIT 780 memset(&sa, 0, sizeof(sa)); 781 sa.sa_handler = sig_child; 782 sa.sa_flags = SA_NOCLDWAIT; 783 sigemptyset(&sa.sa_mask); 784 sigaction(SIGCHLD, &sa, (struct sigaction *)0); 785 #else 786 if (signal(SIGCHLD, sig_child) == SIG_ERR) { 787 exit_failure("signal CHLD: %s", strerror(errno)); 788 /*NOTREACHED*/ 789 } 790 #endif 791 792 if (signal(SIGTERM, sig_terminate) == SIG_ERR) { 793 exit_failure("signal TERM: %s", strerror(errno)); 794 /*NOTREACHED*/ 795 } 796 } 797 798 static void 799 exit_stderr(const char *fmt, ...) 800 { 801 va_list ap; 802 char buf[BUFSIZ]; 803 804 va_start(ap, fmt); 805 vsnprintf(buf, sizeof(buf), fmt, ap); 806 va_end(ap); 807 fprintf(stderr, "%s\n", buf); 808 exit(EXIT_FAILURE); 809 } 810 811 void 812 exit_failure(const char *fmt, ...) 813 { 814 va_list ap; 815 char buf[BUFSIZ]; 816 817 va_start(ap, fmt); 818 vsnprintf(buf, sizeof(buf), fmt, ap); 819 va_end(ap); 820 syslog(LOG_ERR, "%s", buf); 821 exit(EXIT_FAILURE); 822 } 823 824 void 825 exit_success(const char *fmt, ...) 826 { 827 va_list ap; 828 char buf[BUFSIZ]; 829 830 va_start(ap, fmt); 831 vsnprintf(buf, sizeof(buf), fmt, ap); 832 va_end(ap); 833 syslog(LOG_INFO, "%s", buf); 834 exit(EXIT_SUCCESS); 835 } 836 837 #ifdef USE_ROUTE 838 static void 839 grab_myaddrs() 840 { 841 struct ifaddrs *ifap, *ifa; 842 struct myaddrs *p; 843 struct sockaddr_in6 *sin6; 844 845 if (getifaddrs(&ifap) != 0) { 846 exit_failure("getifaddrs"); 847 /*NOTREACHED*/ 848 } 849 850 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 851 switch (ifa->ifa_addr->sa_family) { 852 case AF_INET: 853 case AF_INET6: 854 break; 855 default: 856 continue; 857 } 858 859 p = (struct myaddrs *)malloc(sizeof(struct myaddrs) + 860 ifa->ifa_addr->sa_len); 861 if (!p) { 862 exit_failure("not enough core"); 863 /*NOTREACHED*/ 864 } 865 memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len); 866 p->next = myaddrs; 867 p->addr = (struct sockaddr *)(p + 1); 868 #ifdef __KAME__ 869 if (ifa->ifa_addr->sa_family == AF_INET6) { 870 sin6 = (struct sockaddr_in6 *)p->addr; 871 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) 872 || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 873 sin6->sin6_scope_id = 874 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); 875 sin6->sin6_addr.s6_addr[2] = 0; 876 sin6->sin6_addr.s6_addr[3] = 0; 877 } 878 } 879 #endif 880 myaddrs = p; 881 if (dflag) { 882 char hbuf[NI_MAXHOST]; 883 getnameinfo(p->addr, p->addr->sa_len, 884 hbuf, sizeof(hbuf), NULL, 0, 885 NI_NUMERICHOST); 886 syslog(LOG_INFO, "my interface: %s %s", hbuf, 887 ifa->ifa_name); 888 } 889 } 890 891 freeifaddrs(ifap); 892 } 893 894 static void 895 free_myaddrs() 896 { 897 struct myaddrs *p, *q; 898 899 p = myaddrs; 900 while (p) { 901 q = p->next; 902 free(p); 903 p = q; 904 } 905 myaddrs = NULL; 906 } 907 908 static void 909 update_myaddrs() 910 { 911 char msg[BUFSIZ]; 912 int len; 913 struct rt_msghdr *rtm; 914 915 len = read(sockfd, msg, sizeof(msg)); 916 if (len < 0) { 917 syslog(LOG_ERR, "read(PF_ROUTE) failed"); 918 return; 919 } 920 rtm = (struct rt_msghdr *)msg; 921 if (len < 4 || len < rtm->rtm_msglen) { 922 syslog(LOG_ERR, "read(PF_ROUTE) short read"); 923 return; 924 } 925 if (rtm->rtm_version != RTM_VERSION) { 926 syslog(LOG_ERR, "routing socket version mismatch"); 927 close(sockfd); 928 sockfd = 0; 929 return; 930 } 931 switch (rtm->rtm_type) { 932 case RTM_NEWADDR: 933 case RTM_DELADDR: 934 case RTM_IFINFO: 935 break; 936 default: 937 return; 938 } 939 /* XXX more filters here? */ 940 941 syslog(LOG_INFO, "update interface address list"); 942 free_myaddrs(); 943 grab_myaddrs(); 944 } 945 #endif /*USE_ROUTE*/ 946 947 static void 948 usage() 949 { 950 fprintf(stderr, "usage: %s [-dp] [-f conf] service [serverpath [serverargs]]\n", 951 faithdname); 952 exit(0); 953 } 954