void control_close(int fd, struct control_sock *cs) { struct ctl_conn *c; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_close: fd %d: not found", fd); return; } msgbuf_clear(&c->iev.ibuf.w); TAILQ_REMOVE(&ctl_conns, c, entry); event_del(&c->iev.ev); close(c->iev.ibuf.fd); /* Some file descriptors are available again. */ if (evtimer_pending(&cs->cs_evt, NULL)) { evtimer_del(&cs->cs_evt); event_add(&cs->cs_ev, NULL); } npppd_ctl_destroy(c->ctx); free(c); }
void control_close(int fd) { struct ctl_conn *c; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_close: fd %d: not found", fd); return; } msgbuf_clear(&c->iev.ibuf.w); TAILQ_REMOVE(&ctl_conns, c, entry); event_del(&c->iev.ev); close(c->iev.ibuf.fd); free(c); accept_unpause(); }
static void control_imsg(struct imsgev *iev, struct imsg *imsg) { struct ctl_conn *c; char *key; struct stat_value val; if (iev->proc == PROC_SMTP) { switch (imsg->hdr.type) { case IMSG_SMTP_ENQUEUE: c = control_connbyfd(imsg->hdr.peerid); if (c == NULL) return; imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, imsg->fd, NULL, 0); return; } } switch (imsg->hdr.type) { case IMSG_STAT_INCREMENT: memmove(&val, imsg->data, sizeof (val)); key = (char*)imsg->data + sizeof (val); if (stat_backend) stat_backend->increment(key, val.u.counter); return; case IMSG_STAT_DECREMENT: memmove(&val, imsg->data, sizeof (val)); key = (char*)imsg->data + sizeof (val); if (stat_backend) stat_backend->decrement(key, val.u.counter); return; case IMSG_STAT_SET: memmove(&val, imsg->data, sizeof (val)); key = (char*)imsg->data + sizeof (val); if (stat_backend) stat_backend->set(key, &val); return; } errx(1, "control_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); }
void control_close(int fd) { struct ctl_conn *c; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_close: fd %d: not found", fd); return; } TAILQ_REMOVE(&ctl_conns, c, entry); event_del(&c->iev.ev); imsg_clear(&c->iev.ibuf); close(fd); free(c); if (stat_decrement(STATS_CONTROL_SESSION) < env->sc_maxconn && !event_pending(&control_state.ev, EV_READ, NULL)) { log_warnx("re-enabling ctl connections"); event_add(&control_state.ev, NULL); } }
void control_imsg(struct imsgev *iev, struct imsg *imsg) { struct ctl_conn *c; log_imsg(PROC_CONTROL, iev->proc, imsg); if (iev->proc == PROC_SMTP) { switch (imsg->hdr.type) { case IMSG_SMTP_ENQUEUE: c = control_connbyfd(imsg->hdr.peerid); if (c == NULL) return; imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, imsg->fd, NULL, 0); return; } } errx(1, "control_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); }
void control_close(int fd) { struct ctl_conn *c; if ((c = control_connbyfd(fd)) == NULL) { log_warnx("%s: fd %d: not found", __func__, fd); return; } msgbuf_clear(&c->iev.ibuf.w); TAILQ_REMOVE(&ctl_conns, c, entry); event_del(&c->iev.ev); close(c->iev.ibuf.fd); /* Some file descriptors are available again. */ if (evtimer_pending(&control_state.evt, NULL)) { evtimer_del(&control_state.evt); event_add(&control_state.ev, NULL); } free(c); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *bula) { struct ctl_conn *c; struct imsg imsg; ssize_t n; unsigned int ifidx; int verbose; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_dispatch_imsg: fd %d: not found", fd); return; } if (event & EV_READ) { if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { control_close(fd); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) == -1) { control_close(fd); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd); return; } if (n == 0) break; switch (imsg.hdr.type) { case IMSG_CTL_FIB_COUPLE: case IMSG_CTL_FIB_DECOUPLE: ospfe_fib_update(imsg.hdr.type); /* FALLTHROUGH */ case IMSG_CTL_FIB_RELOAD: case IMSG_CTL_RELOAD: c->iev.ibuf.pid = imsg.hdr.pid; ospfe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0); break; case IMSG_CTL_KROUTE: case IMSG_CTL_KROUTE_ADDR: case IMSG_CTL_IFINFO: c->iev.ibuf.pid = imsg.hdr.pid; ospfe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; case IMSG_CTL_SHOW_INTERFACE: if (imsg.hdr.len == IMSG_HEADER_SIZE + sizeof(ifidx)) { memcpy(&ifidx, imsg.data, sizeof(ifidx)); ospfe_iface_ctl(c, ifidx); imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_SHOW_DATABASE: case IMSG_CTL_SHOW_DB_EXT: case IMSG_CTL_SHOW_DB_NET: case IMSG_CTL_SHOW_DB_RTR: case IMSG_CTL_SHOW_DB_SELF: case IMSG_CTL_SHOW_DB_SUM: case IMSG_CTL_SHOW_DB_ASBR: case IMSG_CTL_SHOW_DB_OPAQ: case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_SUM: c->iev.ibuf.pid = imsg.hdr.pid; ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; case IMSG_CTL_SHOW_NBR: ospfe_nbr_ctl(c); break; case IMSG_CTL_LOG_VERBOSE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(verbose)) break; /* forward to other processes */ ospfe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); break; default: log_debug("control_dispatch_imsg: " "error handling imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } imsg_event_add(&c->iev); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *arg) { struct control_sock *cs = arg; struct iked *env = cs->cs_env; struct ctl_conn *c; struct imsg imsg; int n, v; if ((c = control_connbyfd(fd)) == NULL) { log_warn("%s: fd %d: not found", __func__, fd); return; } if (event & EV_READ) { if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { control_close(fd, cs); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) <= 0 && errno != EAGAIN) { control_close(fd, cs); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd, cs); return; } if (n == 0) break; control_imsg_forward(&imsg); switch (imsg.hdr.type) { case IMSG_CTL_NOTIFY: if (c->flags & CTL_CONN_NOTIFY) { log_debug("%s: " "client requested notify more than once", __func__); imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } c->flags |= CTL_CONN_NOTIFY; break; case IMSG_CTL_VERBOSE: IMSG_SIZE_CHECK(&imsg, &v); memcpy(&v, imsg.data, sizeof(v)); log_verbose(v); proc_forward_imsg(&env->sc_ps, &imsg, PROC_PARENT, -1); proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV2, -1); proc_forward_imsg(&env->sc_ps, &imsg, PROC_IKEV1, -1); break; case IMSG_CTL_RELOAD: case IMSG_CTL_RESET: case IMSG_CTL_COUPLE: case IMSG_CTL_DECOUPLE: case IMSG_CTL_ACTIVE: case IMSG_CTL_PASSIVE: proc_forward_imsg(&env->sc_ps, &imsg, PROC_PARENT, -1); break; default: log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); break; } imsg_free(&imsg); } imsg_event_add(&c->iev); }
/* ARGSUSED */ void control_dispatch_ext(int fd, short event, void *arg) { struct ctl_conn *c; struct imsg imsg; int n; uid_t euid; gid_t egid; if (getpeereid(fd, &euid, &egid) == -1) fatal("getpeereid"); if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_dispatch_ext: fd %d: not found", fd); return; } if (event & EV_READ) { if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { control_close(fd); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) < 0) { control_close(fd); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd); return; } if (n == 0) break; switch (imsg.hdr.type) { case IMSG_SMTP_ENQUEUE: if (env->sc_flags & (SMTPD_SMTP_PAUSED | SMTPD_CONFIGURING | SMTPD_EXITING)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_ENQUEUE, fd, 0, -1, &euid, sizeof(euid)); break; case IMSG_STATS: if (euid) goto badcred; imsg_compose_event(&c->iev, IMSG_STATS, 0, 0, -1, env->stats, sizeof(struct stats)); break; case IMSG_CTL_SHUTDOWN: /* NEEDS_FIX */ log_debug("received shutdown request"); if (euid) goto badcred; if (env->sc_flags & SMTPD_EXITING) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags |= SMTPD_EXITING; imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_CTL_VERBOSE: { int verbose; if (euid) goto badcred; if (IMSG_DATA_SIZE(&imsg) != sizeof(verbose)) goto badcred; memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); imsg_compose_event(env->sc_ievs[PROC_PARENT], IMSG_CTL_VERBOSE, 0, 0, -1, &verbose, sizeof(verbose)); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; } case IMSG_QUEUE_PAUSE_MDA: if (euid) goto badcred; if (env->sc_flags & SMTPD_MDA_PAUSED) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags |= SMTPD_MDA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_PAUSE_MDA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_PAUSE_MTA: if (euid) goto badcred; if (env->sc_flags & SMTPD_MTA_PAUSED) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags |= SMTPD_MTA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_PAUSE_MTA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_SMTP_PAUSE: if (euid) goto badcred; if (env->sc_flags & SMTPD_SMTP_PAUSED) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags |= SMTPD_SMTP_PAUSED; imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_PAUSE, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_RESUME_MDA: if (euid) goto badcred; if (! (env->sc_flags & SMTPD_MDA_PAUSED)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags &= ~SMTPD_MDA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_RESUME_MDA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_RESUME_MTA: if (euid) goto badcred; if (!(env->sc_flags & SMTPD_MTA_PAUSED)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags &= ~SMTPD_MTA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_RESUME_MTA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_SMTP_RESUME: if (euid) goto badcred; if (!(env->sc_flags & SMTPD_SMTP_PAUSED)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags &= ~SMTPD_SMTP_PAUSED; imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_RUNNER_SCHEDULE: { u_int64_t ullval; if (euid) goto badcred; ullval = *(u_int64_t *)imsg.data; imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_RUNNER_SCHEDULE, 0, 0, -1, &ullval, sizeof(ullval)); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; } case IMSG_RUNNER_REMOVE: { u_int64_t ullval; if (euid) goto badcred; ullval = *(u_int64_t *)imsg.data; imsg_compose_event(env->sc_ievs[PROC_RUNNER], IMSG_RUNNER_REMOVE, 0, 0, -1, &ullval, sizeof(ullval)); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; } default: log_debug("control_dispatch_ext: " "error handling %s imsg", imsg_to_str(imsg.hdr.type)); break; } imsg_free(&imsg); continue; badcred: imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); } imsg_event_add(&c->iev); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *bula) { struct ctl_conn *c; struct imsg imsg; int n; unsigned int ifidx; int verbose; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_dispatch_imsg: fd %d: not found", fd); return; } if (event & EV_READ) { if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { control_close(fd); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) == -1 && errno != EAGAIN) { control_close(fd); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd); return; } if (n == 0) break; switch (imsg.hdr.type) { case IMSG_CTL_MFC_COUPLE: case IMSG_CTL_MFC_DECOUPLE: case IMSG_CTL_RELOAD: dvmrpe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0); break; case IMSG_CTL_SHOW_IFACE: if (imsg.hdr.len == IMSG_HEADER_SIZE + sizeof(ifidx)) { memcpy(&ifidx, imsg.data, sizeof(ifidx)); dvmrpe_iface_ctl(c, ifidx); imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_SHOW_IGMP: if (imsg.hdr.len == IMSG_HEADER_SIZE + sizeof(ifidx)) { memcpy(&ifidx, imsg.data, sizeof(ifidx)); dvmrpe_iface_igmp_ctl(c, ifidx); imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_SHOW_NBR: dvmrpe_nbr_ctl(c); break; case IMSG_CTL_SHOW_RIB: case IMSG_CTL_SHOW_MFC: case IMSG_CTL_SHOW_SUM: c->iev.ibuf.pid = imsg.hdr.pid; dvmrpe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; case IMSG_CTL_LOG_VERBOSE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(verbose)) break; /* forward to other processes */ dvmrpe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); dvmrpe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); break; default: log_debug("control_dispatch_imsg: " "error handling imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } imsg_event_add(&c->iev); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *arg) { struct control_sock *cs = (struct control_sock *)arg; struct ctl_conn *c; struct imsg imsg; int n, retval; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_dispatch_imsg: fd %d: not found", fd); return; } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) < 0) { control_close(fd, cs); return; } if (!c->iev.ibuf.w.queued) npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf); imsg_event_add(&c->iev); if (!(event & EV_READ)) return; } if (event & EV_READ) { if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { control_close(fd, cs); return; } } else fatalx("unknown event"); for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd, cs); return; } if (n == 0) break; if (cs->cs_restricted || (c->flags & CTL_CONN_LOCKED)) { switch (imsg.hdr.type) { default: log_debug("control_dispatch_imsg: " "client requested restricted command"); imsg_free(&imsg); control_close(fd, cs); return; } } switch (imsg.hdr.type) { case IMSG_CTL_NOP: imsg_compose(&c->iev.ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_CTL_WHO: case IMSG_CTL_MONITOR: case IMSG_CTL_WHO_AND_MONITOR: if (imsg.hdr.type == IMSG_CTL_WHO) retval = npppd_ctl_who(c->ctx); else if (imsg.hdr.type == IMSG_CTL_MONITOR) retval = npppd_ctl_monitor(c->ctx); else retval = npppd_ctl_who_and_monitor(c->ctx); imsg_compose(&c->iev.ibuf, (retval == 0)? IMSG_CTL_OK : IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; case IMSG_CTL_DISCONNECT: { struct npppd_disconnect_request *req; struct npppd_disconnect_response res; req = (struct npppd_disconnect_request *)imsg.data; retval = npppd_ctl_disconnect(c->ctx, req->ppp_id, req->count); res.count = retval; imsg_compose(&c->iev.ibuf, IMSG_CTL_OK, 0, 0, -1, &res, sizeof(res)); break; } default: imsg_compose(&c->iev.ibuf, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } imsg_free(&imsg); } if (!c->iev.ibuf.w.queued) npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf); imsg_event_add(&c->iev); }
/* ARGSUSED */ static void control_dispatch_ext(int fd, short event, void *arg) { struct ctl_conn *c; struct imsg imsg; int n, verbose; uid_t euid; gid_t egid; uint64_t id; struct stat_kv *kvp; char *key; struct stat_value val; size_t len; if (getpeereid(fd, &euid, &egid) == -1) fatal("getpeereid"); if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_dispatch_ext: fd %d: not found", fd); return; } if (event & EV_READ) { if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) { control_close(c); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) < 0) { control_close(c); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(c); return; } if (n == 0) break; switch (imsg.hdr.type) { case IMSG_SMTP_ENQUEUE: if (env->sc_flags & (SMTPD_SMTP_PAUSED | SMTPD_CONFIGURING | SMTPD_EXITING)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_ENQUEUE, fd, 0, -1, &euid, sizeof(euid)); break; case IMSG_STATS: if (euid) goto badcred; imsg_compose_event(&c->iev, IMSG_STATS, 0, 0, -1, NULL, 0); break; case IMSG_STATS_GET: if (euid) goto badcred; kvp = imsg.data; if (! stat_backend->iter(&kvp->iter, &key, &val)) kvp->iter = NULL; else { strlcpy(kvp->key, key, sizeof kvp->key); kvp->val = val; } imsg_compose_event(&c->iev, IMSG_STATS_GET, 0, 0, -1, kvp, sizeof *kvp); break; case IMSG_CTL_SHUTDOWN: /* NEEDS_FIX */ log_debug("received shutdown request"); if (euid) goto badcred; if (env->sc_flags & SMTPD_EXITING) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } env->sc_flags |= SMTPD_EXITING; imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); imsg_compose_event(env->sc_ievs[PROC_PARENT], IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0); break; case IMSG_CTL_VERBOSE: if (euid) goto badcred; if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(verbose)) goto badcred; memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); imsg_compose_event(env->sc_ievs[PROC_PARENT], IMSG_CTL_VERBOSE, 0, 0, -1, &verbose, sizeof(verbose)); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_PAUSE_MDA: if (euid) goto badcred; if (env->sc_flags & SMTPD_MDA_PAUSED) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } log_info("mda paused"); env->sc_flags |= SMTPD_MDA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_PAUSE_MDA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_PAUSE_MTA: if (euid) goto badcred; if (env->sc_flags & SMTPD_MTA_PAUSED) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } log_info("mta paused"); env->sc_flags |= SMTPD_MTA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_PAUSE_MTA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_SMTP_PAUSE: if (euid) goto badcred; if (env->sc_flags & SMTPD_SMTP_PAUSED) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } log_info("smtp paused"); env->sc_flags |= SMTPD_SMTP_PAUSED; imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_PAUSE, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_RESUME_MDA: if (euid) goto badcred; if (! (env->sc_flags & SMTPD_MDA_PAUSED)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } log_info("mda resumed"); env->sc_flags &= ~SMTPD_MDA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_RESUME_MDA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_QUEUE_RESUME_MTA: if (euid) goto badcred; if (!(env->sc_flags & SMTPD_MTA_PAUSED)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } log_info("mta resumed"); env->sc_flags &= ~SMTPD_MTA_PAUSED; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_RESUME_MTA, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_SMTP_RESUME: if (euid) goto badcred; if (!(env->sc_flags & SMTPD_SMTP_PAUSED)) { imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } log_info("smtp resumed"); env->sc_flags &= ~SMTPD_SMTP_PAUSED; imsg_compose_event(env->sc_ievs[PROC_SMTP], IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_SCHEDULER_SCHEDULE: if (euid) goto badcred; id = *(uint64_t *)imsg.data; imsg_compose_event(env->sc_ievs[PROC_SCHEDULER], IMSG_SCHEDULER_SCHEDULE, 0, 0, -1, &id, sizeof id); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_SCHEDULER_REMOVE: if (euid) goto badcred; id = *(uint64_t *)imsg.data; imsg_compose_event(env->sc_ievs[PROC_SCHEDULER], IMSG_SCHEDULER_REMOVE, 0, 0, -1, &id, sizeof id); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_LKA_UPDATE_MAP: if (euid) goto badcred; /* map name too long */ len = strlen(imsg.data); if (len >= MAX_LINE_SIZE) goto invalid; imsg_compose_event(env->sc_ievs[PROC_LKA], IMSG_LKA_UPDATE_MAP, 0, 0, -1, imsg.data, len + 1); break; default: log_debug("control_dispatch_ext: " "error handling %s imsg", imsg_to_str(imsg.hdr.type)); break; } imsg_free(&imsg); continue; badcred: invalid: imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); } imsg_event_add(&c->iev); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *bula) { struct ctl_conn *c; struct imsg imsg; ssize_t n; unsigned int ifidx; int verbose; if ((c = control_connbyfd(fd)) == NULL) { log_warnx("%s: fd %d: not found", __func__, fd); return; } if (event & EV_READ) { if (((n = imsg_read(&c->iev.ibuf)) == -1 && errno != EAGAIN) || n == 0) { control_close(fd); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) <= 0 && errno != EAGAIN) { control_close(fd); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd); return; } if (n == 0) break; switch (imsg.hdr.type) { case IMSG_CTL_FIB_COUPLE: case IMSG_CTL_FIB_DECOUPLE: case IMSG_CTL_RELOAD: c->iev.ibuf.pid = imsg.hdr.pid; eigrpe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0); break; case IMSG_CTL_KROUTE: case IMSG_CTL_IFINFO: c->iev.ibuf.pid = imsg.hdr.pid; eigrpe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; case IMSG_CTL_SHOW_INTERFACE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(ifidx)) break; memcpy(&ifidx, imsg.data, sizeof(ifidx)); eigrpe_iface_ctl(c, ifidx); imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); break; case IMSG_CTL_SHOW_TOPOLOGY: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_topology_req)) break; c->iev.ibuf.pid = imsg.hdr.pid; eigrpe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); break; case IMSG_CTL_SHOW_NBR: eigrpe_nbr_ctl(c); break; case IMSG_CTL_SHOW_STATS: eigrpe_stats_ctl(c); break; case IMSG_CTL_CLEAR_NBR: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_nbr)) break; nbr_clear_ctl(imsg.data); break; case IMSG_CTL_LOG_VERBOSE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(verbose)) break; /* forward to other processes */ eigrpe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); eigrpe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); break; default: log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); break; } imsg_free(&imsg); } imsg_event_add(&c->iev); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *arg) { struct control_sock *cs = arg; struct ctl_conn *c; struct imsg imsg; struct ctl_id id; int n; int verbose; struct relayd *env = cs->cs_env; if ((c = control_connbyfd(fd)) == NULL) { log_warn("%s: fd %d not found", __func__, fd); return; } if (event & EV_READ) { if (((n = imsg_read(&c->iev.ibuf)) == -1 && errno != EAGAIN) || n == 0) { control_close(fd, cs); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) <= 0 && errno != EAGAIN) { control_close(fd, cs); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(fd, cs); return; } if (n == 0) break; if (c->waiting) { log_debug("%s: unexpected imsg %d", __func__, imsg.hdr.type); imsg_free(&imsg); control_close(fd, cs); return; } switch (imsg.hdr.type) { case IMSG_CTL_SHOW_SUM: show(c); break; case IMSG_CTL_SESSION: show_sessions(c); break; case IMSG_CTL_RDR_DISABLE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); if (disable_rdr(c, &id)) imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { memcpy(imsg.data, &id, sizeof(id)); control_imsg_forward(&imsg); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_RDR_ENABLE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); if (enable_rdr(c, &id)) imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { memcpy(imsg.data, &id, sizeof(id)); control_imsg_forward(&imsg); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_TABLE_DISABLE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); if (disable_table(c, &id)) imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { memcpy(imsg.data, &id, sizeof(id)); control_imsg_forward(&imsg); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_TABLE_ENABLE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); if (enable_table(c, &id)) imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { memcpy(imsg.data, &id, sizeof(id)); control_imsg_forward(&imsg); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_HOST_DISABLE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); if (disable_host(c, &id, NULL)) imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { memcpy(imsg.data, &id, sizeof(id)); control_imsg_forward(&imsg); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_HOST_ENABLE: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id)) fatalx("invalid imsg header len"); memcpy(&id, imsg.data, sizeof(id)); if (enable_host(c, &id, NULL)) imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); else { memcpy(imsg.data, &id, sizeof(id)); control_imsg_forward(&imsg); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); } break; case IMSG_CTL_SHUTDOWN: case IMSG_CTL_RELOAD: proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT, -1); break; case IMSG_CTL_POLL: proc_compose(env->sc_ps, PROC_HCE, IMSG_CTL_POLL, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); break; case IMSG_CTL_NOTIFY: if (c->flags & CTL_CONN_NOTIFY) { log_debug("%s: " "client requested notify more than once", __func__); imsg_compose_event(&c->iev, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0); break; } c->flags |= CTL_CONN_NOTIFY; break; case IMSG_CTL_VERBOSE: IMSG_SIZE_CHECK(&imsg, &verbose); memcpy(&verbose, imsg.data, sizeof(verbose)); proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT, -1); proc_forward_imsg(env->sc_ps, &imsg, PROC_HCE, -1); proc_forward_imsg(env->sc_ps, &imsg, PROC_RELAY, -1); memcpy(imsg.data, &verbose, sizeof(verbose)); control_imsg_forward(&imsg); log_verbose(verbose); break; default: log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); break; } imsg_free(&imsg); } imsg_event_add(&c->iev); }