Пример #1
0
/* ARGSUSED */
void
client_callback(unused int fd, short events, unused void *data)
{
	ssize_t	n;

	if (events & EV_READ) {
		if ((n = imsg_read(&client_ibuf)) == -1 || n == 0)
			goto lost_server;
		if (client_dispatch() != 0) {
			event_loopexit(NULL);
			return;
		}
	}

	if (events & EV_WRITE) {
		if (msgbuf_write(&client_ibuf.w) < 0)
			goto lost_server;
	}

	client_update_event();
	return;

lost_server:
	client_exitmsg = "lost server";
	client_exitval = 1;
	event_loopexit(NULL);
}
Пример #2
0
int
imsg_flush(struct imsgbuf *ibuf)
{
	while (ibuf->w.queued)
		if (msgbuf_write(&ibuf->w) <= 0)
			return (-1);
	return (0);
}
Пример #3
0
void
imsgev_dispatch(int fd, short ev, void *humppa)
{
	struct imsgev	*iev = humppa;
	struct imsgbuf	*ibuf = &iev->ibuf;
	struct imsg	 imsg;
	ssize_t		 n;

	iev->events = 0;

	if (ev & EV_READ) {
		if ((n = imsg_read(ibuf)) == -1) {
			imsgev_disconnect(iev, IMSGEV_EREAD);
			return;
		}
		if (n == 0) {
			/*
			 * Connection is closed for reading, and we assume
			 * it is also closed for writing, so we error out
			 * if write data is pending.
			 */
			imsgev_disconnect(iev,
			    (iev->ibuf.w.queued) ? IMSGEV_EWRITE : IMSGEV_DONE);
			return;
		}
	}

	if (ev & EV_WRITE) {
		/*
		 * We wanted to write data out but the connection is either
		 * closed, or some error occured. Both case are not recoverable
		 * from the imsg perspective, so we treat it as a WRITE error.
		 */
		if ((n = msgbuf_write(&ibuf->w)) != 0) {
			imsgev_disconnect(iev, IMSGEV_EWRITE);
			return;
		}
	}

	while (iev->terminate == 0) {
		if ((n = imsg_get(ibuf, &imsg)) == -1) {
			imsgev_disconnect(iev, IMSGEV_EIMSG);
			return;
		}
		if (n == 0)
			break;
		iev->callback(iev, IMSGEV_IMSG, &imsg);
		imsg_free(&imsg);
	}

	if (iev->terminate && iev->ibuf.w.queued == 0) {
		imsgev_disconnect(iev, IMSGEV_DONE);
		return;
	}

	imsgev_add(iev);
}
Пример #4
0
Файл: proc.c Проект: icetan/tmux
static void
proc_event_cb(unused int fd, short events, void *arg)
{
	struct tmuxpeer	*peer = arg;
	ssize_t		 n;
	struct imsg	 imsg;
	int		 v;

	if (!(peer->flags & PEER_BAD) && (events & EV_READ)) {
		if ((n = imsg_read(&peer->ibuf)) == -1 || n == 0) {
			peer->dispatchcb(NULL, peer->arg);
			return;
		}
		for (;;) {
			if ((n = imsg_get(&peer->ibuf, &imsg)) == -1) {
				peer->dispatchcb(NULL, peer->arg);
				return;
			}
			if (n == 0)
				break;
			log_debug("peer %p message %d", peer, imsg.hdr.type);

			v = imsg.hdr.peerid;
			if (imsg.hdr.type != MSG_VERSION &&
			    v != PROTOCOL_VERSION) {
				log_debug("peer %p bad version %d", peer, v);

				proc_send(peer, MSG_VERSION, -1, NULL, 0);
				peer->flags |= PEER_BAD;

				if (imsg.fd != -1)
					close(imsg.fd);
				imsg_free(&imsg);
				break;
			}

			peer->dispatchcb(&imsg, peer->arg);
			imsg_free(&imsg);
		}
	}

	if (events & EV_WRITE) {
		if (msgbuf_write(&peer->ibuf.w) <= 0 && errno != EAGAIN) {
			peer->dispatchcb(NULL, peer->arg);
			return;
		}
	}

	if ((peer->flags & PEER_BAD) && peer->ibuf.w.queued == 0) {
		peer->dispatchcb(NULL, peer->arg);
		return;
	}

	proc_update_event(peer);
}
Пример #5
0
static void
proc_event_cb(__unused int fd, short events, void *arg)
{
	struct tmuxpeer	*peer = arg;
	ssize_t		 n;
	struct imsg	 imsg;

	if (!(peer->flags & PEER_BAD) && (events & EV_READ)) {
		if (((n = imsg_read(&peer->ibuf)) == -1 && errno != EAGAIN) ||
		    n == 0) {
			peer->dispatchcb(NULL, peer->arg);
			return;
		}
		for (;;) {
			if ((n = imsg_get(&peer->ibuf, &imsg)) == -1) {
				peer->dispatchcb(NULL, peer->arg);
				return;
			}
			if (n == 0)
				break;
			log_debug("peer %p message %d", peer, imsg.hdr.type);

			if (peer_check_version(peer, &imsg) != 0) {
				if (imsg.fd != -1)
					close(imsg.fd);
				imsg_free(&imsg);
				break;
			}

			peer->dispatchcb(&imsg, peer->arg);
			imsg_free(&imsg);
		}
	}

	if (events & EV_WRITE) {
		if (msgbuf_write(&peer->ibuf.w) <= 0 && errno != EAGAIN) {
			peer->dispatchcb(NULL, peer->arg);
			return;
		}
	}

	if ((peer->flags & PEER_BAD) && peer->ibuf.w.queued == 0) {
		peer->dispatchcb(NULL, peer->arg);
		return;
	}

	proc_update_event(peer);
}
Пример #6
0
static void
tnt_imsg_callback(evutil_socket_t fd, short events, void *args) {
    (void)fd;
    struct imsg_data *data = args;
    struct imsgbuf *ibuf = data->ibuf;

    if (events & EV_READ || data->is_ready_read == 1) {
        data->is_ready_read = 1;
        if (tnt_dispatch_imsg(data) == -1)
            data->is_ready_read = 0;
    }
    if (events & EV_WRITE || data->is_ready_write == 1) {
        data->is_ready_write = 1;
        if (ibuf->w.queued > 0) {
            if (msgbuf_write(&ibuf->w) == -1)
                data->is_ready_write = 0;
        }
    }
}
Пример #7
0
static int
open_connection(void)
{
	struct imsg	imsg;
	int		fd;
	int		n;

	imsg_compose(ibuf, IMSG_SMTP_ENQUEUE, 0, 0, -1, NULL, 0);

	while (ibuf->w.queued)
		if (msgbuf_write(&ibuf->w) < 0)
			err(1, "write error");

	while (1) {
		if ((n = imsg_read(ibuf)) == -1)
			errx(1, "imsg_read error");
		if (n == 0)
			errx(1, "pipe closed");

		if ((n = imsg_get(ibuf, &imsg)) == -1)
			errx(1, "imsg_get error");
		if (n == 0)
			continue;

		switch (imsg.hdr.type) {
		case IMSG_CTL_OK:
			break;
		case IMSG_CTL_FAIL:
			errx(1, "server disallowed submission request");
		default:
			errx(1, "unexpected imsg reply type");
		}

		fd = imsg.fd;
		imsg_free(&imsg);

		break;
	}

	return fd;
}
Пример #8
0
/*
 * Loop waiting for packets, timeouts or routing messages.
 */
void
dispatch(void)
{
	int count, to_msec;
	struct pollfd fds[3];
	time_t cur_time, howlong;
	void (*func)(void);

	while (quit == 0) {
		/*
		 * Call expired timeout, and then if there's still
		 * a timeout registered, time out the select call then.
		 */
another:
		if (!ifi) {
			warning("No interfaces available");
			quit = INTERNALSIG;
			continue;
		}

		if (ifi->rdomain != get_rdomain(ifi->name)) {
			warning("Interface %s:"
			    " rdomain changed out from under us",
			    ifi->name);
			quit = INTERNALSIG;
			continue;
		}

		if (timeout.func) {
			time(&cur_time);
			if (timeout.when <= cur_time) {
				func = timeout.func;
				cancel_timeout();
				(*(func))();
				goto another;
			}
			/*
			 * Figure timeout in milliseconds, and check for
			 * potential overflow, so we can cram into an
			 * int for poll, while not polling with a
			 * negative timeout and blocking indefinitely.
			 */
			howlong = timeout.when - cur_time;
			if (howlong > INT_MAX / 1000)
				howlong = INT_MAX / 1000;
			to_msec = howlong * 1000;
		} else
			to_msec = -1;

		/* Set up the descriptors to be polled. */
		if (!ifi || ifi->rfdesc == -1) {
			warning("No live interface to poll on");
			quit = INTERNALSIG;
			continue;
		}

		fds[0].fd = ifi->rfdesc;
		fds[1].fd = routefd; /* Could be -1, which will be ignored. */
		fds[2].fd = unpriv_ibuf->fd;
		fds[0].events = fds[1].events = fds[2].events = POLLIN;

		if (unpriv_ibuf->w.queued)
			fds[2].events |= POLLOUT;

		/* Wait for a packet or a timeout or unpriv_ibuf->fd. XXX */
		count = poll(fds, 3, to_msec);

		/* Not likely to be transitory. */
		if (count == -1) {
			if (errno == EAGAIN || errno == EINTR) {
				continue;
			} else {
				warning("poll: %s", strerror(errno));
				quit = INTERNALSIG;
				continue;
			}
		}

		if ((fds[0].revents & (POLLIN | POLLHUP))) {
			if (ifi && ifi->linkstat && ifi->rfdesc != -1)
				got_one();
		}
		if ((fds[1].revents & (POLLIN | POLLHUP))) {
			if (ifi)
				routehandler();
		}
		if (fds[2].revents & POLLOUT) {
			if (msgbuf_write(&unpriv_ibuf->w) <= 0 &&
			    errno != EAGAIN) {
				warning("pipe write error to [priv]");
				quit = INTERNALSIG;
				continue;
			}
		}
		if ((fds[2].revents & (POLLIN | POLLHUP))) {
			/* Pipe to [priv] closed. Assume it emitted error. */
			quit = INTERNALSIG;
			continue;
		}
	}

	if (quit == SIGHUP) {
		/* Tell [priv] process that HUP has occurred. */
		sendhup(client->active);
		warning("%s; restarting", strsignal(quit));
		exit (0);
	} else if (quit != INTERNALSIG) {
		warning("%s; exiting", strsignal(quit));
		exit(1);
	}
}
Пример #9
0
static void
mproc_dispatch(int fd, short event, void *arg)
{
	struct mproc	*p = arg;
	struct imsg	 imsg;
	ssize_t		 n;

	p->events = 0;

	if (event & EV_READ) {

		if (p->proc == PROC_CLIENT)
			n = imsg_read_nofd(&p->imsgbuf);
		else
			n = imsg_read(&p->imsgbuf);

		switch (n) {
		case -1:
			if (errno == EAGAIN)
				break;
			log_warn("warn: %s -> %s: imsg_read",
			    proc_name(smtpd_process),  p->name);
			fatal("exiting");
			/* NOTREACHED */
		case 0:
			/* this pipe is dead, so remove the event handler */
			log_debug("debug: %s -> %s: pipe closed",
			    proc_name(smtpd_process),  p->name);
			p->handler(p, NULL);
			return;
		default:
			break;
		}
	}

	if (event & EV_WRITE) {
		n = msgbuf_write(&p->imsgbuf.w);
		if (n == 0 || (n == -1 && errno != EAGAIN)) {
			/* this pipe is dead, so remove the event handler */
			log_debug("debug: %s -> %s: pipe closed",
			    proc_name(smtpd_process),  p->name);
			p->handler(p, NULL);
			return;
		}
	}

	for (;;) {
		if ((n = imsg_get(&p->imsgbuf, &imsg)) == -1) {

			if (smtpd_process == PROC_CONTROL &&
			    p->proc == PROC_CLIENT) {
				log_warnx("warn: client sent invalid imsg "
				    "over control socket");
				p->handler(p, NULL);
				return;
			}
			log_warn("fatal: %s: error in imsg_get for %s",
			    proc_name(smtpd_process),  p->name);
			fatalx(NULL);
		}
		if (n == 0)
			break;

		p->handler(p, &imsg);

		imsg_free(&imsg);
	}

	mproc_event_add(p);
}
Пример #10
0
/* 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);
}
Пример #11
0
int
main(int argc, char *argv[])
{
	struct sockaddr_un	 sun;
	struct parse_result	*res;
	struct imsg		 imsg;
	int			 ctl_sock;
	int			 done = 0;
	int			 n, verbose = 0;

	/* parse options */
	if ((res = parse(argc - 1, argv + 1)) == NULL)
		exit(1);

	/* connect to relayd control socket */
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket");

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_UNIX;
	strlcpy(sun.sun_path, RELAYD_SOCKET, sizeof(sun.sun_path));
 reconnect:
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
		/* Keep retrying if running in monitor mode */
		if (res->action == MONITOR &&
		    (errno == ENOENT || errno == ECONNREFUSED)) {
			usleep(100);
			goto reconnect;
		}
		err(1, "connect: %s", RELAYD_SOCKET);
	}

	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
		err(1, NULL);
	imsg_init(ibuf, ctl_sock);
	done = 0;

	/* process user request */
	switch (res->action) {
	case NONE:
		usage();
		/* not reached */
	case SHOW_SUM:
	case SHOW_HOSTS:
	case SHOW_RDRS:
	case SHOW_RELAYS:
	case SHOW_ROUTERS:
		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
		printf("%-4s\t%-8s\t%-24s\t%-7s\tStatus\n",
		    "Id", "Type", "Name", "Avlblty");
		break;
	case SHOW_SESSIONS:
		imsg_compose(ibuf, IMSG_CTL_SESSION, 0, 0, -1, NULL, 0);
		break;
	case RDR_ENABLE:
		imsg_compose(ibuf, IMSG_CTL_RDR_ENABLE, 0, 0, -1,
		    &res->id, sizeof(res->id));
		break;
	case RDR_DISABLE:
		imsg_compose(ibuf, IMSG_CTL_RDR_DISABLE, 0, 0, -1,
		    &res->id, sizeof(res->id));
		break;
	case TABLE_ENABLE:
		imsg_compose(ibuf, IMSG_CTL_TABLE_ENABLE, 0, 0, -1,
		    &res->id, sizeof(res->id));
		break;
	case TABLE_DISABLE:
		imsg_compose(ibuf, IMSG_CTL_TABLE_DISABLE, 0, 0, -1,
		    &res->id, sizeof(res->id));
		break;
	case HOST_ENABLE:
		imsg_compose(ibuf, IMSG_CTL_HOST_ENABLE, 0, 0, -1,
		    &res->id, sizeof(res->id));
		break;
	case HOST_DISABLE:
		imsg_compose(ibuf, IMSG_CTL_HOST_DISABLE, 0, 0, -1,
		    &res->id, sizeof(res->id));
		break;
	case SHUTDOWN:
		imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
		break;
	case POLL:
		imsg_compose(ibuf, IMSG_CTL_POLL, 0, 0, -1, NULL, 0);
		break;
	case LOAD:
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1,
		    res->path, strlen(res->path));
		done = 1;
		break;
	case RELOAD:
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
		done = 1;
		break;
	case MONITOR:
		imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
		break;
	case LOG_VERBOSE:
		verbose = 2;
		/* FALLTHROUGH */
	case LOG_BRIEF:
		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1,
		    &verbose, sizeof(verbose));
		printf("logging request sent.\n");
		done = 1;
		break;
	}

	while (ibuf->w.queued)
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
			err(1, "write error");

	while (!done) {
		if ((n = imsg_read(ibuf)) == -1)
			errx(1, "imsg_read error");
		if (n == 0)
			errx(1, "pipe closed");

		while (!done) {
			if ((n = imsg_get(ibuf, &imsg)) == -1)
				errx(1, "imsg_get error");
			if (n == 0)
				break;
			switch (res->action) {
			case SHOW_SUM:
			case SHOW_HOSTS:
			case SHOW_RDRS:
			case SHOW_RELAYS:
			case SHOW_ROUTERS:
				done = show_summary_msg(&imsg, res->action);
				break;
			case SHOW_SESSIONS:
				done = show_session_msg(&imsg);
				break;
			case RDR_DISABLE:
			case RDR_ENABLE:
			case TABLE_DISABLE:
			case TABLE_ENABLE:
			case HOST_DISABLE:
			case HOST_ENABLE:
			case POLL:
			case SHUTDOWN:
				done = show_command_output(&imsg);
				break;
			case NONE:
			case LOG_VERBOSE:
			case LOG_BRIEF:
			case RELOAD:
			case LOAD:
				break;
			case MONITOR:
				done = monitor(&imsg);
				break;
			}
			imsg_free(&imsg);
		}
	}
	close(ctl_sock);
	free(ibuf);

	return (error ? 1 : 0);
}
Пример #12
0
int
main(int argc, char *argv[])
{
	struct sockaddr_un	 sun;
	struct parse_result	*res;
	struct imsg		 imsg;
	int			 ctl_sock;
	int			 done = 1;
	int			 n;
	int			 ch;
	int			 v = 0;
	int			 quiet = 0;
	const char		*sock = IKED_SOCKET;

	while ((ch = getopt(argc, argv, "qs:")) != -1) {
		switch (ch) {
		case 'q':
			quiet = 1;
			break;
		case 's':
			sock = optarg;
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	/* parse options */
	if ((res = parse(argc, argv)) == NULL)
		exit(1);

	res->quiet = quiet;

	switch (res->action) {
	case CA_CREATE:
	case CA_DELETE:
	case CA_INSTALL:
	case CA_EXPORT:
	case CA_CERT_CREATE:
	case CA_CLIENT:
	case CA_SERVER:
	case CA_OCSP:
	case CA_CERT_DELETE:
	case CA_CERT_INSTALL:
	case CA_CERT_EXPORT:
	case CA_CERT_REVOKE:
	case SHOW_CA:
	case SHOW_CA_CERTIFICATES:
	case CA_KEY_CREATE:
	case CA_KEY_DELETE:
	case CA_KEY_INSTALL:
	case CA_KEY_IMPORT:
	case CA_SUBCA_CREATE:
	case CA_SUBCA_REVOKE:
		if (pledge("stdio proc exec rpath wpath cpath fattr tty", NULL)
		    == -1)
			err(1, "pledge");
		ca_opt(res);
		break;
	case NONE:
		usage();
		break;
	default:
		goto connect;
	}

	return (0);

 connect:
	/* connect to iked control socket */
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket");

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_UNIX;
	strlcpy(sun.sun_path, sock, sizeof(sun.sun_path));
 reconnect:
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
		/* Keep retrying if running in monitor mode */
		if (res->action == MONITOR &&
		    (errno == ENOENT || errno == ECONNREFUSED)) {
			usleep(100);
			goto reconnect;
		}
		err(1, "connect: %s", sock);
	}

	if (pledge("stdio", NULL) == -1)
		err(1, "pledge");

	if (res->ibuf != NULL)
		ibuf = res->ibuf;
	else
		if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
			err(1, "malloc");
	imsg_init(ibuf, ctl_sock);

	/* process user request */
	switch (res->action) {
	case RESETALL:
		v = RESET_ALL;
		break;
	case RESETCA:
		v = RESET_CA;
		break;
	case RESETPOLICY:
		v = RESET_POLICY;
		break;
	case RESETSA:
		v = RESET_SA;
		break;
	case RESETUSER:
		v = RESET_USER;
		break;
	case LOG_VERBOSE:
		v = 2;
		break;
	case LOG_BRIEF:
	default:
		v = 0;
		break;
	}

	switch (res->action) {
	case NONE:
		usage();
		/* NOTREACHED */
		break;
	case RESETALL:
	case RESETCA:
	case RESETPOLICY:
	case RESETSA:
	case RESETUSER:
		imsg_compose(ibuf, IMSG_CTL_RESET, 0, 0, -1, &v, sizeof(v));
		printf("reset request sent.\n");
		break;
	case LOAD:
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1,
		    res->path, strlen(res->path));
		break;
	case RELOAD:
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
		break;
	case MONITOR:
		imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
		done = 0;
		break;
	case COUPLE:
		imsg_compose(ibuf, IMSG_CTL_COUPLE, 0, 0, -1, NULL, 0);
		break;
	case DECOUPLE:
		imsg_compose(ibuf, IMSG_CTL_DECOUPLE, 0, 0, -1, NULL, 0);
		break;
	case ACTIVE:
		imsg_compose(ibuf, IMSG_CTL_ACTIVE, 0, 0, -1, NULL, 0);
		break;
	case PASSIVE:
		imsg_compose(ibuf, IMSG_CTL_PASSIVE, 0, 0, -1, NULL, 0);
		break;
	case LOG_VERBOSE:
	case LOG_BRIEF:
		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &v, sizeof(v));
		printf("logging request sent.\n");
		break;
	default:
		break;
	}

	while (ibuf->w.queued)
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
			err(1, "write error");

	while (!done) {
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
			errx(1, "imsg_read error");
		if (n == 0)
			errx(1, "pipe closed");

		while (!done) {
			if ((n = imsg_get(ibuf, &imsg)) == -1)
				errx(1, "imsg_get error");
			if (n == 0)
				break;
			switch (res->action) {
			case MONITOR:
				done = monitor(&imsg);
				break;
			default:
				break;
			}
			imsg_free(&imsg);
		}
	}
	close(ctl_sock);
	free(ibuf);

	return (0);
}
Пример #13
0
/* ARGSUSED */
void
rde_dispatch_parent(int fd, short event, void *bula)
{
	struct imsg		 imsg;
	struct rt_node		*rt;
	struct kroute		 kr;
	struct imsgev		*iev = bula;
	struct imsgbuf		*ibuf = &iev->ibuf;
	ssize_t			 n;
	int			 shut = 0;

	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_parent: imsg_read error");
		if (n == 0)
			break;

		switch (imsg.hdr.type) {
		case IMSG_NETWORK_ADD:
			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) {
				log_warnx("rde_dispatch: wrong imsg len");
				break;
			}

			memcpy(&kr, imsg.data, sizeof(kr));

			rt = rt_new_kr(&kr);
			rt_insert(rt);
			break;
		case IMSG_NETWORK_DEL:
			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(kr)) {
				log_warnx("rde_dispatch: wrong imsg len");
				break;
			}
			memcpy(&kr, imsg.data, sizeof(kr));

			if ((rt = rt_find(kr.prefix.s_addr,
			    kr.netmask.s_addr)) != NULL)
				rt_remove(rt);
			break;
		default:
			log_debug("rde_dispatch_parent: 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);
	}
}
Пример #14
0
int
tnt_fork(int imsg_fds[2]) {
    pid_t pid;
    struct imsgbuf ibuf;
    struct imsg_data data;
    struct passwd *pw;
    struct event_base *evbase = NULL;
    struct event *sigterm = NULL;
    struct event *sigint = NULL;
    struct event *imsg_event = NULL;
    struct server server;
    struct event_config *evcfg;

    switch ((pid = fork())) {
        case -1:
            log_err(TNT_OSERR, "fork");
            break;
        case 0:
            tnt_setproctitle("[unpriv]");
            log_set_prefix("unpriv");
            break;
        default:
            tnt_setproctitle("[priv]");
            log_set_prefix("priv");
            return pid;
    }

    if ((pw = getpwnam(TNETACLE_USER)) == NULL) {
        log_errx(1, "unknown user " TNETACLE_USER);
        return TNT_NOUSER;
    }

    /*Allocate the event config*/
    evcfg = event_config_new();

    /* Initialize the OpenSSL library */
    SSL_library_init();
    SSL_load_error_strings();
    /* We MUST have entropy, or else there's no point to crypto. */
    if (!RAND_poll())
    {
        log_errx(TNT_SOFTWARE, "[INIT] failed to find an entropy source");
        /* never returns */
    }

    if (serv_opts.encryption)
        server.server_ctx = evssl_init();
    else
        server.server_ctx = NULL;

    tnt_priv_drop(pw);

#if defined(Darwin)
    /* It's sad isn't it ?*/
    event_config_avoid_method(evcfg, "kqueue");
    event_config_avoid_method(evcfg, "poll");
    event_config_avoid_method(evcfg, "devpoll");
    if ((evbase = event_base_new_with_config(evcfg)) == NULL) {
        log_err(1, "libevent");
    }
#else
    if ((evbase = event_base_new_with_config(evcfg)) == NULL) {
        log_err(1, "libevent");
    }
#endif

    sigterm = event_new(evbase, SIGTERM, EV_SIGNAL, &chld_sighdlr, evbase);
    sigint = event_new(evbase, SIGINT, EV_SIGNAL, &chld_sighdlr, evbase);

    signal(SIGPIPE, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGCHLD, SIG_DFL);

    if (server_init(&server, evbase) == -1)
        log_errx(1, "failed to init the server socket");

    data.ibuf = &ibuf;
    data.evbase = evbase;
    data.server = &server;
    imsg_event = init_pipe_endpoint(imsg_fds, &data);

    event_add(sigterm, NULL);
    event_add(sigint, NULL);
    event_add(imsg_event, NULL);

    log_info("tnetacle ready");

    /* Immediately request the creation of a tun interface */
    imsg_compose(&ibuf, IMSG_CREATE_DEV, 0, 0, -1, NULL, 0);

    log_info("starting event loop");
    event_base_dispatch(evbase);

    /* cleanely exit */
    msgbuf_write(&ibuf.w);
    msgbuf_clear(&ibuf.w);

    /* Shutdown the server */
    server_delete(&server);

    /*
     * It may look like we freed this one twice,
     * once here and once in tnetacled.c but this is not the case.
     * Please don't erase this !
     */

    event_free(sigterm);
    event_free(sigint);
    close(event_get_fd(imsg_event));
    event_free(imsg_event);
    event_base_free(evbase);
    event_config_free(evcfg);

    log_info("tnetacle exiting");
    exit(TNT_OK);
}
Пример #15
0
/* 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);
}
Пример #16
0
void
dns_dispatch_imsg(int fd, short events, void *p)
{
	struct imsg		 imsg;
	int			 n, cnt;
	char			*name;
	struct ypldap_addr_list	hn = TAILQ_HEAD_INITIALIZER(hn);
	struct ypldap_addr	*h;
	struct ibuf		*buf;
	struct env		*env = p;
	struct imsgev		*iev = env->sc_iev;
	struct imsgbuf		*ibuf = &iev->ibuf;
	int			 shut = 0;

	if ((events & (EV_READ | EV_WRITE)) == 0)
		fatalx("unknown event");

	if (events & EV_READ) {
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
			fatal("imsg_read error");
		if (n == 0)
			shut = 1;
	}
	if (events & EV_WRITE) {
		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
			fatal("msgbuf_write");
		if (n == 0)
			shut = 1;
		goto done;
	}

	for (;;) {
		if ((n = imsg_get(ibuf, &imsg)) == -1)
			fatal("client_dispatch_imsg: imsg_get error");
		if (n == 0)
			break;

		switch (imsg.hdr.type) {
		case IMSG_HOST_DNS:
			name = imsg.data;
			if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
				fatalx("invalid IMSG_HOST_DNS received");
			imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
			if (name[imsg.hdr.len] != '\0' ||
			    strlen(name) != imsg.hdr.len)
				fatalx("invalid IMSG_HOST_DNS received");
			if ((cnt = host_dns(name, &hn)) == -1)
				break;
			buf = imsg_create(ibuf, IMSG_HOST_DNS,
			    imsg.hdr.peerid, 0,
			    cnt * sizeof(struct sockaddr_storage));
			if (buf == NULL)
				break;
			if (cnt > 0) {
				while(!TAILQ_EMPTY(&hn)) {
					h = TAILQ_FIRST(&hn);
					TAILQ_REMOVE(&hn, h, next);
					imsg_add(buf, &h->ss, sizeof(h->ss));
					free(h);
				}
			}

			imsg_close(ibuf, buf);
			break;
		default:
			break;
		}
		imsg_free(&imsg);
	}

done:
	if (!shut)
		imsg_event_add(iev);
	else {
		/* this pipe is dead, so remove the event handler */
		event_del(&iev->ev);
		event_loopexit(NULL);
	}
}
Пример #17
0
static void
filter_handler(int fd, short event, void *p)
{
	struct imsg		imsg;
	ssize_t			n;
	short			evflags = EV_READ;
	enum filter_status	ret;
	struct filter_msg	fm;

	if (event & EV_READ) {
		n = imsg_read(&fi.ibuf);
		if (n == -1)
			err(1, "imsg_read");
		if (n == 0) {
			event_del(&fi.ev);
			event_loopexit(NULL);
			return;
		}
	}

	if (event & EV_WRITE) {
		if (msgbuf_write(&fi.ibuf.w) == -1)
			err(1, "msgbuf_write");
		if (fi.ibuf.w.queued)
			evflags |= EV_WRITE;
	}

	for (;;) {
		n = imsg_get(&fi.ibuf, &imsg);
		if (n == -1)
			errx(1, "imsg_get");
		if (n == 0)
			break;

		if ((imsg.hdr.len - IMSG_HEADER_SIZE)
		    != sizeof(fm))
			errx(1, "corrupted imsg");

		memcpy(&fm, imsg.data, sizeof (fm));
		if (fm.version != FILTER_API_VERSION)
			errx(1, "API version mismatch");

		switch (imsg.hdr.type) {
		case FILTER_CONNECT:
			if (fi.connect_cb == NULL)
				goto ignore;
			ret = fi.connect_cb(fm.cl_id, &fm.u.connect,
			    fi.connect_cb_arg);
			break;
		case FILTER_HELO:
			if (fi.helo_cb == NULL)
				goto ignore;
			ret = fi.helo_cb(fm.cl_id, &fm.u.helo,
			    fi.helo_cb_arg);
			break;
		case FILTER_EHLO:
			if (fi.ehlo_cb == NULL)
				goto ignore;
			ret = fi.ehlo_cb(fm.cl_id, &fm.u.helo,
			    fi.ehlo_cb_arg);
			break;
		case FILTER_MAIL:
			if (fi.mail_cb == NULL)
				goto ignore;
			ret = fi.mail_cb(fm.cl_id, &fm.u.mail,
			    fi.mail_cb_arg);
			break;
		case FILTER_RCPT:
			if (fi.rcpt_cb == NULL)
				goto ignore;
			ret = fi.rcpt_cb(fm.cl_id, &fm.u.rcpt,
			    fi.rcpt_cb_arg);
			break;
		case FILTER_DATALINE:
			if (fi.dataline_cb == NULL)
				goto ignore;
			ret = fi.dataline_cb(fm.cl_id, &fm.u.dataline,
			    fi.dataline_cb_arg);
			break;
		case FILTER_QUIT:
			if (fi.quit_cb == NULL)
				goto ignore;
			ret = fi.quit_cb(fm.cl_id, fi.quit_cb_arg);
			break;
		case FILTER_CLOSE:
			if (fi.close_cb == NULL)
				goto ignore;
			ret = fi.close_cb(fm.cl_id, fi.close_cb_arg);
			break;
		case FILTER_RSET:
			if (fi.rset_cb == NULL)
				goto ignore;
			ret = fi.rset_cb(fm.cl_id, fi.rset_cb_arg);
 			break;

		default:
			errx(1, "unsupported imsg");
		}

		switch (ret) {
		case STATUS_ACCEPT:
		case STATUS_REJECT:
			fm.code = ret;
			imsg_compose(&fi.ibuf, imsg.hdr.type, 0, 0, -1, &fm,
			    sizeof fm);
			evflags |= EV_WRITE;
			break;
		case STATUS_WAITING:
			/* waiting for asynchronous call ... */
			break;
		}

		imsg_free(&imsg);
	}

	event_set(&fi.ev, 0, evflags, filter_handler, &fi);
	event_add(&fi.ev, NULL);
	return;

ignore:
	imsg_free(&imsg);
	fm.code = STATUS_IGNORE;
	imsg_compose(&fi.ibuf, imsg.hdr.type, 0, 0, -1, &fm, sizeof fm);
	evflags |= EV_WRITE;
	event_set(&fi.ev, 0, evflags, filter_handler, &fi);
	event_add(&fi.ev, NULL);
}
Пример #18
0
int
main(int argc, char *argv[])
{
	struct sockaddr_un	 sun;
	struct parse_result	*res;
	struct imsg		 imsg;
	unsigned int		 ifidx = 0;
	int			 ctl_sock;
	int			 done = 0, verbose = 0;
	int			 n;
	int			 ch;
	char			*sockname;

	sockname = OSPF6D_SOCKET;
	while ((ch = getopt(argc, argv, "s:")) != -1) {
		switch (ch) {
		case 's':
			sockname = optarg;
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	/* parse options */
	if ((res = parse(argc, argv)) == NULL)
		exit(1);

	/* connect to ospf6d control socket */
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket");

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_UNIX;
	strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
		err(1, "connect: %s", sockname);

	if (pledge("stdio", NULL) == -1)
		err(1, "pledge");

	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
		err(1, NULL);
	imsg_init(ibuf, ctl_sock);
	done = 0;

	/* process user request */
	switch (res->action) {
	case NONE:
		usage();
		/* not reached */
	case SHOW:
	case SHOW_SUM:
		imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
		break;
	case SHOW_IFACE:
		printf("%-11s %-29s %-6s %-10s %-10s %-8s\n",
		    "Interface", "Address", "State", "HelloTimer", "Linkstate",
		    "Uptime");
		/*FALLTHROUGH*/
	case SHOW_IFACE_DTAIL:
		if (*res->ifname) {
			ifidx = if_nametoindex(res->ifname);
			if (ifidx == 0)
				errx(1, "no such interface %s", res->ifname);
		}
		imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
		    &ifidx, sizeof(ifidx));
		break;
	case SHOW_NBR:
		printf("%-15s %-3s %-12s %-9s %-11s %s\n", "ID", "Pri",
		    "State", "DeadTime", "Iface","Uptime");
		/*FALLTHROUGH*/
	case SHOW_NBR_DTAIL:
		imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DB:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBBYAREA:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
		    &res->addr, sizeof(res->addr));
		break;
	case SHOW_DBEXT:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBLINK:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_LINK, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBNET:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBRTR:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBINTRA:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_INTRA, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBSELF:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBSUM:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
		break;
	case SHOW_DBASBR:
		imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
		break;
	case SHOW_RIB:
		printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
		    "Nexthop", "Path Type", "Type", "Cost", "Uptime");
		/*FALLTHROUGH*/
	case SHOW_RIB_DTAIL:
		imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
		break;
	case SHOW_FIB:
		if (IN6_IS_ADDR_UNSPECIFIED(&res->addr))
			imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
			    &res->flags, sizeof(res->flags));
		else
			imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
			    &res->addr, sizeof(res->addr));
		show_fib_head();
		break;
	case FIB:
		errx(1, "fib couple|decouple");
		break;
	case FIB_COUPLE:
		imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
		printf("couple request sent.\n");
		done = 1;
		break;
	case FIB_DECOUPLE:
		imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
		printf("decouple request sent.\n");
		done = 1;
		break;
	case LOG_VERBOSE:
		verbose = 1;
		/* FALLTHROUGH */
	case LOG_BRIEF:
		imsg_compose(ibuf, IMSG_CTL_LOG_VERBOSE, 0, 0, -1,
		    &verbose, sizeof(verbose));
		printf("logging request sent.\n");
		done = 1;
		break;
	case RELOAD:
		imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
		printf("reload request sent.\n");
		done = 1;
		break;
	}

	while (ibuf->w.queued)
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
			err(1, "write error");

	while (!done) {
		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
			errx(1, "imsg_read error");
		if (n == 0)
			errx(1, "pipe closed");

		while (!done) {
			if ((n = imsg_get(ibuf, &imsg)) == -1)
				errx(1, "imsg_get error");
			if (n == 0)
				break;
			switch (res->action) {
			case SHOW:
			case SHOW_SUM:
				done = show_summary_msg(&imsg);
				break;
			case SHOW_IFACE:
				done = show_interface_msg(&imsg);
				break;
			case SHOW_IFACE_DTAIL:
				done = show_interface_detail_msg(&imsg);
				break;
			case SHOW_NBR:
				done = show_nbr_msg(&imsg);
				break;
			case SHOW_NBR_DTAIL:
				done = show_nbr_detail_msg(&imsg);
				break;
			case SHOW_DB:
			case SHOW_DBBYAREA:
			case SHOW_DBSELF:
				done = show_database_msg(&imsg);
				break;
			case SHOW_DBEXT:
			case SHOW_DBLINK:
			case SHOW_DBNET:
			case SHOW_DBRTR:
			case SHOW_DBINTRA:
			case SHOW_DBSUM:
			case SHOW_DBASBR:
				done = show_db_msg_detail(&imsg);
				break;
			case SHOW_RIB:
				done = show_rib_msg(&imsg);
				break;
			case SHOW_RIB_DTAIL:
				done = show_rib_detail_msg(&imsg);
				break;
			case SHOW_FIB:
				done = show_fib_msg(&imsg);
				break;
			case NONE:
			case FIB:
			case FIB_COUPLE:
			case FIB_DECOUPLE:
			case LOG_VERBOSE:
			case LOG_BRIEF:
			case RELOAD:
				break;
			}
			imsg_free(&imsg);
		}
	}
	close(ctl_sock);
	free(ibuf);

	return (0);
}
Пример #19
0
int
main(int argc, char *argv[])
{
	struct sockaddr_un	sun;
	struct parse_result	*res = NULL;
	struct imsg		imsg;
	struct smtpd		smtpd;
	int			ctl_sock;
	int			done = 0;
	int			n, verbose = 0;

	/* parse options */
	if (strcmp(__progname, "sendmail") == 0 || strcmp(__progname, "send-mail") == 0)
		sendmail = 1;
	else if (strcmp(__progname, "mailq") == 0) {
		if (geteuid())
			errx(1, "need root privileges");
		setup_env(&smtpd);
		show_queue(0);
		return 0;
	} else if (strcmp(__progname, "smtpctl") == 0) {

		/* check for root privileges */
		if (geteuid())
			errx(1, "need root privileges");

		setup_env(&smtpd);

		if ((res = parse(argc - 1, argv + 1)) == NULL)
			exit(1);

		/* handle "disconnected" commands */
		switch (res->action) {
		case SHOW_QUEUE:
			show_queue(0);
			break;
		case SHOW_RUNQUEUE:
			break;
		default:
			goto connected;
		}
		return 0;
	} else
		errx(1, "unsupported mode");

connected:
	/* connect to smtpd control socket */
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket");

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_UNIX;
	strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path));
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
		if (sendmail)
			return enqueue_offline(argc, argv);
		err(1, "connect: %s", SMTPD_SOCKET);
	}

	if ((ibuf = calloc(1, sizeof(struct imsgbuf))) == NULL)
		err(1, NULL);
	imsg_init(ibuf, ctl_sock);

	if (sendmail)
		return enqueue(argc, argv);

	/* process user request */
	switch (res->action) {
	case NONE:
		usage();
		/* not reached */

	case SCHEDULE:
	case REMOVE: {
		u_int64_t ulval;
		char *ep;

		errno = 0;
		ulval = strtoull(res->data, &ep, 16);
		if (res->data[0] == '\0' || *ep != '\0')
			errx(1, "invalid msgid/evpid");
		if (errno == ERANGE && ulval == ULLONG_MAX)
			errx(1, "invalid msgid/evpid");
		if (ulval == 0)
			errx(1, "invalid msgid/evpid");

		if (res->action == SCHEDULE)
			imsg_compose(ibuf, IMSG_SCHEDULER_SCHEDULE, 0, 0, -1, &ulval,
			    sizeof(ulval));
		if (res->action == REMOVE)
			imsg_compose(ibuf, IMSG_SCHEDULER_REMOVE, 0, 0, -1, &ulval,
			    sizeof(ulval));
		break;
	}

	case SCHEDULE_ALL: {
		u_int64_t ulval = 0;

		imsg_compose(ibuf, IMSG_SCHEDULER_SCHEDULE, 0, 0, -1, &ulval,
		    sizeof(ulval));
		break;
	}

	case SHUTDOWN:
		imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
		break;
	case PAUSE_MDA:
		imsg_compose(ibuf, IMSG_QUEUE_PAUSE_MDA, 0, 0, -1, NULL, 0);
		break;
	case PAUSE_MTA:
		imsg_compose(ibuf, IMSG_QUEUE_PAUSE_MTA, 0, 0, -1, NULL, 0);
		break;
	case PAUSE_SMTP:
		imsg_compose(ibuf, IMSG_SMTP_PAUSE, 0, 0, -1, NULL, 0);
		break;
	case RESUME_MDA:
		imsg_compose(ibuf, IMSG_QUEUE_RESUME_MDA, 0, 0, -1, NULL, 0);
		break;
	case RESUME_MTA:
		imsg_compose(ibuf, IMSG_QUEUE_RESUME_MTA, 0, 0, -1, NULL, 0);
		break;
	case RESUME_SMTP:
		imsg_compose(ibuf, IMSG_SMTP_RESUME, 0, 0, -1, NULL, 0);
		break;
	case SHOW_STATS:
		imsg_compose(ibuf, IMSG_STATS, 0, 0, -1, NULL, 0);
		break;
	case MONITOR:
		/* XXX */
		break;
	case LOG_VERBOSE:
		verbose = 1;
		/* FALLTHROUGH */
	case LOG_BRIEF:
		imsg_compose(ibuf, IMSG_CTL_VERBOSE, 0, 0, -1, &verbose,
		    sizeof(verbose));
		printf("logging request sent.\n");
		done = 1;
		break;
	default:
		errx(1, "unknown request (%d)", res->action);
	}

	while (ibuf->w.queued)
		if (msgbuf_write(&ibuf->w) < 0)
			err(1, "write error");

	while (!done) {
		if ((n = imsg_read(ibuf)) == -1)
			errx(1, "imsg_read error");
		if (n == 0)
			errx(1, "pipe closed");

		while (!done) {
			if ((n = imsg_get(ibuf, &imsg)) == -1)
				errx(1, "imsg_get error");
			if (n == 0)
				break;
			switch(res->action) {
			case REMOVE:
			case SCHEDULE:
			case SCHEDULE_ALL:
			case SHUTDOWN:
			case PAUSE_MDA:
			case PAUSE_MTA:
			case PAUSE_SMTP:
			case RESUME_MDA:
			case RESUME_MTA:
			case RESUME_SMTP:
			case LOG_VERBOSE:
			case LOG_BRIEF:
				done = show_command_output(&imsg);
				break;
			case SHOW_STATS:
				done = show_stats_output(&imsg);
				break;
			case NONE:
				break;
			case MONITOR:
				break;
			default:
				err(1, "unexpected reply (%d)", res->action);
			}
			/* insert imsg replies switch here */

			imsg_free(&imsg);
		}
	}
	close(ctl_sock);
	free(ibuf);

	return (0);
}
Пример #20
0
/* ARGSUSED */
void
control_dispatch_imsg(int fd, short event, void *arg)
{
	struct control_sock	*cs = (struct control_sock *)arg;
	struct ctl_conn		*c;
	struct imsg		 imsg;
	int			 n, retval;

	if ((c = control_connbyfd(fd)) == NULL) {
		log_warn("control_dispatch_imsg: fd %d: not found", fd);
		return;
	}


	if (event & EV_WRITE) {
		if (msgbuf_write(&c->iev.ibuf.w) < 0) {
			control_close(fd, cs);
			return;
		}
		if (!c->iev.ibuf.w.queued)
			npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
		imsg_event_add(&c->iev);
		if (!(event & EV_READ))
			return;
	}
	if (event & EV_READ) {
		if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
			control_close(fd, cs);
			return;
		}
	} else
		fatalx("unknown event");

	for (;;) {
		if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
			control_close(fd, cs);
			return;
		}

		if (n == 0)
			break;

		if (cs->cs_restricted || (c->flags & CTL_CONN_LOCKED)) {
			switch (imsg.hdr.type) {
			default:
				log_debug("control_dispatch_imsg: "
				    "client requested restricted command");
				imsg_free(&imsg);
				control_close(fd, cs);
				return;
			}
		}

		switch (imsg.hdr.type) {
		case IMSG_CTL_NOP:
			imsg_compose(&c->iev.ibuf, IMSG_CTL_OK, 0, 0, -1,
			    NULL, 0);
			break;

		case IMSG_CTL_WHO:
		case IMSG_CTL_MONITOR:
		case IMSG_CTL_WHO_AND_MONITOR:
			if (imsg.hdr.type == IMSG_CTL_WHO)
				retval = npppd_ctl_who(c->ctx);
			else if (imsg.hdr.type == IMSG_CTL_MONITOR)
				retval = npppd_ctl_monitor(c->ctx);
			else
				retval = npppd_ctl_who_and_monitor(c->ctx);
			imsg_compose(&c->iev.ibuf,
			    (retval == 0)? IMSG_CTL_OK : IMSG_CTL_FAIL, 0, 0,
			    -1, NULL, 0);
			break;

		case IMSG_CTL_DISCONNECT:
		    {
			struct npppd_disconnect_request  *req;
			struct npppd_disconnect_response  res;

			req = (struct npppd_disconnect_request *)imsg.data;
			retval = npppd_ctl_disconnect(c->ctx,
			    req->ppp_id, req->count);
			res.count = retval;
			imsg_compose(&c->iev.ibuf, IMSG_CTL_OK, 0, 0,
			    -1, &res, sizeof(res));
			break;
		    }
		default:
			imsg_compose(&c->iev.ibuf, IMSG_CTL_FAIL, 0, 0, -1,
			    NULL, 0);
			break;
		}
		imsg_free(&imsg);
	}
	if (!c->iev.ibuf.w.queued)
		npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
	imsg_event_add(&c->iev);
}
Пример #21
0
/* 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);
}
Пример #22
0
/* 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);
	}
}
Пример #23
0
int
client_main(struct client_ctx *cctx)
{
	struct pollfd	 pfd;
	int		 n, nfds;

	siginit();

	logfile("client");

	/*
	 * imsg_read in the first client poll loop (before the terminal has
	 * been initialiased) may have read messages into the buffer after the
	 * MSG_READY switched to here. Process anything outstanding now so poll
	 * doesn't hang waiting for messages that have already arrived.
	 */
	if (client_msg_dispatch(cctx) != 0)
		goto out;

	for (;;) {
		if (sigterm)
			client_write_server(cctx, MSG_EXITING, NULL, 0);
		if (sigchld) {
			waitpid(WAIT_ANY, NULL, WNOHANG);
			sigchld = 0;
		}
		if (sigwinch)
			client_handle_winch(cctx);
		if (sigcont) {
			siginit();
			client_write_server(cctx, MSG_WAKEUP, NULL, 0);
			sigcont = 0;
		}

		pfd.fd = cctx->ibuf.fd;
		pfd.events = POLLIN;
		if (cctx->ibuf.w.queued > 0)
			pfd.events |= POLLOUT;

		if ((nfds = poll(&pfd, 1, INFTIM)) == -1) {
			if (errno == EAGAIN || errno == EINTR)
				continue;
			fatal("poll failed");
		}
		if (nfds == 0)
			continue;

		if (pfd.revents & (POLLERR|POLLHUP|POLLNVAL))
			fatalx("socket error");

		if (pfd.revents & POLLIN) {
			if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) {
				cctx->exittype = CCTX_DIED;
				break;
			}
			if (client_msg_dispatch(cctx) != 0)
				break;
		}

		if (pfd.revents & POLLOUT) {
			if (msgbuf_write(&cctx->ibuf.w) < 0) {
				cctx->exittype = CCTX_DIED;
				break;
			}
		}
	}

out:
 	if (sigterm) {
 		printf("[terminated]\n");
 		return (1);
 	}
	switch (cctx->exittype) {
	case CCTX_DIED:
		printf("[lost server]\n");
		return (0);
	case CCTX_SHUTDOWN:
		printf("[server exited]\n");
		return (0);
	case CCTX_EXIT:
		if (cctx->errstr != NULL) {
			printf("[error: %s]\n", cctx->errstr);
			return (1);
		}
		printf("[exited]\n");
		return (0);
	case CCTX_DETACH:
		printf("[detached]\n");
		return (0);
	default:
		printf("[unknown error]\n");
		return (1);
	}
}
Пример #24
0
void
ctl_main(int argc, char *argv[])
{
	struct sockaddr_un	 sa;
	struct imsg		 imsg;
	struct imsgbuf		*ibuf_ctl;
	int			 fd, n, done, ch, action;
	char			*sockname;

	sockname = CTLSOCKET;

	if (argc < 2) {
		usage();
		/* NOTREACHED */
	}

	while ((ch = getopt(argc, argv, "s:")) != -1) {
		switch (ch) {
		case 's':
			showopt = ctl_lookup_option(optarg, ctl_showopt_list);
			if (showopt == NULL) {
				warnx("Unknown show modifier '%s'", optarg);
				usage();
			}
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}

	action = -1;
	if (showopt != NULL) {
		switch (*showopt) {
		case 'p':
			action = CTL_SHOW_PEERS;
			break;
		case 's':
			action = CTL_SHOW_STATUS;
			break;
		case 'S':
			action = CTL_SHOW_SENSORS;
			break;
		case 'a':
			action = CTL_SHOW_ALL;
			break;
		}
	}
	if (action == -1)
		usage();
		/* NOTREACHED */

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "ntpctl: socket");

	bzero(&sa, sizeof(sa));
	sa.sun_family = AF_UNIX;
	if (strlcpy(sa.sun_path, sockname, sizeof(sa.sun_path)) >=
	    sizeof(sa.sun_path))
		errx(1, "ctl socket name too long");
	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
		err(1, "connect: %s", sockname);

	if ((ibuf_ctl = malloc(sizeof(struct imsgbuf))) == NULL)
		err(1, NULL);
	imsg_init(ibuf_ctl, fd);

	switch (action) {
	case CTL_SHOW_STATUS:
		imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_STATUS,
		    0, 0, -1, NULL, 0);
		break;
	case CTL_SHOW_PEERS:
		imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_PEERS,
		    0, 0, -1, NULL, 0);
		break;
	case CTL_SHOW_SENSORS:
		imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_SENSORS,
		    0, 0, -1, NULL, 0);
		break;
	case CTL_SHOW_ALL:
		imsg_compose(ibuf_ctl, IMSG_CTL_SHOW_ALL,
		    0, 0, -1, NULL, 0);
		break;
	default:
		errx(1, "invalid action");
		break; /* NOTREACHED */
	}

	while (ibuf_ctl->w.queued)
		if (msgbuf_write(&ibuf_ctl->w) <= 0 && errno != EAGAIN)
			err(1, "ibuf_ctl: msgbuf_write error");

	done = 0;
	while (!done) {
		if ((n = imsg_read(ibuf_ctl)) == -1)
			err(1, "ibuf_ctl: imsg_read error");
		if (n == 0)
			errx(1, "ntpctl: pipe closed");

		while (!done) {
			if ((n = imsg_get(ibuf_ctl, &imsg)) == -1)
				err(1, "ibuf_ctl: imsg_get error");
			if (n == 0)
				break;

			switch (action) {
			case CTL_SHOW_STATUS:
				show_status_msg(&imsg);
				done = 1;
				break;
			case CTL_SHOW_PEERS:
				show_peer_msg(&imsg, 0);
				if (imsg.hdr.type ==
				    IMSG_CTL_SHOW_PEERS_END)
					done = 1;
				break;
			case CTL_SHOW_SENSORS:
				show_sensor_msg(&imsg, 0);
				if (imsg.hdr.type ==
				    IMSG_CTL_SHOW_SENSORS_END)
					done = 1;
				break;
			case CTL_SHOW_ALL:
				switch (imsg.hdr.type) {
				case IMSG_CTL_SHOW_STATUS:
					show_status_msg(&imsg);
					break;
				case IMSG_CTL_SHOW_PEERS:
					show_peer_msg(&imsg, 1);
					break;
				case IMSG_CTL_SHOW_SENSORS:
					show_sensor_msg(&imsg, 1);
					break;
				case IMSG_CTL_SHOW_PEERS_END:
				case IMSG_CTL_SHOW_SENSORS_END:
					/* do nothing */
					break;
				case IMSG_CTL_SHOW_ALL_END:
					done=1;
					break;
				default:
					/* no action taken */
					break;
				}
			default:
				/* no action taken */
				break;
			}
			imsg_free(&imsg);
		}
	}
	close(fd);
	free(ibuf_ctl);
	exit(0);
}
Пример #25
0
/* 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);
}
Пример #26
0
void
proc_dispatch(int fd, short event, void *arg)
{
	struct privsep_proc	*p = (struct privsep_proc *)arg;
	struct privsep		*ps = p->p_ps;
	struct imsgev		*iev;
	struct imsgbuf		*ibuf;
	struct imsg		 imsg;
	ssize_t			 n;
	int			 verbose;
	const char		*title;

	title = ps->ps_title[privsep_process];
	iev = &ps->ps_ievs[p->p_id];
	ibuf = &iev->ibuf;

	if (event & EV_READ) {
		if ((n = imsg_read(ibuf)) == -1)
			fatal(title);
		if (n == 0) {
			/* this pipe is dead, so remove the event handler */
			event_del(&iev->ev);
			event_loopexit(NULL);
			return;
		}
	}

	if (event & EV_WRITE) {
		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
			fatal(title);
	}

	for (;;) {
		if ((n = imsg_get(ibuf, &imsg)) == -1)
			fatal(title);
		if (n == 0)
			break;

		/*
		 * Check the message with the program callback
		 */
		if ((p->p_cb)(fd, p, &imsg) == 0) {
			/* Message was handled by the callback, continue */
			imsg_free(&imsg);
			continue;
		}

		/*
		 * Generic message handling
		 */
		switch (imsg.hdr.type) {
		case IMSG_CTL_VERBOSE:
			IMSG_SIZE_CHECK(&imsg, &verbose);

			memcpy(&verbose, imsg.data, sizeof(verbose));
			log_verbose(verbose);
			break;
		default:
			log_warnx("%s: %s got imsg %d", __func__, p->p_title,
			    imsg.hdr.type);
			fatalx(title);
		}
		imsg_free(&imsg);
	}
	imsg_event_add(iev);
}
Пример #27
0
/* 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);
}
Пример #28
0
/* 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);
}
Пример #29
0
int
main(int argc, char *argv[])
{
	struct sockaddr_un	 sun;
	struct parse_result	*res;
	struct imsg		 imsg;
	int			 ctl_sock;
	int			 done = 0;
	int			 n;
	int			 ch;
	const char		*sock = SNMPD_SOCKET;

	if ((env = calloc(1, sizeof(struct snmpd))) == NULL)
		err(1, "calloc");
	gettimeofday(&env->sc_starttime, NULL);

	while ((ch = getopt(argc, argv, "ns:")) != -1) {
		switch (ch) {
		case 'n':
			env->sc_flags |= SNMPD_F_NONAMES;
			break;
		case 's':
			sock = optarg;
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}
	argc -= optind;
	argv += optind;

	smi_init();

	/* parse options */
	if ((res = parse(argc, argv)) == NULL)
		exit(1);

	switch (res->action) {
	case NONE:
		usage();
		break;
	case SHOW_MIB:
		show_mib();
		break;
	case WALK:
	case GET:
	case BULKWALK:
		snmpclient(res);
		break;
	default:
		goto connect;
	}

	free(env);
	return (0);

 connect:
	/* connect to snmpd control socket */
	if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
		err(1, "socket");

	bzero(&sun, sizeof(sun));
	sun.sun_family = AF_UNIX;
	strlcpy(sun.sun_path, sock, sizeof(sun.sun_path));
 reconnect:
	if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
		/* Keep retrying if running in monitor mode */
		if (res->action == MONITOR &&
		    (errno == ENOENT || errno == ECONNREFUSED)) {
			usleep(100);
			goto reconnect;
		}
		err(1, "connect: %s", sock);
	}

	imsg_init(&ibuf, ctl_sock);
	done = 0;

	/* process user request */
	switch (res->action) {
	case MONITOR:
		imsg_compose(&ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
		break;
	case NONE:
	case SHOW_MIB:
	case WALK:
	case GET:
	case BULKWALK:
		break;
	case TRAP:
		/* explicitly downgrade the socket */
		imsg_compose(&ibuf, IMSG_SNMP_AGENTX, 0, 0, -1, NULL, 0);
		break;
	}

	while (ibuf.w.queued)
		if (msgbuf_write(&ibuf.w) <= 0 && errno != EAGAIN)
			err(1, "write error");

	while (!done) {
		if ((n = imsg_read(&ibuf)) == -1)
			errx(1, "imsg_read error");
		if (n == 0)
			errx(1, "pipe closed");

		while (!done) {
			if ((n = imsg_get(&ibuf, &imsg)) == -1)
				errx(1, "imsg_get error");
			if (n == 0)
				break;
			switch (res->action) {
			case MONITOR:
				done = monitor(&imsg);
				break;
			case TRAP:
				if (imsg.hdr.type == IMSG_CTL_OK) {
					snmpctl_trap(ctl_sock, res);
					done = 1;
				} else
					errx(1, "snmpd refused connection");
				break;
			case NONE:
			case SHOW_MIB:
			case WALK:
			case GET:
			case BULKWALK:
				break;
			}
			imsg_free(&imsg);
		}
	}
	close(ctl_sock);

	return (0);
}
Пример #30
0
int
main(int argc, char *argv[])
{
	struct ntpd_conf	 lconf;
	struct pollfd		 pfd[POLL_MAX];
	pid_t			 chld_pid = 0, pid;
	const char		*conffile;
	int			 fd_ctl, ch, nfds;
	int			 pipe_chld[2];
	struct passwd		*pw;
	extern char		*__progname;

	if (strcmp(__progname, "ntpctl") == 0) {
		ctl_main(argc, argv);
		/* NOTREACHED */
	}

	conffile = CONFFILE;

	bzero(&lconf, sizeof(lconf));

	log_init(1);		/* log to stderr until daemonized */

	while ((ch = getopt(argc, argv, "df:nsSv")) != -1) {
		switch (ch) {
		case 'd':
			lconf.debug = 1;
			log_verbose(1);
			break;
		case 'f':
			conffile = optarg;
			break;
		case 'n':
			lconf.noaction = 1;
			break;
		case 's':
			lconf.settime = 1;
			break;
		case 'S':
			lconf.settime = 0;
			break;
		case 'v':
			log_verbose(1);
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}

	argc -= optind;
	argv += optind;
	if (argc > 0)
		usage();

	if (parse_config(conffile, &lconf))
		exit(1);

	if (lconf.noaction) {
		fprintf(stderr, "configuration OK\n");
		exit(0);
	}

	if (geteuid())
		errx(1, "need root privileges");

	if ((pw = getpwnam(NTPD_USER)) == NULL)
		errx(1, "unknown user %s", NTPD_USER);

	if (setpriority(PRIO_PROCESS, 0, -20) == -1)
		warn("can't set priority");

	reset_adjtime();
	if (!lconf.settime) {
		log_init(lconf.debug);
		if (!lconf.debug)
			if (daemon(1, 0))
				fatal("daemon");
	} else
		timeout = SETTIME_TIMEOUT * 1000;

	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1)
		fatal("socketpair");

	if ((fd_ctl = control_init(CTLSOCKET)) == -1)
		fatalx("control socket init failed");
	if (control_listen(fd_ctl) == -1)
		fatalx("control socket listen failed");

	signal(SIGCHLD, sighdlr);
	/* fork child process */
	chld_pid = ntp_main(pipe_chld, fd_ctl, &lconf, pw);

	setproctitle("[priv]");
	readfreq();

	signal(SIGTERM, sighdlr);
	signal(SIGINT, sighdlr);
	signal(SIGHUP, sighdlr);

	close(pipe_chld[1]);

	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
		fatal(NULL);
	imsg_init(ibuf, pipe_chld[0]);

	while (quit == 0) {
		pfd[PFD_PIPE].fd = ibuf->fd;
		pfd[PFD_PIPE].events = POLLIN;
		if (ibuf->w.queued)
			pfd[PFD_PIPE].events |= POLLOUT;

		if ((nfds = poll(pfd, 1, timeout)) == -1)
			if (errno != EINTR) {
				log_warn("poll error");
				quit = 1;
			}

		if (nfds == 0 && lconf.settime) {
			lconf.settime = 0;
			timeout = INFTIM;
			log_init(lconf.debug);
			log_warnx("no reply received in time, skipping initial "
			    "time setting");
			if (!lconf.debug)
				if (daemon(1, 0))
					fatal("daemon");
		}

		if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
			if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
				log_warn("pipe write error (to child)");
				quit = 1;
			}

		if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) {
			nfds--;
			if (dispatch_imsg(&lconf) == -1)
				quit = 1;
		}

		if (sigchld) {
			if (check_child(chld_pid, "child")) {
				quit = 1;
				chld_pid = 0;
			}
			sigchld = 0;
		}

	}

	signal(SIGCHLD, SIG_DFL);

	if (chld_pid)
		kill(chld_pid, SIGTERM);

	do {
		if ((pid = wait(NULL)) == -1 &&
		    errno != EINTR && errno != ECHILD)
			fatal("wait");
	} while (pid != -1 || (pid == -1 && errno == EINTR));

	msgbuf_clear(&ibuf->w);
	free(ibuf);
	log_info("Terminating");
	return (0);
}