1e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/*
2e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * dhcpcd - DHCP client daemon
3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt * Copyright (c) 2006-2010 Roy Marples <roy@marples.name>
4e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * All rights reserved
5e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
6e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Redistribution and use in source and binary forms, with or without
7e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * modification, are permitted provided that the following conditions
8e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * are met:
9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 1. Redistributions of source code must retain the above copyright
10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    notice, this list of conditions and the following disclaimer.
11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 2. Redistributions in binary form must reproduce the above copyright
12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    notice, this list of conditions and the following disclaimer in the
13e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *    documentation and/or other materials provided with the distribution.
14e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *
15e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * SUCH DAMAGE.
26e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt */
27e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
28e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <sys/time.h>
29e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <errno.h>
31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <limits.h>
32e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <poll.h>
33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdarg.h>
34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdlib.h>
35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h>
36e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h"
38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h"
39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct timeval now;
41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct event {
43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int fd;
44e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	void (*callback)(void *);
45e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	void *arg;
46e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct event *next;
47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} *events;
48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct event *free_events;
49e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct timeout {
51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeval when;
52e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	void (*callback)(void *);
53e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	void *arg;
54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int queue;
55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeout *next;
56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} *timeouts;
57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct timeout *free_timeouts;
58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct pollfd *fds;
60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic size_t fds_len;
61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_event(int fd, void (*callback)(void *), void *arg)
64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct event *e, *last = NULL;
66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* We should only have one callback monitoring the fd */
68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (e = events; e; e = e->next) {
69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (e->fd == fd) {
70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			e->callback = callback;
71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			e->arg = arg;
72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		last = e;
75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Allocate a new event if no free ones already allocated */
78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (free_events) {
79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		e = free_events;
80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free_events = e->next;
81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	} else
82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		e = xmalloc(sizeof(*e));
83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	e->fd = fd;
84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	e->callback = callback;
85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	e->arg = arg;
86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	e->next = NULL;
87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (last)
88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		last->next = e;
89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	else
90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		events = e;
91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdelete_event(int fd)
95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct event *e, *last = NULL;
97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (e = events; e; e = e->next) {
99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (e->fd == fd) {
100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (last)
101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				last->next = e->next;
102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				events = e->next;
104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			e->next = free_events;
105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free_events = e;
106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		last = e;
109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_q_timeout_tv(int queue,
114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    const struct timeval *when, void (*callback)(void *), void *arg)
115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeval w;
117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeout *t, *tt = NULL;
118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	get_monotonic(&now);
120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	timeradd(&now, when, &w);
121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Check for time_t overflow. */
122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (timercmp(&w, &now, <)) {
123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		errno = ERANGE;
124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* Remove existing timeout if present */
128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (t = timeouts; t; t = t->next) {
129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (t->callback == callback && t->arg == arg) {
130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (tt)
131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				tt->next = t->next;
132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				timeouts = t->next;
134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			break;
135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		tt = t;
137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!t) {
140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* No existing, so allocate or grab one from the free pool */
141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (free_timeouts) {
142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			t = free_timeouts;
143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free_timeouts = t->next;
144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else
145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			t = xmalloc(sizeof(*t));
146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	t->when.tv_sec = w.tv_sec;
149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	t->when.tv_usec = w.tv_usec;
150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	t->callback = callback;
151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	t->arg = arg;
152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	t->queue = queue;
153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	/* The timeout list should be in chronological order,
155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * soonest first.
156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * This is the easiest algorithm - check the head, then middle
157e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	 * and finally the end. */
158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	if (!timeouts || timercmp(&t->when, &timeouts->when, <)) {
159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		t->next = timeouts;
160e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		timeouts = t;
161e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		return;
162e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
163e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (tt = timeouts; tt->next; tt = tt->next)
164e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (timercmp(&t->when, &tt->next->when, <)) {
165e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			t->next = tt->next;
166e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			tt->next = t;
167e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			return;
168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	tt->next = t;
170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	t->next = NULL;
171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
174e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtadd_q_timeout_sec(int queue, time_t when, void (*callback)(void *), void *arg)
175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeval tv;
177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	tv.tv_sec = when;
179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	tv.tv_usec = 0;
180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	add_q_timeout_tv(queue, &tv, callback, arg);
181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* This deletes all timeouts for the interface EXCEPT for ones with the
184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * callbacks given. Handy for deleting everything apart from the expire
185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * timeout. */
186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtv_delete_q_timeouts(int queue, void *arg, void (*callback)(void *), va_list v)
188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeout *t, *tt, *last = NULL;
190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	va_list va;
191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	void (*f)(void *);
192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (t = timeouts; t && (tt = t->next, 1); t = tt) {
194e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (t->queue == queue && t->arg == arg &&
195e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    t->callback != callback)
196e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			va_copy(va, v);
198e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			while ((f = va_arg(va, void (*)(void *))))
199e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (f == t->callback)
200e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
201e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			va_end(va);
202e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (!f) {
203e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (last)
204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					last->next = t->next;
205e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				else
206e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					timeouts = t->next;
207e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				t->next = free_timeouts;
208e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free_timeouts = t;
209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
210e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
211e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
212e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		last = t;
213e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
214e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
215e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
216e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
217e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdelete_q_timeouts(int queue, void *arg, void (*callback)(void *), ...)
218e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
219e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	va_list va;
220e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
221e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	va_start(va, callback);
222e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	v_delete_q_timeouts(queue, arg, callback, va);
223e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	va_end(va);
224e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
225e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
226e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid
227e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtdelete_q_timeout(int queue, void (*callback)(void *), void *arg)
228e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeout *t, *tt, *last = NULL;
230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (t = timeouts; t && (tt = t->next, 1); t = tt) {
232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (t->queue == queue && t->arg == arg &&
233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		    (!callback || t->callback == callback))
234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		{
235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (last)
236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				last->next = t->next;
237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				timeouts = t->next;
239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			t->next = free_timeouts;
240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free_timeouts = t;
241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		last = t;
244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY
248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* Define this to free all malloced memory.
249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Normally we don't do this as the OS will do it for us at exit,
250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * but it's handy for debugging other leaks in valgrind. */
251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic void
252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtcleanup(void)
253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct event *e;
255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeout *t;
256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (events) {
258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		e = events->next;
259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(events);
260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		events = e;
261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (free_events) {
263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		e = free_events->next;
264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(free_events);
265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free_events = e;
266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (timeouts) {
268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		t = timeouts->next;
269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(timeouts);
270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		timeouts = t;
271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	while (free_timeouts) {
273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		t = free_timeouts->next;
274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free(free_timeouts);
275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		free_timeouts = t;
276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	free(fds);
278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt_noreturn void
282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_eloop(void)
283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	int msecs, n;
285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	nfds_t nfds, i;
286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct event *e;
287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeout *t;
288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	struct timeval tv;
289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifdef DEBUG_MEMORY
291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	atexit(cleanup);
292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	for (;;) {
295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Run all timeouts first.
296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * When we have one that has not yet occured,
297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * calculate milliseconds until it does for use in poll. */
298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (timeouts) {
299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (timercmp(&now, &timeouts->when, >)) {
300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				t = timeouts;
301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				timeouts = timeouts->next;
302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				t->callback(t->arg);
303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				t->next = free_timeouts;
304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				free_timeouts = t;
305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			timersub(&timeouts->when, &now, &tv);
308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (tv.tv_sec > INT_MAX / 1000 ||
309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			    (tv.tv_sec == INT_MAX / 1000 &&
310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				(tv.tv_usec + 999) / 1000 > INT_MAX % 1000))
311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				msecs = INT_MAX;
312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			else
313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				msecs = tv.tv_sec * 1000 +
314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				    (tv.tv_usec + 999) / 1000;
315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		} else
316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* No timeouts, so wait forever. */
317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			msecs = -1;
318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Allocate memory for our pollfds as and when needed.
320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		 * We don't bother shrinking it. */
321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		nfds = 0;
322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (e = events; e; e = e->next)
323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			nfds++;
324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (msecs == -1 && nfds == 0) {
325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "nothing to do");
326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (nfds > fds_len) {
329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			free(fds);
330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			/* Allocate 5 more than we need for future use */
331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			fds_len = nfds + 5;
332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			fds = xmalloc(sizeof(*fds) * fds_len);
333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		nfds = 0;
335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (e = events; e; e = e->next) {
336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			fds[nfds].fd = e->fd;
337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			fds[nfds].events = POLLIN;
338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			fds[nfds].revents = 0;
339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			nfds++;
340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
341e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		n = poll(fds, nfds, msecs);
342e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (n == -1) {
343e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (errno == EAGAIN || errno == EINTR) {
344e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				get_monotonic(&now);
345e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
346e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			syslog(LOG_ERR, "poll: %m");
348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			exit(EXIT_FAILURE);
349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		/* Get the now time and process any triggered events. */
352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		get_monotonic(&now);
353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		if (n == 0)
354e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			continue;
355e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		for (i = 0; i < nfds; i++) {
356e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			if (!(fds[i].revents & (POLLIN | POLLHUP)))
357e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				continue;
358e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			for (e = events; e; e = e->next) {
359e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				if (e->fd == fds[i].fd) {
360e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					e->callback(e->arg);
361e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt					break;
362e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt				}
363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt			}
364e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt		}
365e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt	}
366e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
367