Example #1
0
/* Set up a helper connection to parent using getenv() */
mowgli_eventloop_helper_proc_t *
mowgli_helper_setup(mowgli_eventloop_t *eventloop)
{
	mowgli_eventloop_helper_proc_t *helper;
	const char *env_io_fd;

	env_io_fd = getenv("IO_FD");

	/* this shouldn't be a hard-fail because some idiot may run the helper from
	 * the cmdline.  allow the helper to error out gracefully if not spawned as
	 * a helper.
	 */
	if (env_io_fd == NULL)
		return NULL;

	helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t));
	helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER;
	helper->eventloop = eventloop;
	helper->fd = atoi(env_io_fd);
	helper->pfd = mowgli_pollable_create(helper->eventloop, helper->fd, helper);

	mowgli_pollable_set_nonblocking(helper->pfd, true);

	return helper;
}
Example #2
0
u_link_origin *u_link_origin_create_from_fd(mowgli_eventloop_t *ev, int fd)
{
	const char *operation;
	u_link_origin *origin = NULL;

	/* Set the fd to be close-on-exec. All listening sockets will be closed when
	 * we upgrade. This may cause some slight disturbance for users currently
	 * connecting, but this is acceptable.
	 */
	operation = "set close-on-exec";
	if (set_cloexec(fd) < 0)
		goto error;

	u_log(LG_DEBUG, "u_link_origin_create_from_fd: %d", fd);

	origin = malloc(sizeof(*origin));

	operation = "create pollable";
	if (!(origin->poll = mowgli_pollable_create(ev, fd, origin))) {
		errno = -EINVAL; /* XXX */
		goto error;
	}

	mowgli_node_add(origin, &origin->n, &all_origins);
	mowgli_pollable_setselect(ev, origin->poll, MOWGLI_EVENTLOOP_IO_READ,
	                          accept_ready);

	return origin;
error:
	u_perror(operation);
	free(origin);
	return NULL;
}
Example #3
0
mowgli_eventloop_helper_proc_t *
mowgli_helper_spawn(mowgli_eventloop_t *eventloop, const char *path, char *const argv[])
{
	mowgli_eventloop_helper_proc_t *helper;
	int io_fd[2];
	char buf[64];

	return_val_if_fail(eventloop != NULL, NULL);
	return_val_if_fail(path != NULL, NULL);

	helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t));
	helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER;
	helper->eventloop = eventloop;

	socketpair(AF_UNIX, SOCK_STREAM, 0, io_fd);

	/* set up helper/child fd mapping */
	helper->fd = io_fd[0];

	/* make pollables and make them non-blocking */
	helper->pfd = mowgli_pollable_create(eventloop, helper->fd, helper);

	snprintf(buf, sizeof buf, "%d", io_fd[1]);
	setenv("IO_FD", buf, 1);

	/* Spawn helper process using mowgli_process_spawn(), helper will get
	 * IO_FD mapping from getenv().  Ugly hack, but it works...
	 *     --nenolod
	 */
	helper->child = mowgli_process_spawn(path, argv);

	if (helper->child == NULL)
	{
		mowgli_pollable_destroy(eventloop, helper->pfd);

		close(io_fd[0]);
		close(io_fd[1]);

		mowgli_free(helper);
		return NULL;
	}

	close(io_fd[1]);

	return helper;
}
Example #4
0
int
main(void)
{
	mowgli_eventloop_t *evloop = mowgli_eventloop_create();
	mowgli_dns_t *dns = mowgli_dns_create(evloop, MOWGLI_DNS_TYPE_ASYNC);
	mowgli_eventloop_pollable_t *stdin_pollable = mowgli_pollable_create(evloop, STDIN_FILENO, dns);

	mowgli_pollable_set_nonblocking(stdin_pollable, true);

	mowgli_pollable_setselect(evloop, stdin_pollable, MOWGLI_EVENTLOOP_IO_READ, read_data);

	mowgli_eventloop_run(evloop);

	mowgli_eventloop_destroy(evloop);

	return 0;
}
Example #5
0
mowgli_eventloop_helper_proc_t *
mowgli_helper_create(mowgli_eventloop_t *eventloop, mowgli_eventloop_helper_start_fn_t *start_fn, const char *helpername, void *userdata)
{
	mowgli_eventloop_helper_proc_t *helper;
	mowgli_helper_create_req_t child;
	int io_fd[2];

	return_val_if_fail(eventloop != NULL, NULL);
	return_val_if_fail(start_fn != NULL, NULL);

	child.start_fn = start_fn;
	child.userdata = userdata;

	helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t));
	helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER;
	helper->eventloop = eventloop;

	socketpair(AF_UNIX, SOCK_STREAM, 0, io_fd);

	/* set up helper/child fd mapping */
	helper->fd = io_fd[0];
	child.fd = io_fd[1];

	/* make pollables and make them non-blocking */
	helper->pfd = mowgli_pollable_create(eventloop, helper->fd, helper);
	mowgli_pollable_set_nonblocking(helper->pfd, true);

	/* spawn helper process using mowgli_process_clone() */
	helper->child = mowgli_process_clone((mowgli_process_start_fn_t) mowgli_helper_trampoline, helpername, &child);

	if (helper->child == NULL)
	{
		mowgli_pollable_destroy(eventloop, helper->pfd);

		close(io_fd[0]);
		close(io_fd[1]);

		mowgli_free(helper);
		return NULL;
	}

	close(child.fd);

	return helper;
}
Example #6
0
static void
mowgli_helper_trampoline(mowgli_helper_create_req_t *req)
{
	mowgli_eventloop_helper_proc_t *helper;
#ifndef _WIN32
	int i, x;
#endif

	return_if_fail(req != NULL);
	return_if_fail(req->start_fn != NULL);

	helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t));
	helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER;
	helper->fd = req->fd;

#ifndef _WIN32
	for (i = 0; i < 1024; i++)
	{
		if (i != req->fd)
			close(i);
	}

	x = open("/dev/null", O_RDWR);

	for (i = 0; i < 2; i++)
	{
		if (req->fd != i)
			dup2(x, i);
	}

	if (x > 2)
		close(x);
#endif

	helper->eventloop = mowgli_eventloop_create();
	helper->pfd = mowgli_pollable_create(helper->eventloop, helper->fd, helper);
	helper->userdata = req->userdata;

	mowgli_pollable_set_nonblocking(helper->pfd, true);

	req->start_fn(helper, helper->userdata);
}
Example #7
0
mowgli_eventloop_pollable_t* irc_connect(const char * host, const char * port)
{
    mowgli_eventloop_pollable_t* out;
    mowgli_descriptor_t fd;
    struct addrinfo hints, *res;
    
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    
    getaddrinfo(host, port, &hints, &res);

    fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    connect(fd, res->ai_addr, res->ai_addrlen);
    
    out = mowgli_pollable_create(base_eventloop, fd, NULL);
    mowgli_pollable_set_nonblocking(out, true);
    mowgli_pollable_setselect(base_eventloop, out, MOWGLI_EVENTLOOP_POLL_READ, irc_read);
    
    return out;
}
Example #8
0
static int
linux_prepare(mowgli_eventloop_t *eventloop, mowgli_config_file_entry_t *entry)
{
	mowgli_eventloop_pollable_t *pollable;
	mowgli_config_file_entry_t *ce;
	char *interface = NULL;
	int fd;
	int ifindex = 0;
	bool promisc;

	MOWGLI_ITER_FOREACH(ce, entry)
	{
		if (!strcasecmp(ce->varname, "interface"))
			interface = strdup(ce->vardata);
		if (!strcasecmp(ce->varname, "promisc"))
			promisc = true;
	}

	fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
	if (fd < 0)
		return;

	if (interface)
	{
		struct sockaddr_ll sll;
		struct ifreq ethreq = {};

		mowgli_strlcpy(ethreq.ifr_name, interface, IFNAMSIZ);
		ioctl(fd, SIOCGIFINDEX, &ethreq);

		DPRINTF("ifindex for %s: %d\n", interface, ethreq.ifr_ifindex);

		ifindex = ethreq.ifr_ifindex;

		sll.sll_family = AF_PACKET;
		sll.sll_protocol = htons(ETH_P_IP);
		sll.sll_ifindex = ifindex;

		if (bind(fd, (struct sockaddr *) &sll, sizeof sll) < 0)
		{
			DPRINTF("unable to bind(2) to interface '%s' (index %d): %s\n", interface, ifindex, strerror(errno));
			goto out;
		}

		DPRINTF("bound to interface '%s'\n", interface);
	}

	if (promisc)
	{
		struct packet_mreq mr;

		mr.mr_ifindex = ifindex;
		mr.mr_type = PACKET_MR_PROMISC;

		if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof mr) < 0)
		{
			DPRINTF("unable to add packet membership for fd=%d\n", fd);
			goto out;
		}

		DPRINTF("enabled promisc mode for fd=%d\n", fd);
	}

out:
	DPRINTF("opened raw packet socket as fd=%d\n", fd);

	pollable = mowgli_pollable_create(eventloop, fd, NULL);
	mowgli_pollable_setselect(eventloop, pollable, MOWGLI_EVENTLOOP_IO_READ, linux_handle);
}