1 /* $OpenBSD: relayd.c,v 1.130 2014/07/13 00:32:08 benno Exp $ */ 2 3 /* 4 * Copyright (c) 2007 - 2014 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 <fnmatch.h> 37 #include <err.h> 38 #include <errno.h> 39 #include <event.h> 40 #include <unistd.h> 41 #include <ctype.h> 42 #include <pwd.h> 43 #include <sha1.h> 44 #include <md5.h> 45 46 #include <openssl/ssl.h> 47 48 #include "relayd.h" 49 50 __dead void usage(void); 51 52 int parent_configure(struct relayd *); 53 void parent_configure_done(struct relayd *); 54 void parent_reload(struct relayd *, u_int, const char *); 55 void parent_sig_handler(int, short, void *); 56 void parent_shutdown(struct relayd *); 57 int parent_dispatch_pfe(int, struct privsep_proc *, struct imsg *); 58 int parent_dispatch_hce(int, struct privsep_proc *, struct imsg *); 59 int parent_dispatch_relay(int, struct privsep_proc *, 60 struct imsg *); 61 int parent_dispatch_ca(int, struct privsep_proc *, 62 struct imsg *); 63 int bindany(struct ctl_bindany *); 64 65 struct relayd *relayd_env; 66 67 static struct privsep_proc procs[] = { 68 { "pfe", PROC_PFE, parent_dispatch_pfe, pfe }, 69 { "hce", PROC_HCE, parent_dispatch_hce, hce }, 70 { "relay", PROC_RELAY, parent_dispatch_relay, relay }, 71 { "ca", PROC_CA, parent_dispatch_ca, ca } 72 }; 73 74 void 75 parent_sig_handler(int sig, short event, void *arg) 76 { 77 struct privsep *ps = arg; 78 int die = 0, status, fail, id; 79 pid_t pid; 80 char *cause; 81 82 switch (sig) { 83 case SIGTERM: 84 case SIGINT: 85 die = 1; 86 /* FALLTHROUGH */ 87 case SIGCHLD: 88 do { 89 pid = waitpid(WAIT_ANY, &status, WNOHANG); 90 if (pid <= 0) 91 continue; 92 93 fail = 0; 94 if (WIFSIGNALED(status)) { 95 fail = 1; 96 asprintf(&cause, "terminated; signal %d", 97 WTERMSIG(status)); 98 } else if (WIFEXITED(status)) { 99 if (WEXITSTATUS(status) != 0) { 100 fail = 1; 101 asprintf(&cause, "exited abnormally"); 102 } else 103 asprintf(&cause, "exited okay"); 104 } else 105 fatalx("unexpected cause of SIGCHLD"); 106 107 die = 1; 108 109 for (id = 0; id < PROC_MAX; id++) 110 if (pid == ps->ps_pid[id]) { 111 if (fail) 112 log_warnx("lost child: %s %s", 113 ps->ps_title[id], cause); 114 break; 115 } 116 117 free(cause); 118 } while (pid > 0 || (pid == -1 && errno == EINTR)); 119 120 if (die) 121 parent_shutdown(ps->ps_env); 122 break; 123 case SIGHUP: 124 log_info("%s: reload requested with SIGHUP", __func__); 125 126 /* 127 * This is safe because libevent uses async signal handlers 128 * that run in the event loop and not in signal context. 129 */ 130 parent_reload(ps->ps_env, CONFIG_RELOAD, NULL); 131 break; 132 case SIGPIPE: 133 /* ignore */ 134 break; 135 default: 136 fatalx("unexpected signal"); 137 } 138 } 139 140 __dead void 141 usage(void) 142 { 143 extern char *__progname; 144 145 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n", 146 __progname); 147 exit(1); 148 } 149 150 int 151 main(int argc, char *argv[]) 152 { 153 int c; 154 int debug = 0, verbose = 0; 155 u_int32_t opts = 0; 156 struct relayd *env; 157 struct privsep *ps; 158 const char *conffile = CONF_FILE; 159 160 while ((c = getopt(argc, argv, "dD:nf:v")) != -1) { 161 switch (c) { 162 case 'd': 163 debug = 2; 164 break; 165 case 'D': 166 if (cmdline_symset(optarg) < 0) 167 log_warnx("could not parse macro definition %s", 168 optarg); 169 break; 170 case 'n': 171 debug = 2; 172 opts |= RELAYD_OPT_NOACTION; 173 break; 174 case 'f': 175 conffile = optarg; 176 break; 177 case 'v': 178 verbose++; 179 opts |= RELAYD_OPT_VERBOSE; 180 break; 181 default: 182 usage(); 183 } 184 } 185 186 log_init(debug ? debug : 1); /* log to stderr until daemonized */ 187 188 argc -= optind; 189 if (argc > 0) 190 usage(); 191 192 if ((env = calloc(1, sizeof(*env))) == NULL || 193 (ps = calloc(1, sizeof(*ps))) == NULL) 194 exit(1); 195 196 relayd_env = env; 197 env->sc_ps = ps; 198 ps->ps_env = env; 199 TAILQ_INIT(&ps->ps_rcsocks); 200 env->sc_conffile = conffile; 201 env->sc_opts = opts; 202 203 if (parse_config(env->sc_conffile, env) == -1) 204 exit(1); 205 206 if (debug) 207 env->sc_opts |= RELAYD_OPT_LOGUPDATE; 208 209 if (geteuid()) 210 errx(1, "need root privileges"); 211 212 if ((ps->ps_pw = getpwnam(RELAYD_USER)) == NULL) 213 errx(1, "unknown user %s", RELAYD_USER); 214 215 /* Configure the control socket */ 216 ps->ps_csock.cs_name = RELAYD_SOCKET; 217 218 log_init(debug); 219 log_verbose(verbose); 220 221 if (!debug && daemon(1, 0) == -1) 222 err(1, "failed to daemonize"); 223 224 if (env->sc_opts & RELAYD_OPT_NOACTION) 225 ps->ps_noaction = 1; 226 else 227 log_info("startup"); 228 229 ps->ps_instances[PROC_RELAY] = env->sc_prefork_relay; 230 ps->ps_instances[PROC_CA] = env->sc_prefork_relay; 231 ps->ps_ninstances = env->sc_prefork_relay; 232 233 proc_init(ps, procs, nitems(procs)); 234 235 setproctitle("parent"); 236 237 event_init(); 238 239 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps); 240 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps); 241 signal_set(&ps->ps_evsigchld, SIGCHLD, parent_sig_handler, ps); 242 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps); 243 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps); 244 245 signal_add(&ps->ps_evsigint, NULL); 246 signal_add(&ps->ps_evsigterm, NULL); 247 signal_add(&ps->ps_evsigchld, NULL); 248 signal_add(&ps->ps_evsighup, NULL); 249 signal_add(&ps->ps_evsigpipe, NULL); 250 251 proc_listen(ps, procs, nitems(procs)); 252 253 if (load_config(env->sc_conffile, env) == -1) { 254 proc_kill(env->sc_ps); 255 exit(1); 256 } 257 258 if (env->sc_opts & RELAYD_OPT_NOACTION) { 259 fprintf(stderr, "configuration OK\n"); 260 proc_kill(env->sc_ps); 261 exit(0); 262 } 263 264 if (env->sc_flags & (F_SSL|F_SSLCLIENT)) 265 ssl_init(env); 266 267 if (parent_configure(env) == -1) 268 fatalx("configuration failed"); 269 270 init_routes(env); 271 272 event_dispatch(); 273 274 parent_shutdown(env); 275 /* NOTREACHED */ 276 277 return (0); 278 } 279 280 int 281 parent_configure(struct relayd *env) 282 { 283 struct table *tb; 284 struct rdr *rdr; 285 struct router *rt; 286 struct protocol *proto; 287 struct relay *rlay; 288 int id; 289 struct ctl_flags cf; 290 int s, ret = -1; 291 292 TAILQ_FOREACH(tb, env->sc_tables, entry) 293 config_settable(env, tb); 294 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 295 config_setrdr(env, rdr); 296 TAILQ_FOREACH(rt, env->sc_rts, rt_entry) 297 config_setrt(env, rt); 298 TAILQ_FOREACH(proto, env->sc_protos, entry) 299 config_setproto(env, proto); 300 TAILQ_FOREACH(proto, env->sc_protos, entry) 301 config_setrule(env, proto); 302 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) { 303 /* Check for SSL Inspection */ 304 if ((rlay->rl_conf.flags & (F_SSL|F_SSLCLIENT)) == 305 (F_SSL|F_SSLCLIENT) && 306 rlay->rl_conf.ssl_cacert_len && 307 rlay->rl_conf.ssl_cakey_len) 308 rlay->rl_conf.flags |= F_SSLINSPECT; 309 310 config_setrelay(env, rlay); 311 } 312 313 /* HCE, PFE, CA and the relays need to reload their config. */ 314 env->sc_reload = 2 + (2 * env->sc_prefork_relay); 315 316 for (id = 0; id < PROC_MAX; id++) { 317 if (id == privsep_process) 318 continue; 319 cf.cf_opts = env->sc_opts; 320 cf.cf_flags = env->sc_flags; 321 322 if ((env->sc_flags & F_NEEDPF) && id == PROC_PFE) { 323 /* Send pf socket to the pf engine */ 324 if ((s = open(PF_SOCKET, O_RDWR)) == -1) { 325 log_debug("%s: cannot open pf socket", 326 __func__); 327 goto done; 328 } 329 } else 330 s = -1; 331 332 proc_compose_imsg(env->sc_ps, id, -1, IMSG_CFG_DONE, s, 333 &cf, sizeof(cf)); 334 } 335 336 ret = 0; 337 338 done: 339 config_purge(env, CONFIG_ALL & ~CONFIG_RELAYS); 340 return (ret); 341 } 342 343 void 344 parent_reload(struct relayd *env, u_int reset, const char *filename) 345 { 346 if (env->sc_reload) { 347 log_debug("%s: already in progress: %d pending", 348 __func__, env->sc_reload); 349 return; 350 } 351 352 /* Switch back to the default config file */ 353 if (filename == NULL || *filename == '\0') 354 filename = env->sc_conffile; 355 356 log_debug("%s: level %d config file %s", __func__, reset, filename); 357 358 config_purge(env, CONFIG_ALL); 359 360 if (reset == CONFIG_RELOAD) { 361 if (load_config(filename, env) == -1) { 362 log_debug("%s: failed to load config file %s", 363 __func__, filename); 364 } 365 366 config_setreset(env, CONFIG_ALL); 367 368 if (parent_configure(env) == -1) { 369 log_debug("%s: failed to commit config from %s", 370 __func__, filename); 371 } 372 } else 373 config_setreset(env, reset); 374 } 375 376 void 377 parent_configure_done(struct relayd *env) 378 { 379 int id; 380 381 if (env->sc_reload == 0) { 382 log_warnx("%s: configuration already finished", __func__); 383 return; 384 } 385 386 env->sc_reload--; 387 if (env->sc_reload == 0) { 388 for (id = 0; id < PROC_MAX; id++) { 389 if (id == privsep_process) 390 continue; 391 392 proc_compose_imsg(env->sc_ps, id, -1, IMSG_CTL_START, 393 -1, NULL, 0); 394 } 395 } 396 } 397 398 void 399 parent_shutdown(struct relayd *env) 400 { 401 config_purge(env, CONFIG_ALL); 402 403 proc_kill(env->sc_ps); 404 control_cleanup(&env->sc_ps->ps_csock); 405 carp_demote_shutdown(); 406 407 free(env->sc_ps); 408 free(env); 409 410 log_info("parent terminating, pid %d", getpid()); 411 412 exit(0); 413 } 414 415 int 416 parent_dispatch_pfe(int fd, struct privsep_proc *p, struct imsg *imsg) 417 { 418 struct relayd *env = p->p_env; 419 struct ctl_demote demote; 420 struct ctl_netroute crt; 421 u_int v; 422 char *str = NULL; 423 424 switch (imsg->hdr.type) { 425 case IMSG_DEMOTE: 426 IMSG_SIZE_CHECK(imsg, &demote); 427 memcpy(&demote, imsg->data, sizeof(demote)); 428 carp_demote_set(demote.group, demote.level); 429 break; 430 case IMSG_RTMSG: 431 IMSG_SIZE_CHECK(imsg, &crt); 432 memcpy(&crt, imsg->data, sizeof(crt)); 433 pfe_route(env, &crt); 434 break; 435 case IMSG_CTL_RESET: 436 IMSG_SIZE_CHECK(imsg, &v); 437 memcpy(&v, imsg->data, sizeof(v)); 438 parent_reload(env, v, NULL); 439 break; 440 case IMSG_CTL_RELOAD: 441 if (IMSG_DATA_SIZE(imsg) > 0) 442 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg)); 443 parent_reload(env, CONFIG_RELOAD, str); 444 if (str != NULL) 445 free(str); 446 break; 447 case IMSG_CTL_SHUTDOWN: 448 parent_shutdown(env); 449 break; 450 case IMSG_CFG_DONE: 451 parent_configure_done(env); 452 break; 453 default: 454 return (-1); 455 } 456 457 return (0); 458 } 459 460 int 461 parent_dispatch_hce(int fd, struct privsep_proc *p, struct imsg *imsg) 462 { 463 struct relayd *env = p->p_env; 464 struct privsep *ps = env->sc_ps; 465 struct ctl_script scr; 466 467 switch (imsg->hdr.type) { 468 case IMSG_SCRIPT: 469 IMSG_SIZE_CHECK(imsg, &scr); 470 bcopy(imsg->data, &scr, sizeof(scr)); 471 scr.retval = script_exec(env, &scr); 472 proc_compose_imsg(ps, PROC_HCE, -1, IMSG_SCRIPT, 473 -1, &scr, sizeof(scr)); 474 break; 475 case IMSG_SNMPSOCK: 476 (void)snmp_setsock(env, p->p_id); 477 break; 478 case IMSG_CFG_DONE: 479 parent_configure_done(env); 480 break; 481 default: 482 return (-1); 483 } 484 485 return (0); 486 } 487 488 int 489 parent_dispatch_relay(int fd, struct privsep_proc *p, struct imsg *imsg) 490 { 491 struct relayd *env = p->p_env; 492 struct privsep *ps = env->sc_ps; 493 struct ctl_bindany bnd; 494 int s; 495 496 switch (imsg->hdr.type) { 497 case IMSG_BINDANY: 498 IMSG_SIZE_CHECK(imsg, &bnd); 499 bcopy(imsg->data, &bnd, sizeof(bnd)); 500 if (bnd.bnd_proc > env->sc_prefork_relay) 501 fatalx("pfe_dispatch_relay: " 502 "invalid relay proc"); 503 switch (bnd.bnd_proto) { 504 case IPPROTO_TCP: 505 case IPPROTO_UDP: 506 break; 507 default: 508 fatalx("pfe_dispatch_relay: requested socket " 509 "for invalid protocol"); 510 /* NOTREACHED */ 511 } 512 s = bindany(&bnd); 513 proc_compose_imsg(ps, PROC_RELAY, bnd.bnd_proc, 514 IMSG_BINDANY, s, &bnd.bnd_id, sizeof(bnd.bnd_id)); 515 break; 516 case IMSG_CFG_DONE: 517 parent_configure_done(env); 518 break; 519 default: 520 return (-1); 521 } 522 523 return (0); 524 } 525 526 int 527 parent_dispatch_ca(int fd, struct privsep_proc *p, struct imsg *imsg) 528 { 529 struct relayd *env = p->p_env; 530 531 switch (imsg->hdr.type) { 532 case IMSG_CFG_DONE: 533 parent_configure_done(env); 534 break; 535 default: 536 return (-1); 537 } 538 539 return (0); 540 } 541 542 void 543 purge_table(struct tablelist *head, struct table *table) 544 { 545 struct host *host; 546 547 while ((host = TAILQ_FIRST(&table->hosts)) != NULL) { 548 TAILQ_REMOVE(&table->hosts, host, entry); 549 if (event_initialized(&host->cte.ev)) { 550 event_del(&host->cte.ev); 551 close(host->cte.s); 552 } 553 if (host->cte.buf != NULL) 554 ibuf_free(host->cte.buf); 555 if (host->cte.ssl != NULL) 556 SSL_free(host->cte.ssl); 557 free(host); 558 } 559 if (table->sendbuf != NULL) 560 free(table->sendbuf); 561 if (table->conf.flags & F_SSL) 562 SSL_CTX_free(table->ssl_ctx); 563 564 if (head != NULL) 565 TAILQ_REMOVE(head, table, entry); 566 free(table); 567 } 568 569 void 570 purge_key(char **ptr, off_t len) 571 { 572 char *key = *ptr; 573 574 if (key == NULL || len == 0) 575 return; 576 577 explicit_bzero(key, len); 578 free(key); 579 580 *ptr = NULL; 581 } 582 583 void 584 purge_relay(struct relayd *env, struct relay *rlay) 585 { 586 struct rsession *con; 587 struct relay_table *rlt; 588 589 /* shutdown and remove relay */ 590 if (event_initialized(&rlay->rl_ev)) 591 event_del(&rlay->rl_ev); 592 close(rlay->rl_s); 593 TAILQ_REMOVE(env->sc_relays, rlay, rl_entry); 594 595 /* cleanup sessions */ 596 while ((con = 597 SPLAY_ROOT(&rlay->rl_sessions)) != NULL) 598 relay_close(con, NULL); 599 600 /* cleanup relay */ 601 if (rlay->rl_bev != NULL) 602 bufferevent_free(rlay->rl_bev); 603 if (rlay->rl_dstbev != NULL) 604 bufferevent_free(rlay->rl_dstbev); 605 606 purge_key(&rlay->rl_ssl_cert, rlay->rl_conf.ssl_cert_len); 607 purge_key(&rlay->rl_ssl_key, rlay->rl_conf.ssl_key_len); 608 purge_key(&rlay->rl_ssl_ca, rlay->rl_conf.ssl_ca_len); 609 purge_key(&rlay->rl_ssl_cakey, rlay->rl_conf.ssl_cakey_len); 610 611 if (rlay->rl_ssl_x509 != NULL) { 612 X509_free(rlay->rl_ssl_x509); 613 rlay->rl_ssl_x509 = NULL; 614 } 615 if (rlay->rl_ssl_pkey != NULL) { 616 EVP_PKEY_free(rlay->rl_ssl_pkey); 617 rlay->rl_ssl_pkey = NULL; 618 } 619 if (rlay->rl_ssl_cacertx509 != NULL) { 620 X509_free(rlay->rl_ssl_cacertx509); 621 rlay->rl_ssl_cacertx509 = NULL; 622 } 623 if (rlay->rl_ssl_capkey != NULL) { 624 EVP_PKEY_free(rlay->rl_ssl_capkey); 625 rlay->rl_ssl_capkey = NULL; 626 } 627 628 if (rlay->rl_ssl_ctx != NULL) 629 SSL_CTX_free(rlay->rl_ssl_ctx); 630 631 while ((rlt = TAILQ_FIRST(&rlay->rl_tables))) { 632 TAILQ_REMOVE(&rlay->rl_tables, rlt, rlt_entry); 633 free(rlt); 634 } 635 636 free(rlay); 637 } 638 639 640 struct kv * 641 kv_add(struct kvtree *keys, char *key, char *value) 642 { 643 struct kv *kv, *oldkv; 644 645 if (key == NULL) 646 return (NULL); 647 if ((kv = calloc(1, sizeof(*kv))) == NULL) 648 return (NULL); 649 if ((kv->kv_key = strdup(key)) == NULL) { 650 free(kv); 651 return (NULL); 652 } 653 if (value != NULL && 654 (kv->kv_value = strdup(value)) == NULL) { 655 free(kv->kv_key); 656 free(kv); 657 return (NULL); 658 } 659 TAILQ_INIT(&kv->kv_children); 660 661 if ((oldkv = RB_INSERT(kvtree, keys, kv)) != NULL) { 662 TAILQ_INSERT_TAIL(&oldkv->kv_children, kv, kv_entry); 663 kv->kv_parent = oldkv; 664 } 665 666 return (kv); 667 } 668 669 int 670 kv_set(struct kv *kv, char *fmt, ...) 671 { 672 va_list ap; 673 char *value = NULL; 674 struct kv *ckv; 675 676 va_start(ap, fmt); 677 if (vasprintf(&value, fmt, ap) == -1) 678 return (-1); 679 va_end(ap); 680 681 /* Remove all children */ 682 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) { 683 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry); 684 kv_free(ckv); 685 free(ckv); 686 } 687 688 /* Set the new value */ 689 if (kv->kv_value != NULL) 690 free(kv->kv_value); 691 kv->kv_value = value; 692 693 return (0); 694 } 695 696 int 697 kv_setkey(struct kv *kv, char *fmt, ...) 698 { 699 va_list ap; 700 char *key = NULL; 701 702 va_start(ap, fmt); 703 if (vasprintf(&key, fmt, ap) == -1) 704 return (-1); 705 va_end(ap); 706 707 if (kv->kv_key != NULL) 708 free(kv->kv_key); 709 kv->kv_key = key; 710 711 return (0); 712 } 713 714 void 715 kv_delete(struct kvtree *keys, struct kv *kv) 716 { 717 struct kv *ckv; 718 719 RB_REMOVE(kvtree, keys, kv); 720 721 /* Remove all children */ 722 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) { 723 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry); 724 kv_free(ckv); 725 free(ckv); 726 } 727 728 kv_free(kv); 729 free(kv); 730 } 731 732 struct kv * 733 kv_extend(struct kvtree *keys, struct kv *kv, char *value) 734 { 735 char *newvalue; 736 737 if (kv == NULL) { 738 return (NULL); 739 } else if (kv->kv_value != NULL) { 740 if (asprintf(&newvalue, "%s%s", kv->kv_value, value) == -1) 741 return (NULL); 742 743 free(kv->kv_value); 744 kv->kv_value = newvalue; 745 } else if ((kv->kv_value = strdup(value)) == NULL) 746 return (NULL); 747 748 return (kv); 749 } 750 751 void 752 kv_purge(struct kvtree *keys) 753 { 754 struct kv *kv; 755 756 while ((kv = RB_MIN(kvtree, keys)) != NULL) 757 kv_delete(keys, kv); 758 } 759 760 void 761 kv_free(struct kv *kv) 762 { 763 if (kv->kv_type == KEY_TYPE_NONE) 764 return; 765 if (kv->kv_key != NULL) { 766 free(kv->kv_key); 767 } 768 kv->kv_key = NULL; 769 if (kv->kv_value != NULL) { 770 free(kv->kv_value); 771 } 772 kv->kv_value = NULL; 773 kv->kv_matchtree = NULL; 774 kv->kv_match = NULL; 775 memset(kv, 0, sizeof(*kv)); 776 } 777 778 struct kv * 779 kv_inherit(struct kv *dst, struct kv *src) 780 { 781 memset(dst, 0, sizeof(*dst)); 782 memcpy(dst, src, sizeof(*dst)); 783 TAILQ_INIT(&dst->kv_children); 784 785 if (src->kv_key != NULL) { 786 if ((dst->kv_key = strdup(src->kv_key)) == NULL) { 787 kv_free(dst); 788 return (NULL); 789 } 790 } 791 if (src->kv_value != NULL) { 792 if ((dst->kv_value = strdup(src->kv_value)) == NULL) { 793 kv_free(dst); 794 return (NULL); 795 } 796 } 797 798 if (src->kv_match != NULL) 799 dst->kv_match = src->kv_match; 800 if (src->kv_matchtree != NULL) 801 dst->kv_matchtree = src->kv_matchtree; 802 803 return (dst); 804 } 805 806 int 807 kv_log(struct rsession *con, struct kv *kv, u_int16_t labelid, 808 enum direction dir) 809 { 810 char *msg; 811 812 if (con->se_log == NULL) 813 return (0); 814 if (asprintf(&msg, " %s%s%s%s%s%s%s", 815 dir == RELAY_DIR_REQUEST ? "[" : "{", 816 labelid == 0 ? "" : label_id2name(labelid), 817 labelid == 0 ? "" : ", ", 818 kv->kv_key == NULL ? "(unknown)" : kv->kv_key, 819 kv->kv_value == NULL ? "" : ": ", 820 kv->kv_value == NULL ? "" : kv->kv_value, 821 dir == RELAY_DIR_REQUEST ? "]" : "}") == -1) 822 return (-1); 823 if (evbuffer_add(con->se_log, msg, strlen(msg)) == -1) { 824 free(msg); 825 return (-1); 826 } 827 free(msg); 828 con->se_haslog = 1; 829 return (0); 830 } 831 832 struct kv * 833 kv_find(struct kvtree *keys, struct kv *kv) 834 { 835 struct kv *match; 836 const char *key; 837 838 if (kv->kv_flags & KV_FLAG_GLOBBING) { 839 /* Test header key using shell globbing rules */ 840 key = kv->kv_key == NULL ? "" : kv->kv_key; 841 RB_FOREACH(match, kvtree, keys) { 842 if (fnmatch(key, match->kv_key, FNM_CASEFOLD) == 0) 843 break; 844 } 845 } else { 846 /* Fast tree-based lookup only works without globbing */ 847 match = RB_FIND(kvtree, keys, kv); 848 } 849 850 return (match); 851 } 852 853 int 854 kv_cmp(struct kv *a, struct kv *b) 855 { 856 return (strcasecmp(a->kv_key, b->kv_key)); 857 } 858 859 RB_GENERATE(kvtree, kv, kv_node, kv_cmp); 860 861 int 862 rule_add(struct protocol *proto, struct relay_rule *rule, const char *rulefile) 863 { 864 struct relay_rule *r = NULL; 865 struct kv *kv = NULL; 866 FILE *fp = NULL; 867 char buf[BUFSIZ]; 868 int ret = -1; 869 u_int i; 870 871 for (i = 0; i < KEY_TYPE_MAX; i++) { 872 kv = &rule->rule_kv[i]; 873 if (kv->kv_type != i) 874 continue; 875 876 switch (kv->kv_option) { 877 case KEY_OPTION_LOG: 878 /* log action needs a key or a file to be specified */ 879 if (kv->kv_key == NULL && rulefile == NULL && 880 (kv->kv_key = strdup("*")) == NULL) 881 goto fail; 882 break; 883 default: 884 break; 885 } 886 887 switch (kv->kv_type) { 888 case KEY_TYPE_QUERY: 889 case KEY_TYPE_PATH: 890 case KEY_TYPE_URL: 891 if (rule->rule_dir != RELAY_DIR_REQUEST) 892 goto fail; 893 break; 894 default: 895 break; 896 } 897 898 if (kv->kv_value != NULL && strchr(kv->kv_value, '$') != NULL) 899 kv->kv_flags |= KV_FLAG_MACRO; 900 if (kv->kv_key != NULL && strpbrk(kv->kv_key, "*?[") != NULL) 901 kv->kv_flags |= KV_FLAG_GLOBBING; 902 } 903 904 if (rulefile == NULL) { 905 TAILQ_INSERT_TAIL(&proto->rules, rule, rule_entry); 906 return (0); 907 } 908 909 if ((fp = fopen(rulefile, "r")) == NULL) 910 goto fail; 911 912 while (fgets(buf, sizeof(buf), fp) != NULL) { 913 /* strip whitespace and newline characters */ 914 buf[strcspn(buf, "\r\n\t ")] = '\0'; 915 if (!strlen(buf) || buf[0] == '#') 916 continue; 917 918 if ((r = rule_inherit(rule)) == NULL) 919 goto fail; 920 921 for (i = 0; i < KEY_TYPE_MAX; i++) { 922 kv = &r->rule_kv[i]; 923 if (kv->kv_type != i) 924 continue; 925 if (kv->kv_key != NULL) 926 free(kv->kv_key); 927 if ((kv->kv_key = strdup(buf)) == NULL) { 928 rule_free(r); 929 free(r); 930 goto fail; 931 } 932 } 933 934 TAILQ_INSERT_TAIL(&proto->rules, r, rule_entry); 935 } 936 937 ret = 0; 938 rule_free(rule); 939 free(rule); 940 941 fail: 942 if (fp != NULL) 943 fclose(fp); 944 return (ret); 945 } 946 947 struct relay_rule * 948 rule_inherit(struct relay_rule *rule) 949 { 950 struct relay_rule *r; 951 u_int i; 952 struct kv *kv; 953 954 if ((r = calloc(1, sizeof(*r))) == NULL) 955 return (NULL); 956 memcpy(r, rule, sizeof(*r)); 957 958 for (i = 0; i < KEY_TYPE_MAX; i++) { 959 kv = &rule->rule_kv[i]; 960 if (kv->kv_type != i) 961 continue; 962 if (kv_inherit(&r->rule_kv[i], kv) == NULL) { 963 free(r); 964 return(NULL); 965 } 966 } 967 968 if (r->rule_label > 0) 969 label_ref(r->rule_label); 970 if (r->rule_tag > 0) 971 tag_ref(r->rule_tag); 972 if (r->rule_tagged > 0) 973 tag_ref(r->rule_tagged); 974 975 return (r); 976 } 977 978 void 979 rule_free(struct relay_rule *rule) 980 { 981 u_int i; 982 983 for (i = 0; i < KEY_TYPE_MAX; i++) 984 kv_free(&rule->rule_kv[i]); 985 if (rule->rule_label > 0) 986 label_unref(rule->rule_label); 987 if (rule->rule_tag > 0) 988 tag_unref(rule->rule_tag); 989 if (rule->rule_tagged > 0) 990 tag_unref(rule->rule_tagged); 991 } 992 993 void 994 rule_delete(struct relay_rules *rules, struct relay_rule *rule) 995 { 996 TAILQ_REMOVE(rules, rule, rule_entry); 997 rule_free(rule); 998 free(rule); 999 } 1000 1001 void 1002 rule_settable(struct relay_rules *rules, struct relay_table *rlt) 1003 { 1004 struct relay_rule *r; 1005 char pname[TABLE_NAME_SIZE]; 1006 1007 if (rlt->rlt_table == NULL || strlcpy(pname, rlt->rlt_table->conf.name, 1008 sizeof(pname)) >= sizeof(pname)) 1009 return; 1010 1011 pname[strcspn(pname, ":")] = '\0'; 1012 1013 TAILQ_FOREACH(r, rules, rule_entry) { 1014 if (r->rule_tablename[0] && 1015 strcmp(pname, r->rule_tablename) == 0) { 1016 r->rule_table = rlt; 1017 } else { 1018 r->rule_table = NULL; 1019 } 1020 } 1021 } 1022 1023 /* 1024 * Utility functions 1025 */ 1026 1027 struct host * 1028 host_find(struct relayd *env, objid_t id) 1029 { 1030 struct table *table; 1031 struct host *host; 1032 1033 TAILQ_FOREACH(table, env->sc_tables, entry) 1034 TAILQ_FOREACH(host, &table->hosts, entry) 1035 if (host->conf.id == id) 1036 return (host); 1037 return (NULL); 1038 } 1039 1040 struct table * 1041 table_find(struct relayd *env, objid_t id) 1042 { 1043 struct table *table; 1044 1045 TAILQ_FOREACH(table, env->sc_tables, entry) 1046 if (table->conf.id == id) 1047 return (table); 1048 return (NULL); 1049 } 1050 1051 struct rdr * 1052 rdr_find(struct relayd *env, objid_t id) 1053 { 1054 struct rdr *rdr; 1055 1056 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 1057 if (rdr->conf.id == id) 1058 return (rdr); 1059 return (NULL); 1060 } 1061 1062 struct relay * 1063 relay_find(struct relayd *env, objid_t id) 1064 { 1065 struct relay *rlay; 1066 1067 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 1068 if (rlay->rl_conf.id == id) 1069 return (rlay); 1070 return (NULL); 1071 } 1072 1073 struct protocol * 1074 proto_find(struct relayd *env, objid_t id) 1075 { 1076 struct protocol *p; 1077 1078 TAILQ_FOREACH(p, env->sc_protos, entry) 1079 if (p->id == id) 1080 return (p); 1081 return (NULL); 1082 } 1083 1084 struct rsession * 1085 session_find(struct relayd *env, objid_t id) 1086 { 1087 struct relay *rlay; 1088 struct rsession *con; 1089 1090 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 1091 SPLAY_FOREACH(con, session_tree, &rlay->rl_sessions) 1092 if (con->se_id == id) 1093 return (con); 1094 return (NULL); 1095 } 1096 1097 struct netroute * 1098 route_find(struct relayd *env, objid_t id) 1099 { 1100 struct netroute *nr; 1101 1102 TAILQ_FOREACH(nr, env->sc_routes, nr_route) 1103 if (nr->nr_conf.id == id) 1104 return (nr); 1105 return (NULL); 1106 } 1107 1108 struct router * 1109 router_find(struct relayd *env, objid_t id) 1110 { 1111 struct router *rt; 1112 1113 TAILQ_FOREACH(rt, env->sc_rts, rt_entry) 1114 if (rt->rt_conf.id == id) 1115 return (rt); 1116 return (NULL); 1117 } 1118 1119 struct host * 1120 host_findbyname(struct relayd *env, const char *name) 1121 { 1122 struct table *table; 1123 struct host *host; 1124 1125 TAILQ_FOREACH(table, env->sc_tables, entry) 1126 TAILQ_FOREACH(host, &table->hosts, entry) 1127 if (strcmp(host->conf.name, name) == 0) 1128 return (host); 1129 return (NULL); 1130 } 1131 1132 struct table * 1133 table_findbyname(struct relayd *env, const char *name) 1134 { 1135 struct table *table; 1136 1137 TAILQ_FOREACH(table, env->sc_tables, entry) 1138 if (strcmp(table->conf.name, name) == 0) 1139 return (table); 1140 return (NULL); 1141 } 1142 1143 struct table * 1144 table_findbyconf(struct relayd *env, struct table *tb) 1145 { 1146 struct table *table; 1147 struct table_config a, b; 1148 1149 bcopy(&tb->conf, &a, sizeof(a)); 1150 a.id = a.rdrid = 0; 1151 a.flags &= ~(F_USED|F_BACKUP); 1152 1153 TAILQ_FOREACH(table, env->sc_tables, entry) { 1154 bcopy(&table->conf, &b, sizeof(b)); 1155 b.id = b.rdrid = 0; 1156 b.flags &= ~(F_USED|F_BACKUP); 1157 1158 /* 1159 * Compare two tables and return the existing table if 1160 * the configuration seems to be the same. 1161 */ 1162 if (bcmp(&a, &b, sizeof(b)) == 0 && 1163 ((tb->sendbuf == NULL && table->sendbuf == NULL) || 1164 (tb->sendbuf != NULL && table->sendbuf != NULL && 1165 strcmp(tb->sendbuf, table->sendbuf) == 0))) 1166 return (table); 1167 } 1168 return (NULL); 1169 } 1170 1171 struct rdr * 1172 rdr_findbyname(struct relayd *env, const char *name) 1173 { 1174 struct rdr *rdr; 1175 1176 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) 1177 if (strcmp(rdr->conf.name, name) == 0) 1178 return (rdr); 1179 return (NULL); 1180 } 1181 1182 struct relay * 1183 relay_findbyname(struct relayd *env, const char *name) 1184 { 1185 struct relay *rlay; 1186 1187 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 1188 if (strcmp(rlay->rl_conf.name, name) == 0) 1189 return (rlay); 1190 return (NULL); 1191 } 1192 1193 struct relay * 1194 relay_findbyaddr(struct relayd *env, struct relay_config *rc) 1195 { 1196 struct relay *rlay; 1197 1198 TAILQ_FOREACH(rlay, env->sc_relays, rl_entry) 1199 if (bcmp(&rlay->rl_conf.ss, &rc->ss, sizeof(rc->ss)) == 0 && 1200 rlay->rl_conf.port == rc->port) 1201 return (rlay); 1202 return (NULL); 1203 } 1204 1205 EVP_PKEY * 1206 pkey_find(struct relayd *env, objid_t id) 1207 { 1208 struct ca_pkey *pkey; 1209 1210 TAILQ_FOREACH(pkey, env->sc_pkeys, pkey_entry) 1211 if (pkey->pkey_id == id) 1212 return (pkey->pkey); 1213 return (NULL); 1214 } 1215 1216 struct ca_pkey * 1217 pkey_add(struct relayd *env, EVP_PKEY *pkey, objid_t id) 1218 { 1219 struct ca_pkey *ca_pkey; 1220 1221 if (env->sc_pkeys == NULL) 1222 fatalx("pkeys"); 1223 1224 if ((ca_pkey = calloc(1, sizeof(*ca_pkey))) == NULL) 1225 return (NULL); 1226 1227 ca_pkey->pkey = pkey; 1228 ca_pkey->pkey_id = id; 1229 1230 TAILQ_INSERT_TAIL(env->sc_pkeys, ca_pkey, pkey_entry); 1231 1232 return (ca_pkey); 1233 } 1234 1235 void 1236 event_again(struct event *ev, int fd, short event, 1237 void (*fn)(int, short, void *), 1238 struct timeval *start, struct timeval *end, void *arg) 1239 { 1240 struct timeval tv_next, tv_now, tv; 1241 1242 getmonotime(&tv_now); 1243 bcopy(end, &tv_next, sizeof(tv_next)); 1244 timersub(&tv_now, start, &tv_now); 1245 timersub(&tv_next, &tv_now, &tv_next); 1246 1247 bzero(&tv, sizeof(tv)); 1248 if (timercmp(&tv_next, &tv, >)) 1249 bcopy(&tv_next, &tv, sizeof(tv)); 1250 1251 event_del(ev); 1252 event_set(ev, fd, event, fn, arg); 1253 event_add(ev, &tv); 1254 } 1255 1256 int 1257 expand_string(char *label, size_t len, const char *srch, const char *repl) 1258 { 1259 char *tmp; 1260 char *p, *q; 1261 1262 if ((tmp = calloc(1, len)) == NULL) { 1263 log_debug("%s: calloc", __func__); 1264 return (-1); 1265 } 1266 p = q = label; 1267 while ((q = strstr(p, srch)) != NULL) { 1268 *q = '\0'; 1269 if ((strlcat(tmp, p, len) >= len) || 1270 (strlcat(tmp, repl, len) >= len)) { 1271 log_debug("%s: string too long", __func__); 1272 free(tmp); 1273 return (-1); 1274 } 1275 q += strlen(srch); 1276 p = q; 1277 } 1278 if (strlcat(tmp, p, len) >= len) { 1279 log_debug("%s: string too long", __func__); 1280 free(tmp); 1281 return (-1); 1282 } 1283 (void)strlcpy(label, tmp, len); /* always fits */ 1284 free(tmp); 1285 1286 return (0); 1287 } 1288 1289 void 1290 translate_string(char *str) 1291 { 1292 char *reader; 1293 char *writer; 1294 1295 reader = writer = str; 1296 1297 while (*reader) { 1298 if (*reader == '\\') { 1299 reader++; 1300 switch (*reader) { 1301 case 'n': 1302 *writer++ = '\n'; 1303 break; 1304 case 'r': 1305 *writer++ = '\r'; 1306 break; 1307 default: 1308 *writer++ = *reader; 1309 } 1310 } else 1311 *writer++ = *reader; 1312 reader++; 1313 } 1314 *writer = '\0'; 1315 } 1316 1317 char * 1318 digeststr(enum digest_type type, const u_int8_t *data, size_t len, char *buf) 1319 { 1320 switch (type) { 1321 case DIGEST_SHA1: 1322 return (SHA1Data(data, len, buf)); 1323 break; 1324 case DIGEST_MD5: 1325 return (MD5Data(data, len, buf)); 1326 break; 1327 default: 1328 break; 1329 } 1330 return (NULL); 1331 } 1332 1333 const char * 1334 canonicalize_host(const char *host, char *name, size_t len) 1335 { 1336 struct sockaddr_in sin4; 1337 struct sockaddr_in6 sin6; 1338 u_int i, j; 1339 size_t plen; 1340 char c; 1341 1342 if (len < 2) 1343 goto fail; 1344 1345 /* 1346 * Canonicalize an IPv4/6 address 1347 */ 1348 if (inet_pton(AF_INET, host, &sin4) == 1) 1349 return (inet_ntop(AF_INET, &sin4, name, len)); 1350 if (inet_pton(AF_INET6, host, &sin6) == 1) 1351 return (inet_ntop(AF_INET6, &sin6, name, len)); 1352 1353 /* 1354 * Canonicalize a hostname 1355 */ 1356 1357 /* 1. remove repeated dots and convert upper case to lower case */ 1358 plen = strlen(host); 1359 bzero(name, len); 1360 for (i = j = 0; i < plen; i++) { 1361 if (j >= (len - 1)) 1362 goto fail; 1363 c = tolower(host[i]); 1364 if ((c == '.') && (j == 0 || name[j - 1] == '.')) 1365 continue; 1366 name[j++] = c; 1367 } 1368 1369 /* 2. remove trailing dots */ 1370 for (i = j; i > 0; i--) { 1371 if (name[i - 1] != '.') 1372 break; 1373 name[i - 1] = '\0'; 1374 j--; 1375 } 1376 if (j <= 0) 1377 goto fail; 1378 1379 return (name); 1380 1381 fail: 1382 errno = EINVAL; 1383 return (NULL); 1384 } 1385 1386 int 1387 bindany(struct ctl_bindany *bnd) 1388 { 1389 int s, v; 1390 1391 s = -1; 1392 v = 1; 1393 1394 if (relay_socket_af(&bnd->bnd_ss, bnd->bnd_port) == -1) 1395 goto fail; 1396 if ((s = socket(bnd->bnd_ss.ss_family, 1397 bnd->bnd_proto == IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM, 1398 bnd->bnd_proto)) == -1) 1399 goto fail; 1400 if (setsockopt(s, SOL_SOCKET, SO_BINDANY, 1401 &v, sizeof(v)) == -1) 1402 goto fail; 1403 if (bind(s, (struct sockaddr *)&bnd->bnd_ss, 1404 bnd->bnd_ss.ss_len) == -1) 1405 goto fail; 1406 1407 return (s); 1408 1409 fail: 1410 if (s != -1) 1411 close(s); 1412 return (-1); 1413 } 1414 1415 int 1416 map6to4(struct sockaddr_storage *in6) 1417 { 1418 struct sockaddr_storage out4; 1419 struct sockaddr_in *sin4 = (struct sockaddr_in *)&out4; 1420 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)in6; 1421 1422 bzero(sin4, sizeof(*sin4)); 1423 sin4->sin_len = sizeof(*sin4); 1424 sin4->sin_family = AF_INET; 1425 sin4->sin_port = sin6->sin6_port; 1426 1427 bcopy(&sin6->sin6_addr.s6_addr[12], &sin4->sin_addr.s_addr, 1428 sizeof(sin4->sin_addr)); 1429 1430 if (sin4->sin_addr.s_addr == INADDR_ANY || 1431 sin4->sin_addr.s_addr == INADDR_BROADCAST || 1432 IN_MULTICAST(ntohl(sin4->sin_addr.s_addr))) 1433 return (-1); 1434 1435 bcopy(&out4, in6, sizeof(*in6)); 1436 1437 return (0); 1438 } 1439 1440 int 1441 map4to6(struct sockaddr_storage *in4, struct sockaddr_storage *map) 1442 { 1443 struct sockaddr_storage out6; 1444 struct sockaddr_in *sin4 = (struct sockaddr_in *)in4; 1445 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&out6; 1446 struct sockaddr_in6 *map6 = (struct sockaddr_in6 *)map; 1447 1448 if (sin4->sin_addr.s_addr == INADDR_ANY || 1449 sin4->sin_addr.s_addr == INADDR_BROADCAST || 1450 IN_MULTICAST(ntohl(sin4->sin_addr.s_addr))) 1451 return (-1); 1452 1453 bcopy(map6, sin6, sizeof(*sin6)); 1454 sin6->sin6_len = sizeof(*sin6); 1455 sin6->sin6_family = AF_INET6; 1456 sin6->sin6_port = sin4->sin_port; 1457 1458 bcopy(&sin4->sin_addr.s_addr, &sin6->sin6_addr.s6_addr[12], 1459 sizeof(sin4->sin_addr)); 1460 1461 bcopy(&out6, in4, sizeof(*in4)); 1462 1463 return (0); 1464 } 1465 1466 void 1467 socket_rlimit(int maxfd) 1468 { 1469 struct rlimit rl; 1470 1471 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) 1472 fatal("socket_rlimit: failed to get resource limit"); 1473 log_debug("%s: max open files %llu", __func__, rl.rlim_max); 1474 1475 /* 1476 * Allow the maximum number of open file descriptors for this 1477 * login class (which should be the class "daemon" by default). 1478 */ 1479 if (maxfd == -1) 1480 rl.rlim_cur = rl.rlim_max; 1481 else 1482 rl.rlim_cur = MAX(rl.rlim_max, (rlim_t)maxfd); 1483 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) 1484 fatal("socket_rlimit: failed to set resource limit"); 1485 } 1486 1487 char * 1488 get_string(u_int8_t *ptr, size_t len) 1489 { 1490 size_t i; 1491 char *str; 1492 1493 for (i = 0; i < len; i++) 1494 if (!(isprint(ptr[i]) || isspace(ptr[i]))) 1495 break; 1496 1497 if ((str = calloc(1, i + 1)) == NULL) 1498 return (NULL); 1499 memcpy(str, ptr, i); 1500 1501 return (str); 1502 } 1503 1504 void * 1505 get_data(u_int8_t *ptr, size_t len) 1506 { 1507 u_int8_t *data; 1508 1509 if ((data = calloc(1, len)) == NULL) 1510 return (NULL); 1511 memcpy(data, ptr, len); 1512 1513 return (data); 1514 } 1515 1516 int 1517 sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen) 1518 { 1519 struct sockaddr_in *a4, *b4; 1520 struct sockaddr_in6 *a6, *b6; 1521 u_int32_t av[4], bv[4], mv[4]; 1522 1523 if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC) 1524 return (0); 1525 else if (a->sa_family > b->sa_family) 1526 return (1); 1527 else if (a->sa_family < b->sa_family) 1528 return (-1); 1529 1530 if (prefixlen == -1) 1531 memset(&mv, 0xff, sizeof(mv)); 1532 1533 switch (a->sa_family) { 1534 case AF_INET: 1535 a4 = (struct sockaddr_in *)a; 1536 b4 = (struct sockaddr_in *)b; 1537 1538 av[0] = a4->sin_addr.s_addr; 1539 bv[0] = b4->sin_addr.s_addr; 1540 if (prefixlen != -1) 1541 mv[0] = prefixlen2mask(prefixlen); 1542 1543 if ((av[0] & mv[0]) > (bv[0] & mv[0])) 1544 return (1); 1545 if ((av[0] & mv[0]) < (bv[0] & mv[0])) 1546 return (-1); 1547 break; 1548 case AF_INET6: 1549 a6 = (struct sockaddr_in6 *)a; 1550 b6 = (struct sockaddr_in6 *)b; 1551 1552 memcpy(&av, &a6->sin6_addr.s6_addr, 16); 1553 memcpy(&bv, &b6->sin6_addr.s6_addr, 16); 1554 if (prefixlen != -1) 1555 prefixlen2mask6(prefixlen, mv); 1556 1557 if ((av[3] & mv[3]) > (bv[3] & mv[3])) 1558 return (1); 1559 if ((av[3] & mv[3]) < (bv[3] & mv[3])) 1560 return (-1); 1561 if ((av[2] & mv[2]) > (bv[2] & mv[2])) 1562 return (1); 1563 if ((av[2] & mv[2]) < (bv[2] & mv[2])) 1564 return (-1); 1565 if ((av[1] & mv[1]) > (bv[1] & mv[1])) 1566 return (1); 1567 if ((av[1] & mv[1]) < (bv[1] & mv[1])) 1568 return (-1); 1569 if ((av[0] & mv[0]) > (bv[0] & mv[0])) 1570 return (1); 1571 if ((av[0] & mv[0]) < (bv[0] & mv[0])) 1572 return (-1); 1573 break; 1574 } 1575 1576 return (0); 1577 } 1578 1579 u_int32_t 1580 prefixlen2mask(u_int8_t prefixlen) 1581 { 1582 if (prefixlen == 0) 1583 return (0); 1584 1585 if (prefixlen > 32) 1586 prefixlen = 32; 1587 1588 return (htonl(0xffffffff << (32 - prefixlen))); 1589 } 1590 1591 struct in6_addr * 1592 prefixlen2mask6(u_int8_t prefixlen, u_int32_t *mask) 1593 { 1594 static struct in6_addr s6; 1595 int i; 1596 1597 if (prefixlen > 128) 1598 prefixlen = 128; 1599 1600 bzero(&s6, sizeof(s6)); 1601 for (i = 0; i < prefixlen / 8; i++) 1602 s6.s6_addr[i] = 0xff; 1603 i = prefixlen % 8; 1604 if (i) 1605 s6.s6_addr[prefixlen / 8] = 0xff00 >> i; 1606 1607 memcpy(mask, &s6, sizeof(s6)); 1608 1609 return (&s6); 1610 } 1611 1612 int 1613 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen, 1614 int reserve, volatile int *counter) 1615 { 1616 int ret; 1617 if (getdtablecount() + reserve + 1618 *counter >= getdtablesize()) { 1619 errno = EMFILE; 1620 return (-1); 1621 } 1622 1623 if ((ret = accept(sockfd, addr, addrlen)) > -1) { 1624 (*counter)++; 1625 DPRINTF("%s: inflight incremented, now %d",__func__, *counter); 1626 } 1627 return (ret); 1628 } 1629