1 /* $OpenBSD: config.c,v 1.2 2011/05/19 09:13:07 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2011 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/socket.h> 21 #include <sys/stat.h> 22 #include <sys/queue.h> 23 #include <sys/uio.h> 24 25 #include <net/if.h> 26 #include <net/pfvar.h> 27 #include <netinet/in.h> 28 #include <arpa/inet.h> 29 #include <arpa/nameser.h> 30 #include <net/route.h> 31 32 #include <ctype.h> 33 #include <unistd.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <event.h> 37 #include <limits.h> 38 #include <stdint.h> 39 #include <stdarg.h> 40 #include <stdio.h> 41 #include <netdb.h> 42 #include <string.h> 43 #include <ifaddrs.h> 44 45 #include <openssl/ssl.h> 46 47 #include "relayd.h" 48 49 int 50 config_init(struct relayd *env) 51 { 52 struct privsep *ps = env->sc_ps; 53 u_int what; 54 55 /* Global configuration */ 56 if (privsep_process == PROC_PARENT) { 57 env->sc_timeout.tv_sec = CHECK_TIMEOUT / 1000; 58 env->sc_timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000; 59 env->sc_interval.tv_sec = CHECK_INTERVAL; 60 env->sc_interval.tv_usec = 0; 61 env->sc_prefork_relay = RELAY_NUMPROC; 62 env->sc_statinterval.tv_sec = RELAY_STATINTERVAL; 63 64 ps->ps_what[PROC_PARENT] = CONFIG_ALL; 65 ps->ps_what[PROC_PFE] = CONFIG_ALL & ~CONFIG_PROTOS; 66 ps->ps_what[PROC_HCE] = CONFIG_TABLES; 67 ps->ps_what[PROC_RELAY] = 68 CONFIG_TABLES|CONFIG_RELAYS|CONFIG_PROTOS; 69 } 70 71 /* Other configuration */ 72 what = ps->ps_what[privsep_process]; 73 if (what & CONFIG_TABLES) { 74 if ((env->sc_tables = 75 calloc(1, sizeof(*env->sc_tables))) == NULL) 76 return (-1); 77 TAILQ_INIT(env->sc_tables); 78 79 memset(&env->sc_empty_table, 0, sizeof(env->sc_empty_table)); 80 env->sc_empty_table.conf.id = EMPTY_TABLE; 81 env->sc_empty_table.conf.flags |= F_DISABLE; 82 (void)strlcpy(env->sc_empty_table.conf.name, "empty", 83 sizeof(env->sc_empty_table.conf.name)); 84 85 } 86 if (what & CONFIG_RDRS) { 87 if ((env->sc_rdrs = 88 calloc(1, sizeof(*env->sc_rdrs))) == NULL) 89 return (-1); 90 TAILQ_INIT(env->sc_rdrs); 91 92 } 93 if (what & CONFIG_RELAYS) { 94 if ((env->sc_relays = 95 calloc(1, sizeof(*env->sc_relays))) == NULL) 96 return (-1); 97 TAILQ_INIT(env->sc_relays); 98 } 99 if (what & CONFIG_PROTOS) { 100 if ((env->sc_protos = 101 calloc(1, sizeof(*env->sc_protos))) == NULL) 102 return (-1); 103 TAILQ_INIT(env->sc_protos); 104 105 bzero(&env->sc_proto_default, sizeof(env->sc_proto_default)); 106 env->sc_proto_default.id = EMPTY_ID; 107 env->sc_proto_default.flags = F_USED; 108 env->sc_proto_default.cache = RELAY_CACHESIZE; 109 env->sc_proto_default.tcpflags = TCPFLAG_DEFAULT; 110 env->sc_proto_default.tcpbacklog = RELAY_BACKLOG; 111 env->sc_proto_default.sslflags = SSLFLAG_DEFAULT; 112 (void)strlcpy(env->sc_proto_default.sslciphers, 113 SSLCIPHERS_DEFAULT, 114 sizeof(env->sc_proto_default.sslciphers)); 115 env->sc_proto_default.type = RELAY_PROTO_TCP; 116 (void)strlcpy(env->sc_proto_default.name, "default", 117 sizeof(env->sc_proto_default.name)); 118 RB_INIT(&env->sc_proto_default.request_tree); 119 RB_INIT(&env->sc_proto_default.response_tree); 120 } 121 if (what & CONFIG_RTS) { 122 if ((env->sc_rts = 123 calloc(1, sizeof(*env->sc_rts))) == NULL) 124 return (-1); 125 TAILQ_INIT(env->sc_rts); 126 } 127 if (what & CONFIG_ROUTES) { 128 if ((env->sc_routes = 129 calloc(1, sizeof(*env->sc_routes))) == NULL) 130 return (-1); 131 TAILQ_INIT(env->sc_routes); 132 } 133 134 return (0); 135 } 136 137 void 138 config_purge(struct relayd *env, u_int reset) 139 { 140 struct privsep *ps = env->sc_ps; 141 struct table *table; 142 struct rdr *rdr; 143 struct address *virt; 144 struct protocol *proto; 145 struct relay *rlay; 146 struct netroute *nr; 147 struct router *rt; 148 u_int what; 149 150 what = ps->ps_what[privsep_process] & reset; 151 152 if (what & CONFIG_TABLES && env->sc_tables != NULL) { 153 while ((table = TAILQ_FIRST(env->sc_tables)) != NULL) 154 purge_table(env->sc_tables, table); 155 env->sc_tablecount = 0; 156 } 157 if (what & CONFIG_RDRS && env->sc_rdrs != NULL) { 158 while ((rdr = TAILQ_FIRST(env->sc_rdrs)) != NULL) { 159 TAILQ_REMOVE(env->sc_rdrs, rdr, entry); 160 while ((virt = TAILQ_FIRST(&rdr->virts)) != NULL) { 161 TAILQ_REMOVE(&rdr->virts, virt, entry); 162 free(virt); 163 } 164 free(rdr); 165 } 166 env->sc_rdrcount = 0; 167 } 168 if (what & CONFIG_RELAYS && env->sc_relays != NULL) { 169 while ((rlay = TAILQ_FIRST(env->sc_relays)) != NULL) 170 purge_relay(env, rlay); 171 env->sc_relaycount = 0; 172 } 173 if (what & CONFIG_PROTOS && env->sc_protos != NULL) { 174 while ((proto = TAILQ_FIRST(env->sc_protos)) != NULL) { 175 TAILQ_REMOVE(env->sc_protos, proto, entry); 176 purge_tree(&proto->request_tree); 177 purge_tree(&proto->response_tree); 178 if (proto->style != NULL) 179 free(proto->style); 180 free(proto); 181 } 182 env->sc_protocount = 0; 183 } 184 if (what & CONFIG_RTS && env->sc_rts != NULL) { 185 while ((rt = TAILQ_FIRST(env->sc_rts)) != NULL) { 186 TAILQ_REMOVE(env->sc_rts, rt, rt_entry); 187 while ((nr = TAILQ_FIRST(&rt->rt_netroutes)) != NULL) { 188 TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry); 189 TAILQ_REMOVE(env->sc_routes, nr, nr_route); 190 free(nr); 191 env->sc_routecount--; 192 } 193 free(rt); 194 } 195 env->sc_routercount = 0; 196 } 197 if (what & CONFIG_ROUTES && env->sc_routes != NULL) { 198 while ((nr = TAILQ_FIRST(env->sc_routes)) != NULL) { 199 if ((rt = nr->nr_router) != NULL) 200 TAILQ_REMOVE(&rt->rt_netroutes, nr, nr_entry); 201 TAILQ_REMOVE(env->sc_routes, nr, nr_route); 202 free(nr); 203 } 204 env->sc_routecount = 0; 205 } 206 } 207 208 int 209 config_setreset(struct relayd *env, u_int reset) 210 { 211 struct privsep *ps = env->sc_ps; 212 int id; 213 214 for (id = 0; id < PROC_MAX; id++) { 215 if ((reset & ps->ps_what[id]) == 0 || 216 id == privsep_process) 217 continue; 218 proc_compose_imsg(ps, id, -1, IMSG_CTL_RESET, -1, 219 &reset, sizeof(reset)); 220 } 221 222 return (0); 223 } 224 225 int 226 config_getreset(struct relayd *env, struct imsg *imsg) 227 { 228 u_int mode; 229 230 IMSG_SIZE_CHECK(imsg, &mode); 231 memcpy(&mode, imsg->data, sizeof(mode)); 232 233 config_purge(env, mode); 234 235 return (0); 236 } 237 238 int 239 config_getcfg(struct relayd *env, struct imsg *imsg) 240 { 241 struct privsep *ps = env->sc_ps; 242 struct table *tb; 243 struct host *h, *ph; 244 struct ctl_flags cf; 245 246 if (IMSG_DATA_SIZE(imsg) != sizeof(cf)) 247 return (0); /* ignore */ 248 249 /* Update runtime flags */ 250 memcpy(&cf, imsg->data, sizeof(cf)); 251 env->sc_opts = cf.cf_opts; 252 env->sc_flags = cf.cf_flags; 253 254 if (ps->ps_what[privsep_process] & CONFIG_TABLES) { 255 /* Update the tables */ 256 TAILQ_FOREACH(tb, env->sc_tables, entry) { 257 TAILQ_FOREACH(h, &tb->hosts, entry) { 258 if (h->conf.parentid && (ph = host_find(env, 259 h->conf.parentid)) != NULL) { 260 SLIST_INSERT_HEAD(&ph->children, 261 h, child); 262 } 263 } 264 } 265 } 266 267 if (env->sc_flags & (F_SSL|F_SSLCLIENT)) 268 ssl_init(env); 269 270 if (privsep_process != PROC_PARENT) 271 proc_compose_imsg(env->sc_ps, PROC_PARENT, -1, 272 IMSG_CFG_DONE, -1, NULL, 0); 273 274 return (0); 275 } 276 277 int 278 config_settable(struct relayd *env, struct table *tb) 279 { 280 struct privsep *ps = env->sc_ps; 281 struct host *host; 282 int id, c; 283 struct iovec iov[2]; 284 285 for (id = 0; id < PROC_MAX; id++) { 286 if ((ps->ps_what[id] & CONFIG_TABLES) == 0 || 287 id == privsep_process) 288 continue; 289 290 /* XXX need to send table to pfe for control socket */ 291 if (id == PROC_HCE && tb->conf.check == CHECK_NOCHECK) 292 continue; 293 294 DPRINTF("%s: sending table %s %d to %s", __func__, 295 tb->conf.name, tb->conf.id, env->sc_ps->ps_title[id]); 296 297 c = 0; 298 iov[c].iov_base = &tb->conf; 299 iov[c++].iov_len = sizeof(tb->conf); 300 if (tb->sendbuf != NULL) { 301 iov[c].iov_base = tb->sendbuf; 302 iov[c++].iov_len = strlen(tb->sendbuf); 303 } 304 305 proc_composev_imsg(ps, id, -1, IMSG_CFG_TABLE, -1, iov, c); 306 307 TAILQ_FOREACH(host, &tb->hosts, entry) { 308 proc_compose_imsg(ps, id, -1, IMSG_CFG_HOST, -1, 309 &host->conf, sizeof(host->conf)); 310 } 311 } 312 313 return (0); 314 } 315 316 int 317 config_gettable(struct relayd *env, struct imsg *imsg) 318 { 319 struct table *tb; 320 size_t sb; 321 u_int8_t *p = imsg->data; 322 size_t s; 323 324 if ((tb = calloc(1, sizeof(*tb))) == NULL) 325 return (-1); 326 327 IMSG_SIZE_CHECK(imsg, &tb->conf); 328 memcpy(&tb->conf, p, sizeof(tb->conf)); 329 s = sizeof(tb->conf); 330 331 sb = IMSG_DATA_SIZE(imsg) - s; 332 if (sb > 0) { 333 if ((tb->sendbuf = get_string(p + s, sb)) == NULL) { 334 free(tb); 335 return (-1); 336 } 337 } 338 339 TAILQ_INIT(&tb->hosts); 340 TAILQ_INSERT_TAIL(env->sc_tables, tb, entry); 341 342 env->sc_tablecount++; 343 344 DPRINTF("%s: %s %d received table %d (%s)", __func__, 345 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 346 tb->conf.id, tb->conf.name); 347 348 return (0); 349 } 350 351 int 352 config_gethost(struct relayd *env, struct imsg *imsg) 353 { 354 struct table *tb; 355 struct host *host; 356 357 if ((host = calloc(1, sizeof(*host))) == NULL) 358 return (-1); 359 360 IMSG_SIZE_CHECK(imsg, &host->conf); 361 memcpy(&host->conf, imsg->data, sizeof(host->conf)); 362 363 if (host_find(env, host->conf.id) != NULL) { 364 log_debug("%s: host %d already exists", 365 __func__, host->conf.id); 366 free(host); 367 return (-1); 368 } 369 370 if ((tb = table_find(env, host->conf.tableid)) == NULL) { 371 log_debug("%s: " 372 "received host for unknown table %d", __func__, 373 host->conf.tableid); 374 free(host); 375 return (-1); 376 } 377 378 host->tablename = tb->conf.name; 379 host->cte.s = -1; 380 381 SLIST_INIT(&host->children); 382 TAILQ_INSERT_TAIL(&tb->hosts, host, entry); 383 384 DPRINTF("%s: %s %d received host %s for table %s", __func__, 385 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 386 host->conf.name, tb->conf.name); 387 388 return (0); 389 } 390 391 int 392 config_setrdr(struct relayd *env, struct rdr *rdr) 393 { 394 struct privsep *ps = env->sc_ps; 395 struct address *virt; 396 int id; 397 398 for (id = 0; id < PROC_MAX; id++) { 399 if ((ps->ps_what[id] & CONFIG_RDRS) == 0 || 400 id == privsep_process) 401 continue; 402 403 DPRINTF("%s: sending rdr %s to %s", __func__, 404 rdr->conf.name, ps->ps_title[id]); 405 406 proc_compose_imsg(ps, id, -1, IMSG_CFG_RDR, -1, 407 &rdr->conf, sizeof(rdr->conf)); 408 409 TAILQ_FOREACH(virt, &rdr->virts, entry) { 410 virt->rdrid = rdr->conf.id; 411 proc_compose_imsg(ps, id, -1, IMSG_CFG_VIRT, -1, 412 virt, sizeof(*virt)); 413 } 414 } 415 416 return (0); 417 } 418 419 int 420 config_getrdr(struct relayd *env, struct imsg *imsg) 421 { 422 struct rdr *rdr; 423 424 if ((rdr = calloc(1, sizeof(*rdr))) == NULL) 425 return (-1); 426 427 IMSG_SIZE_CHECK(imsg, &rdr->conf); 428 memcpy(&rdr->conf, imsg->data, sizeof(rdr->conf)); 429 430 if ((rdr->table = table_find(env, rdr->conf.table_id)) == NULL) { 431 log_debug("%s: table not found", __func__); 432 free(rdr); 433 return (-1); 434 } 435 if ((rdr->backup = table_find(env, rdr->conf.backup_id)) == NULL) { 436 rdr->conf.backup_id = EMPTY_TABLE; 437 rdr->backup = &env->sc_empty_table; 438 } 439 440 TAILQ_INIT(&rdr->virts); 441 TAILQ_INSERT_TAIL(env->sc_rdrs, rdr, entry); 442 443 env->sc_rdrcount++; 444 445 DPRINTF("%s: %s %d received rdr %s", __func__, 446 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 447 rdr->conf.name); 448 449 return (0); 450 } 451 452 int 453 config_getvirt(struct relayd *env, struct imsg *imsg) 454 { 455 struct rdr *rdr; 456 struct address *virt; 457 458 IMSG_SIZE_CHECK(imsg, virt); 459 460 if ((virt = calloc(1, sizeof(*virt))) == NULL) 461 return (-1); 462 memcpy(virt, imsg->data, sizeof(*virt)); 463 464 if ((rdr = rdr_find(env, virt->rdrid)) == NULL) { 465 log_debug("%s: rdr not found", __func__); 466 free(virt); 467 return (-1); 468 } 469 470 TAILQ_INSERT_TAIL(&rdr->virts, virt, entry); 471 472 DPRINTF("%s: %s %d received address for rdr %s", __func__, 473 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 474 rdr->conf.name); 475 476 return (0); 477 } 478 479 int 480 config_setrt(struct relayd *env, struct router *rt) 481 { 482 struct privsep *ps = env->sc_ps; 483 struct netroute *nr; 484 int id; 485 486 for (id = 0; id < PROC_MAX; id++) { 487 if ((ps->ps_what[id] & CONFIG_RTS) == 0 || 488 id == privsep_process) 489 continue; 490 491 DPRINTF("%s: sending router %s to %s tbl %d", __func__, 492 rt->rt_conf.name, ps->ps_title[id], rt->rt_conf.gwtable); 493 494 proc_compose_imsg(ps, id, -1, IMSG_CFG_ROUTER, -1, 495 &rt->rt_conf, sizeof(rt->rt_conf)); 496 497 TAILQ_FOREACH(nr, &rt->rt_netroutes, nr_entry) { 498 proc_compose_imsg(ps, id, -1, IMSG_CFG_ROUTE, -1, 499 &nr->nr_conf, sizeof(nr->nr_conf)); 500 } 501 } 502 503 return (0); 504 } 505 506 int 507 config_getrt(struct relayd *env, struct imsg *imsg) 508 { 509 struct router *rt; 510 511 if ((rt = calloc(1, sizeof(*rt))) == NULL) 512 return (-1); 513 514 IMSG_SIZE_CHECK(imsg, &rt->rt_conf); 515 memcpy(&rt->rt_conf, imsg->data, sizeof(rt->rt_conf)); 516 517 if ((rt->rt_gwtable = table_find(env, rt->rt_conf.gwtable)) == NULL) { 518 log_debug("%s: table not found", __func__); 519 free(rt); 520 return (-1); 521 } 522 523 TAILQ_INIT(&rt->rt_netroutes); 524 TAILQ_INSERT_TAIL(env->sc_rts, rt, rt_entry); 525 526 env->sc_routercount++; 527 528 DPRINTF("%s: %s %d received router %s", __func__, 529 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 530 rt->rt_conf.name); 531 532 return (0); 533 } 534 535 int 536 config_getroute(struct relayd *env, struct imsg *imsg) 537 { 538 struct router *rt; 539 struct netroute *nr; 540 541 if ((nr = calloc(1, sizeof(*nr))) == NULL) 542 return (-1); 543 544 IMSG_SIZE_CHECK(imsg, &nr->nr_conf); 545 memcpy(&nr->nr_conf, imsg->data, sizeof(nr->nr_conf)); 546 547 if (route_find(env, nr->nr_conf.id) != NULL) { 548 log_debug("%s: route %d already exists", 549 __func__, nr->nr_conf.id); 550 free(nr); 551 return (-1); 552 } 553 554 if ((rt = router_find(env, nr->nr_conf.routerid)) == NULL) { 555 log_debug("%s: received route for unknown router", __func__); 556 free(nr); 557 return (-1); 558 } 559 560 nr->nr_router = rt; 561 562 TAILQ_INSERT_TAIL(env->sc_routes, nr, nr_route); 563 TAILQ_INSERT_TAIL(&rt->rt_netroutes, nr, nr_entry); 564 565 env->sc_routecount++; 566 567 DPRINTF("%s: %s %d received route %d for router %s", __func__, 568 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 569 nr->nr_conf.id, rt->rt_conf.name); 570 571 return (0); 572 } 573 574 int 575 config_setproto(struct relayd *env, struct protocol *proto) 576 { 577 struct privsep *ps = env->sc_ps; 578 int id; 579 struct iovec iov[2]; 580 size_t c; 581 582 for (id = 0; id < PROC_MAX; id++) { 583 if ((ps->ps_what[id] & CONFIG_PROTOS) == 0 || 584 id == privsep_process) 585 continue; 586 587 DPRINTF("%s: sending protocol %s to %s", __func__, 588 proto->name, ps->ps_title[id]); 589 590 c = 0; 591 iov[c].iov_base = proto; 592 iov[c++].iov_len = sizeof(*proto); 593 594 if (proto->style != NULL) { 595 iov[c].iov_base = proto->style; 596 iov[c++].iov_len = strlen(proto->style); 597 } 598 599 /* XXX struct protocol should be split */ 600 proc_composev_imsg(ps, id, -1, IMSG_CFG_PROTO, -1, iov, c); 601 602 /* Now send all the protocol key/value nodes */ 603 if (config_setprotonode(env, id, proto, 604 RELAY_DIR_REQUEST) == -1 || 605 config_setprotonode(env, id, proto, 606 RELAY_DIR_RESPONSE) == -1) 607 return (-1); 608 } 609 610 return (0); 611 } 612 613 int 614 config_getproto(struct relayd *env, struct imsg *imsg) 615 { 616 struct protocol *proto; 617 size_t styl; 618 size_t s; 619 u_int8_t *p = imsg->data; 620 621 if ((proto = calloc(1, sizeof(*proto))) == NULL) 622 return (-1); 623 624 IMSG_SIZE_CHECK(imsg, proto); 625 memcpy(proto, p, sizeof(*proto)); 626 s = sizeof(*proto); 627 628 styl = IMSG_DATA_SIZE(imsg) - s; 629 if (styl > 0) { 630 if ((proto->style = get_string(p + s, styl)) == NULL) { 631 free(proto); 632 return (-1); 633 } 634 } 635 636 proto->request_nodes = 0; 637 proto->response_nodes = 0; 638 RB_INIT(&proto->request_tree); 639 RB_INIT(&proto->response_tree); 640 641 TAILQ_INSERT_TAIL(env->sc_protos, proto, entry); 642 643 env->sc_protocount++; 644 645 DPRINTF("%s: %s %d received protocol %s", __func__, 646 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 647 proto->name); 648 649 return (0); 650 } 651 652 int 653 config_setprotonode(struct relayd *env, enum privsep_procid id, 654 struct protocol *proto, enum direction dir) 655 { 656 struct privsep *ps = env->sc_ps; 657 struct iovec iov[IOV_MAX]; 658 size_t c, sz; 659 struct protonode *proot, *pn; 660 struct proto_tree *tree; 661 662 if (dir == RELAY_DIR_RESPONSE) 663 tree = &proto->response_tree; 664 else 665 tree = &proto->request_tree; 666 667 sz = c = 0; 668 RB_FOREACH(proot, proto_tree, tree) { 669 PROTONODE_FOREACH(pn, proot, entry) { 670 pn->conf.protoid = proto->id; 671 pn->conf.dir = dir; 672 pn->conf.keylen = pn->key ? strlen(pn->key) : 0; 673 pn->conf.valuelen = pn->value ? strlen(pn->value) : 0; 674 pn->conf.len = sizeof(*pn) + 675 pn->conf.keylen + pn->conf.valuelen; 676 677 if (pn->conf.len > (MAX_IMSGSIZE - IMSG_HEADER_SIZE)) 678 return (-1); 679 680 if (c && ((c + 3) >= IOV_MAX || (sz + pn->conf.len) > 681 (MAX_IMSGSIZE - IMSG_HEADER_SIZE))) { 682 proc_composev_imsg(ps, id, -1, 683 IMSG_CFG_PROTONODE, -1, iov, c); 684 c = sz = 0; 685 } 686 687 iov[c].iov_base = pn; 688 iov[c++].iov_len = sizeof(*pn); 689 if (pn->conf.keylen) { 690 iov[c].iov_base = pn->key; 691 iov[c++].iov_len = pn->conf.keylen; 692 } 693 if (pn->conf.valuelen) { 694 iov[c].iov_base = pn->value; 695 iov[c++].iov_len = pn->conf.valuelen; 696 } 697 sz += pn->conf.len; 698 } 699 } 700 701 if (c && sz) 702 proc_composev_imsg(ps, id, -1, IMSG_CFG_PROTONODE, -1, iov, c); 703 704 return (0); 705 } 706 707 int 708 config_getprotonode(struct relayd *env, struct imsg *imsg) 709 { 710 struct protocol *proto = NULL; 711 struct protonode pn; 712 size_t z, s, c = 0; 713 u_int8_t *p = imsg->data; 714 715 bzero(&pn, sizeof(pn)); 716 717 IMSG_SIZE_CHECK(imsg, &pn); 718 for (z = 0; z < (IMSG_DATA_SIZE(imsg) - sizeof(pn)); z += pn.conf.len) { 719 s = z; 720 memcpy(&pn, p + s, sizeof(pn)); 721 s += sizeof(pn); 722 723 if ((proto = proto_find(env, pn.conf.protoid)) == NULL) { 724 log_debug("%s: unknown protocol %d", __func__, 725 pn.conf.protoid); 726 return (-1); 727 } 728 729 pn.key = pn.value = NULL; 730 bzero(&pn.entry, sizeof(pn.entry)); 731 bzero(&pn.nodes, sizeof(pn.nodes)); 732 bzero(&pn.head, sizeof(pn.head)); 733 734 if (pn.conf.keylen) { 735 if ((pn.key = get_string(p + s, 736 pn.conf.keylen)) == NULL) { 737 log_debug("%s: failed to get key", __func__); 738 return (-1); 739 } 740 s += pn.conf.keylen; 741 } 742 if (pn.conf.valuelen) { 743 if ((pn.value = get_string(p + s, 744 pn.conf.valuelen)) == NULL) { 745 log_debug("%s: failed to get value", __func__); 746 if (pn.key != NULL) 747 free(pn.key); 748 return (-1); 749 } 750 s += pn.conf.valuelen; 751 } 752 753 if (protonode_add(pn.conf.dir, proto, &pn) == -1) { 754 if (pn.key != NULL) 755 free(pn.key); 756 if (pn.value != NULL) 757 free(pn.value); 758 log_debug("%s: failed to add protocol node", __func__); 759 return (-1); 760 } 761 c++; 762 } 763 764 if (!c) 765 return (0); 766 767 DPRINTF("%s: %s %d received %d nodes for protocol %s", __func__, 768 env->sc_ps->ps_title[privsep_process], env->sc_ps->ps_instance, 769 c, proto->name); 770 771 return (0); 772 } 773 774 int 775 config_setrelay(struct relayd *env, struct relay *rlay) 776 { 777 struct privsep *ps = env->sc_ps; 778 int id; 779 int fd, n, m; 780 struct iovec iov[4]; 781 size_t c; 782 783 /* opens listening sockets etc. */ 784 if (relay_privinit(rlay) == -1) 785 return (-1); 786 787 for (id = 0; id < PROC_MAX; id++) { 788 if ((ps->ps_what[id] & CONFIG_RELAYS) == 0 || 789 id == privsep_process) 790 continue; 791 792 DPRINTF("%s: sending relay %s to %s fd %d", __func__, 793 rlay->rl_conf.name, ps->ps_title[id], rlay->rl_s); 794 795 c = 0; 796 iov[c].iov_base = &rlay->rl_conf; 797 iov[c++].iov_len = sizeof(rlay->rl_conf); 798 if (rlay->rl_conf.ssl_cert_len) { 799 iov[c].iov_base = rlay->rl_ssl_cert; 800 iov[c++].iov_len = rlay->rl_conf.ssl_cert_len; 801 } 802 if (rlay->rl_conf.ssl_key_len) { 803 iov[c].iov_base = rlay->rl_ssl_key; 804 iov[c++].iov_len = rlay->rl_conf.ssl_key_len; 805 } 806 if (rlay->rl_conf.ssl_ca_len) { 807 iov[c].iov_base = rlay->rl_ssl_ca; 808 iov[c++].iov_len = rlay->rl_conf.ssl_ca_len; 809 } 810 811 if (id == PROC_RELAY) { 812 /* XXX imsg code will close the fd after 1st call */ 813 n = -1; 814 proc_range(ps, id, &n, &m); 815 for (n = 0; n < m; n++) { 816 if ((fd = dup(rlay->rl_s)) == -1) 817 return (-1); 818 proc_composev_imsg(ps, id, n, 819 IMSG_CFG_RELAY, fd, iov, c); 820 } 821 } else { 822 proc_composev_imsg(ps, id, -1, IMSG_CFG_RELAY, -1, 823 iov, c); 824 } 825 } 826 827 close(rlay->rl_s); 828 rlay->rl_s = -1; 829 830 return (0); 831 } 832 833 int 834 config_getrelay(struct relayd *env, struct imsg *imsg) 835 { 836 struct privsep *ps = env->sc_ps; 837 struct relay *rlay; 838 u_int8_t *p = imsg->data; 839 size_t s; 840 841 if ((rlay = calloc(1, sizeof(*rlay))) == NULL) 842 return (-1); 843 844 IMSG_SIZE_CHECK(imsg, &rlay->rl_conf); 845 memcpy(&rlay->rl_conf, p, sizeof(rlay->rl_conf)); 846 s = sizeof(rlay->rl_conf); 847 848 rlay->rl_s = imsg->fd; 849 850 if (ps->ps_what[privsep_process] & CONFIG_PROTOS) { 851 if (rlay->rl_conf.proto == EMPTY_ID) 852 rlay->rl_proto = &env->sc_proto_default; 853 else if ((rlay->rl_proto = 854 proto_find(env, rlay->rl_conf.proto)) == NULL) { 855 log_debug("%s: unknown protocol", __func__); 856 goto fail; 857 } 858 } 859 860 if (rlay->rl_conf.dsttable != EMPTY_ID && 861 (rlay->rl_dsttable = table_find(env, 862 rlay->rl_conf.dsttable)) == NULL) { 863 log_debug("%s: unknown table", __func__); 864 goto fail; 865 } 866 867 rlay->rl_backuptable = &env->sc_empty_table; 868 if (rlay->rl_conf.backuptable != EMPTY_ID && 869 (rlay->rl_backuptable = table_find(env, 870 rlay->rl_conf.backuptable)) == NULL) { 871 log_debug("%s: unknown backup table", __func__); 872 goto fail; 873 } 874 875 if ((u_int)(IMSG_DATA_SIZE(imsg) - s) < 876 (rlay->rl_conf.ssl_cert_len + 877 rlay->rl_conf.ssl_key_len + 878 rlay->rl_conf.ssl_ca_len)) { 879 log_debug("%s: invalid message length", __func__); 880 goto fail; 881 } 882 883 if (rlay->rl_conf.ssl_cert_len) { 884 if ((rlay->rl_ssl_cert = get_data(p + s, 885 rlay->rl_conf.ssl_cert_len)) == NULL) 886 goto fail; 887 s += rlay->rl_conf.ssl_cert_len; 888 } 889 if (rlay->rl_conf.ssl_key_len) { 890 if ((rlay->rl_ssl_key = get_data(p + s, 891 rlay->rl_conf.ssl_key_len)) == NULL) 892 goto fail; 893 s += rlay->rl_conf.ssl_key_len; 894 } 895 if (rlay->rl_conf.ssl_ca_len) { 896 if ((rlay->rl_ssl_ca = get_data(p + s, 897 rlay->rl_conf.ssl_ca_len)) == NULL) 898 goto fail; 899 s += rlay->rl_conf.ssl_ca_len; 900 } 901 902 TAILQ_INSERT_TAIL(env->sc_relays, rlay, rl_entry); 903 904 env->sc_relaycount++; 905 906 DPRINTF("%s: %s %d received relay %s", __func__, 907 ps->ps_title[privsep_process], ps->ps_instance, 908 rlay->rl_conf.name); 909 910 return (0); 911 912 fail: 913 if (rlay->rl_ssl_cert) 914 free(rlay->rl_ssl_cert); 915 if (rlay->rl_ssl_key) 916 free(rlay->rl_ssl_key); 917 if (rlay->rl_ssl_ca) 918 free(rlay->rl_ssl_ca); 919 close(rlay->rl_s); 920 free(rlay); 921 return (-1); 922 } 923