xref: /dflybsd-src/sbin/dhclient/dispatch.c (revision d99acfb3025b6646178c37f8ee3dee8e2af162a1)
177618c32SAntonio Huete Jimenez /*     $OpenBSD: src/sbin/dhclient/dispatch.c,v 1.59 2012/10/11 08:05:05 sthen Exp $   */
2846204b6SHasso Tepper 
3846204b6SHasso Tepper /*
4846204b6SHasso Tepper  * Copyright 2004 Henning Brauer <henning@openbsd.org>
5846204b6SHasso Tepper  * Copyright (c) 1995, 1996, 1997, 1998, 1999
6846204b6SHasso Tepper  * The Internet Software Consortium.   All rights reserved.
7846204b6SHasso Tepper  *
8846204b6SHasso Tepper  * Redistribution and use in source and binary forms, with or without
9846204b6SHasso Tepper  * modification, are permitted provided that the following conditions
10846204b6SHasso Tepper  * are met:
11846204b6SHasso Tepper  *
12846204b6SHasso Tepper  * 1. Redistributions of source code must retain the above copyright
13846204b6SHasso Tepper  *    notice, this list of conditions and the following disclaimer.
14846204b6SHasso Tepper  * 2. Redistributions in binary form must reproduce the above copyright
15846204b6SHasso Tepper  *    notice, this list of conditions and the following disclaimer in the
16846204b6SHasso Tepper  *    documentation and/or other materials provided with the distribution.
17846204b6SHasso Tepper  * 3. Neither the name of The Internet Software Consortium nor the names
18846204b6SHasso Tepper  *    of its contributors may be used to endorse or promote products derived
19846204b6SHasso Tepper  *    from this software without specific prior written permission.
20846204b6SHasso Tepper  *
21846204b6SHasso Tepper  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
22846204b6SHasso Tepper  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23846204b6SHasso Tepper  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24846204b6SHasso Tepper  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25846204b6SHasso Tepper  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
26846204b6SHasso Tepper  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27846204b6SHasso Tepper  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28846204b6SHasso Tepper  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29846204b6SHasso Tepper  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30846204b6SHasso Tepper  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31846204b6SHasso Tepper  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32846204b6SHasso Tepper  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33846204b6SHasso Tepper  * SUCH DAMAGE.
34846204b6SHasso Tepper  *
35846204b6SHasso Tepper  * This software has been written for the Internet Software Consortium
36846204b6SHasso Tepper  * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
37846204b6SHasso Tepper  * Enterprises.  To learn more about the Internet Software Consortium,
38846204b6SHasso Tepper  * see ``http://www.vix.com/isc''.  To learn more about Vixie
39846204b6SHasso Tepper  * Enterprises, see ``http://www.vix.com''.
40846204b6SHasso Tepper  */
41846204b6SHasso Tepper 
42846204b6SHasso Tepper #include <sys/ioctl.h>
43846204b6SHasso Tepper 
44846204b6SHasso Tepper #include <net/if_media.h>
45846204b6SHasso Tepper 
46846204b6SHasso Tepper #include <ifaddrs.h>
47846204b6SHasso Tepper #include <poll.h>
48846204b6SHasso Tepper 
49846204b6SHasso Tepper #include "dhcpd.h"
50846204b6SHasso Tepper 
518d05e1a0SAntonio Huete Jimenez struct timeout timeout;
52846204b6SHasso Tepper 
53846204b6SHasso Tepper /*
543281ce24SAntonio Huete Jimenez  * Use getifaddrs() to get a list of all the attached interfaces.  Find
553281ce24SAntonio Huete Jimenez  * our interface on the list and store the interesting information about it.
56846204b6SHasso Tepper  */
57846204b6SHasso Tepper void
discover_interface(void)58846204b6SHasso Tepper discover_interface(void)
59846204b6SHasso Tepper {
60846204b6SHasso Tepper 	struct ifaddrs *ifap, *ifa;
61846204b6SHasso Tepper 	struct ifreq *tif;
62846204b6SHasso Tepper 	int len = IFNAMSIZ + sizeof(struct sockaddr_storage);
63846204b6SHasso Tepper 
64846204b6SHasso Tepper 	if (getifaddrs(&ifap) != 0)
65846204b6SHasso Tepper 		error("getifaddrs failed");
66846204b6SHasso Tepper 
67846204b6SHasso Tepper 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
68846204b6SHasso Tepper 		if ((ifa->ifa_flags & IFF_LOOPBACK) ||
69846204b6SHasso Tepper 		    (ifa->ifa_flags & IFF_POINTOPOINT) ||
70846204b6SHasso Tepper 		    (!(ifa->ifa_flags & IFF_UP)))
71846204b6SHasso Tepper 			continue;
72846204b6SHasso Tepper 
73846204b6SHasso Tepper 		if (strcmp(ifi->name, ifa->ifa_name))
74846204b6SHasso Tepper 			continue;
75846204b6SHasso Tepper 
76846204b6SHasso Tepper 		/*
773281ce24SAntonio Huete Jimenez 		 * If we have the capability, extract & save link information.
78846204b6SHasso Tepper 		 */
79846204b6SHasso Tepper 		if (ifa->ifa_addr->sa_family == AF_LINK) {
80846204b6SHasso Tepper 			struct sockaddr_dl *foo =
81846204b6SHasso Tepper 			    (struct sockaddr_dl *)ifa->ifa_addr;
82846204b6SHasso Tepper 
83846204b6SHasso Tepper 			ifi->index = foo->sdl_index;
84846204b6SHasso Tepper 			ifi->hw_address.hlen = foo->sdl_alen;
85846204b6SHasso Tepper 			ifi->hw_address.htype = HTYPE_ETHER; /* XXX */
86846204b6SHasso Tepper 			memcpy(ifi->hw_address.haddr,
87846204b6SHasso Tepper 			    LLADDR(foo), foo->sdl_alen);
88846204b6SHasso Tepper 		}
89846204b6SHasso Tepper 		if (!ifi->ifp) {
90846204b6SHasso Tepper 			if ((tif = malloc(len)) == NULL)
91846204b6SHasso Tepper 				error("no space to remember ifp");
92846204b6SHasso Tepper 			strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
93846204b6SHasso Tepper 			ifi->ifp = tif;
94846204b6SHasso Tepper 		}
95846204b6SHasso Tepper 	}
96846204b6SHasso Tepper 
97846204b6SHasso Tepper 	if (!ifi->ifp)
98846204b6SHasso Tepper 		error("%s: not found", ifi->name);
99846204b6SHasso Tepper 
100846204b6SHasso Tepper 	/* Register the interface... */
101846204b6SHasso Tepper 	if_register_receive();
102846204b6SHasso Tepper 	if_register_send();
103846204b6SHasso Tepper 	freeifaddrs(ifap);
104846204b6SHasso Tepper }
105846204b6SHasso Tepper 
106846204b6SHasso Tepper /*
1073281ce24SAntonio Huete Jimenez  * Loop waiting for packets, timeouts or routing messages.
108846204b6SHasso Tepper  */
109846204b6SHasso Tepper void
dispatch(void)110846204b6SHasso Tepper dispatch(void)
111846204b6SHasso Tepper {
112846204b6SHasso Tepper 	int count, to_msec;
113846204b6SHasso Tepper 	struct pollfd fds[2];
1143c279f6eSAntonio Huete Jimenez 	time_t cur_time, howlong;
1158d05e1a0SAntonio Huete Jimenez 	void (*func)(void);
116846204b6SHasso Tepper 
117846204b6SHasso Tepper 	do {
118846204b6SHasso Tepper 		/*
1198d05e1a0SAntonio Huete Jimenez 		 * Call expired timeout, and then if there's still
120846204b6SHasso Tepper 		 * a timeout registered, time out the select call then.
121846204b6SHasso Tepper 		 */
122846204b6SHasso Tepper another:
123d19bab2eSAntonio Huete Jimenez 		if (!ifi)
124d19bab2eSAntonio Huete Jimenez 			error("No interfaces available");
125d19bab2eSAntonio Huete Jimenez 
1268d05e1a0SAntonio Huete Jimenez 		if (timeout.func) {
1278d05e1a0SAntonio Huete Jimenez 			time(&cur_time);
1288d05e1a0SAntonio Huete Jimenez 			if (timeout.when <= cur_time) {
1298d05e1a0SAntonio Huete Jimenez 				func = timeout.func;
1308d05e1a0SAntonio Huete Jimenez 				cancel_timeout();
1318d05e1a0SAntonio Huete Jimenez 				(*(func))();
132846204b6SHasso Tepper 				goto another;
133846204b6SHasso Tepper 			}
134846204b6SHasso Tepper 			/*
135846204b6SHasso Tepper 			 * Figure timeout in milliseconds, and check for
136846204b6SHasso Tepper 			 * potential overflow, so we can cram into an
137846204b6SHasso Tepper 			 * int for poll, while not polling with a
138846204b6SHasso Tepper 			 * negative timeout and blocking indefinitely.
139846204b6SHasso Tepper 			 */
1408d05e1a0SAntonio Huete Jimenez 			howlong = timeout.when - cur_time;
141846204b6SHasso Tepper 			if (howlong > INT_MAX / 1000)
142846204b6SHasso Tepper 				howlong = INT_MAX / 1000;
143846204b6SHasso Tepper 			to_msec = howlong * 1000;
144846204b6SHasso Tepper 		} else
145846204b6SHasso Tepper 			to_msec = -1;
146846204b6SHasso Tepper 
147846204b6SHasso Tepper 		/* Set up the descriptors to be polled. */
148846204b6SHasso Tepper 		if (!ifi || ifi->rfdesc == -1)
149846204b6SHasso Tepper 			error("No live interface to poll on");
150846204b6SHasso Tepper 
151846204b6SHasso Tepper 		fds[0].fd = ifi->rfdesc;
152846204b6SHasso Tepper 		fds[1].fd = routefd; /* Could be -1, which will be ignored. */
153846204b6SHasso Tepper 		fds[0].events = fds[1].events = POLLIN;
154846204b6SHasso Tepper 
155846204b6SHasso Tepper 		/* Wait for a packet or a timeout... XXX */
156846204b6SHasso Tepper 		count = poll(fds, 2, to_msec);
157846204b6SHasso Tepper 
158846204b6SHasso Tepper 		/* Not likely to be transitory... */
159846204b6SHasso Tepper 		if (count == -1) {
160846204b6SHasso Tepper 			if (errno == EAGAIN || errno == EINTR) {
161846204b6SHasso Tepper 				continue;
162846204b6SHasso Tepper 			} else
163846204b6SHasso Tepper 				error("poll: %m");
164846204b6SHasso Tepper 		}
165846204b6SHasso Tepper 
166846204b6SHasso Tepper 		if ((fds[0].revents & (POLLIN | POLLHUP))) {
167*d99acfb3SMarkus Pfeiffer 			/* XXX profmakx: I am not sure whether updating the linkstate
168*d99acfb3SMarkus Pfeiffer 			  here is the best idea, but it being not up to date leads
169*d99acfb3SMarkus Pfeiffer 			  to a busy loop.
170*d99acfb3SMarkus Pfeiffer 			  Alternatively we can just remove the link state check since
171*d99acfb3SMarkus Pfeiffer 			  the link state is checked in got_one() later on
172*d99acfb3SMarkus Pfeiffer 			 */
173*d99acfb3SMarkus Pfeiffer 			ifi->linkstat = interface_status(ifi->name);
174*d99acfb3SMarkus Pfeiffer 
175bdf60627SAntonio Huete Jimenez 			if (ifi && ifi->linkstat && ifi->rfdesc != -1)
176846204b6SHasso Tepper 				got_one();
177846204b6SHasso Tepper 		}
178846204b6SHasso Tepper 		if ((fds[1].revents & (POLLIN | POLLHUP))) {
179f57dac5bSAntonio Huete Jimenez 			if (ifi)
180846204b6SHasso Tepper 				routehandler();
181846204b6SHasso Tepper 		}
182846204b6SHasso Tepper 	} while (1);
183846204b6SHasso Tepper }
184846204b6SHasso Tepper 
185846204b6SHasso Tepper void
got_one(void)186846204b6SHasso Tepper got_one(void)
187846204b6SHasso Tepper {
188846204b6SHasso Tepper 	struct sockaddr_in from;
189846204b6SHasso Tepper 	struct hardware hfrom;
190846204b6SHasso Tepper 	struct iaddr ifrom;
191846204b6SHasso Tepper 	ssize_t result;
192846204b6SHasso Tepper 
193846204b6SHasso Tepper 	if ((result = receive_packet(&from, &hfrom)) == -1) {
194846204b6SHasso Tepper 		warning("receive_packet failed on %s: %s", ifi->name,
195846204b6SHasso Tepper 		    strerror(errno));
196846204b6SHasso Tepper 		ifi->errors++;
197846204b6SHasso Tepper 		if ((!interface_status(ifi->name)) ||
198846204b6SHasso Tepper 		    (ifi->noifmedia && ifi->errors > 20)) {
199846204b6SHasso Tepper 			/* our interface has gone away. */
2009930e9a8SAntonio Huete Jimenez 			error("Interface %s no longer appears valid.",
201846204b6SHasso Tepper 			    ifi->name);
202846204b6SHasso Tepper 		}
203846204b6SHasso Tepper 		return;
204846204b6SHasso Tepper 	}
205846204b6SHasso Tepper 	if (result == 0)
206846204b6SHasso Tepper 		return;
207846204b6SHasso Tepper 
208846204b6SHasso Tepper 	ifrom.len = 4;
209846204b6SHasso Tepper 	memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
210846204b6SHasso Tepper 
211846204b6SHasso Tepper 	do_packet(result, from.sin_port, ifrom, &hfrom);
212846204b6SHasso Tepper }
213846204b6SHasso Tepper 
214852231a5SMatthew Dillon /*
215852231a5SMatthew Dillon  * Normally its ok to force the interface link up, but don't do it
216852231a5SMatthew Dillon  * if it is an 80211 interface.
217852231a5SMatthew Dillon  */
218846204b6SHasso Tepper int
interface_link_forceup(char * ifname)219846204b6SHasso Tepper interface_link_forceup(char *ifname)
220846204b6SHasso Tepper {
221846204b6SHasso Tepper 	struct ifreq ifr;
222852231a5SMatthew Dillon 	struct ifmediareq ifmr;
223846204b6SHasso Tepper 	int sock;
224846204b6SHasso Tepper 
225846204b6SHasso Tepper 	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
226846204b6SHasso Tepper 		error("Can't create socket");
227846204b6SHasso Tepper 
228846204b6SHasso Tepper 	memset(&ifr, 0, sizeof(ifr));
229846204b6SHasso Tepper 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
230846204b6SHasso Tepper 	if (ioctl(sock, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) {
231846204b6SHasso Tepper 		close(sock);
232846204b6SHasso Tepper 		return (-1);
233846204b6SHasso Tepper 	}
234852231a5SMatthew Dillon 	memset(&ifmr, 0, sizeof(ifmr));
235852231a5SMatthew Dillon 	strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
236852231a5SMatthew Dillon 	if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) != -1) {
237852231a5SMatthew Dillon 		if (IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) {
238852231a5SMatthew Dillon 			return 0;
239852231a5SMatthew Dillon 		}
240852231a5SMatthew Dillon 	}
241846204b6SHasso Tepper 
242846204b6SHasso Tepper 	if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
243846204b6SHasso Tepper 		ifr.ifr_flags |= IFF_UP;
244846204b6SHasso Tepper 		if (ioctl(sock, SIOCSIFFLAGS, (caddr_t)&ifr) == -1) {
245846204b6SHasso Tepper 			close(sock);
246846204b6SHasso Tepper 			return (-1);
247846204b6SHasso Tepper 		}
248846204b6SHasso Tepper 		close(sock);
249846204b6SHasso Tepper 		return (0);
250846204b6SHasso Tepper 	}
251846204b6SHasso Tepper 	close(sock);
252846204b6SHasso Tepper 	return (1);
253846204b6SHasso Tepper }
254846204b6SHasso Tepper 
255846204b6SHasso Tepper int
interface_status(char * ifname)256846204b6SHasso Tepper interface_status(char *ifname)
257846204b6SHasso Tepper {
258846204b6SHasso Tepper 	struct ifreq ifr;
259846204b6SHasso Tepper 	struct ifmediareq ifmr;
260846204b6SHasso Tepper 	int sock;
261846204b6SHasso Tepper 
262846204b6SHasso Tepper 	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
263846204b6SHasso Tepper 		error("Can't create socket");
264846204b6SHasso Tepper 
265846204b6SHasso Tepper 	/* get interface flags */
266846204b6SHasso Tepper 	memset(&ifr, 0, sizeof(ifr));
267846204b6SHasso Tepper 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
268f6c633e7SAntonio Huete Jimenez 	if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
2699930e9a8SAntonio Huete Jimenez 		error("ioctl(SIOCGIFFLAGS) on %s: %m", ifname);
270846204b6SHasso Tepper 	}
271846204b6SHasso Tepper 
272846204b6SHasso Tepper 	/*
273846204b6SHasso Tepper 	 * if one of UP and RUNNING flags is dropped,
274846204b6SHasso Tepper 	 * the interface is not active.
275846204b6SHasso Tepper 	 */
276846204b6SHasso Tepper 	if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
277846204b6SHasso Tepper 		goto inactive;
278846204b6SHasso Tepper 
279846204b6SHasso Tepper 	/* Next, check carrier on the interface, if possible */
280846204b6SHasso Tepper 	if (ifi->noifmedia)
281846204b6SHasso Tepper 		goto active;
282846204b6SHasso Tepper 	memset(&ifmr, 0, sizeof(ifmr));
283846204b6SHasso Tepper 	strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
284f6c633e7SAntonio Huete Jimenez 	if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
285846204b6SHasso Tepper 		/*
286846204b6SHasso Tepper 		 * EINVAL or ENOTTY simply means that the interface
287846204b6SHasso Tepper 		 * does not support the SIOCGIFMEDIA ioctl. We regard it alive.
288846204b6SHasso Tepper 		 */
2894cada237SAntonio Huete Jimenez #ifdef DEBUG
290846204b6SHasso Tepper 		if (errno != EINVAL && errno != ENOTTY)
291846204b6SHasso Tepper 			debug("ioctl(SIOCGIFMEDIA) on %s: %m", ifname);
2924cada237SAntonio Huete Jimenez #endif
293846204b6SHasso Tepper 		ifi->noifmedia = 1;
294846204b6SHasso Tepper 		goto active;
295846204b6SHasso Tepper 	}
296846204b6SHasso Tepper 	if (ifmr.ifm_status & IFM_AVALID) {
297846204b6SHasso Tepper 		if (ifmr.ifm_status & IFM_ACTIVE)
298846204b6SHasso Tepper 			goto active;
299846204b6SHasso Tepper 		else
300846204b6SHasso Tepper 			goto inactive;
301846204b6SHasso Tepper 	}
3022de2b2feSAntonio Huete Jimenez 
3032de2b2feSAntonio Huete Jimenez 	/* Assume 'active' if IFM_AVALID is not set. */
3042de2b2feSAntonio Huete Jimenez 
305846204b6SHasso Tepper active:
306846204b6SHasso Tepper 	close(sock);
307846204b6SHasso Tepper 	return (1);
3082de2b2feSAntonio Huete Jimenez inactive:
3092de2b2feSAntonio Huete Jimenez 	close(sock);
3102de2b2feSAntonio Huete Jimenez 	return (0);
311846204b6SHasso Tepper }
312846204b6SHasso Tepper 
313846204b6SHasso Tepper void
set_timeout(time_t when,void (* where)(void))3148d05e1a0SAntonio Huete Jimenez set_timeout(time_t when, void (*where)(void))
315846204b6SHasso Tepper {
3168d05e1a0SAntonio Huete Jimenez 	timeout.when = when;
3178d05e1a0SAntonio Huete Jimenez 	timeout.func = where;
318846204b6SHasso Tepper }
319846204b6SHasso Tepper 
320846204b6SHasso Tepper void
set_timeout_interval(time_t secs,void (* where)(void))3213c279f6eSAntonio Huete Jimenez set_timeout_interval(time_t secs, void (*where)(void))
3223c279f6eSAntonio Huete Jimenez {
3233c279f6eSAntonio Huete Jimenez 	timeout.when = time(NULL) + secs;
3243c279f6eSAntonio Huete Jimenez 	timeout.func = where;
3253c279f6eSAntonio Huete Jimenez }
3263c279f6eSAntonio Huete Jimenez 
3273c279f6eSAntonio Huete Jimenez void
cancel_timeout(void)3288d05e1a0SAntonio Huete Jimenez cancel_timeout(void)
329846204b6SHasso Tepper {
3308d05e1a0SAntonio Huete Jimenez 	timeout.when = 0;
3318d05e1a0SAntonio Huete Jimenez 	timeout.func = NULL;
332846204b6SHasso Tepper }
333107428a4SAntonio Huete Jimenez 
334107428a4SAntonio Huete Jimenez int
subnet_exists(struct client_lease * l)335107428a4SAntonio Huete Jimenez subnet_exists(struct client_lease *l)
336107428a4SAntonio Huete Jimenez {
337107428a4SAntonio Huete Jimenez 	struct ifaddrs *ifap, *ifa;
338107428a4SAntonio Huete Jimenez 	in_addr_t mymask, myaddr, mynet, hismask, hisaddr, hisnet;
339107428a4SAntonio Huete Jimenez 
340107428a4SAntonio Huete Jimenez 	bcopy(l->options[DHO_SUBNET_MASK].data, &mymask, 4);
341107428a4SAntonio Huete Jimenez 	bcopy(l->address.iabuf, &myaddr, 4);
342107428a4SAntonio Huete Jimenez 	mynet = mymask & myaddr;
343107428a4SAntonio Huete Jimenez 
344107428a4SAntonio Huete Jimenez 	if (getifaddrs(&ifap) != 0)
345107428a4SAntonio Huete Jimenez 		error("getifaddrs failed");
346107428a4SAntonio Huete Jimenez 
347107428a4SAntonio Huete Jimenez 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
348107428a4SAntonio Huete Jimenez 		if (strcmp(ifi->name, ifa->ifa_name) == 0)
349107428a4SAntonio Huete Jimenez 			continue;
350107428a4SAntonio Huete Jimenez 
351107428a4SAntonio Huete Jimenez 		if (ifa->ifa_addr->sa_family != AF_INET)
352107428a4SAntonio Huete Jimenez 			continue;
353107428a4SAntonio Huete Jimenez 
354107428a4SAntonio Huete Jimenez 		hismask = ((struct sockaddr_in *)ifa->ifa_netmask)->
355107428a4SAntonio Huete Jimenez 		    sin_addr.s_addr;
356107428a4SAntonio Huete Jimenez 		hisaddr = ((struct sockaddr_in *)ifa->ifa_addr)->
357107428a4SAntonio Huete Jimenez 		    sin_addr.s_addr;
358107428a4SAntonio Huete Jimenez 		hisnet = hisaddr & hismask;
359107428a4SAntonio Huete Jimenez 
360107428a4SAntonio Huete Jimenez 		if (hisnet == 0)
361107428a4SAntonio Huete Jimenez 			continue;
362107428a4SAntonio Huete Jimenez 
363107428a4SAntonio Huete Jimenez 		/* Would his packets go out *my* interface? */
364107428a4SAntonio Huete Jimenez 		if (mynet == (hisaddr & mymask)) {
365107428a4SAntonio Huete Jimenez 			note("interface %s already has the offered subnet!",
366107428a4SAntonio Huete Jimenez 			    ifa->ifa_name);
367107428a4SAntonio Huete Jimenez 			return (1);
368107428a4SAntonio Huete Jimenez 		}
369107428a4SAntonio Huete Jimenez 
370107428a4SAntonio Huete Jimenez 		/* Would my packets go out *his* interface? */
371107428a4SAntonio Huete Jimenez 		if (hisnet == (myaddr & hismask)) {
372107428a4SAntonio Huete Jimenez 			note("interface %s already has the offered subnet!",
373107428a4SAntonio Huete Jimenez 			    ifa->ifa_name);
374107428a4SAntonio Huete Jimenez 			return (1);
375107428a4SAntonio Huete Jimenez 		}
376107428a4SAntonio Huete Jimenez 	}
377107428a4SAntonio Huete Jimenez 
378107428a4SAntonio Huete Jimenez 	freeifaddrs(ifap);
379107428a4SAntonio Huete Jimenez 
380107428a4SAntonio Huete Jimenez 	return (0);
381107428a4SAntonio Huete Jimenez }
382