void MGT_Run(void) { struct sigaction sac; struct vev *e; int i; mgt_uptime_t0 = VTIM_real(); e = vev_new(); XXXAN(e); e->callback = mgt_uptime; e->timeout = 1.0; e->name = "mgt_uptime"; AZ(vev_add(mgt_evb, e)); e = vev_new(); XXXAN(e); e->sig = SIGTERM; e->callback = mgt_sigint; e->name = "mgt_sigterm"; AZ(vev_add(mgt_evb, e)); e = vev_new(); XXXAN(e); e->sig = SIGINT; e->callback = mgt_sigint; e->name = "mgt_sigint"; AZ(vev_add(mgt_evb, e)); #ifdef HAVE_SETPROCTITLE setproctitle("Varnish-Mgr %s", heritage.name); #endif memset(&sac, 0, sizeof sac); sac.sa_handler = SIG_IGN; sac.sa_flags = SA_RESTART; AZ(sigaction(SIGPIPE, &sac, NULL)); AZ(sigaction(SIGHUP, &sac, NULL)); if (!d_flag && !mgt_has_vcl()) MGT_complain(C_ERR, "No VCL loaded yet"); else if (!d_flag) { mgt_launch_child(NULL); if (child_state != CH_RUNNING) { // XXX correct? or 0? exit_status = 2; return; } } mgt_SHM_Commit(); i = vev_schedule(mgt_evb); if (i != 0) MGT_complain(C_ERR, "vev_schedule() = %d", i); MGT_complain(C_INFO, "manager dies"); }
Marg_poker(const struct vev *e, int what) { int s; struct m_addr *ma; assert(e == M_poker); (void)what; M_poker->timeout = M_poll; /* XXX nasty ? */ if (M_fd > 0) return (0); ma = VTAILQ_FIRST(&m_addr_list); AN(ma); /* Try to connect asynchronously */ s = VTCP_connect(ma->sa, -1); if (s < 0) return (0); mgt_got_fd(s); M_conn = vev_new(); AN(M_conn); M_conn->callback = Marg_connect; M_conn->name = "-M connector"; M_conn->fd_flags = EV_WR; M_conn->fd = s; M_fd = s; AZ(vev_add(mgt_evb, M_conn)); return (0); }
mct_callback(void *priv, const struct suckaddr *sa) { int sock; struct vsb *vsb = priv; const char *err; char abuf[VTCP_ADDRBUFSIZE]; char pbuf[VTCP_PORTBUFSIZE]; struct telnet *tn; VJ_master(JAIL_MASTER_PRIVPORT); sock = VTCP_listen(sa, 10, &err); VJ_master(JAIL_MASTER_LOW); assert(sock != 0); // We know where stdin is if (sock > 0) { VTCP_myname(sock, abuf, sizeof abuf, pbuf, sizeof pbuf); VSB_printf(vsb, "%s %s\n", abuf, pbuf); tn = telnet_new(sock); tn->ev = vev_new(); AN(tn->ev); tn->ev->fd = sock; tn->ev->fd_flags = POLLIN; tn->ev->callback = telnet_accept; tn->ev->priv = tn; AZ(vev_add(mgt_evb, tn->ev)); } return (0); }
void mgt_cli_setup(int fdi, int fdo, int verbose, const char *ident, mgt_cli_close_f *closefunc, void *priv) { struct cli *cli; struct vev *ev; (void)ident; (void)verbose; cli = VCLS_AddFd(mgt_cls, fdi, fdo, closefunc, priv); cli->ident = strdup(ident); if (fdi != 0 && secret_file != NULL) { cli->auth = MCF_NOAUTH; mgt_cli_challenge(cli); } else { cli->auth = MCF_AUTH; mcf_banner(cli, NULL, NULL); } AZ(VSB_finish(cli->sb)); (void)VCLI_WriteResult(fdo, cli->result, VSB_data(cli->sb)); ev = vev_new(); AN(ev); ev->name = cli->ident; ev->fd = fdi; ev->fd_flags = EV_RD; ev->callback = mgt_cli_callback2; ev->priv = cli; AZ(vev_add(mgt_evb, ev)); }
static int Marg_poker(const struct vev *e, int what) { struct vsb *vsb; int s, k; socklen_t l; (void)what; /* XXX: ??? */ if (e == M_conn) { /* Our connect(2) returned, check result */ l = sizeof k; AZ(getsockopt(M_fd, SOL_SOCKET, SO_ERROR, &k, &l)); if (k) { errno = k; syslog(LOG_INFO, "Could not connect to CLI-master: %m"); (void)close(M_fd); M_fd = -1; /* Try next address */ if (++M_nxt >= M_nta) { M_nxt = 0; if (M_poll < 10) M_poll *= 2; } return (1); } vsb = sock_id("master", M_fd); mgt_cli_setup(M_fd, M_fd, 0, VSB_data(vsb), Marg_closer, NULL); VSB_delete(vsb); M_poll = 1; return (1); } assert(e == M_poker); M_poker->timeout = M_poll; /* XXX nasty ? */ if (M_fd >= 0) return (0); /* Try to connect asynchronously */ s = VSS_connect(M_ta[M_nxt], 1); if (s < 0) return (0); mgt_got_fd(s); M_conn = vev_new(); AN(M_conn); M_conn->callback = Marg_poker; M_conn->name = "-M connector"; M_conn->fd_flags = EV_WR; M_conn->fd = s; M_fd = s; AZ(vev_add(mgt_evb, M_conn)); return (0); }
void mgt_cli_telnet(const char *T_arg) { struct vss_addr **ta; int i, n, sock, good; struct telnet *tn; char *p; struct vsb *vsb; char abuf[VTCP_ADDRBUFSIZE]; char pbuf[VTCP_PORTBUFSIZE]; n = VSS_resolve(T_arg, NULL, &ta); if (n == 0) { REPORT(LOG_ERR, "-T %s Could not be resolved\n", T_arg); exit(2); } good = 0; vsb = VSB_new_auto(); XXXAN(vsb); for (i = 0; i < n; ++i) { sock = VSS_listen(ta[i], 10); if (sock < 0) continue; VTCP_myname(sock, abuf, sizeof abuf, pbuf, sizeof pbuf); VSB_printf(vsb, "%s %s\n", abuf, pbuf); good++; tn = telnet_new(sock); tn->ev = vev_new(); XXXAN(tn->ev); tn->ev->fd = sock; tn->ev->fd_flags = POLLIN; tn->ev->callback = telnet_accept; AZ(vev_add(mgt_evb, tn->ev)); free(ta[i]); ta[i] = NULL; } free(ta); if (good == 0) { REPORT(LOG_ERR, "-T %s could not be listened on.", T_arg); exit(2); } AZ(VSB_finish(vsb)); /* Save in shmem */ p = VSM_Alloc(VSB_len(vsb) + 1, "Arg", "-T", ""); AN(p); strcpy(p, VSB_data(vsb)); VSB_delete(vsb); }
void mgt_cli_master(const char *M_arg) { (void)M_arg; M_nta = VSS_resolve(M_arg, NULL, &M_ta); if (M_nta <= 0) { fprintf(stderr, "Could resolve -M argument to address\n"); exit (1); } M_nxt = 0; AZ(M_poker); M_poker = vev_new(); AN(M_poker); M_poker->timeout = M_poll; M_poker->callback = Marg_poker; M_poker->name = "-M poker"; AZ(vev_add(mgt_evb, M_poker)); }
void mgt_cli_master(const char *M_arg) { const char *err; int error; AN(M_arg); error = VSS_resolver(M_arg, NULL, marg_cb, NULL, &err); if (err != NULL) ARGV_ERR("Could resolve -M argument to address\n\t%s\n", err); AZ(error); if (VTAILQ_EMPTY(&m_addr_list)) ARGV_ERR("Could not resolve -M argument to address\n"); AZ(M_poker); M_poker = vev_new(); AN(M_poker); M_poker->timeout = M_poll; M_poker->callback = Marg_poker; M_poker->name = "-M poker"; AZ(vev_add(mgt_evb, M_poker)); }
static void mgt_launch_child(struct cli *cli) { pid_t pid; unsigned u; char *p; struct vev *e; int i, j, k, cp[2]; struct sigaction sa; if (child_state != CH_STOPPED && child_state != CH_DIED) return; if (!MAC_sockets_ready(cli)) { child_state = CH_STOPPED; if (cli != NULL) { VCLI_SetResult(cli, CLIS_CANT); return; } MGT_complain(C_ERR, "Child start failed: could not open sockets"); return; } child_state = CH_STARTING; /* Open pipe for mgr->child CLI */ AZ(pipe(cp)); heritage.cli_in = cp[0]; mgt_child_inherit(heritage.cli_in, "cli_in"); child_cli_out = cp[1]; /* Open pipe for child->mgr CLI */ AZ(pipe(cp)); heritage.cli_out = cp[1]; mgt_child_inherit(heritage.cli_out, "cli_out"); child_cli_in = cp[0]; /* * Open pipe for child stdout/err * NB: not inherited, because we dup2() it to stdout/stderr in child */ AZ(pipe(cp)); heritage.std_fd = cp[1]; child_output = cp[0]; AN(heritage.vsm); mgt_SHM_Size_Adjust(); AN(heritage.vsm); AN(heritage.param); if ((pid = fork()) < 0) { /* XXX */ perror("Could not fork child"); exit(1); } if (pid == 0) { /* Redirect stdin/out/err */ AZ(close(STDIN_FILENO)); assert(open("/dev/null", O_RDONLY) == STDIN_FILENO); assert(dup2(heritage.std_fd, STDOUT_FILENO) == STDOUT_FILENO); assert(dup2(heritage.std_fd, STDERR_FILENO) == STDERR_FILENO); /* * Close all FDs the child shouldn't know about * * We cannot just close these filedescriptors, some random * library routine might miss it later on and wantonly close * a FD we use at that point in time. (See bug #1841). * We close the FD and replace it with /dev/null instead, * That prevents security leakage, and gives the library * code a valid FD to close when it discovers the changed * circumstances. */ closelog(); for (i = STDERR_FILENO + 1; i < CLOSE_FD_UP_TO; i++) { if (vbit_test(fd_map, i)) continue; if (close(i) == 0) { k = open("/dev/null", O_RDONLY); assert(k >= 0); j = dup2(k, i); assert(j == i); AZ(close(k)); } } #ifdef HAVE_SETPROCTITLE setproctitle("Varnish-Chld %s", heritage.name); #endif if (mgt_param.sigsegv_handler) { memset(&sa, 0, sizeof sa); sa.sa_sigaction = child_sigsegv_handler; sa.sa_flags = SA_SIGINFO; (void)sigaction(SIGSEGV, &sa, NULL); (void)sigaction(SIGBUS, &sa, NULL); (void)sigaction(SIGABRT, &sa, NULL); } (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); VJ_subproc(JAIL_SUBPROC_WORKER); child_main(); exit(0); } assert(pid > 1); MGT_complain(C_DEBUG, "Child (%jd) Started", (intmax_t)pid); VSC_C_mgt->child_start = ++static_VSC_C_mgt.child_start; /* Close stuff the child got */ closex(&heritage.std_fd); mgt_child_inherit(heritage.cli_in, NULL); closex(&heritage.cli_in); mgt_child_inherit(heritage.cli_out, NULL); closex(&heritage.cli_out); child_std_vlu = VLU_New(NULL, child_line, 0); AN(child_std_vlu); AZ(ev_listen); e = vev_new(); XXXAN(e); e->fd = child_output; e->fd_flags = EV_RD; e->name = "Child listener"; e->callback = child_listener; AZ(vev_add(mgt_evb, e)); ev_listen = e; AZ(ev_poker); if (mgt_param.ping_interval > 0) { e = vev_new(); XXXAN(e); e->timeout = mgt_param.ping_interval; e->callback = child_poker; e->name = "child poker"; AZ(vev_add(mgt_evb, e)); ev_poker = e; } mgt_cli_start_child(child_cli_in, child_cli_out); child_pid = pid; if (mgt_push_vcls_and_start(cli, &u, &p)) { VCLI_SetResult(cli, u); MGT_complain(C_ERR, "Child (%jd) Pushing vcls failed:\n%s", (intmax_t)child_pid, p); free(p); child_state = CH_RUNNING; mgt_stop_child(); } else child_state = CH_RUNNING; }