int imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) { int ret; if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, datalen)) == -1) return (ret); imsg_event_add(iev); return (ret); }
int imsg_composev_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, pid_t pid, int fd, const struct iovec *iov, int iovcnt) { int ret; if ((ret = imsg_composev(&iev->ibuf, type, peerid, pid, fd, iov, iovcnt)) == -1) return (ret); imsg_event_add(iev); return (ret); }
int snmp_element(const char *oid, enum snmp_type type, void *buf, int64_t val) { struct iovec iov[2]; int iovcnt = 2; u_int32_t d; u_int64_t l; struct snmp_imsg sm; DPRINTF("%s: oid %s type %d buf %p val %lld", __func__, oid, type, buf, val); bzero(&iov, sizeof(iov)); switch (type) { case SNMP_COUNTER32: case SNMP_GAUGE32: case SNMP_TIMETICKS: case SNMP_OPAQUE: case SNMP_UINTEGER32: case SNMP_INTEGER32: d = (u_int32_t)val; iov[1].iov_base = &d; iov[1].iov_len = sizeof(d); break; case SNMP_COUNTER64: l = (u_int64_t)val; iov[1].iov_base = &l; iov[1].iov_len = sizeof(l); break; case SNMP_NSAPADDR: case SNMP_BITSTRING: case SNMP_OCTETSTRING: case SNMP_IPADDR: case SNMP_OBJECT: iov[1].iov_base = buf; if (val == 0) iov[1].iov_len = strlen((char *)buf); else iov[1].iov_len = val; break; case SNMP_NULL: iovcnt--; break; } bzero(&sm, sizeof(sm)); if (strlcpy(sm.snmp_oid, oid, sizeof(sm.snmp_oid)) >= sizeof(sm.snmp_oid)) return (-1); sm.snmp_type = type; sm.snmp_len = iov[1].iov_len; iov[0].iov_base = &sm; iov[0].iov_len = sizeof(sm); if (imsg_composev(&iev_snmp->ibuf, IMSG_SNMP_ELEMENT, 0, 0, -1, iov, iovcnt) == -1) return (-1); imsg_event_add(iev_snmp); return (0); }
/* 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 lde_dispatch_parent(int fd, short event, void *bula) { struct imsg imsg; struct kroute kr; struct imsgev *iev = bula; struct imsgbuf *ibuf = &iev->ibuf; ssize_t n; int shut = 0; if (event & EV_READ) { if ((n = imsg_read(ibuf)) == -1) fatal("imsg_read error"); if (n == 0) /* connection closed */ shut = 1; } if (event & EV_WRITE) { if (msgbuf_write(&ibuf->w) == -1) fatal("msgbuf_write"); } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("lde_dispatch_parent: imsg_read error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_NETWORK_ADD: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { log_warnx("lde_dispatch_parent: " "wrong imsg len"); break; } memcpy(&kr, imsg.data, sizeof(kr)); lde_kernel_insert(&kr); break; case IMSG_NETWORK_DEL: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { log_warnx("lde_dispatch_parent: " "wrong imsg len"); break; } memcpy(&kr, imsg.data, sizeof(kr)); lde_kernel_remove(&kr); break; case IMSG_RECONF_CONF: if ((nconf = malloc(sizeof(struct ldpd_conf))) == NULL) fatal(NULL); memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); break; case IMSG_RECONF_IFACE: break; case IMSG_RECONF_END: break; default: log_debug("lde_dispatch_parent: unexpected imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } if (!shut) imsg_event_add(iev); else { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); } }
void proc_dispatch(int fd, short event, void *arg) { struct privsep_proc *p = (struct privsep_proc *)arg; struct privsep *ps = p->p_ps; struct imsgev *iev; struct imsgbuf *ibuf; struct imsg imsg; ssize_t n; int verbose; const char *title; title = ps->ps_title[privsep_process]; iev = &ps->ps_ievs[p->p_id]; ibuf = &iev->ibuf; if (event & EV_READ) { if ((n = imsg_read(ibuf)) == -1) fatal(title); if (n == 0) { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); return; } } if (event & EV_WRITE) { if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) fatal(title); } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal(title); if (n == 0) break; /* * Check the message with the program callback */ if ((p->p_cb)(fd, p, &imsg) == 0) { /* Message was handled by the callback, continue */ imsg_free(&imsg); continue; } /* * Generic message handling */ switch (imsg.hdr.type) { case IMSG_CTL_VERBOSE: IMSG_SIZE_CHECK(&imsg, &verbose); memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); break; default: log_warnx("%s: %s got imsg %d", __func__, p->p_title, imsg.hdr.type); fatalx(title); } imsg_free(&imsg); } imsg_event_add(iev); }
/* ARGSUSED */ void control_dispatch_imsg(int fd, short event, void *arg) { struct ctl_conn *c = arg; struct control_sock *cs = c->cs; struct snmpd *env = cs->cs_env; struct imsg imsg; int n, v, i; if (event & EV_READ) { if (((n = imsg_read_nofd(&c->iev.ibuf)) == -1 && errno != EAGAIN) || n == 0) { control_close(c, "could not read imsg", NULL); return; } } if (event & EV_WRITE) { if (msgbuf_write(&c->iev.ibuf.w) <= 0 && errno != EAGAIN) { control_close(c, "could not write imsg", NULL); return; } } for (;;) { if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) { control_close(c, "could not get imsg", NULL); return; } if (n == 0) break; if (cs->cs_restricted || (c->flags & CTL_CONN_LOCKED)) { switch (imsg.hdr.type) { case IMSG_SNMP_AGENTX: case IMSG_SNMP_ELEMENT: case IMSG_SNMP_END: case IMSG_SNMP_LOCK: break; default: control_close(c, "client requested restricted command", &imsg); return; } } control_imsg_forward(&imsg); switch (imsg.hdr.type) { case IMSG_CTL_NOTIFY: if (IMSG_DATA_SIZE(&imsg)) return control_close(c, "invalid size", &imsg); 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_SNMP_LOCK: if (IMSG_DATA_SIZE(&imsg)) return control_close(c, "invalid size", &imsg); /* enable restricted control mode */ c->flags |= CTL_CONN_LOCKED; break; case IMSG_SNMP_AGENTX: if (IMSG_DATA_SIZE(&imsg)) return control_close(c, "invalid size", &imsg); /* rendezvous with the client */ imsg_compose_event(&c->iev, IMSG_CTL_OK, 0, 0, -1, NULL, 0); if (imsg_flush(&c->iev.ibuf) == -1) { control_close(c, "could not rendezvous with agentx client", &imsg); return; } /* enable AgentX socket */ c->handle = snmp_agentx_alloc(c->iev.ibuf.fd); if (c->handle == NULL) { control_close(c, "could not allocate agentx socket", &imsg); return; } /* disable IMSG notifications */ c->flags &= ~CTL_CONN_NOTIFY; c->flags |= CTL_CONN_LOCKED; c->iev.handler = control_dispatch_agentx; break; case IMSG_CTL_VERBOSE: if (IMSG_DATA_SIZE(&imsg) != sizeof(v)) return control_close(c, "invalid size", &imsg); memcpy(&v, imsg.data, sizeof(v)); log_verbose(v); for (i = 0; i < PROC_MAX; i++) { if (privsep_process == PROC_CONTROL) continue; proc_forward_imsg(&env->sc_ps, &imsg, i, -1); } break; case IMSG_CTL_RELOAD: if (IMSG_DATA_SIZE(&imsg)) return control_close(c, "invalid size", &imsg); proc_forward_imsg(&env->sc_ps, &imsg, PROC_PARENT, -1); break; default: control_close(c, "invalid type", &imsg); return; } 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 */ void rde_dispatch_parent(int fd, short event, void *bula) { struct imsg imsg; struct rt_node *rt; struct kroute kr; struct imsgev *iev = bula; struct imsgbuf *ibuf = &iev->ibuf; ssize_t n; int shut = 0; if (event & EV_READ) { if ((n = imsg_read(ibuf)) == -1) fatal("imsg_read error"); if (n == 0) /* connection closed */ shut = 1; } if (event & EV_WRITE) { if (msgbuf_write(&ibuf->w) == -1 && errno != EAGAIN) fatal("msgbuf_write"); } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("rde_dispatch_parent: imsg_read error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_NETWORK_ADD: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) { log_warnx("rde_dispatch: wrong imsg len"); break; } memcpy(&kr, imsg.data, sizeof(kr)); rt = rt_new_kr(&kr); rt_insert(rt); break; case IMSG_NETWORK_DEL: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) { log_warnx("rde_dispatch: wrong imsg len"); break; } memcpy(&kr, imsg.data, sizeof(kr)); if ((rt = rt_find(kr.prefix.s_addr, kr.netmask.s_addr)) != NULL) rt_remove(rt); break; default: log_debug("rde_dispatch_parent: unexpected imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } if (!shut) imsg_event_add(iev); else { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); } }
/* 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 rde_dispatch_imsg(int fd, short event, void *bula) { struct imsgev *iev = bula; struct imsgbuf *ibuf = &iev->ibuf; struct rip_route rr; struct imsg imsg; ssize_t n; int shut = 0, verbose; if (event & EV_READ) { if ((n = imsg_read(ibuf)) == -1) fatal("imsg_read error"); if (n == 0) /* connection closed */ shut = 1; } if (event & EV_WRITE) { if (msgbuf_write(&ibuf->w) == -1 && errno != EAGAIN) fatal("msgbuf_write"); } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("rde_dispatch_imsg: imsg_read error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_ROUTE_FEED: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rr)) fatalx("invalid size of RDE request"); memcpy(&rr, imsg.data, sizeof(rr)); if (rde_check_route(&rr) == -1) log_debug("rde_dispatch_imsg: " "packet malformed\n"); break; case IMSG_FULL_REQUEST: bzero(&rr, sizeof(rr)); /* * AFI == 0 && metric == INFINITY request the * whole routing table */ rr.metric = INFINITY; rde_imsg_compose_ripe(IMSG_REQUEST_ADD, 0, 0, &rr, sizeof(rr)); rde_imsg_compose_ripe(IMSG_SEND_REQUEST, 0, 0, NULL, 0); break; case IMSG_FULL_RESPONSE: rt_snap(imsg.hdr.peerid); rde_imsg_compose_ripe(IMSG_SEND_RESPONSE, imsg.hdr.peerid, 0, NULL, 0); break; case IMSG_ROUTE_REQUEST: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rr)) fatalx("invalid size of RDE request"); memcpy(&rr, imsg.data, sizeof(rr)); rt_complete(&rr); rde_imsg_compose_ripe(IMSG_RESPONSE_ADD, imsg.hdr.peerid, 0, &rr, sizeof(rr)); break; case IMSG_ROUTE_REQUEST_END: rde_imsg_compose_ripe(IMSG_SEND_RESPONSE, imsg.hdr.peerid, 0, NULL, 0); break; case IMSG_CTL_SHOW_RIB: rt_dump(imsg.hdr.pid); imsg_compose_event(iev_ripe, IMSG_CTL_END, 0, imsg.hdr.pid, -1, NULL, 0); break; case IMSG_CTL_LOG_VERBOSE: /* already checked by ripe */ memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); break; default: log_debug("rde_dispatch_msg: unexpected imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } if (!shut) imsg_event_add(iev); else { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); } }
/* 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); }
/* 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); }
void dns_dispatch_imsg(int fd, short events, void *p) { struct imsg imsg; int n, cnt; char *name; struct ypldap_addr_list hn = TAILQ_HEAD_INITIALIZER(hn); struct ypldap_addr *h; struct ibuf *buf; struct env *env = p; struct imsgev *iev = env->sc_iev; struct imsgbuf *ibuf = &iev->ibuf; int shut = 0; if ((events & (EV_READ | EV_WRITE)) == 0) fatalx("unknown event"); if (events & EV_READ) { if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) fatal("imsg_read error"); if (n == 0) shut = 1; } if (events & EV_WRITE) { if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) fatal("msgbuf_write"); if (n == 0) shut = 1; goto done; } for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("client_dispatch_imsg: imsg_get error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_HOST_DNS: name = imsg.data; if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) fatalx("invalid IMSG_HOST_DNS received"); imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; if (name[imsg.hdr.len] != '\0' || strlen(name) != imsg.hdr.len) fatalx("invalid IMSG_HOST_DNS received"); if ((cnt = host_dns(name, &hn)) == -1) break; buf = imsg_create(ibuf, IMSG_HOST_DNS, imsg.hdr.peerid, 0, cnt * sizeof(struct sockaddr_storage)); if (buf == NULL) break; if (cnt > 0) { while(!TAILQ_EMPTY(&hn)) { h = TAILQ_FIRST(&hn); TAILQ_REMOVE(&hn, h, next); imsg_add(buf, &h->ss, sizeof(h->ss)); free(h); } } imsg_close(ibuf, buf); break; default: break; } imsg_free(&imsg); } done: if (!shut) imsg_event_add(iev); else { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); } }
/* 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 lde_dispatch_imsg(int fd, short event, void *bula) { struct imsgev *iev = bula; struct imsgbuf *ibuf = &iev->ibuf; struct imsg imsg; struct lde_nbr rn, *nbr; struct map map; struct timespec tp; struct in_addr addr; ssize_t n; time_t now; int state, shut = 0, verbose; if (event & EV_READ) { if ((n = imsg_read(ibuf)) == -1) fatal("imsg_read error"); if (n == 0) /* connection closed */ shut = 1; } if (event & EV_WRITE) { if (msgbuf_write(&ibuf->w) == -1) fatal("msgbuf_write"); } clock_gettime(CLOCK_MONOTONIC, &tp); now = tp.tv_sec; for (;;) { if ((n = imsg_get(ibuf, &imsg)) == -1) fatal("lde_dispatch_imsg: imsg_read error"); if (n == 0) break; switch (imsg.hdr.type) { case IMSG_LABEL_MAPPING_FULL: nbr = lde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) { log_debug("lde_dispatch_imsg: cannot find " "lde neighbor"); return; } rt_snap(nbr); lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, imsg.hdr.peerid, 0, NULL, 0); break; case IMSG_LABEL_MAPPING: case IMSG_LABEL_REQUEST: case IMSG_LABEL_RELEASE: case IMSG_LABEL_WITHDRAW: case IMSG_LABEL_ABORT: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map)) fatalx("invalid size of OE request"); memcpy(&map, imsg.data, sizeof(map)); nbr = lde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) { log_debug("lde_dispatch_imsg: cannot find " "lde neighbor"); return; } switch (imsg.hdr.type) { case IMSG_LABEL_MAPPING: lde_check_mapping(&map, nbr); break; case IMSG_LABEL_REQUEST: lde_check_request(&map, nbr); break; case IMSG_LABEL_RELEASE: lde_check_release(&map, nbr); break; case IMSG_LABEL_WITHDRAW: lde_check_withdraw(&map, nbr); break; default: log_warnx("type %d not yet handled. nbr %s", imsg.hdr.type, inet_ntoa(nbr->id)); } break; case IMSG_ADDRESS_ADD: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) fatalx("invalid size of OE request"); memcpy(&addr, imsg.data, sizeof(addr)); nbr = lde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) { log_debug("lde_dispatch_imsg: cannot find " "lde neighbor"); return; } if (lde_address_add(nbr, &addr) < 0) { log_debug("lde_dispatch_imsg: cannot add " "address %s, it already exists", inet_ntoa(addr)); } break; case IMSG_ADDRESS_DEL: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr)) fatalx("invalid size of OE request"); memcpy(&addr, imsg.data, sizeof(addr)); nbr = lde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) { log_debug("lde_dispatch_imsg: cannot find " "lde neighbor"); return; } if (lde_address_del(nbr, &addr) < 0) { log_debug("lde_dispatch_imsg: cannot delete " "address %s, it does not exists", inet_ntoa(addr)); } break; case IMSG_NEIGHBOR_UP: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn)) fatalx("invalid size of OE request"); memcpy(&rn, imsg.data, sizeof(rn)); if (lde_nbr_find(imsg.hdr.peerid)) fatalx("lde_dispatch_imsg: " "neighbor already exists"); lde_nbr_new(imsg.hdr.peerid, &rn); break; case IMSG_NEIGHBOR_DOWN: lde_nbr_del(lde_nbr_find(imsg.hdr.peerid)); break; case IMSG_NEIGHBOR_CHANGE: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state)) fatalx("invalid size of OE request"); memcpy(&state, imsg.data, sizeof(state)); nbr = lde_nbr_find(imsg.hdr.peerid); if (nbr == NULL) break; nbr->state = state; break; case IMSG_CTL_SHOW_LIB: rt_dump(imsg.hdr.pid); imsg_compose_event(iev_ldpe, IMSG_CTL_END, 0, imsg.hdr.pid, -1, NULL, 0); break; case IMSG_CTL_LOG_VERBOSE: /* already checked by ldpe */ memcpy(&verbose, imsg.data, sizeof(verbose)); log_verbose(verbose); break; default: log_debug("lde_dispatch_imsg: unexpected imsg %d", imsg.hdr.type); break; } imsg_free(&imsg); } if (!shut) imsg_event_add(iev); else { /* this pipe is dead, so remove the event handler */ event_del(&iev->ev); event_loopexit(NULL); } }