/* 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 = 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_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); }