1*adf98c11Spyr /* $OpenBSD: hce.c,v 1.26 2007/06/07 07:19:50 pyr Exp $ */ 2feb9ff76Sreyk 3feb9ff76Sreyk /* 4feb9ff76Sreyk * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> 5feb9ff76Sreyk * 6feb9ff76Sreyk * Permission to use, copy, modify, and distribute this software for any 7feb9ff76Sreyk * purpose with or without fee is hereby granted, provided that the above 8feb9ff76Sreyk * copyright notice and this permission notice appear in all copies. 9feb9ff76Sreyk * 10feb9ff76Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11feb9ff76Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12feb9ff76Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13feb9ff76Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14feb9ff76Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15feb9ff76Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16feb9ff76Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17feb9ff76Sreyk */ 18feb9ff76Sreyk 19feb9ff76Sreyk #include <sys/queue.h> 20feb9ff76Sreyk #include <sys/param.h> 21feb9ff76Sreyk #include <sys/types.h> 22feb9ff76Sreyk #include <sys/time.h> 23feb9ff76Sreyk #include <sys/stat.h> 24feb9ff76Sreyk #include <sys/socket.h> 25feb9ff76Sreyk #include <sys/un.h> 26feb9ff76Sreyk #include <netinet/in_systm.h> 27feb9ff76Sreyk #include <netinet/in.h> 28feb9ff76Sreyk #include <netinet/ip.h> 29feb9ff76Sreyk #include <net/if.h> 30feb9ff76Sreyk #include <errno.h> 31feb9ff76Sreyk #include <event.h> 32feb9ff76Sreyk #include <fcntl.h> 33feb9ff76Sreyk #include <stdlib.h> 34feb9ff76Sreyk #include <string.h> 35feb9ff76Sreyk #include <unistd.h> 36feb9ff76Sreyk #include <err.h> 37feb9ff76Sreyk #include <pwd.h> 38feb9ff76Sreyk 39e8fb3979Spyr #include <openssl/ssl.h> 40e8fb3979Spyr 41ee9f3836Sderaadt #include "hoststated.h" 42feb9ff76Sreyk 43feb9ff76Sreyk void hce_sig_handler(int sig, short, void *); 44feb9ff76Sreyk void hce_shutdown(void); 45feb9ff76Sreyk void hce_dispatch_imsg(int, short, void *); 46feb9ff76Sreyk void hce_dispatch_parent(int, short, void *); 47feb9ff76Sreyk void hce_launch_checks(int, short, void *); 48641b8bafSpyr void hce_setup_events(void); 49641b8bafSpyr void hce_disable_events(void); 50feb9ff76Sreyk 518f79868bSpyr static struct hoststated *env = NULL; 52feb9ff76Sreyk struct imsgbuf *ibuf_pfe; 53feb9ff76Sreyk struct imsgbuf *ibuf_main; 54780e8f79Spyr int pipe_pfe; 55780e8f79Spyr int pipe_parent; 56780e8f79Spyr int running = 0; 57feb9ff76Sreyk 58feb9ff76Sreyk void 59feb9ff76Sreyk hce_sig_handler(int sig, short event, void *arg) 60feb9ff76Sreyk { 61feb9ff76Sreyk switch (sig) { 62feb9ff76Sreyk case SIGINT: 63feb9ff76Sreyk case SIGTERM: 64feb9ff76Sreyk hce_shutdown(); 65780e8f79Spyr break; 66780e8f79Spyr case SIGHUP: 67*adf98c11Spyr /* nothing */ 68780e8f79Spyr break; 69feb9ff76Sreyk default: 70feb9ff76Sreyk fatalx("hce_sig_handler: unexpected signal"); 71feb9ff76Sreyk } 72feb9ff76Sreyk } 73feb9ff76Sreyk 74feb9ff76Sreyk pid_t 758f79868bSpyr hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2], 76053249cdSpyr int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2], 772edd718bSreyk int pipe_pfe2relay[RELAY_MAXPROC][2]) 78feb9ff76Sreyk { 79feb9ff76Sreyk pid_t pid; 80feb9ff76Sreyk struct passwd *pw; 812edd718bSreyk int i; 82641b8bafSpyr struct event ev_sigint; 83641b8bafSpyr struct event ev_sigterm; 84*adf98c11Spyr struct event ev_sighup; 85feb9ff76Sreyk 86feb9ff76Sreyk switch (pid = fork()) { 87feb9ff76Sreyk case -1: 88feb9ff76Sreyk fatal("hce: cannot fork"); 89feb9ff76Sreyk case 0: 90feb9ff76Sreyk break; 91feb9ff76Sreyk default: 92feb9ff76Sreyk return (pid); 93feb9ff76Sreyk } 94feb9ff76Sreyk 95feb9ff76Sreyk env = x_env; 9679446c9fSpyr purge_config(env, PURGE_SERVICES|PURGE_RELAYS|PURGE_PROTOS); 97feb9ff76Sreyk 988f79868bSpyr if ((pw = getpwnam(HOSTSTATED_USER)) == NULL) 99feb9ff76Sreyk fatal("hce: getpwnam"); 100feb9ff76Sreyk 101*adf98c11Spyr #ifndef DEBUG 102feb9ff76Sreyk if (chroot(pw->pw_dir) == -1) 103feb9ff76Sreyk fatal("hce: chroot"); 104feb9ff76Sreyk if (chdir("/") == -1) 105feb9ff76Sreyk fatal("hce: chdir(\"/\")"); 106*adf98c11Spyr #else 107*adf98c11Spyr #warning disabling privilege revocation and chroot in DEBUG mode 108*adf98c11Spyr #endif 109feb9ff76Sreyk 110feb9ff76Sreyk setproctitle("host check engine"); 1118f79868bSpyr hoststated_process = PROC_HCE; 112feb9ff76Sreyk 11301d85ec5Sreyk /* this is needed for icmp tests */ 11401d85ec5Sreyk icmp_init(env); 11501d85ec5Sreyk 116*adf98c11Spyr #ifndef DEBUG 117feb9ff76Sreyk if (setgroups(1, &pw->pw_gid) || 118feb9ff76Sreyk setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 119feb9ff76Sreyk setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 120feb9ff76Sreyk fatal("hce: can't drop privileges"); 121*adf98c11Spyr #endif 122feb9ff76Sreyk 123641b8bafSpyr event_init(); 124feb9ff76Sreyk 125641b8bafSpyr if ((ibuf_pfe = calloc(1, sizeof(struct imsgbuf))) == NULL || 126641b8bafSpyr (ibuf_main = calloc(1, sizeof(struct imsgbuf))) == NULL) 127641b8bafSpyr fatal("hce"); 128641b8bafSpyr imsg_init(ibuf_pfe, pipe_pfe2hce[0], hce_dispatch_imsg); 129641b8bafSpyr imsg_init(ibuf_main, pipe_parent2hce[1], hce_dispatch_parent); 130641b8bafSpyr 131641b8bafSpyr ibuf_pfe->events = EV_READ; 132641b8bafSpyr event_set(&ibuf_pfe->ev, ibuf_pfe->fd, ibuf_pfe->events, 133641b8bafSpyr ibuf_pfe->handler, ibuf_pfe); 134641b8bafSpyr event_add(&ibuf_pfe->ev, NULL); 135641b8bafSpyr 136641b8bafSpyr ibuf_main->events = EV_READ; 137641b8bafSpyr event_set(&ibuf_main->ev, ibuf_main->fd, ibuf_main->events, 138641b8bafSpyr ibuf_main->handler, ibuf_main); 139641b8bafSpyr event_add(&ibuf_main->ev, NULL); 140641b8bafSpyr 141641b8bafSpyr signal_set(&ev_sigint, SIGINT, hce_sig_handler, NULL); 142641b8bafSpyr signal_set(&ev_sigterm, SIGTERM, hce_sig_handler, NULL); 143*adf98c11Spyr signal_set(&ev_sighup, SIGHUP, hce_sig_handler, NULL); 144641b8bafSpyr signal_add(&ev_sigint, NULL); 145641b8bafSpyr signal_add(&ev_sigterm, NULL); 146*adf98c11Spyr signal_add(&ev_sighup, NULL); 147641b8bafSpyr signal(SIGPIPE, SIG_IGN); 148feb9ff76Sreyk 149feb9ff76Sreyk /* setup pipes */ 150feb9ff76Sreyk close(pipe_pfe2hce[1]); 151feb9ff76Sreyk close(pipe_parent2hce[0]); 152feb9ff76Sreyk close(pipe_parent2pfe[0]); 153feb9ff76Sreyk close(pipe_parent2pfe[1]); 1542edd718bSreyk for (i = 0; i < env->prefork_relay; i++) { 155053249cdSpyr close(pipe_parent2relay[i][0]); 156053249cdSpyr close(pipe_parent2relay[i][1]); 1572edd718bSreyk close(pipe_pfe2relay[i][0]); 1582edd718bSreyk close(pipe_pfe2relay[i][1]); 1592edd718bSreyk } 160feb9ff76Sreyk 161641b8bafSpyr hce_setup_events(); 162641b8bafSpyr event_dispatch(); 163780e8f79Spyr hce_shutdown(); 164780e8f79Spyr 165780e8f79Spyr return (0); 166780e8f79Spyr } 167780e8f79Spyr 168780e8f79Spyr void 169641b8bafSpyr hce_setup_events(void) 170780e8f79Spyr { 171780e8f79Spyr struct timeval tv; 172780e8f79Spyr struct table *table; 173780e8f79Spyr 174780e8f79Spyr if (!TAILQ_EMPTY(env->tables)) { 17501d85ec5Sreyk evtimer_set(&env->ev, hce_launch_checks, env); 17601d85ec5Sreyk bzero(&tv, sizeof(tv)); 177feb9ff76Sreyk evtimer_add(&env->ev, &tv); 1782edd718bSreyk } 179feb9ff76Sreyk 180e8fb3979Spyr if (env->flags & F_SSL) { 181e8fb3979Spyr ssl_init(env); 182780e8f79Spyr TAILQ_FOREACH(table, env->tables, entry) { 18368b79041Spyr if (!(table->conf.flags & F_SSL)) 184e8fb3979Spyr continue; 185e8fb3979Spyr table->ssl_ctx = ssl_ctx_create(env); 186e8fb3979Spyr } 187e8fb3979Spyr } 188641b8bafSpyr } 189641b8bafSpyr 190641b8bafSpyr void 191641b8bafSpyr hce_disable_events(void) 192641b8bafSpyr { 193641b8bafSpyr struct table *table; 194641b8bafSpyr struct host *host; 195641b8bafSpyr 196641b8bafSpyr evtimer_del(&env->ev); 197641b8bafSpyr TAILQ_FOREACH(table, env->tables, entry) { 198641b8bafSpyr TAILQ_FOREACH(host, &table->hosts, entry) { 199641b8bafSpyr event_del(&host->cte.ev); 200641b8bafSpyr close(host->cte.s); 201641b8bafSpyr } 202641b8bafSpyr } 203641b8bafSpyr if (env->has_icmp) { 204641b8bafSpyr event_del(&env->icmp_send.ev); 205641b8bafSpyr event_del(&env->icmp_recv.ev); 206641b8bafSpyr } 207641b8bafSpyr if (env->has_icmp6) { 208641b8bafSpyr event_del(&env->icmp6_send.ev); 209641b8bafSpyr event_del(&env->icmp6_recv.ev); 210641b8bafSpyr } 211feb9ff76Sreyk } 212feb9ff76Sreyk 213feb9ff76Sreyk void 214feb9ff76Sreyk hce_launch_checks(int fd, short event, void *arg) 215feb9ff76Sreyk { 216feb9ff76Sreyk struct host *host; 217feb9ff76Sreyk struct table *table; 21801d85ec5Sreyk struct timeval tv; 21901d85ec5Sreyk 22001d85ec5Sreyk /* 22101d85ec5Sreyk * notify pfe checks are done and schedule next check 22201d85ec5Sreyk */ 22301d85ec5Sreyk imsg_compose(ibuf_pfe, IMSG_SYNC, 0, 0, NULL, 0); 224780e8f79Spyr TAILQ_FOREACH(table, env->tables, entry) { 22501d85ec5Sreyk TAILQ_FOREACH(host, &table->hosts, entry) { 22601d85ec5Sreyk host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE); 22701d85ec5Sreyk event_del(&host->cte.ev); 22801d85ec5Sreyk } 22901d85ec5Sreyk } 23001d85ec5Sreyk 23101d85ec5Sreyk if (gettimeofday(&tv, NULL)) 23201d85ec5Sreyk fatal("hce_launch_checks: gettimeofday"); 233feb9ff76Sreyk 234780e8f79Spyr TAILQ_FOREACH(table, env->tables, entry) { 23568b79041Spyr if (table->conf.flags & F_DISABLE) 2367e351ffdSreyk continue; 23768b79041Spyr if (table->conf.check == CHECK_NOCHECK) 2387e351ffdSreyk fatalx("hce_launch_checks: unknown check type"); 23901d85ec5Sreyk 2407e351ffdSreyk TAILQ_FOREACH(host, &table->hosts, entry) { 2417e351ffdSreyk if (host->flags & F_DISABLE) 2427e351ffdSreyk continue; 2434156152fSreyk switch (table->conf.check) { 2444156152fSreyk case CHECK_ICMP: 24501d85ec5Sreyk schedule_icmp(env, host); 2464156152fSreyk break; 2474156152fSreyk case CHECK_SCRIPT: 2484156152fSreyk check_script(host); 2494156152fSreyk break; 2504156152fSreyk default: 25101d85ec5Sreyk /* Any other TCP-style checks */ 2527e351ffdSreyk bzero(&host->cte, sizeof(host->cte)); 2537e351ffdSreyk host->last_up = host->up; 2547e351ffdSreyk host->cte.host = host; 2557e351ffdSreyk host->cte.table = table; 25601d85ec5Sreyk bcopy(&tv, &host->cte.tv_start, 25701d85ec5Sreyk sizeof(host->cte.tv_start)); 2587e351ffdSreyk check_tcp(&host->cte); 2594156152fSreyk break; 2604156152fSreyk } 2617e351ffdSreyk } 2627e351ffdSreyk } 26301d85ec5Sreyk check_icmp(env, &tv); 26401d85ec5Sreyk 26501d85ec5Sreyk bcopy(&env->interval, &tv, sizeof(tv)); 26601d85ec5Sreyk evtimer_add(&env->ev, &tv); 2677e351ffdSreyk } 2687e351ffdSreyk 2697e351ffdSreyk void 2707e351ffdSreyk hce_notify_done(struct host *host, const char *msg) 2717e351ffdSreyk { 272609cf3a7Sreyk struct table *table; 2737e351ffdSreyk struct ctl_status st; 274609cf3a7Sreyk struct timeval tv_now, tv_dur; 275609cf3a7Sreyk u_long duration; 276609cf3a7Sreyk u_int logopt; 2777e351ffdSreyk 2782edd718bSreyk if (host->up == HOST_DOWN && host->retry_cnt) { 2792edd718bSreyk log_debug("hce_notify_done: host %s retry %d", 28068b79041Spyr host->conf.name, host->retry_cnt); 281bd2508bcSreyk host->up = host->last_up; 2822edd718bSreyk host->retry_cnt--; 2832edd718bSreyk } else 28468b79041Spyr host->retry_cnt = host->conf.retry; 2852edd718bSreyk if (host->up != HOST_UNKNOWN) { 2862edd718bSreyk host->check_cnt++; 2872edd718bSreyk if (host->up == HOST_UP) 2882edd718bSreyk host->up_cnt++; 2892edd718bSreyk } 29068b79041Spyr st.id = host->conf.id; 291feb9ff76Sreyk st.up = host->up; 2922edd718bSreyk st.check_cnt = host->check_cnt; 2932edd718bSreyk st.retry_cnt = host->retry_cnt; 29401d85ec5Sreyk host->flags |= (F_CHECK_SENT|F_CHECK_DONE); 2957e351ffdSreyk if (msg) 29668b79041Spyr log_debug("hce_notify_done: %s (%s)", host->conf.name, msg); 297609cf3a7Sreyk 2987e351ffdSreyk imsg_compose(ibuf_pfe, IMSG_HOST_STATUS, 0, 0, &st, sizeof(st)); 2992edd718bSreyk if (host->up != host->last_up) 3002edd718bSreyk logopt = HOSTSTATED_OPT_LOGUPDATE; 3012edd718bSreyk else 302609cf3a7Sreyk logopt = HOSTSTATED_OPT_LOGNOTIFY; 303609cf3a7Sreyk 304609cf3a7Sreyk if (gettimeofday(&tv_now, NULL)) 305609cf3a7Sreyk fatal("hce_notify_done: gettimeofday"); 306609cf3a7Sreyk timersub(&tv_now, &host->cte.tv_start, &tv_dur); 307609cf3a7Sreyk if (timercmp(&host->cte.tv_start, &tv_dur, >)) 308609cf3a7Sreyk duration = (tv_dur.tv_sec * 1000) + (tv_dur.tv_usec / 1000.0); 309609cf3a7Sreyk else 310609cf3a7Sreyk duration = 0; 311609cf3a7Sreyk 31268b79041Spyr if ((table = table_find(env, host->conf.tableid)) == NULL) 3132edd718bSreyk fatalx("hce_notify_done: invalid table id"); 3142edd718bSreyk 315609cf3a7Sreyk if (env->opts & logopt) { 3162edd718bSreyk log_info("host %s, check %s%s (%lums), state %s -> %s, " 3172edd718bSreyk "availability %s", 31868b79041Spyr host->conf.name, table_check(table->conf.check), 31968b79041Spyr (table->conf.flags & F_SSL) ? " use ssl" : "", duration, 3202edd718bSreyk host_status(host->last_up), host_status(host->up), 3212edd718bSreyk print_availability(host->check_cnt, host->up_cnt)); 322feb9ff76Sreyk } 323609cf3a7Sreyk host->last_up = host->up; 324feb9ff76Sreyk } 325feb9ff76Sreyk 326feb9ff76Sreyk void 327feb9ff76Sreyk hce_shutdown(void) 328feb9ff76Sreyk { 329feb9ff76Sreyk log_info("host check engine exiting"); 330feb9ff76Sreyk _exit(0); 331feb9ff76Sreyk } 332feb9ff76Sreyk 333feb9ff76Sreyk void 334feb9ff76Sreyk hce_dispatch_imsg(int fd, short event, void *ptr) 335feb9ff76Sreyk { 336feb9ff76Sreyk struct imsgbuf *ibuf; 337feb9ff76Sreyk struct imsg imsg; 338feb9ff76Sreyk ssize_t n; 339feb9ff76Sreyk objid_t id; 340feb9ff76Sreyk struct host *host; 341feb9ff76Sreyk struct table *table; 342feb9ff76Sreyk 343feb9ff76Sreyk ibuf = ptr; 344feb9ff76Sreyk switch (event) { 345feb9ff76Sreyk case EV_READ: 346feb9ff76Sreyk if ((n = imsg_read(ibuf)) == -1) 347feb9ff76Sreyk fatal("hce_dispatch_imsg: imsg_read_error"); 348feb9ff76Sreyk if (n == 0) 349feb9ff76Sreyk fatalx("hce_dispatch_imsg: pipe closed"); 350feb9ff76Sreyk break; 351feb9ff76Sreyk case EV_WRITE: 352feb9ff76Sreyk if (msgbuf_write(&ibuf->w) == -1) 353feb9ff76Sreyk fatal("hce_dispatch_imsg: msgbuf_write"); 354feb9ff76Sreyk imsg_event_add(ibuf); 355feb9ff76Sreyk return; 356feb9ff76Sreyk default: 357feb9ff76Sreyk fatalx("hce_dispatch_imsg: unknown event"); 358feb9ff76Sreyk } 359feb9ff76Sreyk 360feb9ff76Sreyk for (;;) { 361feb9ff76Sreyk if ((n = imsg_get(ibuf, &imsg)) == -1) 362feb9ff76Sreyk fatal("hce_dispatch_imsg: imsg_read error"); 363feb9ff76Sreyk if (n == 0) 364feb9ff76Sreyk break; 365feb9ff76Sreyk 366feb9ff76Sreyk switch (imsg.hdr.type) { 367feb9ff76Sreyk case IMSG_HOST_DISABLE: 368feb9ff76Sreyk memcpy(&id, imsg.data, sizeof(id)); 369feb9ff76Sreyk if ((host = host_find(env, id)) == NULL) 370feb9ff76Sreyk fatalx("hce_dispatch_imsg: desynchronized"); 371feb9ff76Sreyk host->flags |= F_DISABLE; 372feb9ff76Sreyk host->up = HOST_UNKNOWN; 3732edd718bSreyk host->check_cnt = 0; 3742edd718bSreyk host->up_cnt = 0; 375feb9ff76Sreyk break; 376feb9ff76Sreyk case IMSG_HOST_ENABLE: 377feb9ff76Sreyk memcpy(&id, imsg.data, sizeof(id)); 378feb9ff76Sreyk if ((host = host_find(env, id)) == NULL) 379feb9ff76Sreyk fatalx("hce_dispatch_imsg: desynchronized"); 380feb9ff76Sreyk host->flags &= ~(F_DISABLE); 381feb9ff76Sreyk host->up = HOST_UNKNOWN; 382feb9ff76Sreyk break; 383feb9ff76Sreyk case IMSG_TABLE_DISABLE: 384feb9ff76Sreyk memcpy(&id, imsg.data, sizeof(id)); 385feb9ff76Sreyk if ((table = table_find(env, id)) == NULL) 386feb9ff76Sreyk fatalx("hce_dispatch_imsg: desynchronized"); 38768b79041Spyr table->conf.flags |= F_DISABLE; 388feb9ff76Sreyk TAILQ_FOREACH(host, &table->hosts, entry) 389feb9ff76Sreyk host->up = HOST_UNKNOWN; 390feb9ff76Sreyk break; 391feb9ff76Sreyk case IMSG_TABLE_ENABLE: 392feb9ff76Sreyk memcpy(&id, imsg.data, sizeof(id)); 393feb9ff76Sreyk if ((table = table_find(env, id)) == NULL) 394feb9ff76Sreyk fatalx("hce_dispatch_imsg: desynchronized"); 39568b79041Spyr table->conf.flags &= ~(F_DISABLE); 396feb9ff76Sreyk TAILQ_FOREACH(host, &table->hosts, entry) 397feb9ff76Sreyk host->up = HOST_UNKNOWN; 398feb9ff76Sreyk break; 399feb9ff76Sreyk default: 400feb9ff76Sreyk log_debug("hce_dispatch_msg: unexpected imsg %d", 401feb9ff76Sreyk imsg.hdr.type); 402feb9ff76Sreyk break; 403feb9ff76Sreyk } 404feb9ff76Sreyk imsg_free(&imsg); 405feb9ff76Sreyk } 406feb9ff76Sreyk imsg_event_add(ibuf); 407feb9ff76Sreyk } 408feb9ff76Sreyk 409feb9ff76Sreyk void 410feb9ff76Sreyk hce_dispatch_parent(int fd, short event, void * ptr) 411feb9ff76Sreyk { 412feb9ff76Sreyk struct imsgbuf *ibuf; 413feb9ff76Sreyk struct imsg imsg; 4144156152fSreyk struct ctl_script scr; 415feb9ff76Sreyk ssize_t n; 416*adf98c11Spyr size_t len; 417*adf98c11Spyr 418*adf98c11Spyr static struct table *table = NULL; 419*adf98c11Spyr struct host *host; 420feb9ff76Sreyk 421feb9ff76Sreyk ibuf = ptr; 422feb9ff76Sreyk switch (event) { 423feb9ff76Sreyk case EV_READ: 424feb9ff76Sreyk if ((n = imsg_read(ibuf)) == -1) 425feb9ff76Sreyk fatal("hce_dispatch_parent: imsg_read error"); 4262edd718bSreyk if (n == 0) 427feb9ff76Sreyk fatalx("hce_dispatch_parent: pipe closed"); 428feb9ff76Sreyk break; 429feb9ff76Sreyk case EV_WRITE: 430feb9ff76Sreyk if (msgbuf_write(&ibuf->w) == -1) 431feb9ff76Sreyk fatal("hce_dispatch_parent: msgbuf_write"); 432feb9ff76Sreyk imsg_event_add(ibuf); 433feb9ff76Sreyk return; 434feb9ff76Sreyk default: 435feb9ff76Sreyk fatalx("hce_dispatch_parent: unknown event"); 436feb9ff76Sreyk } 437feb9ff76Sreyk 438feb9ff76Sreyk for (;;) { 439feb9ff76Sreyk if ((n = imsg_get(ibuf, &imsg)) == -1) 440feb9ff76Sreyk fatal("hce_dispatch_parent: imsg_read error"); 441feb9ff76Sreyk if (n == 0) 442feb9ff76Sreyk break; 443feb9ff76Sreyk 444feb9ff76Sreyk switch (imsg.hdr.type) { 4454156152fSreyk case IMSG_SCRIPT: 4464156152fSreyk if (imsg.hdr.len - IMSG_HEADER_SIZE != 4474156152fSreyk sizeof(scr)) 4484156152fSreyk fatalx("hce_dispatch_parent: " 4494156152fSreyk "invalid size of script request"); 4504156152fSreyk bcopy(imsg.data, &scr, sizeof(scr)); 4514156152fSreyk script_done(env, &scr); 4524156152fSreyk break; 453*adf98c11Spyr case IMSG_RECONF: 454*adf98c11Spyr log_debug("hce: reloading configuration"); 455*adf98c11Spyr if (imsg.hdr.len != 456*adf98c11Spyr sizeof(struct hoststated) + IMSG_HEADER_SIZE) 457*adf98c11Spyr fatalx("corrupted reload data"); 458*adf98c11Spyr hce_disable_events(); 459*adf98c11Spyr purge_config(env, PURGE_TABLES); 460*adf98c11Spyr merge_config(env, (struct hoststated *)imsg.data); 461*adf98c11Spyr 462*adf98c11Spyr env->tables = calloc(1, sizeof(*env->tables)); 463*adf98c11Spyr if (env->tables == NULL) 464*adf98c11Spyr fatal(NULL); 465*adf98c11Spyr 466*adf98c11Spyr TAILQ_INIT(env->tables); 467*adf98c11Spyr break; 468*adf98c11Spyr case IMSG_RECONF_TABLE: 469*adf98c11Spyr if ((table = calloc(1, sizeof(*table))) == NULL) 470*adf98c11Spyr fatal(NULL); 471*adf98c11Spyr memcpy(&table->conf, imsg.data, sizeof(table->conf)); 472*adf98c11Spyr TAILQ_INIT(&table->hosts); 473*adf98c11Spyr TAILQ_INSERT_TAIL(env->tables, table, entry); 474*adf98c11Spyr break; 475*adf98c11Spyr case IMSG_RECONF_SENDBUF: 476*adf98c11Spyr len = imsg.hdr.len - IMSG_HEADER_SIZE; 477*adf98c11Spyr table->sendbuf = calloc(1, len); 478*adf98c11Spyr (void)strlcpy(table->sendbuf, (char *)imsg.data, len); 479*adf98c11Spyr break; 480*adf98c11Spyr case IMSG_RECONF_HOST: 481*adf98c11Spyr if ((host = calloc(1, sizeof(*host))) == NULL) 482*adf98c11Spyr fatal(NULL); 483*adf98c11Spyr memcpy(&host->conf, imsg.data, sizeof(host->conf)); 484*adf98c11Spyr host->tablename = table->conf.name; 485*adf98c11Spyr TAILQ_INSERT_TAIL(&table->hosts, host, entry); 486*adf98c11Spyr break; 487*adf98c11Spyr case IMSG_RECONF_END: 488*adf98c11Spyr log_warnx("hce: configuration reloaded"); 489*adf98c11Spyr hce_setup_events(); 490*adf98c11Spyr break; 491feb9ff76Sreyk default: 492feb9ff76Sreyk log_debug("hce_dispatch_parent: unexpected imsg %d", 493feb9ff76Sreyk imsg.hdr.type); 494feb9ff76Sreyk break; 495feb9ff76Sreyk } 496feb9ff76Sreyk imsg_free(&imsg); 497feb9ff76Sreyk } 4984156152fSreyk imsg_event_add(ibuf); 499feb9ff76Sreyk } 500