dispatch.c revision 1.7
1/* dispatch.c
2
3   Network input dispatcher... */
4
5/*
6 * Copyright (c) 1995, 1996, 1997, 1998, 1999
7 * The Internet Software Consortium.   All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 *    of its contributors may be used to endorse or promote products derived
20 *    from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38 * Enterprises.  To learn more about the Internet Software Consortium,
39 * see ``http://www.vix.com/isc''.  To learn more about Vixie
40 * Enterprises, see ``http://www.vix.com''.
41 */
42
43#include "dhcpd.h"
44#include <ifaddrs.h>
45#include <sys/ioctl.h>
46#include <poll.h>
47#include <net/if_media.h>
48
49
50/* Most boxes has less than 16 interfaces, so this might be a good guess.  */
51#define INITIAL_IFREQ_COUNT 16
52
53struct interface_info *interfaces, *dummy_interfaces, *fallback_interface;
54struct protocol *protocols;
55struct timeout *timeouts;
56static struct timeout *free_timeouts;
57static int interfaces_invalidated;
58void (*bootp_packet_handler)(struct interface_info *,
59    struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
60
61static int interface_status(struct interface_info *ifinfo);
62
63int quiet_interface_discovery;
64
65/* Use getifaddrs() to get a list of all the attached interfaces.
66   For each interface that's of type INET and not the loopback interface,
67   register that interface with the network I/O software, figure out what
68   subnet it's on, and add it to the list of interfaces. */
69
70void
71discover_interfaces(int state)
72{
73	struct interface_info *tmp;
74	struct interface_info *last, *next;
75	struct subnet *subnet;
76	struct shared_network *share;
77	struct sockaddr_in foo;
78	int ir;
79	struct ifreq *tif;
80	struct ifaddrs *ifap, *ifa;
81#ifdef ALIAS_NAMES_PERMUTED
82	char *s;
83#endif
84
85	if (getifaddrs(&ifap) != 0)
86		error("getifaddrs failed");
87
88	/* If we already have a list of interfaces, and we're running as
89	   a DHCP server, the interfaces were requested. */
90	if (interfaces && (state == DISCOVER_SERVER ||
91	    state == DISCOVER_RELAY || state == DISCOVER_REQUESTED))
92		ir = 0;
93	else if (state == DISCOVER_UNCONFIGURED)
94		ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC;
95	else
96		ir = INTERFACE_REQUESTED;
97
98	/* Cycle through the list of interfaces looking for IP addresses. */
99	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
100		/*
101		 * See if this is the sort of interface we want to
102		 * deal with.  Skip loopback, point-to-point and down
103		 * interfaces, except don't skip down interfaces if we're
104		 * trying to get a list of configurable interfaces.
105		 */
106		if ((ifa->ifa_flags & IFF_LOOPBACK) ||
107		    (ifa->ifa_flags & IFF_POINTOPOINT) ||
108		    (!(ifa->ifa_flags & IFF_UP) &&
109		    state != DISCOVER_UNCONFIGURED))
110			continue;
111
112		/* See if we've seen an interface that matches this one. */
113		for (tmp = interfaces; tmp; tmp = tmp->next)
114			if (!strcmp(tmp->name, ifa->ifa_name))
115				break;
116
117		/* If there isn't already an interface by this name,
118		   allocate one. */
119		if (!tmp) {
120			tmp = ((struct interface_info *)dmalloc(sizeof *tmp,
121			    "discover_interfaces"));
122			if (!tmp)
123				error("Insufficient memory to %s %s",
124				    "record interface", ifa->ifa_name);
125			strlcpy(tmp->name, ifa->ifa_name, sizeof(tmp->name));
126			tmp->next = interfaces;
127			tmp->flags = ir;
128			tmp->noifmedia = tmp->dead = tmp->errors = 0;
129			interfaces = tmp;
130		}
131
132		/* If we have the capability, extract link information
133		   and record it in a linked list. */
134		if (ifa->ifa_addr->sa_family == AF_LINK) {
135			struct sockaddr_dl *foo =
136			    ((struct sockaddr_dl *)(ifa->ifa_addr));
137			tmp->index = foo->sdl_index;
138			tmp->hw_address.hlen = foo->sdl_alen;
139			tmp->hw_address.htype = HTYPE_ETHER; /* XXX */
140			memcpy(tmp->hw_address.haddr,
141			    LLADDR(foo), foo->sdl_alen);
142		} else if (ifa->ifa_addr->sa_family == AF_INET) {
143			struct iaddr addr;
144
145			/* Get a pointer to the address... */
146			bcopy(ifa->ifa_addr, &foo, sizeof(foo));
147
148			/* We don't want the loopback interface. */
149			if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK))
150				continue;
151
152			/* If this is the first real IP address we've
153			   found, keep a pointer to ifreq structure in
154			   which we found it. */
155			if (!tmp->ifp) {
156				int len = (IFNAMSIZ + ifa->ifa_addr->sa_len);
157				tif = (struct ifreq *)malloc(len);
158				if (!tif)
159					error("no space to remember ifp.");
160				strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
161				memcpy(&tif->ifr_addr, ifa->ifa_addr,
162				    ifa->ifa_addr->sa_len);
163				tmp->ifp = tif;
164				tmp->primary_address = foo.sin_addr;
165			}
166
167			/* Grab the address... */
168			addr.len = 4;
169			memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len);
170
171			/* If there's a registered subnet for this address,
172			   connect it together... */
173			if ((subnet = find_subnet(addr))) {
174				/* If this interface has multiple aliases
175				   on the same subnet, ignore all but the
176				   first we encounter. */
177				if (!subnet->interface) {
178					subnet->interface = tmp;
179					subnet->interface_address = addr;
180				} else if (subnet->interface != tmp) {
181					warn("Multiple %s %s: %s %s",
182					    "interfaces match the",
183					    "same subnet",
184					    subnet->interface->name,
185					    tmp->name);
186				}
187				share = subnet->shared_network;
188				if (tmp->shared_network &&
189				    tmp->shared_network != share) {
190					warn("Interface %s matches %s",
191					    tmp->name,
192					    "multiple shared networks");
193				} else {
194					tmp->shared_network = share;
195				}
196
197				if (!share->interface) {
198					share->interface = tmp;
199				} else if (share->interface != tmp) {
200					warn("Multiple %s %s: %s %s",
201					    "interfaces match the",
202					    "same shared network",
203					    share->interface->name,
204					    tmp->name);
205				}
206			}
207		}
208	}
209
210	/* Now cycle through all the interfaces we found, looking for
211	   hardware addresses. */
212
213	/* If we're just trying to get a list of interfaces that we might
214	   be able to configure, we can quit now. */
215	if (state == DISCOVER_UNCONFIGURED)
216		return;
217
218	/* Weed out the interfaces that did not have IP addresses. */
219	last = NULL;
220	for (tmp = interfaces; tmp; tmp = next) {
221		next = tmp->next;
222		if ((tmp->flags & INTERFACE_AUTOMATIC) &&
223		    state == DISCOVER_REQUESTED)
224			tmp->flags &=
225			    ~(INTERFACE_AUTOMATIC | INTERFACE_REQUESTED);
226		if (!tmp->ifp || !(tmp->flags & INTERFACE_REQUESTED)) {
227			if ((tmp->flags & INTERFACE_REQUESTED) != ir)
228				error("%s: not found", tmp->name);
229			if (!last)
230				interfaces = interfaces->next;
231			else
232				last->next = tmp->next;
233
234			/* Remember the interface in case we need to know
235			   about it later. */
236			tmp->next = dummy_interfaces;
237			dummy_interfaces = tmp;
238			continue;
239		}
240		last = tmp;
241
242		memcpy(&foo, &tmp->ifp->ifr_addr, sizeof tmp->ifp->ifr_addr);
243
244		/* We must have a subnet declaration for each interface. */
245		if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
246			warn("No subnet declaration for %s (%s).",
247			    tmp->name, inet_ntoa(foo.sin_addr));
248			warn("Please write a subnet declaration in your %s",
249			    "dhcpd.conf file for the");
250			error("network segment to which interface %s %s",
251			    tmp->name, "is attached.");
252		}
253
254		/* Find subnets that don't have valid interface
255		   addresses... */
256		for (subnet = (tmp->shared_network ? tmp->shared_network->subnets :
257		    NULL); subnet; subnet = subnet->next_sibling) {
258			if (!subnet->interface_address.len) {
259				/*
260				 * Set the interface address for this subnet
261				 * to the first address we found.
262				 */
263				subnet->interface_address.len = 4;
264				memcpy(subnet->interface_address.iabuf,
265				    &foo.sin_addr.s_addr, 4);
266			}
267		}
268
269		/* Register the interface... */
270		if_register_receive(tmp);
271		if_register_send(tmp);
272	}
273
274	/* Now register all the remaining interfaces as protocols. */
275	for (tmp = interfaces; tmp; tmp = tmp->next)
276		add_protocol(tmp->name, tmp->rfdesc, got_one, tmp);
277
278	freeifaddrs(ifap);
279}
280
281struct interface_info *
282setup_fallback(void)
283{
284	fallback_interface = ((struct interface_info *)dmalloc(
285	    sizeof *fallback_interface, "discover_interfaces"));
286
287	if (!fallback_interface)
288		error("Insufficient memory to record fallback interface.");
289	memset(fallback_interface, 0, sizeof *fallback_interface);
290	strlcpy(fallback_interface->name, "fallback", IFNAMSIZ);
291	fallback_interface->shared_network =
292	    new_shared_network("parse_statement");
293	if (!fallback_interface->shared_network)
294		error("No memory for shared subnet");
295	memset(fallback_interface->shared_network, 0,
296	    sizeof(struct shared_network));
297	fallback_interface->shared_network->name = "fallback-net";
298	return fallback_interface;
299}
300
301void
302reinitialize_interfaces(void)
303{
304	interfaces_invalidated = 1;
305}
306
307/*
308 * Wait for packets to come in using poll().  When a packet comes in,
309 * call receive_packet to receive the packet and possibly strip hardware
310 * addressing information from it, and then call through the
311 * bootp_packet_handler hook to try to do something with it.
312 */
313void
314dispatch(void)
315{
316	int count, i, nfds = 0, to_msec;
317	struct protocol *l;
318	struct pollfd *fds;
319	time_t howlong;
320
321	for (l = protocols; l; l = l->next)
322		++nfds;
323	fds = (struct pollfd *)malloc((nfds) * sizeof (struct pollfd));
324	if (fds == NULL)
325		error("Can't allocate poll structures.");
326
327	do {
328		/*
329		 * Call any expired timeouts, and then if there's
330		 * still a timeout registered, time out the select
331		 * call then.
332		 */
333another:
334		if (timeouts) {
335			struct timeout *t;
336
337			if (timeouts->when <= cur_time) {
338				t = timeouts;
339				timeouts = timeouts->next;
340				(*(t->func))(t->what);
341				t->next = free_timeouts;
342				free_timeouts = t;
343				goto another;
344			}
345
346			/*
347			 * Figure timeout in milliseconds, and check for
348			 * potential overflow, so we can cram into an int
349			 * for poll, while not polling with a negative
350			 * timeout and blocking indefinetely.
351			 */
352			howlong = timeouts->when - cur_time;
353			if (howlong > INT_MAX / 1000)
354				howlong = INT_MAX / 1000;
355			to_msec = howlong * 1000;
356		} else
357			to_msec = -1;
358
359		/* Set up the descriptors to be polled. */
360		i = 0;
361
362		for (l = protocols; l; l = l->next) {
363			struct interface_info *ip = l->local;
364
365			if (ip && (l->handler != got_one || !ip->dead)) {
366				fds[i].fd = l->fd;
367				fds[i].events = POLLIN;
368				fds[i].revents = 0;
369				++i;
370			}
371		}
372
373		if (i == 0)
374			error("No live interfaces to poll on - exiting.");
375
376		/* Wait for a packet or a timeout... XXX */
377		count = poll(fds, nfds, to_msec);
378
379		/* Not likely to be transitory... */
380		if (count == -1) {
381			if (errno == EAGAIN || errno == EINTR) {
382				time(&cur_time);
383				continue;
384			} else
385				error("poll: %m");
386		}
387
388		/* Get the current time... */
389		time(&cur_time);
390
391		i = 0;
392		for (l = protocols; l; l = l->next) {
393			struct interface_info *ip = l->local;
394
395			if ((fds[i].revents & POLLIN)) {
396				fds[i].revents = 0;
397				if (ip && (l->handler != got_one ||
398				    !ip->dead))
399					(*(l->handler))(l);
400				if (interfaces_invalidated)
401					break;
402			}
403			++i;
404		}
405		interfaces_invalidated = 0;
406	} while (1);
407}
408
409
410void
411got_one(struct protocol *l)
412{
413	struct sockaddr_in from;
414	struct hardware hfrom;
415	struct iaddr ifrom;
416	size_t result;
417	union {
418		unsigned char packbuf[4095];
419		struct dhcp_packet packet;
420	} u;
421	struct interface_info *ip = l->local;
422
423	if ((result = receive_packet (ip, u.packbuf, sizeof u,
424	    &from, &hfrom)) == -1) {
425		warn("receive_packet failed on %s: %s", ip->name,
426		    strerror(errno));
427		ip->errors++;
428		if ((!interface_status(ip)) ||
429		    (ip->noifmedia && ip->errors > 20)) {
430			/* our interface has gone away. */
431			warn("Interface %s no longer appears valid.",
432			    ip->name);
433			ip->dead = 1;
434			interfaces_invalidated = 1;
435			close(l->fd);
436			remove_protocol(l);
437			free(ip);
438		}
439		return;
440	}
441	if (result == 0)
442		return;
443
444	if (bootp_packet_handler) {
445		ifrom.len = 4;
446		memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
447
448		(*bootp_packet_handler)(ip, &u.packet, result,
449		    from.sin_port, ifrom, &hfrom);
450	}
451}
452
453int
454interface_status(struct interface_info *ifinfo)
455{
456	char * ifname = ifinfo->name;
457	int ifsock = ifinfo->rfdesc;
458	struct ifreq ifr;
459	struct ifmediareq ifmr;
460
461	/* get interface flags */
462	memset(&ifr, 0, sizeof(ifr));
463	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
464	if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
465		syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname);
466		goto inactive;
467	}
468	/*
469	 * if one of UP and RUNNING flags is dropped,
470	 * the interface is not active.
471	 */
472	if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
473		goto inactive;
474
475	/* Next, check carrier on the interface, if possible */
476	if (ifinfo->noifmedia)
477		goto active;
478	memset(&ifmr, 0, sizeof(ifmr));
479	strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
480	if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
481		if (errno != EINVAL) {
482			syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
483			    ifname);
484			ifinfo->noifmedia = 1;
485			goto active;
486		}
487		/*
488		 * EINVAL (or ENOTTY) simply means that the interface
489		 * does not support the SIOCGIFMEDIA ioctl. We regard it alive.
490		 */
491		ifinfo->noifmedia = 1;
492		goto active;
493	}
494	if (ifmr.ifm_status & IFM_AVALID) {
495		switch (ifmr.ifm_active & IFM_NMASK) {
496		case IFM_ETHER:
497			if (ifmr.ifm_status & IFM_ACTIVE)
498				goto active;
499			else
500				goto inactive;
501			break;
502		default:
503			goto inactive;
504		}
505	}
506 inactive:
507	return (0);
508 active:
509	return (1);
510}
511
512int
513locate_network(struct packet *packet)
514{
515	struct iaddr ia;
516
517	/* If this came through a gateway, find the corresponding subnet... */
518	if (packet->raw->giaddr.s_addr) {
519		struct subnet *subnet;
520
521		ia.len = 4;
522		memcpy(ia.iabuf, &packet->raw->giaddr, 4);
523		subnet = find_subnet(ia);
524		if (subnet)
525			packet->shared_network = subnet->shared_network;
526		else
527			packet->shared_network = NULL;
528	} else {
529		packet->shared_network = packet->interface->shared_network;
530	}
531	if (packet->shared_network)
532		return 1;
533	return 0;
534}
535
536void
537add_timeout(time_t when, void (*where)(void *), void *what)
538{
539	struct timeout *t, *q;
540
541	/* See if this timeout supersedes an existing timeout. */
542	t = NULL;
543	for (q = timeouts; q; q = q->next) {
544		if (q->func == where && q->what == what) {
545			if (t)
546				t->next = q->next;
547			else
548				timeouts = q->next;
549			break;
550		}
551		t = q;
552	}
553
554	/* If we didn't supersede a timeout, allocate a timeout
555	   structure now. */
556	if (!q) {
557		if (free_timeouts) {
558			q = free_timeouts;
559			free_timeouts = q->next;
560			q->func = where;
561			q->what = what;
562		} else {
563			q = (struct timeout *)malloc(sizeof (struct timeout));
564			if (!q)
565				error("Can't allocate timeout structure!");
566			q->func = where;
567			q->what = what;
568		}
569	}
570
571	q->when = when;
572
573	/* Now sort this timeout into the timeout list. */
574
575	/* Beginning of list? */
576	if (!timeouts || timeouts->when > q->when) {
577		q->next = timeouts;
578		timeouts = q;
579		return;
580	}
581
582	/* Middle of list? */
583	for (t = timeouts; t->next; t = t->next) {
584		if (t->next->when > q->when) {
585			q->next = t->next;
586			t->next = q;
587			return;
588		}
589	}
590
591	/* End of list. */
592	t->next = q;
593	q->next = NULL;
594}
595
596void
597cancel_timeout(void (*where)(void *), void *what)
598{
599	struct timeout *t, *q;
600
601	/* Look for this timeout on the list, and unlink it if we find it. */
602	t = NULL;
603	for (q = timeouts; q; q = q->next) {
604		if (q->func == where && q->what == what) {
605			if (t)
606				t->next = q->next;
607			else
608				timeouts = q->next;
609			break;
610		}
611		t = q;
612	}
613
614	/* If we found the timeout, put it on the free list. */
615	if (q) {
616		q->next = free_timeouts;
617		free_timeouts = q;
618	}
619}
620
621/* Add a protocol to the list of protocols... */
622void
623add_protocol(char *name, int fd, void (*handler)(struct protocol *),
624    void *local)
625{
626	struct protocol *p;
627
628	p = (struct protocol *)malloc(sizeof *p);
629	if (!p)
630		error("can't allocate protocol struct for %s", name);
631	p->fd = fd;
632	p->handler = handler;
633	p->local = local;
634	p->next = protocols;
635	protocols = p;
636}
637
638void
639remove_protocol(struct protocol *proto)
640{
641	struct protocol *p, *next, *prev = NULL;
642
643	for (p = protocols; p; p = next) {
644		next = p->next;
645		if (p == proto) {
646			if (prev)
647				prev->next = p->next;
648			else
649				protocols = p->next;
650			free(p);
651		}
652	}
653}
654