void snmp_hosttrap(struct table *table, struct host *host) { if (iev_snmp == NULL || env->sc_snmp == -1) return; /* * OPENBSD-RELAYD-MIB host status trap * XXX The trap format needs some tweaks and other OIDs */ imsg_compose_event(iev_snmp, IMSG_SNMP_TRAP, 0, 0, -1, NULL, 0); SNMP_ELEMENT(".1", SNMP_NULL, NULL, 0); SNMP_ELEMENT(".1.1", SNMP_OCTETSTRING, host->conf.name, 0); SNMP_ELEMENT(".1.2", SNMP_INTEGER32, NULL, host->up); SNMP_ELEMENT(".1.3", SNMP_INTEGER32, NULL, host->last_up); SNMP_ELEMENT(".1.4", SNMP_INTEGER32, NULL, host->up_cnt); SNMP_ELEMENT(".1.5", SNMP_INTEGER32, NULL, host->check_cnt); SNMP_ELEMENT(".1.6", SNMP_OCTETSTRING, table->conf.name, 0); SNMP_ELEMENT(".1.7", SNMP_INTEGER32, NULL, table->up); if (!host->conf.retry) goto done; SNMP_ELEMENT(".1.8", SNMP_INTEGER32, NULL, host->conf.retry); SNMP_ELEMENT(".1.9", SNMP_INTEGER32, NULL, host->retry_cnt); done: imsg_compose_event(iev_snmp, IMSG_SNMP_END, 0, 0, -1, NULL, 0); }
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 rde_imsg_compose_ripe(int type, u_int32_t peerid, pid_t pid, void *data, u_int16_t datalen) { return (imsg_compose_event(iev_ripe, type, peerid, pid, -1, data, datalen)); }
int proc_compose_imsg(struct iked *env, enum privsep_procid id, u_int16_t type, int fd, void *data, u_int16_t datalen) { return (imsg_compose_event(&env->sc_ps.ps_ievs[id], type, -1, 0, fd, data, datalen)); }
void lde_send_labelrelease(struct lde_nbr *ln, struct rt_node *rn, u_int32_t label) { struct map map; bzero(&map, sizeof(map)); map.prefix = rn->fec.prefix; map.prefixlen = rn->fec.prefixlen; if (label != NO_LABEL) { map.flags = F_MAP_OPTLABEL; map.label = label; } imsg_compose_event(iev_ldpe, IMSG_RELEASE_ADD, ln->peerid, 0, -1, &map, sizeof(map)); imsg_compose_event(iev_ldpe, IMSG_RELEASE_ADD_END, ln->peerid, 0, -1, NULL, 0); }
int control_imsg_relay(struct imsg *imsg) { struct ctl_conn *c; if ((c = control_connbypid(imsg->hdr.pid)) == NULL) return (0); return (imsg_compose_event(&c->iev, imsg->hdr.type, 0, imsg->hdr.pid, -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE)); }
void control_imsg_forward(struct imsg *imsg) { struct ctl_conn *c; TAILQ_FOREACH(c, &ctl_conns, entry) if (c->flags & CTL_CONN_NOTIFY) imsg_compose_event(&c->iev, imsg->hdr.type, 0, imsg->hdr.pid, -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE); }
void session_destroy(struct session *s, const char * reason) { uint32_t msgid; log_debug("smtp: %p: deleting session: %s", s, reason); if (s->s_flags & F_ZOMBIE) goto finalize; log_debug("session_destroy: s->datafp = %p", s->datafp); if (s->datafp != NULL) fclose(s->datafp); if (s->s_msg.id != 0 && s->s_state != S_DONE) { msgid = evpid_to_msgid(s->s_msg.id); imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_REMOVE_MESSAGE, 0, 0, -1, &msgid, sizeof(msgid)); } if (s->s_io.ssl) { if (s->s_l->flags & F_SMTPS) if (s->s_flags & F_SECURE) stat_decrement("smtp.smtps", 1); if (s->s_l->flags & F_STARTTLS) if (s->s_flags & F_SECURE) stat_decrement("smtp.tls", 1); } event_del(&s->s_ev); /* in case something was scheduled */ io_clear(&s->s_io); iobuf_clear(&s->s_iobuf); /* resume when session count decreases to 95% */ stat_decrement("smtp.session", 1); /* If the session is waiting for an imsg, do not kill it now, since * the id must still be valid. */ if (s->s_flags & F_WAITIMSG) { s->s_flags = F_ZOMBIE; return; } finalize: smtp_destroy(s); SPLAY_REMOVE(sessiontree, &env->sc_sessions, s); bzero(s, sizeof(*s)); free(s); }
void lde_send_labelmapping(struct lde_nbr *ln, struct rt_node *rn) { struct lde_req *lre; struct lde_map *me; struct map map; /* * This function skips SL.1 - 3 and SL.9 - 14 because the lable * allocation is done way earlier (because of the merging nature of * ldpd). */ bzero(&map, sizeof(map)); map.label = rn->local_label; map.prefix = rn->fec.prefix; map.prefixlen = rn->fec.prefixlen; /* is there a pending request for this mapping? */ lre = (struct lde_req *)fec_find(&ln->recv_req, &rn->fec); if (lre) { /* set label request msg id in the mapping response. */ map.requestid = lre->msgid; map.flags = F_MAP_REQ_ID; lde_req_del(ln, lre, 0); } me = (struct lde_map *)fec_find(&ln->sent_map, &rn->fec); if (me == NULL) me = lde_map_add(ln, rn, 1); me->label = map.label; imsg_compose_event(iev_ldpe, IMSG_MAPPING_ADD, ln->peerid, 0, -1, &map, sizeof(map)); imsg_compose_event(iev_ldpe, IMSG_MAPPING_ADD_END, ln->peerid, 0, -1, NULL, 0); }
void lde_send_labelrequest(struct lde_nbr *ln, struct rt_node *rn) { struct map map; /* TODO check if status of peer is OK to send requests (SLRq.2 & 6) * For now assume no peer will send no-label-resource notifications */ /* check if request is already pending */ if (fec_find(&ln->sent_req, &rn->fec) != NULL) return; /* and try to add request to pending list */ lde_req_add(ln, &rn->fec, 1); /* msgid does not matter since only one req can be pending */ bzero(&map, sizeof(map)); map.prefix = rn->fec.prefix; map.prefixlen = rn->fec.prefixlen; imsg_compose_event(iev_ldpe, IMSG_REQUEST_ADD, ln->peerid, 0, -1, &map, sizeof(map)); imsg_compose_event(iev_ldpe, IMSG_REQUEST_ADD_END, ln->peerid, 0, -1, NULL, 0); }
void rde_send_delete_kroute(struct rt_node *r) { struct kroute kr; bzero(&kr, sizeof(kr)); kr.prefix.s_addr = r->prefix.s_addr; kr.nexthop.s_addr = r->nexthop.s_addr; kr.netmask.s_addr = r->netmask.s_addr; kr.metric = r->metric; kr.flags = r->flags; kr.ifindex = r->ifindex; imsg_compose_event(iev_main, IMSG_KROUTE_DELETE, 0, 0, -1, &kr, sizeof(kr)); }
void lde_send_notification(u_int32_t peerid, u_int32_t code, u_int32_t msgid, u_int32_t type) { struct notify_msg nm; bzero(&nm, sizeof(nm)); /* Every field is in host byte order, to keep things clear */ nm.status = code; nm.messageid = ntohl(msgid); nm.type = type; imsg_compose_event(iev_ldpe, IMSG_NOTIFICATION_SEND, peerid, 0, -1, &nm, sizeof(nm)); }
static void mta_envelope_done(struct mta_task *task, struct envelope *e, const char *status) { char relay[MAX_LINE_SIZE]; envelope_set_errormsg(e, "%s", status); snprintf(relay, sizeof relay, "relay=%s, ", task->route->hostname); log_envelope(e, relay, e->errorline); imsg_compose_event(env->sc_ievs[PROC_QUEUE], mta_response_delivery(e->errorline), 0, 0, -1, e, sizeof(*e)); TAILQ_REMOVE(&task->envelopes, e, entry); free(e); stat_decrement("mta.envelope", 1); }
void lde_send_delete_klabel(struct rt_node *rr, struct rt_lsp *rl) { struct kroute kr; bzero(&kr, sizeof(kr)); kr.prefix.s_addr = rr->fec.prefix.s_addr; kr.prefixlen = rr->fec.prefixlen; kr.local_label = rr->local_label; kr.nexthop.s_addr = rl->nexthop.s_addr; kr.remote_label = rl->remote_label; imsg_compose_event(iev_main, IMSG_KLABEL_DELETE, 0, 0, -1, &kr, sizeof(kr)); }
/* * Send IMSG, waiting for reply safely. */ static void session_imsg(struct session *s, enum smtp_proc_type proc, enum imsg_type type, uint32_t peerid, pid_t pid, int fd, void *data, uint16_t datalen) { /* * Each outgoing IMSG has a response IMSG associated that must be * waited for before the session can be progressed further. * During the wait period: * 1) session must not be destroyed, * 2) session must not be read from, * 3) session may be written to. */ s->s_flags |= F_WAITIMSG; imsg_compose_event(env->sc_ievs[proc], type, peerid, pid, fd, data, datalen); }
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)); }
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); }
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)); }
static void mta_envelope_done(struct mta_task *task, struct envelope *e, const char *status) { struct mta_host *host = TAILQ_FIRST(&task->session->hosts); char relay[MAX_LINE_SIZE], stat[MAX_LINE_SIZE]; envelope_set_errormsg(e, "%s", status); snprintf(relay, sizeof relay, "relay=%s [%s], ", host->fqdn, ss_to_text(&host->sa)); snprintf(stat, sizeof stat, "%s (%s)", mta_response_status(e->errorline), mta_response_text(e->errorline)); log_envelope(e, relay, stat); imsg_compose_event(env->sc_ievs[PROC_QUEUE], mta_response_delivery(e->errorline), 0, 0, -1, e, sizeof(*e)); TAILQ_REMOVE(&task->envelopes, e, entry); free(e); stat_decrement("mta.envelope", 1); }
static int runner_process_batch(enum delivery_type type, u_int64_t evpid) { struct envelope evp; void *batch; int fd; batch = scheduler->batch(evpid); switch (type) { case D_BOUNCE: while (scheduler->fetch(batch, &evpid)) { if (! queue_envelope_load(evpid, &evp)) goto end; evp.lasttry = time(NULL); imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_SMTP_ENQUEUE, PROC_SMTP, 0, -1, &evp, sizeof evp); scheduler->schedule(evpid); } stat_increment(STATS_RUNNER); stat_increment(STATS_RUNNER_BOUNCES); break; case D_MDA: scheduler->fetch(batch, &evpid); if (! queue_envelope_load(evpid, &evp)) goto end; evp.lasttry = time(NULL); fd = queue_message_fd_r(evpid_to_msgid(evpid)); imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_MDA_SESS_NEW, PROC_MDA, 0, fd, &evp, sizeof evp); scheduler->schedule(evpid); stat_increment(STATS_RUNNER); stat_increment(STATS_MDA_SESSION); break; case D_MTA: { struct mta_batch mta_batch; /* FIXME */ if (! scheduler->fetch(batch, &evpid)) goto end; if (! queue_envelope_load(evpid, &evp)) goto end; bzero(&mta_batch, sizeof mta_batch); mta_batch.id = arc4random(); mta_batch.relay = evp.agent.mta.relay; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_BATCH_CREATE, PROC_MTA, 0, -1, &mta_batch, sizeof mta_batch); while (scheduler->fetch(batch, &evpid)) { if (! queue_envelope_load(evpid, &evp)) goto end; evp.lasttry = time(NULL); /* FIXME */ evp.batch_id = mta_batch.id; imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_BATCH_APPEND, PROC_MTA, 0, -1, &evp, sizeof evp); scheduler->schedule(evpid); stat_increment(STATS_RUNNER); } imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_BATCH_CLOSE, PROC_MTA, 0, -1, &mta_batch, sizeof mta_batch); stat_increment(STATS_MTA_SESSION); break; } default: fatalx("runner_process_batchqueue: unknown type"); } end: scheduler->close(batch); return 1; }
static void mta_enter_state(struct mta_session *s, int newstate) { int oldstate; struct secret secret; struct mta_route *route; struct mta_host *host; struct sockaddr *sa; int max_reuse; ssize_t q; #ifdef VALGRIND bzero(&batch, sizeof(batch)); #endif again: oldstate = s->state; log_trace(TRACE_MTA, "mta: %p: %s -> %s", s, mta_strstate(oldstate), mta_strstate(newstate)); s->state = newstate; /* don't try this at home! */ #define mta_enter_state(_s, _st) do { newstate = _st; goto again; } while(0) switch (s->state) { case MTA_INIT: if (s->route->auth) mta_enter_state(s, MTA_SECRET); else mta_enter_state(s, MTA_MX); break; case MTA_DATA: /* * Obtain message body fd. */ imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_QUEUE_MESSAGE_FD, s->task->msgid, 0, -1, &s->id, sizeof(s->id)); break; case MTA_SECRET: /* * Lookup AUTH secret. */ bzero(&secret, sizeof(secret)); secret.id = s->id; strlcpy(secret.mapname, s->route->auth, sizeof(secret.mapname)); strlcpy(secret.host, s->route->hostname, sizeof(secret.host)); imsg_compose_event(env->sc_ievs[PROC_LKA], IMSG_LKA_SECRET, 0, 0, -1, &secret, sizeof(secret)); break; case MTA_MX: /* * Lookup MX record. */ if (s->flags & MTA_FORCE_MX) /* XXX */ dns_query_host(s->route->hostname, s->route->port, s->id); else dns_query_mx(s->route->hostname, s->route->backupname, 0, s->id); break; case MTA_CONNECT: /* * Connect to the MX. */ /* cleanup previous connection if any */ iobuf_clear(&s->iobuf); io_clear(&s->io); if (s->flags & MTA_FORCE_ANYSSL) max_reuse = 2; else max_reuse = 1; /* pick next mx */ while ((host = TAILQ_FIRST(&s->hosts))) { if (host->used == max_reuse) { TAILQ_REMOVE(&s->hosts, host, entry); free(host); continue; } host->used++; log_debug("mta: %p: connecting to %s...", s, ss_to_text(&host->sa)); sa = (struct sockaddr *)&host->sa; if (s->route->port) sa_set_port(sa, s->route->port); else if ((s->flags & MTA_FORCE_ANYSSL) && host->used == 1) sa_set_port(sa, 465); else if (s->flags & MTA_FORCE_SMTPS) sa_set_port(sa, 465); else sa_set_port(sa, 25); iobuf_xinit(&s->iobuf, 0, 0, "mta_enter_state"); io_init(&s->io, -1, s, mta_io, &s->iobuf); io_set_timeout(&s->io, 10000); if (io_connect(&s->io, sa, NULL) == -1) { log_debug("mta: %p: connection failed: %s", s, strerror(errno)); iobuf_clear(&s->iobuf); /* * This error is most likely a "no route", * so there is no need to try the same * relay again. */ TAILQ_REMOVE(&s->hosts, host, entry); free(host); continue; } return; } /* tried them all? */ mta_route_error(s->route, "150 Can not connect to MX"); mta_enter_state(s, MTA_DONE); break; case MTA_DONE: /* * Kill the mta session. */ log_debug("mta: %p: session done", s); io_clear(&s->io); iobuf_clear(&s->iobuf); if (s->task) fatalx("current task should have been deleted already"); if (s->datafp) fclose(s->datafp); s->datafp = NULL; while ((host = TAILQ_FIRST(&s->hosts))) { TAILQ_REMOVE(&s->hosts, host, entry); free(host); } route = s->route; tree_xpop(&sessions, s->id); free(s); stat_decrement("mta.session", 1); mta_route_collect(route); break; case MTA_SMTP_BANNER: /* just wait for banner */ s->is_reading = 1; io_set_read(&s->io); break; case MTA_SMTP_EHLO: s->ext = 0; mta_send(s, "EHLO %s", env->sc_hostname); break; case MTA_SMTP_HELO: s->ext = 0; mta_send(s, "HELO %s", env->sc_hostname); break; case MTA_SMTP_STARTTLS: if (s->flags & MTA_TLS) /* already started */ mta_enter_state(s, MTA_SMTP_AUTH); else if ((s->ext & MTA_EXT_STARTTLS) == 0) /* server doesn't support starttls, do not use it */ mta_enter_state(s, MTA_SMTP_AUTH); else mta_send(s, "STARTTLS"); break; case MTA_SMTP_AUTH: if (s->secret && s->flags & MTA_TLS) mta_send(s, "AUTH PLAIN %s", s->secret); else if (s->secret) { log_debug("mta: %p: not using AUTH on non-TLS session", s); mta_enter_state(s, MTA_CONNECT); } else { mta_enter_state(s, MTA_SMTP_READY); } break; case MTA_SMTP_READY: /* ready to send a new mail */ if (s->ready == 0) { s->ready = 1; mta_route_ok(s->route); } if (s->msgcount >= s->route->maxmail) { log_debug("mta: %p: cannot send more message to %s", s, mta_route_to_text(s->route)); mta_enter_state(s, MTA_SMTP_QUIT); } else if ((s->task = TAILQ_FIRST(&s->route->tasks))) { log_debug("mta: %p: handling next task for %s", s, mta_route_to_text(s->route)); TAILQ_REMOVE(&s->route->tasks, s->task, entry); s->route->ntask -= 1; s->task->session = s; stat_decrement("mta.task", 1); stat_increment("mta.task.running", 1); mta_enter_state(s, MTA_DATA); } else { log_debug("mta: %p: no pending task for %s", s, mta_route_to_text(s->route)); /* XXX stay open for a while? */ mta_enter_state(s, MTA_SMTP_QUIT); } break; case MTA_SMTP_MAIL: if (s->task->sender.user[0] && s->task->sender.domain[0]) mta_send(s, "MAIL FROM: <%s@%s>", s->task->sender.user, s->task->sender.domain); else mta_send(s, "MAIL FROM: <>"); break; case MTA_SMTP_RCPT: if (s->currevp == NULL) s->currevp = TAILQ_FIRST(&s->task->envelopes); mta_send(s, "RCPT TO: <%s@%s>", s->currevp->dest.user, s->currevp->dest.domain); break; case MTA_SMTP_DATA: fseek(s->datafp, 0, SEEK_SET); mta_send(s, "DATA"); break; case MTA_SMTP_BODY: if (s->datafp == NULL) { log_trace(TRACE_MTA, "mta: %p: end-of-file", s); mta_enter_state(s, MTA_SMTP_DONE); break; } if ((q = mta_queue_data(s)) == -1) { mta_enter_state(s, MTA_DONE); break; } log_trace(TRACE_MTA, "mta: %p: >>> [...%zi bytes...]", s, q); break; case MTA_SMTP_DONE: mta_send(s, "."); break; case MTA_SMTP_QUIT: mta_send(s, "QUIT"); break; case MTA_SMTP_RSET: mta_send(s, "RSET"); break; default: fatalx("mta_enter_state: unknown state"); } #undef mta_enter_state }
/* 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_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 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_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 *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 */ 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); } }