1 /* $OpenBSD: relayd.c,v 1.104 2011/09/04 20:26:58 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org> 5 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/types.h> 21 #include <sys/queue.h> 22 #include <sys/socket.h> 23 #include <sys/wait.h> 24 #include <sys/resource.h> 25 #include <sys/hash.h> 26 27 #include <net/if.h> 28 #include <netinet/in.h> 29 #include <arpa/inet.h> 30 31 #include <string.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <fcntl.h> 35 #include <getopt.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <event.h> 39 #include <unistd.h> 40 #include <ctype.h> 41 #include <pwd.h> 42 #include <sha1.h> 43 #include <md5.h> 44 45 #include <openssl/ssl.h> 46 47 #include "relayd.h" 48 49 __dead void usage(void); 50 51 int parent_configure(struct relayd *); 52 void parent_reload(struct relayd *, u_int, const char *); 53 void parent_sig_handler(int, short, void *); 54 void parent_shutdown(struct relayd *); 55 int parent_dispatch_pfe(int, struct privsep_proc *, struct imsg *); 56 int parent_dispatch_hce(int, struct privsep_proc *, struct imsg *); 57 int parent_dispatch_relay(int, struct privsep_proc *, 58 struct imsg *); 59 int bindany(struct ctl_bindany *); 60 61 struct relayd *relayd_env; 62 63 static struct privsep_proc procs[] = { 64 { "pfe", PROC_PFE, parent_dispatch_pfe, pfe }, 65 { "hce", PROC_HCE, parent_dispatch_hce, hce }, 66 { "relay", PROC_RELAY, parent_dispatch_relay, relay } 67 }; 68 69 void 70 parent_sig_handler(int sig, short event, void *arg) 71 { 72 struct privsep *ps = arg; 73 int die = 0, status, fail, id; 74 pid_t pid; 75 char *cause; 76 77 switch (sig) { 78 case SIGTERM: 79 case SIGINT: 80 die = 1; 81 /* FALLTHROUGH */ 82 case SIGCHLD: 83 do { 84 pid = waitpid(WAIT_ANY, &status, WNOHANG); 85 if (pid <= 0) 86 continue; 87 88 fail = 0; 89 if (WIFSIGNALED(status)) { 90 fail = 1; 91 asprintf(&cause, "terminated; signal %d", 92 WTERMSIG(status)); 93 } else if (WIFEXITED(status)) { 94 if (WEXITSTATUS(status) != 0) { 95 fail = 1; 96 asprintf(&cause, "exited abnormally"); 97 } else 98 asprintf(&cause, "exited okay"); 99 } else 100 fatalx("unexpected cause of SIGCHLD"); 101 102 die = 1; 103 104 for (id = 0; id < PROC_MAX; id++) 105 if (pid == ps->ps_pid[id]) { 106 log_warnx("lost child: %s %s", 107 ps->ps_title[id], cause); 108 break; 109 } 110 111 free(cause); 112 } while (pid > 0 || (pid == -1 && errno == EINTR)); 113 114 if (die) 115 parent_shutdown(ps->ps_env); 116 break; 117 case SIGHUP: 118 log_info("%s: reload requested with SIGHUP", __func__); 119 120 /* 121 * This is safe because libevent uses async signal handlers 122 * that run in the event loop and not in signal context. 123 */ 124 parent_reload(ps->ps_env, CONFIG_RELOAD, NULL); 125 break; 126 case SIGPIPE: 127 /* ignore */ 128 break; 129 default: 130 fatalx("unexpected signal"); 131 } 132 } 133 134 /* __dead is for lint */ 135 __dead void 136 usage(void) 137 { 138 extern char *__progname; 139 140 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n", 141 __progname); 142 exit(1); 143 } 144 145 int 146 main(int argc, char *argv[]) 147 { 148 int c; 149 int debug = 0, verbose = 0; 150 u_int32_t opts = 0; 151 struct relayd *env; 152 struct privsep *ps; 153 const char *conffile = CONF_FILE; 154 155 while ((c = getopt(argc, argv, "dD:nf:v")) != -1) { 156 switch (c) { 157 case 'd': 158 debug = 2; 159 break; 160 case 'D': 161 if (cmdline_symset(optarg) < 0) 162 log_warnx("could not parse macro definition %s", 163 optarg); 164 break; 165 case 'n': 166 debug = 2; 167 opts |= RELAYD_OPT_NOACTION; 168 break; 169 case 'f': 170 conffile = optarg; 171 break; 172 case 'v': 173 verbose++; 174 opts |= RELAYD_OPT_VERBOSE; 175 break; 176 default: 177 usage(); 178 } 179 } 180 181 log_init(debug ? debug : 1); /* log to stderr until daemonized */ 182 183 argc -= optind; 184 argv += optind; 185 if (argc > 0) 186 usage(); 187 188 if ((env = calloc(1, sizeof(*env))) == NULL || 189 (ps = calloc(1, sizeof(*ps))) == NULL) 190 exit(1); 191 192 relayd_env = env; 193 env->sc_ps = ps; 194 ps->ps_env = env; 195 env->sc_conffile = conffile; 196 env->sc_opts = opts; 197 198 if (parse_config(env->sc_conffile, env) == -1) 199 exit(1); 200 201 if (debug) 202 env->sc_opts |= RELAYD_OPT_LOGUPDATE; 203 204 if (geteuid()) 205 errx(1, "need root privileges"); 206 207 if ((ps->ps_pw = getpwnam(RELAYD_USER)) == NULL) 208 errx(1, "unknown user %s", RELAYD_USER); 209 210 /* Configure the control socket */ 211 ps->ps_csock.cs_name = RELAYD_SOCKET; 212 213 log_init(debug); 214 log_verbose(verbose); 215 216 if (!debug && daemon(1, 0) == -1) 217 err(1, "failed to daemonize"); 218 219 if (env->sc_opts & RELAYD_OPT_NOACTION) 220 ps->ps_noaction = 1; 221 else 222 log_info("startup"); 223 224 ps->ps_instances[PROC_RELAY] = env->sc_prefork_relay; 225 proc_init(ps, procs, nitems(procs)); 226 227 setproctitle("parent"); 228 229 event_init(); 230 231 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 232 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 233 signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps); 234 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 235 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 236 237 signal_add(&ps->ps_evsigint, NULL); 238 signal_add(&ps->ps_evsigterm, NULL); 239 signal_add(&ps->ps_evsigchld, NULL); 240 signal_add(&ps->ps_evsighup, NULL); 241 signal_add(&ps->ps_evsigpipe, NULL); 242 243 proc_config(ps, procs, nitems(procs)); 244 245 if (load_config(env->sc_conffile, env) == -1) { 246 proc_kill(env->sc_ps); 247 exit(1); 248 } 249 250 if (env->sc_opts & RELAYD_OPT_NOACTION) { 251 fprintf(stderr, "configuration OK\n"); 252 proc_kill(env->sc_ps); 253 exit(0); 254 } 255 256 if (env->sc_flags & (F_SSL|F_SSLCLIENT)) 257 ssl_init(env); 258 259 if (parent_configure(env) == -1) 260 fatalx("configuration failed"); 261 262 init_routes(env); 263 264 event_dispatch(); 265 266 parent_shutdown(env); 267 /* NOTREACHED */ 268 269 return (0); 270 } 271 272 int 273 parent_configure(struct relayd *env) 274 { 275 struct table *tb; 276 struct rdr *rdr; 277 struct router *rt; 278 struct protocol *proto; 279 struct relay *rlay; 280 int id; 281 struct ctl_flags cf; 282 int s, ret = -1; 283 284 TAILQ_FOREACH(tb, env->sc_tables, entry) 285 config_settable(env, tb); 286 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 287 config_setrdr(env, rdr); 288 TAILQ_FOREACH(rt, env->sc_rts, rt_entry) 289 config_setrt(env, rt); 290 TAILQ_FOREACH(proto, env->sc_protos, entry) 291 config_setproto(env, proto); 292 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 293 config_setrelay(env, rlay); 294 295 for (id = 0; id < PROC_MAX; id++) { 296 if (id == privsep_process) 297 continue; 298 cf.cf_opts = env->sc_opts; 299 cf.cf_flags = env->sc_flags; 300 301 if ((env->sc_flags & F_NEEDPF) && id == PROC_PFE) { 302 /* Send pf socket to the pf engine */ 303 if ((s = open(PF_SOCKET, O_RDWR)) == -1) { 304 log_debug("%s: cannot open pf socket", 305 __func__); 306 goto done; 307 } 308 } else 309 s = -1; 310 311 env->sc_reload++; 312 proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, s, 313 &cf, sizeof(cf)); 314 } 315 316 ret = 0; 317 318 done: 319 config_purge(env, CONFIG_ALL); 320 return (ret); 321 } 322 323 void 324 parent_reload(struct relayd *env, u_int reset, const char *filename) 325 { 326 if (env->sc_reload) { 327 log_debug("%s: already in progress: %d pending", 328 __func__, env->sc_reload); 329 return; 330 } 331 332 /* Switch back to the default config file */ 333 if (filename == NULL || *filename == '\0') 334 filename = env->sc_conffile; 335 336 log_debug("%s: level %d config file %s", __func__, reset, filename); 337 338 config_purge(env, CONFIG_ALL); 339 340 if (reset == CONFIG_RELOAD) { 341 if (load_config(filename, env) == -1) { 342 log_debug("%s: failed to load config file %s", 343 __func__, filename); 344 } 345 346 config_setreset(env, CONFIG_ALL); 347 348 if (parent_configure(env) == -1) { 349 log_debug("%s: failed to commit config from %s", 350 __func__, filename); 351 } 352 } else 353 config_setreset(env, reset); 354 } 355 356 void 357 parent_shutdown(struct relayd *env) 358 { 359 config_purge(env, CONFIG_ALL); 360 361 proc_kill(env->sc_ps); 362 control_cleanup(&env->sc_ps->ps_csock); 363 carp_demote_shutdown(); 364 if (env->sc_flags & F_DEMOTE) 365 carp_demote_reset(env->sc_demote_group, 128); 366 367 free(env->sc_ps); 368 free(env); 369 370 log_info("parent terminating, pid %d", getpid()); 371 372 exit(0); 373 } 374 375 int 376 parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg) 377 { 378 struct relayd *env = p->p_env; 379 struct ctl_demote demote; 380 struct ctl_netroute crt; 381 u_int v; 382 char *str = NULL; 383 384 switch (imsg->hdr.type) { 385 case IMSG_DEMOTE: 386 IMSG_SIZE_CHECK(imsg, &demote); 387 memcpy(&demote, imsg->data, sizeof(demote)); 388 carp_demote_set(demote.group, demote.level); 389 break; 390 case IMSG_RTMSG: 391 IMSG_SIZE_CHECK(imsg, &crt); 392 memcpy(&crt, imsg->data, sizeof(crt)); 393 pfe_route(env, &crt); 394 break; 395 case IMSG_CTL_RESET: 396 IMSG_SIZE_CHECK(imsg, &v); 397 memcpy(&v, imsg->data, sizeof(v)); 398 parent_reload(env, v, NULL); 399 break; 400 case IMSG_CTL_RELOAD: 401 if (IMSG_DATA_SIZE(imsg) > 0) 402 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 403 parent_reload(env, CONFIG_RELOAD, str); 404 if (str != NULL) 405 free(str); 406 break; 407 case IMSG_CTL_SHUTDOWN: 408 parent_shutdown(env); 409 break; 410 case IMSG_CFG_DONE: 411 if (env->sc_reload) 412 env->sc_reload--; 413 break; 414 default: 415 return (-1); 416 } 417 418 return (0); 419 } 420 421 int 422 parent_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg) 423 { 424 struct relayd *env = p->p_env; 425 struct privsep *ps = env->sc_ps; 426 struct ctl_script scr; 427 428 switch (imsg->hdr.type) { 429 case IMSG_SCRIPT: 430 IMSG_SIZE_CHECK(imsg, &scr); 431 bcopy(imsg->data, &scr, sizeof(scr)); 432 scr.retval = script_exec(env, &scr); 433 proc_compose_imsg(ps, PROC_HCE, -1, IMSG_SCRIPT, 434 -1, &scr, sizeof(scr)); 435 break; 436 case IMSG_SNMPSOCK: 437 (void)snmp_setsock(env, p->p_id); 438 break; 439 case IMSG_CFG_DONE: 440 if (env->sc_reload) 441 env->sc_reload--; 442 break; 443 default: 444 return (-1); 445 } 446 447 return (0); 448 } 449 450 int 451 parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg) 452 { 453 struct relayd *env = p->p_env; 454 struct privsep *ps = env->sc_ps; 455 struct ctl_bindany bnd; 456 int s; 457 458 switch (imsg->hdr.type) { 459 case IMSG_BINDANY: 460 IMSG_SIZE_CHECK(imsg, &bnd); 461 bcopy(imsg->data, &bnd, sizeof(bnd)); 462 if (bnd.bnd_proc > env->sc_prefork_relay) 463 fatalx("pfe_dispatch_relay: " 464 "invalid relay proc"); 465 switch (bnd.bnd_proto) { 466 case IPPROTO_TCP: 467 case IPPROTO_UDP: 468 break; 469 default: 470 fatalx("pfe_dispatch_relay: requested socket " 471 "for invalid protocol"); 472 /* NOTREACHED */ 473 } 474 s = bindany(&bnd); 475 proc_compose_imsg(ps, PROC_RELAY, bnd.bnd_proc, 476 IMSG_BINDANY, s, &bnd.bnd_id, sizeof(bnd.bnd_id)); 477 break; 478 case IMSG_CFG_DONE: 479 if (env->sc_reload) 480 env->sc_reload--; 481 break; 482 default: 483 return (-1); 484 } 485 486 return (0); 487 } 488 489 void 490 purge_tree(struct proto_tree *tree) 491 { 492 struct protonode *proot, *pn; 493 494 while ((proot = RB_ROOT(tree)) != NULL) { 495 RB_REMOVE(proto_tree, tree, proot); 496 if (proot->key != NULL) 497 free(proot->key); 498 if (proot->value != NULL) 499 free(proot->value); 500 while ((pn = SIMPLEQ_FIRST(&proot->head)) != NULL) { 501 SIMPLEQ_REMOVE_HEAD(&proot->head, entry); 502 if (pn->key != NULL) 503 free(pn->key); 504 if (pn->value != NULL) 505 free(pn->value); 506 if (pn->label != 0) 507 pn_unref(pn->label); 508 free(pn); 509 } 510 free(proot); 511 } 512 } 513 514 void 515 purge_table(struct tablelist *head, struct table *table) 516 { 517 struct host *host; 518 519 while ((host = TAILQ_FIRST(&table->hosts)) != NULL) { 520 TAILQ_REMOVE(&table->hosts, host, entry); 521 if (event_initialized(&host->cte.ev)) { 522 event_del(&host->cte.ev); 523 close(host->cte.s); 524 } 525 if (host->cte.buf != NULL) 526 ibuf_free(host->cte.buf); 527 if (host->cte.ssl != NULL) 528 SSL_free(host->cte.ssl); 529 free(host); 530 } 531 if (table->sendbuf != NULL) 532 free(table->sendbuf); 533 if (table->conf.flags & F_SSL) 534 SSL_CTX_free(table->ssl_ctx); 535 536 if (head != NULL) 537 TAILQ_REMOVE(head, table, entry); 538 free(table); 539 } 540 541 void 542 purge_relay(struct relayd *env, struct relay *rlay) 543 { 544 struct rsession *con; 545 546 /* shutdown and remove relay */ 547 if (event_initialized(&rlay->rl_ev)) 548 event_del(&rlay->rl_ev); 549 close(rlay->rl_s); 550 TAILQ_REMOVE(env->sc_relays, rlay, rl_entry); 551 552 /* cleanup sessions */ 553 while ((con = 554 SPLAY_ROOT(&rlay->rl_sessions)) != NULL) 555 relay_close(con, NULL); 556 557 /* cleanup relay */ 558 if (rlay->rl_bev != NULL) 559 bufferevent_free(rlay->rl_bev); 560 if (rlay->rl_dstbev != NULL) 561 bufferevent_free(rlay->rl_dstbev); 562 563 if (rlay->rl_ssl_ctx != NULL) 564 SSL_CTX_free(rlay->rl_ssl_ctx); 565 if (rlay->rl_ssl_cert != NULL) 566 free(rlay->rl_ssl_cert); 567 if (rlay->rl_ssl_key != NULL) 568 free(rlay->rl_ssl_key); 569 if (rlay->rl_ssl_ca != NULL) 570 free(rlay->rl_ssl_ca); 571 572 free(rlay); 573 } 574 575 /* 576 * Utility functions 577 */ 578 579 struct host * 580 host_find(struct relayd *env, objid_t id) 581 { 582 struct table *table; 583 struct host *host; 584 585 TAILQ_FOREACH(table, env->sc_tables, entry) 586 TAILQ_FOREACH(host, &table->hosts, entry) 587 if (host->conf.id == id) 588 return (host); 589 return (NULL); 590 } 591 592 struct table * 593 table_find(struct relayd *env, objid_t id) 594 { 595 struct table *table; 596 597 TAILQ_FOREACH(table, env->sc_tables, entry) 598 if (table->conf.id == id) 599 return (table); 600 return (NULL); 601 } 602 603 struct rdr * 604 rdr_find(struct relayd *env, objid_t id) 605 { 606 struct rdr *rdr; 607 608 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 609 if (rdr->conf.id == id) 610 return (rdr); 611 return (NULL); 612 } 613 614 struct relay * 615 relay_find(struct relayd *env, objid_t id) 616 { 617 struct relay *rlay; 618 619 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 620 if (rlay->rl_conf.id == id) 621 return (rlay); 622 return (NULL); 623 } 624 625 struct protocol * 626 proto_find(struct relayd *env, objid_t id) 627 { 628 struct protocol *p; 629 630 TAILQ_FOREACH(p, env->sc_protos, entry) 631 if (p->id == id) 632 return (p); 633 return (NULL); 634 } 635 636 struct rsession * 637 session_find(struct relayd *env, objid_t id) 638 { 639 struct relay *rlay; 640 struct rsession *con; 641 642 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 643 SPLAY_FOREACH(con, session_tree, &rlay->rl_sessions) 644 if (con->se_id == id) 645 return (con); 646 return (NULL); 647 } 648 649 struct netroute * 650 route_find(struct relayd *env, objid_t id) 651 { 652 struct netroute *nr; 653 654 TAILQ_FOREACH(nr, env->sc_routes, nr_route) 655 if (nr->nr_conf.id == id) 656 return (nr); 657 return (NULL); 658 } 659 660 struct router * 661 router_find(struct relayd *env, objid_t id) 662 { 663 struct router *rt; 664 665 TAILQ_FOREACH(rt, env->sc_rts, rt_entry) 666 if (rt->rt_conf.id == id) 667 return (rt); 668 return (NULL); 669 } 670 671 struct host * 672 host_findbyname(struct relayd *env, const char *name) 673 { 674 struct table *table; 675 struct host *host; 676 677 TAILQ_FOREACH(table, env->sc_tables, entry) 678 TAILQ_FOREACH(host, &table->hosts, entry) 679 if (strcmp(host->conf.name, name) == 0) 680 return (host); 681 return (NULL); 682 } 683 684 struct table * 685 table_findbyname(struct relayd *env, const char *name) 686 { 687 struct table *table; 688 689 TAILQ_FOREACH(table, env->sc_tables, entry) 690 if (strcmp(table->conf.name, name) == 0) 691 return (table); 692 return (NULL); 693 } 694 695 struct table * 696 table_findbyconf(struct relayd *env, struct table *tb) 697 { 698 struct table *table; 699 struct table_config a, b; 700 701 bcopy(&tb->conf, &a, sizeof(a)); 702 a.id = a.rdrid = 0; 703 a.flags &= ~(F_USED|F_BACKUP); 704 705 TAILQ_FOREACH(table, env->sc_tables, entry) { 706 bcopy(&table->conf, &b, sizeof(b)); 707 b.id = b.rdrid = 0; 708 b.flags &= ~(F_USED|F_BACKUP); 709 710 /* 711 * Compare two tables and return the existing table if 712 * the configuration seems to be the same. 713 */ 714 if (bcmp(&a, &b, sizeof(b)) == 0 && 715 ((tb->sendbuf == NULL && table->sendbuf == NULL) || 716 (tb->sendbuf != NULL && table->sendbuf != NULL && 717 strcmp(tb->sendbuf, table->sendbuf) == 0))) 718 return (table); 719 } 720 return (NULL); 721 } 722 723 struct rdr * 724 rdr_findbyname(struct relayd *env, const char *name) 725 { 726 struct rdr *rdr; 727 728 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 729 if (strcmp(rdr->conf.name, name) == 0) 730 return (rdr); 731 return (NULL); 732 } 733 734 struct relay * 735 relay_findbyname(struct relayd *env, const char *name) 736 { 737 struct relay *rlay; 738 739 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 740 if (strcmp(rlay->rl_conf.name, name) == 0) 741 return (rlay); 742 return (NULL); 743 } 744 745 struct relay * 746 relay_findbyaddr(struct relayd *env, struct relay_config *rc) 747 { 748 struct relay *rlay; 749 750 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 751 if (bcmp(&rlay->rl_conf.ss, &rc->ss, sizeof(rc->ss)) == 0 && 752 rlay->rl_conf.port == rc->port) 753 return (rlay); 754 return (NULL); 755 } 756 757 void 758 event_again(struct event *ev, int fd, short event, 759 void (*fn)(int, short, void *), 760 struct timeval *start, struct timeval *end, void *arg) 761 { 762 struct timeval tv_next, tv_now, tv; 763 764 if (gettimeofday(&tv_now, NULL) == -1) 765 fatal("event_again: gettimeofday"); 766 767 bcopy(end, &tv_next, sizeof(tv_next)); 768 timersub(&tv_now, start, &tv_now); 769 timersub(&tv_next, &tv_now, &tv_next); 770 771 bzero(&tv, sizeof(tv)); 772 if (timercmp(&tv_next, &tv, >)) 773 bcopy(&tv_next, &tv, sizeof(tv)); 774 775 event_del(ev); 776 event_set(ev, fd, event, fn, arg); 777 event_add(ev, &tv); 778 } 779 780 int 781 expand_string(char *label, size_t len, const char *srch, const char *repl) 782 { 783 char *tmp; 784 char *p, *q; 785 786 if ((tmp = calloc(1, len)) == NULL) { 787 log_debug("%s: calloc", __func__); 788 return (-1); 789 } 790 p = q = label; 791 while ((q = strstr(p, srch)) != NULL) { 792 *q = '\0'; 793 if ((strlcat(tmp, p, len) >= len) || 794 (strlcat(tmp, repl, len) >= len)) { 795 log_debug("%s: string too long", __func__); 796 return (-1); 797 } 798 q += strlen(srch); 799 p = q; 800 } 801 if (strlcat(tmp, p, len) >= len) { 802 log_debug("%s: string too long", __func__); 803 return (-1); 804 } 805 (void)strlcpy(label, tmp, len); /* always fits */ 806 free(tmp); 807 808 return (0); 809 } 810 811 void 812 translate_string(char *str) 813 { 814 char *reader; 815 char *writer; 816 817 reader = writer = str; 818 819 while (*reader) { 820 if (*reader == '\\') { 821 reader++; 822 switch (*reader) { 823 case 'n': 824 *writer++ = '\n'; 825 break; 826 case 'r': 827 *writer++ = '\r'; 828 break; 829 default: 830 *writer++ = *reader; 831 } 832 } else 833 *writer++ = *reader; 834 reader++; 835 } 836 *writer = '\0'; 837 } 838 839 char * 840 digeststr(enum digest_type type, const u_int8_t *data, size_t len, char *buf) 841 { 842 switch (type) { 843 case DIGEST_SHA1: 844 return (SHA1Data(data, len, buf)); 845 break; 846 case DIGEST_MD5: 847 return (MD5Data(data, len, buf)); 848 break; 849 default: 850 break; 851 } 852 return (NULL); 853 } 854 855 const char * 856 canonicalize_host(const char *host, char *name, size_t len) 857 { 858 struct sockaddr_in sin4; 859 struct sockaddr_in6 sin6; 860 u_int i, j; 861 size_t plen; 862 char c; 863 864 if (len < 2) 865 goto fail; 866 867 /* 868 * Canonicalize an IPv4/6 address 869 */ 870 if (inet_pton(AF_INET, host, &sin4) == 1) 871 return (inet_ntop(AF_INET, &sin4, name, len)); 872 if (inet_pton(AF_INET6, host, &sin6) == 1) 873 return (inet_ntop(AF_INET6, &sin6, name, len)); 874 875 /* 876 * Canonicalize a hostname 877 */ 878 879 /* 1. remove repeated dots and convert upper case to lower case */ 880 plen = strlen(host); 881 bzero(name, len); 882 for (i = j = 0; i < plen; i++) { 883 if (j >= (len - 1)) 884 goto fail; 885 c = tolower(host[i]); 886 if ((c == '.') && (j == 0 || name[j - 1] == '.')) 887 continue; 888 name[j++] = c; 889 } 890 891 /* 2. remove trailing dots */ 892 for (i = j; i > 0; i--) { 893 if (name[i - 1] != '.') 894 break; 895 name[i - 1] = '\0'; 896 j--; 897 } 898 if (j <= 0) 899 goto fail; 900 901 return (name); 902 903 fail: 904 errno = EINVAL; 905 return (NULL); 906 } 907 908 struct protonode * 909 protonode_header(enum direction dir, struct protocol *proto, 910 struct protonode *pk) 911 { 912 struct protonode *pn; 913 struct proto_tree *tree; 914 915 if (dir == RELAY_DIR_RESPONSE) 916 tree = &proto->response_tree; 917 else 918 tree = &proto->request_tree; 919 920 pn = RB_FIND(proto_tree, tree, pk); 921 if (pn != NULL) 922 return (pn); 923 if ((pn = (struct protonode *)calloc(1, sizeof(*pn))) == NULL) { 924 log_warn("%s: calloc", __func__); 925 return (NULL); 926 } 927 pn->key = strdup(pk->key); 928 if (pn->key == NULL) { 929 free(pn); 930 log_warn("%s: strdup", __func__); 931 return (NULL); 932 } 933 pn->value = NULL; 934 pn->action = NODE_ACTION_NONE; 935 pn->type = pk->type; 936 SIMPLEQ_INIT(&pn->head); 937 if (dir == RELAY_DIR_RESPONSE) 938 pn->id = 939 proto->response_nodes++; 940 else 941 pn->id = proto->request_nodes++; 942 if (pn->id == INT_MAX) { 943 log_warnx("%s: too many protocol " 944 "nodes defined", __func__); 945 return (NULL); 946 } 947 RB_INSERT(proto_tree, tree, pn); 948 return (pn); 949 } 950 951 int 952 protonode_add(enum direction dir, struct protocol *proto, 953 struct protonode *node) 954 { 955 struct protonode *pn, *proot, pk; 956 struct proto_tree *tree; 957 958 if (dir == RELAY_DIR_RESPONSE) 959 tree = &proto->response_tree; 960 else 961 tree = &proto->request_tree; 962 963 if ((pn = calloc(1, sizeof (*pn))) == NULL) { 964 log_warn("%s: calloc", __func__); 965 return (-1); 966 } 967 bcopy(node, pn, sizeof(*pn)); 968 pn->key = node->key; 969 pn->value = node->value; 970 SIMPLEQ_INIT(&pn->head); 971 if (dir == RELAY_DIR_RESPONSE) 972 pn->id = proto->response_nodes++; 973 else 974 pn->id = proto->request_nodes++; 975 if (pn->id == INT_MAX) { 976 log_warnx("%s: too many protocol nodes defined", __func__); 977 free(pn); 978 return (-1); 979 } 980 if ((proot = 981 RB_INSERT(proto_tree, tree, pn)) != NULL) { 982 /* 983 * A protocol node with the same key already 984 * exists, append it to a queue behind the 985 * existing node-> 986 */ 987 if (SIMPLEQ_EMPTY(&proot->head)) 988 SIMPLEQ_NEXT(proot, entry) = pn; 989 SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry); 990 } 991 if (node->type == NODE_TYPE_COOKIE) 992 pk.key = "Cookie"; 993 else if (node->type == NODE_TYPE_URL) 994 pk.key = "Host"; 995 else 996 pk.key = "GET"; 997 if (node->type != NODE_TYPE_HEADER) { 998 pk.type = NODE_TYPE_HEADER; 999 pn = protonode_header(dir, proto, &pk); 1000 if (pn == NULL) 1001 return (-1); 1002 switch (node->type) { 1003 case NODE_TYPE_QUERY: 1004 pn->flags |= PNFLAG_LOOKUP_QUERY; 1005 break; 1006 case NODE_TYPE_COOKIE: 1007 pn->flags |= PNFLAG_LOOKUP_COOKIE; 1008 break; 1009 case NODE_TYPE_URL: 1010 if (node->flags & 1011 PNFLAG_LOOKUP_URL_DIGEST) 1012 pn->flags |= node->flags & 1013 PNFLAG_LOOKUP_URL_DIGEST; 1014 else 1015 pn->flags |= 1016 PNFLAG_LOOKUP_DIGEST(0); 1017 break; 1018 default: 1019 break; 1020 } 1021 } 1022 1023 return (0); 1024 } 1025 1026 int 1027 protonode_load(enum direction dir, struct protocol *proto, 1028 struct protonode *node, const char *name) 1029 { 1030 FILE *fp; 1031 char buf[BUFSIZ]; 1032 int ret = -1; 1033 struct protonode pn; 1034 1035 bcopy(node, &pn, sizeof(pn)); 1036 pn.key = pn.value = NULL; 1037 1038 if ((fp = fopen(name, "r")) == NULL) 1039 return (-1); 1040 1041 while (fgets(buf, sizeof(buf), fp) != NULL) { 1042 /* strip whitespace and newline characters */ 1043 buf[strcspn(buf, "\r\n\t ")] = '\0'; 1044 if (!strlen(buf) || buf[0] == '#') 1045 continue; 1046 pn.key = strdup(buf); 1047 if (node->value != NULL) 1048 pn.value = strdup(node->value); 1049 if (pn.key == NULL || 1050 (node->value != NULL && pn.value == NULL)) 1051 goto fail; 1052 if (protonode_add(dir, proto, &pn) == -1) 1053 goto fail; 1054 pn.key = pn.value = NULL; 1055 } 1056 1057 ret = 0; 1058 fail: 1059 if (pn.key != NULL) 1060 free(pn.key); 1061 if (pn.value != NULL) 1062 free(pn.value); 1063 fclose(fp); 1064 return (ret); 1065 } 1066 1067 int 1068 bindany(struct ctl_bindany *bnd) 1069 { 1070 int s, v; 1071 1072 s = -1; 1073 v = 1; 1074 1075 if (relay_socket_af(&bnd->bnd_ss, bnd->bnd_port) == -1) 1076 goto fail; 1077 if ((s = socket(bnd->bnd_ss.ss_family, 1078 bnd->bnd_proto == IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM, 1079 bnd->bnd_proto)) == -1) 1080 goto fail; 1081 if (setsockopt(s, SOL_SOCKET, SO_BINDANY, 1082 &v, sizeof(v)) == -1) 1083 goto fail; 1084 if (bind(s, (struct sockaddr *)&bnd->bnd_ss, 1085 bnd->bnd_ss.ss_len) == -1) 1086 goto fail; 1087 1088 return (s); 1089 1090 fail: 1091 if (s != -1) 1092 close(s); 1093 return (-1); 1094 } 1095 1096 int 1097 map6to4(struct sockaddr_storage *in6) 1098 { 1099 struct sockaddr_storage out4; 1100 struct sockaddr_in *sin4 = (struct sockaddr_in *)&out4; 1101 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)in6; 1102 1103 bzero(sin4, sizeof(*sin4)); 1104 sin4->sin_len = sizeof(*sin4); 1105 sin4->sin_family = AF_INET; 1106 sin4->sin_port = sin6->sin6_port; 1107 1108 bcopy(&sin6->sin6_addr.s6_addr[12], &sin4->sin_addr.s_addr, 1109 sizeof(sin4->sin_addr)); 1110 1111 if (sin4->sin_addr.s_addr == INADDR_ANY || 1112 sin4->sin_addr.s_addr == INADDR_BROADCAST || 1113 IN_MULTICAST(ntohl(sin4->sin_addr.s_addr))) 1114 return (-1); 1115 1116 bcopy(&out4, in6, sizeof(*in6)); 1117 1118 return (0); 1119 } 1120 1121 int 1122 map4to6(struct sockaddr_storage *in4, struct sockaddr_storage *map) 1123 { 1124 struct sockaddr_storage out6; 1125 struct sockaddr_in *sin4 = (struct sockaddr_in *)in4; 1126 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&out6; 1127 struct sockaddr_in6 *map6 = (struct sockaddr_in6 *)map; 1128 1129 if (sin4->sin_addr.s_addr == INADDR_ANY || 1130 sin4->sin_addr.s_addr == INADDR_BROADCAST || 1131 IN_MULTICAST(ntohl(sin4->sin_addr.s_addr))) 1132 return (-1); 1133 1134 bcopy(map6, sin6, sizeof(*sin6)); 1135 sin6->sin6_len = sizeof(*sin6); 1136 sin6->sin6_family = AF_INET6; 1137 sin6->sin6_port = sin4->sin_port; 1138 1139 bcopy(&sin4->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12], 1140 sizeof(sin4->sin_addr)); 1141 1142 bcopy(&out6, in4, sizeof(*in4)); 1143 1144 return (0); 1145 } 1146 1147 void 1148 socket_rlimit(int maxfd) 1149 { 1150 struct rlimit rl; 1151 1152 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 1153 fatal("socket_rlimit: failed to get resource limit"); 1154 log_debug("%s: max open files %d", __func__, rl.rlim_max); 1155 1156 /* 1157 * Allow the maximum number of open file descriptors for this 1158 * login class (which should be the class "daemon" by default). 1159 */ 1160 if (maxfd == -1) 1161 rl.rlim_cur = rl.rlim_max; 1162 else 1163 rl.rlim_cur = MAX(rl.rlim_max, (rlim_t)maxfd); 1164 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 1165 fatal("socket_rlimit: failed to set resource limit"); 1166 } 1167 1168 char * 1169 get_string(u_int8_t *ptr, size_t len) 1170 { 1171 size_t i; 1172 char *str; 1173 1174 for (i = 0; i < len; i++) 1175 if (!(isprint((char)ptr[i]) || isspace((char)ptr[i]))) 1176 break; 1177 1178 if ((str = calloc(1, i + 1)) == NULL) 1179 return (NULL); 1180 memcpy(str, ptr, i); 1181 1182 return (str); 1183 } 1184 1185 void * 1186 get_data(u_int8_t *ptr, size_t len) 1187 { 1188 u_int8_t *data; 1189 1190 if ((data = calloc(1, len)) == NULL) 1191 return (NULL); 1192 memcpy(data, ptr, len); 1193 1194 return (data); 1195 } 1196