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");
}
예제 #2
0
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);
}
예제 #3
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);
}
예제 #4
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));
}
예제 #5
0
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);
}
예제 #6
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);
}
예제 #7
0
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));
}
예제 #8
0
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;
}