int snmp_sendsock(struct imsgev *iev) { struct imsgev tmpiev; struct sockaddr_un sun; int s = -1; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) goto fail; bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; strlcpy(sun.sun_path, SNMP_SOCKET, sizeof(sun.sun_path)); if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1) goto fail; /* enable restricted snmp socket mode */ bzero(&tmpiev, sizeof(tmpiev)); imsg_init(&tmpiev.ibuf, s); imsg_compose_event(&tmpiev, IMSG_SNMP_LOCK, 0, 0, -1, NULL, 0); imsg_compose_event(iev, IMSG_SNMPSOCK, 0, 0, s, NULL, 0); imsg_flush(&iev->ibuf); /* need to send the socket now */ close(s); return (0); fail: if (s != -1) close(s); imsg_compose_event(iev, IMSG_NONE, 0, 0, -1, NULL, 0); return (-1); }
int queue_api_dispatch(void) { struct passwd *pw; ssize_t n; pw = getpwnam(user); if (pw == NULL) { log_warn("queue-api: getpwnam"); fatalx("queue-api: exiting"); } if (rootpath) { if (chroot(rootpath) == -1) { log_warn("queue-api: chroot"); fatalx("queue-api: exiting"); } if (chdir("/") == -1) { log_warn("queue-api: chdir"); fatalx("queue-api: exiting"); } } if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) { log_warn("queue-api: cannot drop privileges"); fatalx("queue-api: exiting"); } imsg_init(&ibuf, 0); while (1) { n = imsg_get(&ibuf, &imsg); if (n == -1) { log_warn("warn: queue-api: imsg_get"); break; } if (n) { rdata = imsg.data; rlen = imsg.hdr.len - IMSG_HEADER_SIZE; queue_msg_dispatch(); imsg_flush(&ibuf); continue; } n = imsg_read(&ibuf); if (n == -1) { log_warn("warn: queue-api: imsg_read"); break; } if (n == 0) { log_warnx("warn: queue-api: pipe closed"); break; } } return (1); }
static void table_proc_close(void *arg) { struct table_proc_priv *priv = arg; imsg_compose(&priv->ibuf, PROC_TABLE_CLOSE, 0, 0, -1, NULL, 0); imsg_flush(&priv->ibuf); }
static void dispatch(struct imsgbuf* ibuf, enum exec_type program, char* msg) { int32_t status = EXEC_RESPONSE_OK; char iface[IF_NAMESIZE] = {0}; static char* buf = NULL; if(buf == NULL) { buf = malloc(EXEC_BUF_LEN); } if(buf == NULL) { die("Failed to allocate buffer"); } buf[0] = '\0'; // Check if we were provided an interface on which to operate bool have_iface = (msg != NULL) && (msg = (char*)flatjson_next(msg, iface, sizeof(iface), NULL)) != NULL && validate_iface(iface); switch(program) { case EXEC_IFCONFIG_LIST_INTERFACES: { char* const args[] = {"/sbin/ifconfig", NULL}; if(run_and_read(args, buf) > 0) { status = EXEC_RESPONSE_ERROR; } break; } case EXEC_IFCONFIG_LIST_PSEUDO_INTERFACES: { char* const args[] = {"/sbin/ifconfig", "-C", NULL}; if(run_and_read(args, buf) > 0) { status = EXEC_RESPONSE_ERROR; } break; } case EXEC_IFCONFIG_DOWN: { if(!have_iface) { status = EXEC_RESPONSE_ERROR; break; } char* const args[] = {"/sbin/ifconfig", iface, "down", NULL}; if(run_and_read(args, buf) > 0) { status = EXEC_RESPONSE_ERROR; } break; } case EXEC_NETSTART: { if(!have_iface) { status = EXEC_RESPONSE_ERROR; break; } char* const args[] = {"/bin/sh", "/etc/netstart", iface, NULL}; if(run_and_read(args, buf) > 0) { status = EXEC_RESPONSE_ERROR; } break; } case EXEC_LOGEVENT: { char* const args[] = {"/usr/libexec/loghwevent", msg, NULL}; if(run_and_read(args, buf) > 0) { status = EXEC_RESPONSE_ERROR; } break; } default: warn("Unknown exec mode"); break; } imsg_compose(ibuf, status, 0, 0, -1, buf, strlen(buf) + 1); imsg_flush(ibuf); }
void imsg_event_add(struct imsgev *iev) { if (iev->handler == NULL) { imsg_flush(&iev->ibuf); return; } iev->events = EV_READ; if (iev->ibuf.w.queued) iev->events |= EV_WRITE; event_del(&iev->ev); event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data); event_add(&iev->ev, NULL); }
void m_flush(struct mproc *p) { if (imsg_compose(&p->imsgbuf, p->m_type, p->m_peerid, p->m_pid, p->m_fd, p->m_buf, p->m_pos) == -1) fatal("imsg_compose"); log_trace(TRACE_MPROC, "mproc: %s -> %s : %zu %s (flush)", proc_name(smtpd_process), proc_name(p->proc), p->m_pos, imsg_to_str(p->m_type)); p->m_pos = 0; imsg_flush(&p->imsgbuf); }
int snmp_getsock(struct imsgev *iev) { struct imsg imsg; int n, s = -1, done = 0; imsg_compose_event(iev, IMSG_SNMPSOCK, 0, 0, -1, NULL, 0); imsg_flush(&iev->ibuf); while (!done) { if ((n = imsg_read(&iev->ibuf)) == -1) fatal("snmp_getsock: failed to read imsg"); if (n == 0) fatal("snmp_getsock: pipe closed"); while (!done) { if ((n = imsg_get(&iev->ibuf, &imsg)) == -1) fatal("snmp_getsock: failed to get imsg"); if (n == 0) break; done = 1; switch (imsg.hdr.type) { case IMSG_SNMPSOCK: s = imsg.fd; break; default: break; } imsg_free(&imsg); } } if (s != -1) { log_debug("%s: got new snmp socket %d", __func__, s); if (iev_snmp == NULL && (iev_snmp = (struct imsgev *) calloc(1, sizeof(struct imsgev))) == NULL) fatal("snmp_getsock: calloc"); imsg_init(&iev_snmp->ibuf, s); } return (s); }
/* * Check writability not to spin before calling imsg_flush(3). Wait 'millisec' * until it becomes writable. */ int imsg_sync_flush(struct imsgbuf *ibuf, int millisec) { struct pollfd fds[1]; int retval; if (!ibuf->w.queued) return (0); /* already flushed */ fds[0].fd = ibuf->fd; fds[0].events = POLLOUT; retval = poll(fds, 1, millisec); if (retval == 0) { errno = EAGAIN; return (-1); } if (retval > 0 && (fds[0].revents & POLLOUT) != 0) return imsg_flush(ibuf); return (-1); }
static int m_priv_iked_imsg(u_int cmd) { struct sockaddr_un sun; int fd = -1, ret = -1; struct imsgbuf ibuf; if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { log_err("m_priv_iked_imsg: socket"); goto out; } bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; strlcpy(sun.sun_path, IKED_SOCKET, sizeof(sun.sun_path)); if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { log_err("m_priv_iked_imsg: connect"); goto out; } imsg_init(&ibuf, fd); if (imsg_compose(&ibuf, cmd, 0, 0, -1, NULL, 0) == -1) { log_err("m_priv_iked_imsg: compose"); goto err; } if (imsg_flush(&ibuf) == -1) { log_err("m_priv_iked_imsg: flush"); goto err; } ret = 0; err: imsg_clear(&ibuf); out: if (fd != -1) close(fd); return (ret); }
static void scheduler_proc_call(void) { ssize_t n; if (imsg_flush(&ibuf) == -1) { log_warn("warn: scheduler-proc: imsg_flush"); fatalx("scheduler-proc: exiting"); } while (1) { if ((n = imsg_get(&ibuf, &imsg)) == -1) { log_warn("warn: scheduler-proc: imsg_get"); break; } if (n) { rlen = imsg.hdr.len - IMSG_HEADER_SIZE; rdata = imsg.data; if (imsg.hdr.type != PROC_SCHEDULER_OK) { log_warnx("warn: scheduler-proc: bad response"); break; } return; } if ((n = imsg_read(&ibuf)) == -1) { log_warn("warn: scheduler-proc: imsg_read"); break; } if (n == 0) { log_warnx("warn: scheduler-proc: pipe closed"); break; } } fatalx("scheduler-proc: exiting"); }
static void table_proc_call(struct table_proc_priv *p) { ssize_t n; if (imsg_flush(&p->ibuf) == -1) { log_warn("warn: table-proc: imsg_flush"); fatalx("table-proc: exiting"); } while (1) { if ((n = imsg_get(&p->ibuf, &imsg)) == -1) { log_warn("warn: table-proc: imsg_get"); break; } if (n) { rlen = imsg.hdr.len - IMSG_HEADER_SIZE; rdata = imsg.data; if (imsg.hdr.type != PROC_TABLE_OK) { log_warnx("warn: table-proc: bad response"); break; } return; } if ((n = imsg_read(&p->ibuf)) == -1) { log_warn("warn: table-proc: imsg_read"); break; } if (n == 0) { log_warnx("warn: table-proc: pipe closed"); break; } } fatalx("table-proc: exiting"); }
/* 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); }
void service_send(struct imsgbuf* ibuf, u_int32_t type, const char* msg) { const size_t msg_len = (msg == NULL)? 0 : (strlen(msg) + 1); imsg_compose(ibuf, type, 0, 0, -1, msg, msg_len); imsg_flush(ibuf); }
void proc_flush_imsg(struct iked *env, enum privsep_procid id) { imsg_flush(&env->sc_ps.ps_ievs[id].ibuf); }