Ejemplo n.º 1
0
/* ARGSUSED */
void
control_dispatch(int fd, short event, void *bula)
{
	struct iovec iov[PDU_MAXIOV];
	struct msghdr msg;
	struct control *c = bula;
	struct pdu *pdu;
	ssize_t	 n;
	unsigned int niov = 0;
	short flags = EV_READ;

	if (event & EV_TIMEOUT) {
		log_debug("control connection (fd %d) timed out.", fd);
		control_close(c);
		return;
	}
	if (event & EV_READ) {
		if ((n = recv(fd, cbuf, sizeof(cbuf), 0)) == -1 &&
		    !(errno == EAGAIN || errno == EINTR)) {
			control_close(c);
			return;
		}
		if (n == 0) {
			control_close(c);
			return;
		}
		pdu = control_getpdu(cbuf, n);
		if (!pdu) {
			log_debug("control connection (fd %d) bad msg.", fd);
			control_close(c);
			return;
		}
		iscsid_ctrl_dispatch(c, pdu);
	}
	if (event & EV_WRITE) {
		if ((pdu = TAILQ_FIRST(&c->channel)) != NULL) {
			TAILQ_REMOVE(&c->channel, pdu, entry);

			for (niov = 0; niov < PDU_MAXIOV; niov++) {
				iov[niov].iov_base = pdu->iov[niov].iov_base;
				iov[niov].iov_len = pdu->iov[niov].iov_len;
			}
			bzero(&msg, sizeof(msg));
			msg.msg_iov = iov;
			msg.msg_iovlen = niov;
			if (sendmsg(fd, &msg, 0) == -1 &&
			    !(errno == EAGAIN || errno == ENOBUFS)) {
				control_close(c);
				return;
			}
		}
	}
	if (!TAILQ_EMPTY(&c->channel))
		flags |= EV_WRITE;

	event_del(&c->ev);
	event_set(&c->ev, fd, flags, control_dispatch, c);
	event_add(&c->ev, NULL);
}
Ejemplo n.º 2
0
void
control_cleanup(char *path)
{
	struct control	*c;

	if (path)
		unlink(path);

	while ((c = TAILQ_FIRST(&controls)) != NULL) {
		TAILQ_REMOVE(&controls, c, entry);
		control_close(c);
	}
	control_close(control_state);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
/* ARGSUSED */
static void
control_dispatch_ext(struct mproc *p, struct imsg *imsg)
{
	struct sockaddr_storage	 ss;
	struct ctl_conn		*c;
	int			 v;
	struct stat_kv		*kvp;
	char			*key;
	struct stat_value	 val;
	size_t			 len;
	uint64_t		 evpid;
	uint32_t		 msgid;

	c = p->data;

	if (imsg == NULL) {
		control_close(c);
		return;
	}

	if (imsg->hdr.peerid != IMSG_VERSION) {
		m_compose(p, IMSG_CTL_FAIL, IMSG_VERSION, 0, -1, NULL, 0);
		return;
	}

	switch (imsg->hdr.type) {
	case IMSG_CTL_SMTP_SESSION:
		if (env->sc_flags & (SMTPD_SMTP_PAUSED | SMTPD_EXITING)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		m_compose(p_pony, IMSG_CTL_SMTP_SESSION, c->id, 0, -1,
		    &c->euid, sizeof(c->euid));
		return;

	case IMSG_CTL_GET_DIGEST:
		if (c->euid)
			goto badcred;
		digest.timestamp = time(NULL);
		m_compose(p, IMSG_CTL_GET_DIGEST, 0, 0, -1, &digest, sizeof digest);
		return;

	case IMSG_CTL_GET_STATS:
		if (c->euid)
			goto badcred;
		kvp = imsg->data;
		if (! stat_backend->iter(&kvp->iter, &key, &val))
			kvp->iter = NULL;
		else {
			(void)strlcpy(kvp->key, key, sizeof kvp->key);
			kvp->val = val;
		}
		m_compose(p, IMSG_CTL_GET_STATS, 0, 0, -1, kvp, sizeof *kvp);
		return;

	case IMSG_CTL_SHUTDOWN:
		/* NEEDS_FIX */
		log_debug("debug: received shutdown request");

		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_EXITING) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		env->sc_flags |= SMTPD_EXITING;
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		m_compose(p_parent, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_VERBOSE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		verbose = v;
		log_verbose(verbose);

		control_broadcast_verbose(IMSG_CTL_VERBOSE, verbose);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_TRACE_ENABLE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		verbose |= v;
		log_verbose(verbose);

		control_broadcast_verbose(IMSG_CTL_VERBOSE, verbose);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_TRACE_DISABLE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		verbose &= ~v;
		log_verbose(verbose);

		control_broadcast_verbose(IMSG_CTL_VERBOSE, verbose);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PROFILE_ENABLE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		profiling |= v;

		control_broadcast_verbose(IMSG_CTL_PROFILE, profiling);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PROFILE_DISABLE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		profiling &= ~v;

		control_broadcast_verbose(IMSG_CTL_PROFILE, profiling);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PAUSE_EVP:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_PAUSE_MDA:
		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_MDA_PAUSED) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mda paused");
		env->sc_flags |= SMTPD_MDA_PAUSED;
		m_compose(p_queue, IMSG_CTL_PAUSE_MDA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PAUSE_MTA:
		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_MTA_PAUSED) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mta paused");
		env->sc_flags |= SMTPD_MTA_PAUSED;
		m_compose(p_queue, IMSG_CTL_PAUSE_MTA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PAUSE_SMTP:
		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_SMTP_PAUSED) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: smtp paused");
		env->sc_flags |= SMTPD_SMTP_PAUSED;
		m_compose(p_pony, IMSG_CTL_PAUSE_SMTP, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_EVP:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_RESUME_MDA:
		if (c->euid)
			goto badcred;

		if (! (env->sc_flags & SMTPD_MDA_PAUSED)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mda resumed");
		env->sc_flags &= ~SMTPD_MDA_PAUSED;
		m_compose(p_queue, IMSG_CTL_RESUME_MDA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_MTA:
		if (c->euid)
			goto badcred;

		if (!(env->sc_flags & SMTPD_MTA_PAUSED)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mta resumed");
		env->sc_flags &= ~SMTPD_MTA_PAUSED;
		m_compose(p_queue, IMSG_CTL_RESUME_MTA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_SMTP:
		if (c->euid)
			goto badcred;

		if (!(env->sc_flags & SMTPD_SMTP_PAUSED)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: smtp resumed");
		env->sc_flags &= ~SMTPD_SMTP_PAUSED;
		m_forward(p_pony, imsg);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_ROUTE:
		if (c->euid)
			goto badcred;

		m_forward(p_pony, imsg);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_LIST_MESSAGES:
		if (c->euid)
			goto badcred;
		m_compose(p_scheduler, IMSG_CTL_LIST_MESSAGES, c->id, 0, -1,
		    imsg->data, imsg->hdr.len - sizeof(imsg->hdr));
		return;

	case IMSG_CTL_LIST_ENVELOPES:
		if (c->euid)
			goto badcred;
		m_compose(p_scheduler, IMSG_CTL_LIST_ENVELOPES, c->id, 0, -1,
		    imsg->data, imsg->hdr.len - sizeof(imsg->hdr));
		return;

	case IMSG_CTL_MTA_SHOW_HOSTS:
	case IMSG_CTL_MTA_SHOW_RELAYS:
	case IMSG_CTL_MTA_SHOW_ROUTES:
	case IMSG_CTL_MTA_SHOW_HOSTSTATS:
	case IMSG_CTL_MTA_SHOW_BLOCK:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_pony, imsg);
		return;

	case IMSG_CTL_SHOW_STATUS:
		if (c->euid)
			goto badcred;

		m_compose(p, IMSG_CTL_SHOW_STATUS, 0, 0, -1, &env->sc_flags,
		    sizeof(env->sc_flags));
		return;

	case IMSG_CTL_MTA_BLOCK:
	case IMSG_CTL_MTA_UNBLOCK:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE <= sizeof(ss))
			goto invalid;
		memmove(&ss, imsg->data, sizeof(ss));
		m_create(p_pony, imsg->hdr.type, c->id, 0, -1);
		m_add_sockaddr(p_pony, (struct sockaddr *)&ss);
		m_add_string(p_pony, (char *)imsg->data + sizeof(ss));
		m_close(p_pony);
		return;

	case IMSG_CTL_SCHEDULE:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_REMOVE:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_UPDATE_TABLE:
		if (c->euid)
			goto badcred;

		/* table name too long */
		len = strlen(imsg->data);
		if (len >= LINE_MAX)
			goto invalid;

		m_forward(p_lka, imsg);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_DISCOVER_EVPID:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof evpid)
			goto invalid;

		memmove(&evpid, imsg->data, sizeof evpid);
		m_create(p_queue, imsg->hdr.type, c->id, 0, -1);
		m_add_evpid(p_queue, evpid);
		m_close(p_queue);
		return;

	case IMSG_CTL_DISCOVER_MSGID:
	case IMSG_CTL_UNCORRUPT_MSGID:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof msgid)
			goto invalid;

		memmove(&msgid, imsg->data, sizeof msgid);
		m_create(p_queue, imsg->hdr.type, c->id, 0, -1);
		m_add_msgid(p_queue, msgid);
		m_close(p_queue);
		return;

	default:
		log_debug("debug: control_dispatch_ext: "
		    "error handling %s imsg",
		    imsg_to_str(imsg->hdr.type));
		return;
	}
badcred:
invalid:
	m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
/* ARGSUSED */
static void
control_dispatch_ext(struct mproc *p, struct imsg *imsg)
{
	struct ctl_conn		*c;
	int			 v;
	struct stat_kv		*kvp;
	char			*key;
	struct stat_value	 val;
	size_t			 len;

	c = p->data;

	if (imsg == NULL) {
		control_close(c);
		return;
	}

	if (imsg->hdr.peerid != IMSG_VERSION) {
		m_compose(p, IMSG_CTL_FAIL, IMSG_VERSION, 0, -1, NULL, 0);
		return;
	}

	switch (imsg->hdr.type) {
	case IMSG_SMTP_ENQUEUE_FD:
		if (env->sc_flags & (SMTPD_SMTP_PAUSED | SMTPD_EXITING)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		m_compose(p_smtp, IMSG_SMTP_ENQUEUE_FD, c->id, 0, -1,
		    &c->euid, sizeof(c->euid));
		return;

	case IMSG_STATS:
		if (c->euid)
			goto badcred;
		m_compose(p, IMSG_STATS, 0, 0, -1, NULL, 0);
		return;

	case IMSG_DIGEST:
		if (c->euid)
			goto badcred;
		digest.timestamp = time(NULL);
		m_compose(p, IMSG_DIGEST, 0, 0, -1, &digest, sizeof digest);
		return;

	case IMSG_STATS_GET:
		if (c->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;
		}
		m_compose(p, IMSG_STATS_GET, 0, 0, -1, kvp, sizeof *kvp);
		return;

	case IMSG_CTL_SHUTDOWN:
		/* NEEDS_FIX */
		log_debug("debug: received shutdown request");

		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_EXITING) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		env->sc_flags |= SMTPD_EXITING;
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		m_compose(p_parent, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_VERBOSE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		verbose = v;
		log_verbose(verbose);

		m_create(p_parent, IMSG_CTL_VERBOSE, 0, 0, -1);
		m_add_int(p_parent, verbose);
		m_close(p_parent);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_TRACE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		verbose |= v;
		log_verbose(verbose);

		m_create(p_parent, IMSG_CTL_TRACE, 0, 0, -1);
		m_add_int(p_parent, v);
		m_close(p_parent);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_UNTRACE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		verbose &= ~v;
		log_verbose(verbose);

		m_create(p_parent, IMSG_CTL_UNTRACE, 0, 0, -1);
		m_add_int(p_parent, v);
		m_close(p_parent);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PROFILE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		profiling |= v;

		m_create(p_parent, IMSG_CTL_PROFILE, 0, 0, -1);
		m_add_int(p_parent, v);
		m_close(p_parent);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_UNPROFILE:
		if (c->euid)
			goto badcred;

		if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(verbose))
			goto badcred;

		memcpy(&v, imsg->data, sizeof(v));
		profiling &= ~v;

		m_create(p_parent, IMSG_CTL_UNPROFILE, 0, 0, -1);
		m_add_int(p_parent, v);
		m_close(p_parent);

		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PAUSE_EVP:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_PAUSE_MDA:
		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_MDA_PAUSED) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mda paused");
		env->sc_flags |= SMTPD_MDA_PAUSED;
		m_compose(p_queue, IMSG_CTL_PAUSE_MDA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PAUSE_MTA:
		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_MTA_PAUSED) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mta paused");
		env->sc_flags |= SMTPD_MTA_PAUSED;
		m_compose(p_queue, IMSG_CTL_PAUSE_MTA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_PAUSE_SMTP:
		if (c->euid)
			goto badcred;

		if (env->sc_flags & SMTPD_SMTP_PAUSED) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: smtp paused");
		env->sc_flags |= SMTPD_SMTP_PAUSED;
		m_compose(p_smtp, IMSG_CTL_PAUSE_SMTP, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_EVP:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_RESUME_MDA:
		if (c->euid)
			goto badcred;

		if (! (env->sc_flags & SMTPD_MDA_PAUSED)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mda resumed");
		env->sc_flags &= ~SMTPD_MDA_PAUSED;
		m_compose(p_queue, IMSG_CTL_RESUME_MDA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_MTA:
		if (c->euid)
			goto badcred;

		if (!(env->sc_flags & SMTPD_MTA_PAUSED)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: mta resumed");
		env->sc_flags &= ~SMTPD_MTA_PAUSED;
		m_compose(p_queue, IMSG_CTL_RESUME_MTA, 0, 0, -1, NULL, 0);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_SMTP:
		if (c->euid)
			goto badcred;

		if (!(env->sc_flags & SMTPD_SMTP_PAUSED)) {
			m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
			return;
		}
		log_info("info: smtp resumed");
		env->sc_flags &= ~SMTPD_SMTP_PAUSED;
		m_forward(p_smtp, imsg);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_RESUME_ROUTE:
		if (c->euid)
			goto badcred;

		m_forward(p_mta, imsg);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	case IMSG_CTL_LIST_MESSAGES:
		if (c->euid)
			goto badcred;
		m_compose(p_scheduler, IMSG_CTL_LIST_MESSAGES, c->id, 0, -1,
		    imsg->data, imsg->hdr.len - sizeof(imsg->hdr));
		return;

	case IMSG_CTL_LIST_ENVELOPES:
		if (c->euid)
			goto badcred;
		m_compose(p_scheduler, IMSG_CTL_LIST_ENVELOPES, c->id, 0, -1,
		    imsg->data, imsg->hdr.len - sizeof(imsg->hdr));
		return;

	case IMSG_CTL_MTA_SHOW_HOSTS:
	case IMSG_CTL_MTA_SHOW_RELAYS:
	case IMSG_CTL_MTA_SHOW_ROUTES:
	case IMSG_CTL_MTA_SHOW_HOSTSTATS:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_mta, imsg);
		return;

	case IMSG_CTL_SCHEDULE:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_CTL_REMOVE:
		if (c->euid)
			goto badcred;

		imsg->hdr.peerid = c->id;
		m_forward(p_scheduler, imsg);
		return;

	case IMSG_LKA_UPDATE_TABLE:
		if (c->euid)
			goto badcred;

		/* table name too long */
		len = strlen(imsg->data);
		if (len >= SMTPD_MAXLINESIZE)
			goto invalid;

		m_forward(p_lka, imsg);
		m_compose(p, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
		return;

	default:
		log_debug("debug: control_dispatch_ext: "
		    "error handling %s imsg",
		    imsg_to_str(imsg->hdr.type));
		return;
	}
badcred:
invalid:
	m_compose(p, IMSG_CTL_FAIL, 0, 0, -1, NULL, 0);
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
int threads_linux_init(void)
{
    int status = 0;
    int n = 0;
    int return_value = THREADS_LINUX_SUCCESS;

    // Init data
    status = sensors_init(&battery_data, &gps_data, &imu_data, &pitot_data, &pwm_read_data, &pwm_write_data, &scp1000_data, &sonar_data);
    if(status != SENSORS_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = calibration_init(&calibration_local_coordinate_system_data, &calibration_local_fields_data, &calibration_altimeter_data);
        if(status != CALIBRATION_SUCCESS)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = gps_init(&gps_measure);
        if(status != 1)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = imu_init(&imu_measure);
        if(status != 1)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = magnetometer_init(&magnetometer_measure);
        if(status != 1)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
    	status = sonar_init(&sonar_measure);
    	if(status != 1)
    	{
    		return_value = THREADS_LINUX_FAILURE;
    	}
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = estimation_init(ESTIMATION_DO_NOT_ESTIMATE_ACCEL_BIAS, &estimation_data);
        if(status != ESTIMATION_SUCCESS)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = control_init(&control_data);
        if(status != CONTROL_SUCCESS)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = protocol_init();
        if(status != PROTOCOL_SUCCESS)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = ui_init();
        if(status != UI_SUCCESS)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    if(return_value != THREADS_LINUX_FAILURE)
    {
        status = datalogger_init();
        if(status != DATALOGGER_SUCCESS)
        {
            return_value = THREADS_LINUX_FAILURE;
        }
    }

    // Main Loop
    if(return_value != THREADS_LINUX_FAILURE)
    {
        threads_linux_timer_start_task_1();
        usleep(0.5*task_1_period_us);
        threads_linux_timer_start_task_2();
        usleep(5*task_1_period_us);

        while(quittask == 0)
        {
            #if ANU_COMPILE_FOR_OVERO
            #else
            if(datalogger_status() == DATALOGGER_RUNNING) datalogger_update_IPC();
            #endif
            if(++n>100)
            {
                if(datalogger_status() == DATALOGGER_RUNNING) datalogger_write_file();
                n = 0;
            }
            usleep(5*task_1_period_us);
        }

        threads_linux_timer_stop_task_1();
        usleep(TASK1_PERIOD_US);
        threads_linux_timer_stop_task_2();
        usleep(TASK2_PERIOD_US);
    }

    status = datalogger_close();
    if(status != DATALOGGER_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = ui_close();
    if(status != UI_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = protocol_close();
    if(status != PROTOCOL_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = control_close();
    if(status != CONTROL_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = estimation_close(&estimation_data);
    if(status != ESTIMATION_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = magnetometer_close(&magnetometer_measure);
    if(status != 1)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = imu_close(&imu_measure);
    if(status != 1)
    {
        return_value = THREADS_LINUX_FAILURE;
    }
    status = gps_close(&gps_measure);
    if(status != 1)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = calibration_close(&calibration_local_coordinate_system_data, &calibration_local_fields_data, &calibration_altimeter_data);
    if(status != CALIBRATION_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    status = sensors_close();
    if(status != SENSORS_SUCCESS)
    {
        return_value = THREADS_LINUX_FAILURE;
    }

    return return_value;
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
0
/* ARGSUSED */
void
control_dispatch_agentx(int fd, short event, void *arg)
{
	struct ctl_conn			*c = arg;
	struct agentx_handle		*h = c->handle;
	struct agentx_pdu		*pdu;
	struct timeval			 tv;
	struct agentx_open_timeout	 to;
	struct ber_oid			 oid;
	struct agentx_close_request_data clhdr;
	int				 closing = 0;
	int				 evflags = 0;
	int				 timer = 0;
	int				 error = AGENTX_ERR_NONE;
	int				 idx = 0, vcpylen, dlen, uptime;
	char				*descr, *varcpy;

	varcpy = descr = NULL;
	if (h->timeout != 0)
		tv.tv_sec = h->timeout;
	else
		tv.tv_sec = AGENTX_DEFAULT_TIMEOUT;
	tv.tv_usec = 0;

	if (event & EV_TIMEOUT) {
		log_info("subagent session '%i' timed out after %i seconds",
		    h->sessionid, h->timeout);
		goto teardown;
	}

	if (event & EV_WRITE) {
		if (snmp_agentx_send(h, NULL) == -1) {
			if (errno != EAGAIN)
				goto teardown;

			/* short write */
			evflags |= EV_WRITE;
			timer = 1;
		}
	}

	if (event & EV_READ) {
		if ((pdu = snmp_agentx_recv(h)) == NULL) {
			if (h->error) {
				error = h->error;
				goto respond;
			}
			if (errno != EAGAIN)
				goto teardown;

			/* short read */
			timer = 1;
			goto done;
		}

		switch (pdu->hdr->type) {
		case AGENTX_OPEN:
			if (snmp_agentx_read_raw(pdu, &to, sizeof(to)) == -1 ||
			    snmp_agentx_read_oid(pdu,
			    (struct snmp_oid *)&oid) == -1 ||
			    (descr =
			    snmp_agentx_read_octetstr(pdu, &dlen)) == NULL) {
				error = AGENTX_ERR_PARSE_ERROR;
				break;
			}

			log_info("opening AgentX socket for '%.*s'",
			    dlen, descr);

			h->sessionid = pdu->hdr->sessionid =
			    agentx_sessionid++;
			if (to.timeout != 0)
				h->timeout = to.timeout;
			else
				h->timeout = AGENTX_DEFAULT_TIMEOUT;
			break;

		case AGENTX_CLOSE:
			if (snmp_agentx_read_raw(pdu,
			    &clhdr, sizeof(clhdr)) == -1) {
				error = AGENTX_ERR_PARSE_ERROR;
				break;
			}
			closing = 1;
			break;

		case AGENTX_NOTIFY:
			error = trap_agentx(h, pdu, &idx, &varcpy, &vcpylen);
			break;

		case AGENTX_PING:
			/* no processing, just an empty response */
			break;

		case AGENTX_REGISTER: {
			struct agentx_register_hdr	 rhdr;
			struct oidlist			 oids;
			struct oid			*miboid;
			uint32_t			 ubound = 0;

			TAILQ_INIT(&oids);

			if (snmp_agentx_read_raw(pdu,
			    &rhdr, sizeof(rhdr)) == -1 ||
			    snmp_agentx_read_oid(pdu,
			    (struct snmp_oid *)&oid) == -1) {
				error = AGENTX_ERR_PARSE_ERROR;
				break;
			}

			do {
				if ((miboid = calloc(1, sizeof(*miboid))) == NULL) {
					purge_registered_oids(&oids);
					error = AGENTX_ERR_PARSE_ERROR;
					goto dodone;
				}
				bcopy(&oid, &miboid->o_id, sizeof(oid));
				miboid->o_flags = OID_RD|OID_WR|OID_REGISTERED;
				miboid->o_session = c;
				if (smi_insert(miboid) == -1) {
					purge_registered_oids(&oids);
					error = AGENTX_ERR_DUPLICATE_REGISTRATION;
					goto dodone;
				}
				TAILQ_INSERT_TAIL(&oids, miboid, o_list);
			} while (++oid.bo_id[rhdr.subrange] <= ubound);

			while ((miboid = TAILQ_FIRST(&oids)) != NULL) {
				TAILQ_REMOVE(&oids, miboid, o_list);
				TAILQ_INSERT_TAIL(&c->oids, miboid, o_list);
			}
 dodone:
			break;
		}

		case AGENTX_UNREGISTER: {
			struct agentx_unregister_hdr	 uhdr;
			struct oid			*miboid;
			uint32_t			 ubound = 0;

			if (snmp_agentx_read_raw(pdu,
			    &uhdr, sizeof(uhdr)) == -1 ||
			    snmp_agentx_read_oid(pdu,
			    (struct snmp_oid *)&oid) == -1) {
				error = AGENTX_ERR_PARSE_ERROR;
				break;
			}

			do {
				if ((miboid = smi_find((struct oid *)&oid)) == NULL) {
					log_warnx("attempting to remove unregistered MIB");
					continue;
				}
				if (miboid->o_session != c) {
					log_warnx("attempting to remove MIB registered by other session");
					continue;
				}
				smi_delete(miboid);
			} while (++oid.bo_id[uhdr.subrange] <= ubound);
			break;
		}

		case AGENTX_RESPONSE: {
			struct snmp_message		*msg = pdu->request->cookie;
			struct agentx_response_data	 resp;
			struct agentx_varbind_hdr	 vbhdr;
			struct ber_element		**elm, **iter;

			if (snmp_agentx_read_response(pdu, &resp) == -1) {
				msg->sm_error = SNMP_ERROR_GENERR;
				goto dispatch;
			}

			switch (resp.error) {
			case AGENTX_ERR_NONE:
				break;

			/* per RFC, resp.error may be an SNMP error value */
			case SNMP_ERROR_TOOBIG:
			case SNMP_ERROR_NOSUCHNAME:
			case SNMP_ERROR_BADVALUE:
			case SNMP_ERROR_READONLY:
			case SNMP_ERROR_GENERR:
			case SNMP_ERROR_NOACCESS:
			case SNMP_ERROR_WRONGTYPE:
			case SNMP_ERROR_WRONGLENGTH:
			case SNMP_ERROR_WRONGENC:
			case SNMP_ERROR_WRONGVALUE:
			case SNMP_ERROR_NOCREATION:
			case SNMP_ERROR_INCONVALUE:
			case SNMP_ERROR_RESUNAVAIL:
			case SNMP_ERROR_COMMITFAILED:
			case SNMP_ERROR_UNDOFAILED:
			case SNMP_ERROR_AUTHERROR:
			case SNMP_ERROR_NOTWRITABLE:
			case SNMP_ERROR_INCONNAME:
				msg->sm_error = resp.error;
				msg->sm_errorindex = resp.index;
				break;

			case AGENTX_ERR_INDEX_WRONG_TYPE:
			case AGENTX_ERR_UNSUPPORTED_CONTEXT:
			case AGENTX_ERR_PARSE_ERROR:
			case AGENTX_ERR_REQUEST_DENIED:
			case AGENTX_ERR_PROCESSING_ERROR:
			default:
				msg->sm_error = SNMP_ERROR_GENERR;
				msg->sm_errorindex = resp.index;
				break;
			}

			iter = elm = &msg->sm_varbindresp;

			while (pdu->datalen > sizeof(struct agentx_hdr)) {
				if (snmp_agentx_read_raw(pdu, &vbhdr, sizeof(vbhdr)) == -1 ||
				    varbind_convert(pdu, &vbhdr, elm, iter)
				    != AGENTX_ERR_NONE) {
					msg->sm_error = SNMP_ERROR_GENERR;
					msg->sm_errorindex = msg->sm_i;
					goto dispatch;
				}
			}
 dispatch:
			snmpe_dispatchmsg(msg);
			break;
		}

		/* unimplemented, but parse and accept for now */
		case AGENTX_ADD_AGENT_CAPS:
		case AGENTX_REMOVE_AGENT_CAPS:
			break;

		/* unimplemented */
		case AGENTX_GET:
		case AGENTX_GET_NEXT:
		case AGENTX_GET_BULK:
		case AGENTX_TEST_SET:
		case AGENTX_COMMIT_SET:
		case AGENTX_UNDO_SET:
		case AGENTX_CLEANUP_SET:
		case AGENTX_INDEX_ALLOCATE:
		case AGENTX_INDEX_DEALLOCATE:
			error = AGENTX_ERR_REQUEST_DENIED;
			break;

		/* NB: by RFC, this should precede all other checks. */
		default:
			log_info("unknown AgentX type '%i'", pdu->hdr->type);
			error = AGENTX_ERR_PARSE_ERROR;
			break;
		}
 respond:
		if (pdu)
			snmp_agentx_pdu_free(pdu);

		uptime = smi_getticks();
		if ((pdu = snmp_agentx_response_pdu(uptime, error, idx)) == NULL) {
			log_debug("failed to generate response");
			free(varcpy);
			control_event_add(c, fd, EV_WRITE, NULL);	/* XXX -- EV_WRITE? */
			return;
		}

		if (varcpy) {
			snmp_agentx_raw(pdu, varcpy, vcpylen); /* XXX */
			free(varcpy);
		}
		snmp_agentx_send(h, pdu);

		/* Request processed, now write out response */
		evflags |= EV_WRITE;
	}

	if (closing)
		goto teardown;
 done:
	control_event_add(c, fd, evflags, timer ? &tv : NULL);
	return;

 teardown:
	log_debug("subagent session '%i' destroyed", h->sessionid);
	snmp_agentx_free(h);
	purge_registered_oids(&c->oids);
	free(varcpy);
	control_close(c, "agentx teardown", NULL);
}
Ejemplo n.º 12
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);
}
Ejemplo n.º 13
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);
}
Ejemplo n.º 14
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_warnx("%s: fd %d: not found", __func__, fd);
		return;
	}

	if (event & EV_READ) {
		if (((n = imsg_read(&c->iev.ibuf)) == -1 && errno != EAGAIN) ||
		    n == 0) {
			control_close(fd);
			return;
		}
	}
	if (event & EV_WRITE) {
		if (msgbuf_write(&c->iev.ibuf.w) <= 0 && 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_FIB_COUPLE:
		case IMSG_CTL_FIB_DECOUPLE:
		case IMSG_CTL_RELOAD:
			c->iev.ibuf.pid = imsg.hdr.pid;
			eigrpe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0);
			break;
		case IMSG_CTL_KROUTE:
		case IMSG_CTL_IFINFO:
			c->iev.ibuf.pid = imsg.hdr.pid;
			eigrpe_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))
				break;

			memcpy(&ifidx, imsg.data, sizeof(ifidx));
			eigrpe_iface_ctl(c, ifidx);
			imsg_compose_event(&c->iev, IMSG_CTL_END, 0,
			    0, -1, NULL, 0);
			break;
		case IMSG_CTL_SHOW_TOPOLOGY:
			if (imsg.hdr.len != IMSG_HEADER_SIZE +
			    sizeof(struct ctl_show_topology_req))
				break;

			c->iev.ibuf.pid = imsg.hdr.pid;
			eigrpe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
			break;
		case IMSG_CTL_SHOW_NBR:
			eigrpe_nbr_ctl(c);
			break;
		case IMSG_CTL_SHOW_STATS:
			eigrpe_stats_ctl(c);
			break;
		case IMSG_CTL_CLEAR_NBR:
			if (imsg.hdr.len != IMSG_HEADER_SIZE +
			    sizeof(struct ctl_nbr))
				break;

			nbr_clear_ctl(imsg.data);
			break;
		case IMSG_CTL_LOG_VERBOSE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE +
			    sizeof(verbose))
				break;

			/* forward to other processes */
			eigrpe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
			    imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
			eigrpe_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("%s: error handling imsg %d", __func__,
			    imsg.hdr.type);
			break;
		}
		imsg_free(&imsg);
	}

	imsg_event_add(&c->iev);
}
Ejemplo n.º 15
0
/* ARGSUSED */
void
control_dispatch_imsg(int fd, short event, void *arg)
{
	struct control_sock	*cs = arg;
	struct ctl_conn		*c;
	struct imsg		 imsg;
	struct ctl_id		 id;
	int			 n;
	int			 verbose;
	struct relayd		*env = cs->cs_env;

	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 && errno != EAGAIN) ||
		    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;

		if (c->waiting) {
			log_debug("%s: unexpected imsg %d",
			    __func__, imsg.hdr.type);
			imsg_free(&imsg);
			control_close(fd, cs);
			return;
		}

		switch (imsg.hdr.type) {
		case IMSG_CTL_SHOW_SUM:
			show(c);
			break;
		case IMSG_CTL_SESSION:
			show_sessions(c);
			break;
		case IMSG_CTL_RDR_DISABLE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
				fatalx("invalid imsg header len");
			memcpy(&id, imsg.data, sizeof(id));
			if (disable_rdr(c, &id))
				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
				    0, 0, -1, NULL, 0);
			else {
				memcpy(imsg.data, &id, sizeof(id));
				control_imsg_forward(&imsg);
				imsg_compose_event(&c->iev, IMSG_CTL_OK,
				    0, 0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_RDR_ENABLE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
				fatalx("invalid imsg header len");
			memcpy(&id, imsg.data, sizeof(id));
			if (enable_rdr(c, &id))
				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
				    0, 0, -1, NULL, 0);
			else {
				memcpy(imsg.data, &id, sizeof(id));
				control_imsg_forward(&imsg);
				imsg_compose_event(&c->iev, IMSG_CTL_OK,
				    0, 0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_TABLE_DISABLE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
				fatalx("invalid imsg header len");
			memcpy(&id, imsg.data, sizeof(id));
			if (disable_table(c, &id))
				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
				    0, 0, -1, NULL, 0);
			else {
				memcpy(imsg.data, &id, sizeof(id));
				control_imsg_forward(&imsg);
				imsg_compose_event(&c->iev, IMSG_CTL_OK,
				    0, 0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_TABLE_ENABLE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
				fatalx("invalid imsg header len");
			memcpy(&id, imsg.data, sizeof(id));
			if (enable_table(c, &id))
				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
				    0, 0, -1, NULL, 0);
			else {
				memcpy(imsg.data, &id, sizeof(id));
				control_imsg_forward(&imsg);
				imsg_compose_event(&c->iev, IMSG_CTL_OK,
				    0, 0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_HOST_DISABLE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
				fatalx("invalid imsg header len");
			memcpy(&id, imsg.data, sizeof(id));
			if (disable_host(c, &id, NULL))
				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
				    0, 0, -1, NULL, 0);
			else {
				memcpy(imsg.data, &id, sizeof(id));
				control_imsg_forward(&imsg);
				imsg_compose_event(&c->iev, IMSG_CTL_OK,
				    0, 0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_HOST_ENABLE:
			if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
				fatalx("invalid imsg header len");
			memcpy(&id, imsg.data, sizeof(id));
			if (enable_host(c, &id, NULL))
				imsg_compose_event(&c->iev, IMSG_CTL_FAIL,
				    0, 0, -1, NULL, 0);
			else {
				memcpy(imsg.data, &id, sizeof(id));
				control_imsg_forward(&imsg);
				imsg_compose_event(&c->iev, IMSG_CTL_OK,
				    0, 0, -1, NULL, 0);
			}
			break;
		case IMSG_CTL_SHUTDOWN:
		case IMSG_CTL_RELOAD:
			proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT, -1);
			break;
		case IMSG_CTL_POLL:
			proc_compose(env->sc_ps, PROC_HCE, IMSG_CTL_POLL, NULL, 0);
			imsg_compose_event(&c->iev, IMSG_CTL_OK,
			    0, 0, -1, NULL, 0);
			break;
		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, &verbose);

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

			proc_forward_imsg(env->sc_ps, &imsg, PROC_PARENT, -1);
			proc_forward_imsg(env->sc_ps, &imsg, PROC_HCE, -1);
			proc_forward_imsg(env->sc_ps, &imsg, PROC_RELAY, -1);

			memcpy(imsg.data, &verbose, sizeof(verbose));
			control_imsg_forward(&imsg);
			log_verbose(verbose);
			break;
		default:
			log_debug("%s: error handling imsg %d",
			    __func__, imsg.hdr.type);
			break;
		}
		imsg_free(&imsg);
	}

	imsg_event_add(&c->iev);
}