static void filter_api_init(void) { extern const char *__progname; struct passwd *pw; static int init = 0; if (init) return; init = 1; pw = getpwnam(SMTPD_USER); if (pw == NULL) err(1, "getpwnam"); smtpd_process = PROC_FILTER; filter_name = __progname; tree_init(&queries); event_init(); bzero(&fi, sizeof(fi)); fi.p.proc = PROC_MFA; fi.p.name = "filter"; fi.p.handler = filter_dispatch; fi.uid = pw->pw_uid; fi.gid = pw->pw_gid; fi.rootpath = PATH_CHROOT; mproc_init(&fi.p, 0); }
void config_peer(enum smtp_proc_type proc) { struct mproc *p; if (proc == smtpd_process) fatal("config_peers: cannot peer with oneself"); p = xcalloc(1, sizeof *p, "config_peer"); p->proc = proc; p->name = xstrdup(proc_name(proc), "config_peer"); p->handler = imsg_dispatch; mproc_init(p, pipes[smtpd_process][proc]); mproc_enable(p); pipes[smtpd_process][proc] = -1; if (proc == PROC_CONTROL) p_control = p; else if (proc == PROC_LKA) p_lka = p; else if (proc == PROC_PARENT) p_parent = p; else if (proc == PROC_QUEUE) p_queue = p; else if (proc == PROC_SCHEDULER) p_scheduler = p; else if (proc == PROC_PONY) p_pony = p; else if (proc == PROC_CA) p_ca = p; else fatalx("bad peer"); }
int mproc_fork(struct mproc *p, const char *path, char *argv[]) { int sp[2]; if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0) return (-1); io_set_nonblocking(sp[0]); io_set_nonblocking(sp[1]); if ((p->pid = fork()) == -1) goto err; if (p->pid == 0) { /* child process */ dup2(sp[0], STDIN_FILENO); if (closefrom(STDERR_FILENO + 1) < 0) exit(1); execv(path, argv); err(1, "execv: %s", path); } /* parent process */ close(sp[0]); mproc_init(p, sp[1]); return (0); err: log_warn("warn: Failed to start process %s, instance of %s", argv[0], path); close(sp[0]); close(sp[1]); return (-1); }
/* ARGSUSED */ static void control_accept(int listenfd, short event, void *arg) { int connfd; socklen_t len; struct sockaddr_un sun; struct ctl_conn *c; if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE) goto pause; len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { if (errno == ENFILE || errno == EMFILE) goto pause; if (errno == EINTR || errno == EWOULDBLOCK || errno == ECONNABORTED) return; fatal("control_accept: accept"); } session_socket_blockmode(connfd, BM_NONBLOCK); c = xcalloc(1, sizeof(*c), "control_accept"); if (getpeereid(connfd, &c->euid, &c->egid) == -1) fatal("getpeereid"); c->id = ++connid; c->mproc.proc = PROC_CLIENT; c->mproc.handler = control_dispatch_ext; c->mproc.data = c; mproc_init(&c->mproc, connfd); mproc_enable(&c->mproc); tree_xset(&ctl_conns, c->id, c); stat_backend->increment("control.session", 1); return; pause: log_warnx("warn: ctl client limit hit, disabling new connections"); event_del(&control_state.ev); }
static void filter_api_init(void) { extern const char *__progname; struct passwd *pw; static int init = 0; if (init) return; init = 1; log_init(-1); log_verbose(1); pw = getpwnam(SMTPD_USER); if (pw == NULL) { log_warn("warn: filter-api:%s getpwnam", filter_name); fatalx("filter-api: exiting"); } smtpd_process = PROC_FILTER; filter_name = __progname; tree_init(&queries); tree_init(&sessions); event_init(); memset(&fi, 0, sizeof(fi)); fi.p.proc = PROC_PONY; fi.p.name = "filter"; fi.p.handler = filter_dispatch; fi.uid = pw->pw_uid; fi.gid = pw->pw_gid; fi.rootpath = PATH_CHROOT; /* XXX just for now */ fi.hooks = ~0; mproc_init(&fi.p, 0); }
/* ARGSUSED */ static void control_accept(int listenfd, short event, void *arg) { int connfd; socklen_t len; struct sockaddr_un s_un; struct ctl_conn *c; size_t *count; uid_t euid; gid_t egid; if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE) goto pause; len = sizeof(s_un); if ((connfd = accept(listenfd, (struct sockaddr *)&s_un, &len)) == -1) { if (errno == ENFILE || errno == EMFILE) goto pause; if (errno == EINTR || errno == EWOULDBLOCK || errno == ECONNABORTED) return; fatal("control_accept: accept"); } io_set_nonblocking(connfd); if (getpeereid(connfd, &euid, &egid) == -1) fatal("getpeereid"); count = tree_get(&ctl_count, euid); if (count == NULL) { count = xcalloc(1, sizeof *count, "control_accept"); tree_xset(&ctl_count, euid, count); } if (*count == CONTROL_MAXCONN_PER_CLIENT) { close(connfd); log_warnx("warn: too many connections to control socket " "from user with uid %lu", (unsigned long int)euid); return; } (*count)++; do { ++connid; } while (tree_get(&ctl_conns, connid)); c = xcalloc(1, sizeof(*c), "control_accept"); c->euid = euid; c->egid = egid; c->id = connid; c->mproc.proc = PROC_CLIENT; c->mproc.handler = control_dispatch_ext; c->mproc.data = c; mproc_init(&c->mproc, connfd); mproc_enable(&c->mproc); tree_xset(&ctl_conns, c->id, c); stat_backend->increment("control.session", 1); return; pause: log_warnx("warn: ctl client limit hit, disabling new connections"); event_del(&control_state.ev); }