static void panic (char const *errmsg) { int e = errno ; selfpipe_finish() ; errno = e ; panicnosp(errmsg) ; }
static inline void tryfinish (int islast) { register pid_t pid = fork() ; if (pid < 0) { strerr_warnwu2sys("fork for ", "./finish") ; if (islast) bail() ; state = DOWN ; settimeout(1) ; return ; } else if (!pid) { char fmt0[UINT_FMT] ; char fmt1[UINT_FMT] ; char *cargv[4] = { "finish", fmt0, fmt1, 0 } ; selfpipe_finish() ; fmt0[uint_fmt(fmt0, WIFSIGNALED(status.wstat) ? 256 : WEXITSTATUS(status.wstat))] = 0 ; fmt1[uint_fmt(fmt1, WTERMSIG(status.wstat))] = 0 ; if (flagsetsid) setsid() ; execve("./finish", cargv, (char *const *)environ) ; _exit(127) ; } status.pid = pid ; status.flagfinishing = 1 ; state = islast ? LASTFINISH : FINISH ; }
static void trystart (void) { int p[2] ; pid_t pid ; if (pipecoe(p) < 0) { settimeout(60) ; strerr_warnwu1sys("pipecoe (waiting 60 seconds)") ; return ; } pid = fork() ; if (pid < 0) { settimeout(60) ; strerr_warnwu1sys("fork (waiting 60 seconds)") ; fd_close(p[1]) ; fd_close(p[0]) ; return ; } else if (!pid) { char const *cargv[2] = { "run", 0 } ; PROG = "s6-supervise (child)" ; selfpipe_finish() ; fd_close(p[0]) ; if (unlink(S6_SUPERVISE_READY_FILENAME) < 0 && errno != ENOENT) strerr_warnwu1sys("unlink " S6_SUPERVISE_READY_FILENAME) ; if (flagsetsid) setsid() ; execve("./run", (char *const *)cargv, (char *const *)environ) ; fd_write(p[1], "", 1) ; strerr_dieexec(127, "run") ; } fd_close(p[1]) ; { char c ; switch (fd_read(p[0], &c, 1)) { case -1 : fd_close(p[0]) ; settimeout(60) ; strerr_warnwu1sys("read pipe (waiting 60 seconds)") ; kill(pid, SIGKILL) ; return ; case 1 : { fd_close(p[0]) ; settimeout(10) ; strerr_warnwu1x("spawn ./run - waiting 10 seconds") ; return ; } } } fd_close(p[0]) ; settimeout_infinite() ; state = UP ; status.pid = pid ; tain_copynow(&status.stamp) ; announce() ; ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "u", 1) ; }
static void trystart (unsigned int i, char const *name, int islog) { int pid = fork() ; switch (pid) { case -1 : tain_addsec_g(&services[i].restartafter[islog], CHECK_RETRY_TIMEOUT) ; strerr_warnwu2sys("fork for ", name) ; return ; case 0 : { char const *cargv[3] = { "s6-supervise", name, 0 } ; PROG = "s6-svscan (child)" ; selfpipe_finish() ; if (services[i].flaglog) if (fd_move(!islog, services[i].p[!islog]) == -1) strerr_diefu2sys(111, "set fds for ", name) ; pathexec_run(S6_BINPREFIX "s6-supervise", cargv, (char const **)environ) ; strerr_dieexec(111, S6_BINPREFIX "s6-supervise") ; } } services[i].pid[islog] = pid ; }
int main(int argc, char **argv) { int status; int idx; int active_last = 0; int active = 0; struct redir_t *redir; int keep_going = 1; int reload_config = 0; uint8_t hwaddr[6]; struct ifreq ifr; int selfpipe; int fd = socket(AF_INET, SOCK_DGRAM, 0); options_init(); chilli_signals(&keep_going, &reload_config); process_options(argc, argv, 1); safe_strncpy(ifr.ifr_name, _options.dhcpif, sizeof(ifr.ifr_name)); #ifdef SIOCGIFHWADDR if (ioctl(fd, SIOCGIFHWADDR, (caddr_t)&ifr) == 0) { memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, PKT_ETH_ALEN); } else { log_err(errno, "could not get MAC address"); return -1; } #endif close(fd); /* create an instance of redir */ if (redir_new(&redir, &_options.uamlisten, _options.uamport, #ifdef ENABLE_UAMUIPORT _options.uamuiport #else 0 #endif )) { log_err(0, "Failed to create redir"); return -1; } if (redir_listen(redir)) { log_err(0, "Failed to create redir listen"); return -1; } redir_set(redir, hwaddr, (_options.debug)); redir_set_cb_getstate(redir, sock_redir_getstate); redir->cb_handle_url = redir_handle_url; if (net_select_init(&sctx)) log_err(errno, "select init"); selfpipe = selfpipe_init(); /* epoll */ net_select_addfd(&sctx, selfpipe, SELECT_READ); net_select_addfd(&sctx, redir->fd[0], SELECT_READ); net_select_addfd(&sctx, redir->fd[1], SELECT_READ); if (_options.gid && setgid(_options.gid)) { log_err(errno, "setgid(%d) failed while running with gid = %d\n", _options.gid, getgid()); } if (_options.uid && setuid(_options.uid)) { log_err(errno, "setuid(%d) failed while running with uid = %d\n", _options.uid, getuid()); } while (keep_going) { /* select/poll */ net_select_zero(&sctx); net_select_fd(&sctx, selfpipe, SELECT_READ); net_select_fd(&sctx, redir->fd[0], SELECT_READ); net_select_fd(&sctx, redir->fd[1], SELECT_READ); active = 0; if (reload_config) { reload_options(argc, argv); reload_config = 0; redir_set(redir, hwaddr, _options.debug); } for (idx=0; idx < max_requests; idx++) { conn_select_fd(&requests[idx].conn, &sctx); if (requests[idx].inuse && requests[idx].socket_fd) { time_t now = mainclock_tick(); int fd = requests[idx].socket_fd; int timeout = 60; if (now - requests[idx].last_active > timeout) { log_dbg("timeout connection %d", idx); redir_conn_finish(&requests[idx].conn, &requests[idx]); } else { int evt = SELECT_READ; timeout = 0; if (conn_write_remaining(&requests[idx].conn)) evt |= SELECT_WRITE; net_select_fd(&sctx, fd, evt); active++; } #if(_debug_ > 1) if (_options.debug) { struct sockaddr_in address; socklen_t addrlen = sizeof(address); if (getpeername(fd, (struct sockaddr *)&address, &addrlen) >= 0) { char line[512]; safe_snprintf(line, sizeof(line), "#%d (%d) %d connection from %s %d", timeout ? -1 : active, fd, (int) requests[idx].last_active, inet_ntoa(address.sin_addr), ntohs(address.sin_port)); if (requests[idx].conn.sock) { addrlen = sizeof(address); if (getpeername(requests[idx].conn.sock, (struct sockaddr *)&address, &addrlen) >= 0) { safe_snprintf(line+strlen(line), sizeof(line)-strlen(line), " to %s %d", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); } } if (timeout) { safe_snprintf(line+strlen(line), sizeof(line)-strlen(line), " (timeout)"); } log_dbg("%s", line); } } #endif } } if (active != active_last) { log_dbg("active connections: %d", active); active_last = active; } status = net_select(&sctx); #if defined(USING_POLL) && defined(HAVE_SYS_EPOLL_H) && (_debug_ > 1) if (_options.debug && status > 0) { int i; log_dbg("epoll %d", status); for (i=0; i < status; i++) { log_dbg("epoll fd %d %d", sctx.events[i].data.fd, sctx.events[i].events); } } #endif switch (status) { case -1: log_err(errno, "select() returned -1!"); break; default: if (status > 0) { if (net_select_read_fd(&sctx, selfpipe)==1) { chilli_handle_signal(0, 0); } if (redir->fd[0]) if (net_select_read_fd(&sctx, redir->fd[0])==1 && redir_accept2(redir, 0) < 0) log_err(0, "redir_accept() failed!"); if (redir->fd[1]) if (net_select_read_fd(&sctx, redir->fd[1])==1 && redir_accept2(redir, 1) < 0) log_err(0, "redir_accept() failed!"); for (idx=0; idx < max_requests; idx++) { /* * Update remote connections with activity */ conn_select_update(&requests[idx].conn, &sctx); /* * Check client connections with activity */ if (requests[idx].inuse && requests[idx].socket_fd) { int fd = requests[idx].socket_fd; #ifdef HAVE_SSL if (requests[idx].sslcon) { if (openssl_check_accept(requests[idx].sslcon, 0) < 0) { log_dbg("ssl error %d", errno); redir_conn_finish(&requests[idx].conn, &requests[idx]); continue; } } #endif switch (net_select_write_fd(&sctx, fd)) { case 1: log_dbg("client writeable"); redir_cli_rewrite(&requests[idx], &requests[idx].conn); break; } switch (net_select_read_fd(&sctx, fd)) { case -1: log_dbg("EXCEPTION"); redir_conn_finish(&requests[idx].conn, &requests[idx]); break; case 1: { if (requests[idx].proxy) { char b[PKT_MAX_LEN]; int r; #ifdef HAVE_SSL if (requests[idx].sslcon) { /* log_dbg("proxy_read_ssl"); */ r = openssl_read(requests[idx].sslcon, b, sizeof(b)-1, 0); } else #endif r = safe_read(fd, b, sizeof(b)-1); /* log_dbg("proxy_read: %d %d", fd, r); */ if (r <= 0) { log_dbg("recv %d %d %d", r, requests[idx].conn.read_buf->slen - requests[idx].conn.read_pos, errno); if (!(r == -1 && (errno == EWOULDBLOCK || errno == EAGAIN))) { if (redir_cli_rewrite(&requests[idx], &requests[idx].conn) == 0) { log_dbg("done reading and writing"); redir_conn_finish(&requests[idx].conn, &requests[idx]); } } } else if (r > 0) { int w; requests[idx].last_active = mainclock_tick(); w = net_write(requests[idx].conn.sock, b, r); /* log_dbg("proxy_write: %d", w); */ if (r != w) { log_err(errno, "problem writing what we read from client"); redir_conn_finish(&requests[idx].conn, &requests[idx]); } } } else { #ifdef HAVE_SSL go_again: #endif switch (redir_main(redir, fd, fd, &requests[idx].conn.peer, &requests[idx].baddr, requests[idx].uiidx, &requests[idx])) { case 1: /*log_dbg("redir cont'ed");*/ #ifdef HAVE_SSL if (requests[idx].sslcon && openssl_pending(requests[idx].sslcon) > 0) { log_dbg("ssl_pending, trying again"); goto go_again; } #endif break; case -1: log_dbg("redir error"); default: log_dbg("redir completed"); redir_conn_finish(&requests[idx].conn, &requests[idx]); break; } } } break; } } } } break; } } redir_free(redir); child_killall(SIGKILL); selfpipe_finish(); return 0; }
int main(int argc, char **argv) { struct radius_packet_t radius_pack; struct in_addr radiuslisten; struct timeval timeout; int maxfd = 0; fd_set fdread; fd_set fdwrite; fd_set fdexcep; ssize_t status; int keep_going = 1; int reload_config = 1; int selfpipe; options_init(); selfpipe = selfpipe_init(); chilli_signals(&keep_going, &reload_config); process_options(argc, argv, 1); radiuslisten.s_addr = htonl(INADDR_ANY); memset(&server, 0, sizeof(server)); if (!(server.env = initssl_cli())) { syslog(LOG_ERR, "Failed to create ssl environment"); return -1; } if (radius_new(&server.radius_auth, &radiuslisten, _options.radiusauthport ? _options.radiusauthport : RADIUS_AUTHPORT, 0, 0)) { syslog(LOG_ERR, "Failed to create radius"); return -1; } if (radius_new(&server.radius_acct, &radiuslisten, _options.radiusacctport ? _options.radiusacctport : RADIUS_ACCTPORT, 0, 0)) { syslog(LOG_ERR, "Failed to create radius"); return -1; } if (_options.coaport) { if (radius_new(&server.radius_cli, &radiuslisten, 0, 0, 0) || radius_init_q(server.radius_cli, 8)) { syslog(LOG_ERR, "Failed to create radius"); return -1; } radius_set(server.radius_cli, 0, 0); radius_set_cb_auth_conf(server.radius_cli, cb_radius_auth_conf); } radius_set(server.radius_auth, 0, 0); radius_set(server.radius_acct, 0, 0); if (_options.gid && setgid(_options.gid)) { syslog(LOG_ERR, "%d setgid(%d) failed while running with gid = %d\n", errno, _options.gid, getgid()); } if (_options.uid && setuid(_options.uid)) { syslog(LOG_ERR, "%d setuid(%d) failed while running with uid = %d\n", errno, _options.uid, getuid()); } while (keep_going) { if (reload_config) { reload_options(argc, argv); reload_config = 0; } FD_ZERO(&fdread); FD_ZERO(&fdwrite); FD_ZERO(&fdexcep); FD_SET(selfpipe, &fdread); FD_SET(server.radius_auth->fd, &fdread); FD_SET(server.radius_acct->fd, &fdread); if (server.radius_auth->fd > maxfd) maxfd = server.radius_auth->fd; if (server.radius_acct->fd > maxfd) maxfd = server.radius_acct->fd; if (server.conn.sock) { FD_SET(server.conn.sock, &fdread); if (server.conn.sock > maxfd) maxfd = server.conn.sock; } if (server.radius_cli) { FD_SET(server.radius_cli->fd, &fdread); if (server.radius_cli->fd > maxfd) maxfd = server.radius_cli->fd; } timeout.tv_sec = 1; timeout.tv_usec = 0; status = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); switch (status) { case -1: if (errno != EINTR) syslog(LOG_ERR, "%s: select() returned -1!", strerror(errno)); break; case 0: default: if (status > 0) { struct sockaddr_in addr; socklen_t fromlen = sizeof(addr); if (FD_ISSET(selfpipe, &fdread)) { chilli_handle_signal(0, 0); } if (FD_ISSET(server.radius_auth->fd, &fdread)) { /* * ---> Authentication */ if ((status = recvfrom(server.radius_auth->fd, &radius_pack, sizeof(radius_pack), 0, (struct sockaddr *) &addr, &fromlen)) <= 0) { syslog(LOG_ERR, "%s: recvfrom() failed", strerror(errno)); return -1; } memcpy(&server.auth_peer, &addr, sizeof(addr)); process_radius(&radius_pack, status); } if (FD_ISSET(server.radius_acct->fd, &fdread)) { /* * ---> Accounting */ syslog(LOG_DEBUG, "received accounting"); if ((status = recvfrom(server.radius_acct->fd, &radius_pack, sizeof(radius_pack), 0, (struct sockaddr *) &addr, &fromlen)) <= 0) { syslog(LOG_ERR, "%s: recvfrom() failed", strerror(errno)); return -1; } memcpy(&server.acct_peer, &addr, sizeof(addr)); process_radius(&radius_pack, status); } if (server.radius_cli) { if (FD_ISSET(server.radius_cli->fd, &fdread)) { radius_decaps(server.radius_cli, 0); } } if (server.conn.sock) { if (FD_ISSET(server.conn.sock, &fdread)) { process_radius_reply(); } } } break; } } selfpipe_finish(); return 0; }
int main (int argc, char const *const *argv) { iopause_fd x[2] = { { -1, IOPAUSE_READ, 0 }, { -1, IOPAUSE_READ, 0 } } ; PROG = "s6-svscan" ; { subgetopt_t l = SUBGETOPT_ZERO ; unsigned int t = 5000 ; for (;;) { register int opt = subgetopt_r(argc, argv, "t:c:", &l) ; if (opt == -1) break ; switch (opt) { case 't' : if (uint0_scan(l.arg, &t)) break ; case 'c' : if (uint0_scan(l.arg, &max)) break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; if (t) tain_from_millisecs(&defaulttimeout, t) ; else defaulttimeout = tain_infinite_relative ; if (max < 2) max = 2 ; } /* Init phase. If something fails here, we can die, because it means that something is seriously wrong with the system, and we can't run correctly anyway. */ if (argc && (chdir(argv[0]) < 0)) strerr_diefu1sys(111, "chdir") ; x[1].fd = s6_supervise_lock(S6_SVSCAN_CTLDIR) ; x[0].fd = selfpipe_init() ; if (x[0].fd < 0) strerr_diefu1sys(111, "selfpipe_init") ; if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ; { sigset_t set ; sigemptyset(&set) ; sigaddset(&set, SIGCHLD) ; sigaddset(&set, SIGALRM) ; sigaddset(&set, SIGTERM) ; sigaddset(&set, SIGHUP) ; sigaddset(&set, SIGQUIT) ; sigaddset(&set, SIGABRT) ; sigaddset(&set, SIGINT) ; sigaddset(&set, SIGUSR1) ; if (selfpipe_trapset(&set) < 0) strerr_diefu1sys(111, "trap signals") ; } { struct svinfo_s blob[max] ; /* careful with that stack, Eugene */ services = blob ; tain_now_g() ; /* Loop phase. From now on, we must not die. Temporize on recoverable errors, and panic on serious ones. */ while (cont) { int r ; tain_add_g(&deadline, &defaulttimeout) ; reap() ; scan() ; killthem() ; r = iopause_g(x, 2, &deadline) ; if (r < 0) panic("iopause") ; else if (!r) wantscan = 1 ; else { if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) { errno = EIO ; panic("check internal pipes") ; } if (x[0].revents & IOPAUSE_READ) handle_signals() ; if (x[1].revents & IOPAUSE_READ) handle_control(x[1].fd) ; } } /* Finish phase. */ selfpipe_finish() ; killthem() ; reap() ; } { char const *eargv[3] = { FINISH_PROG, finish_arg, 0 } ; execve(eargv[0], (char **)eargv, (char *const *)environ) ; } panicnosp("exec finish script " FINISH_PROG) ; }