• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * dhcpcd - DHCP client daemon
3   * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
4   * All rights reserved
5  
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions
8   * are met:
9   * 1. Redistributions of source code must retain the above copyright
10   *    notice, this list of conditions and the following disclaimer.
11   * 2. Redistributions in binary form must reproduce the above copyright
12   *    notice, this list of conditions and the following disclaimer in the
13   *    documentation and/or other materials provided with the distribution.
14   *
15   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25   * SUCH DAMAGE.
26   */
27  
28  #include <sys/ioctl.h>
29  #include <sys/param.h>
30  #include <sys/socket.h>
31  #include <sys/stat.h>
32  #include <sys/sysctl.h>
33  #include <sys/types.h>
34  
35  #include <arpa/inet.h>
36  #include <net/if.h>
37  #include <net/if_dl.h>
38  #include <net/route.h>
39  #include <netinet/in.h>
40  #ifdef __DragonFly__
41  #  include <netproto/802_11/ieee80211_ioctl.h>
42  #elif __APPLE__
43    /* FIXME: Add apple includes so we can work out SSID */
44  #else
45  #  include <net80211/ieee80211_ioctl.h>
46  #endif
47  
48  #include <errno.h>
49  #include <fnmatch.h>
50  #include <stddef.h>
51  #include <stdio.h>
52  #include <stdlib.h>
53  #include <string.h>
54  #include <syslog.h>
55  #include <unistd.h>
56  
57  #include "config.h"
58  #include "common.h"
59  #include "configure.h"
60  #include "dhcp.h"
61  #include "if-options.h"
62  #include "net.h"
63  
64  #ifndef RT_ROUNDUP
65  #define RT_ROUNDUP(a)							      \
66  	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
67  #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
68  #endif
69  
70  /* FIXME: Why do we need to check for sa_family 255 */
71  #define COPYOUT(sin, sa)						      \
72  	sin.s_addr = ((sa) != NULL) ?					      \
73  	    (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
74  
75  static int r_fd = -1;
76  static char *link_buf;
77  static ssize_t link_buflen;
78  
79  int
if_init(_unused struct interface * iface)80  if_init(_unused struct interface *iface)
81  {
82  	/* BSD promotes secondary address by default */
83  	return 0;
84  }
85  
86  int
if_conf(_unused struct interface * iface)87  if_conf(_unused struct interface *iface)
88  {
89  	/* No extra checks needed on BSD */
90  	return 0;
91  }
92  
93  #ifdef DEBUG_MEMORY
94  static void
cleanup(void)95  cleanup(void)
96  {
97  
98  	free(link_buf);
99  }
100  #endif
101  
102  int
init_sockets(void)103  init_sockets(void)
104  {
105  	if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
106  		return -1;
107  	set_cloexec(socket_afnet);
108  	if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
109  		return -1;
110  	set_cloexec(r_fd);
111  	return 0;
112  }
113  
114  int
getifssid(const char * ifname,char * ssid)115  getifssid(const char *ifname, char *ssid)
116  {
117  	int retval = -1;
118  #if defined(SIOCG80211NWID)
119  	struct ifreq ifr;
120  	struct ieee80211_nwid nwid;
121  #elif defined(IEEE80211_IOC_SSID)
122  	struct ieee80211req ireq;
123  	char nwid[IEEE80211_NWID_LEN + 1];
124  #endif
125  
126  #if defined(SIOCG80211NWID) /* NetBSD */
127  	memset(&ifr, 0, sizeof(ifr));
128  	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
129  	memset(&nwid, 0, sizeof(nwid));
130  	ifr.ifr_data = (void *)&nwid;
131  	if (ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) {
132  		retval = nwid.i_len;
133  		memcpy(ssid, nwid.i_nwid, nwid.i_len);
134  		ssid[nwid.i_len] = '\0';
135  	}
136  #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
137  	memset(&ireq, 0, sizeof(ireq));
138  	strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
139  	ireq.i_type = IEEE80211_IOC_SSID;
140  	ireq.i_val = -1;
141  	memset(nwid, 0, sizeof(nwid));
142  	ireq.i_data = &nwid;
143  	if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) {
144  		retval = ireq.i_len;
145  		memcpy(ssid, nwid, ireq.i_len);
146  		ssid[ireq.i_len] = '\0';
147  	}
148  #endif
149  	return retval;
150  }
151  
152  int
if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)153  if_address(const struct interface *iface, const struct in_addr *address,
154      const struct in_addr *netmask, const struct in_addr *broadcast,
155      int action)
156  {
157  	int retval;
158  	struct ifaliasreq ifa;
159  	union {
160  		struct sockaddr *sa;
161  		struct sockaddr_in *sin;
162  	} _s;
163  
164  	memset(&ifa, 0, sizeof(ifa));
165  	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));
166  
167  #define ADDADDR(_var, _addr) {						      \
168  		_s.sa = &_var;						      \
169  		_s.sin->sin_family = AF_INET;				      \
170  		_s.sin->sin_len = sizeof(*_s.sin);			      \
171  		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
172  	}
173  
174  	ADDADDR(ifa.ifra_addr, address);
175  	ADDADDR(ifa.ifra_mask, netmask);
176  	if (action >= 0 && broadcast) {
177  		ADDADDR(ifa.ifra_broadaddr, broadcast);
178  	}
179  #undef ADDADDR
180  
181  	if (action < 0)
182  		retval = ioctl(socket_afnet, SIOCDIFADDR, &ifa);
183  	else
184  		retval = ioctl(socket_afnet, SIOCAIFADDR, &ifa);
185  	return retval;
186  }
187  
188  /* ARGSUSED4 */
189  int
if_route(const struct rt * rt,int action)190  if_route(const struct rt *rt, int action)
191  {
192  	union sockunion {
193  		struct sockaddr sa;
194  		struct sockaddr_in sin;
195  #ifdef INET6
196  		struct sockaddr_in6 sin6;
197  #endif
198  		struct sockaddr_dl sdl;
199  		struct sockaddr_storage ss;
200  	} su;
201  	struct rtm
202  	{
203  		struct rt_msghdr hdr;
204  		char buffer[sizeof(su) * 4];
205  	} rtm;
206  	char *bp = rtm.buffer;
207  	size_t l;
208  	int retval = 0;
209  
210  #define ADDSU(_su) {							      \
211  		l = RT_ROUNDUP(_su.sa.sa_len);				      \
212  		memcpy(bp, &(_su), l);					      \
213  		bp += l;						      \
214  	}
215  #define ADDADDR(_a) {							      \
216  		memset (&su, 0, sizeof(su));				      \
217  		su.sin.sin_family = AF_INET;				      \
218  		su.sin.sin_len = sizeof(su.sin);			      \
219  		memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr));	      \
220  		ADDSU(su);						      \
221  	}
222  
223  	memset(&rtm, 0, sizeof(rtm));
224  	rtm.hdr.rtm_version = RTM_VERSION;
225  	rtm.hdr.rtm_seq = 1;
226  	if (action == 0)
227  		rtm.hdr.rtm_type = RTM_CHANGE;
228  	else if (action > 0)
229  		rtm.hdr.rtm_type = RTM_ADD;
230  	else
231  		rtm.hdr.rtm_type = RTM_DELETE;
232  	rtm.hdr.rtm_flags = RTF_UP;
233  	/* None interface subnet routes are static. */
234  	if (rt->gate.s_addr != INADDR_ANY ||
235  	    rt->net.s_addr != rt->iface->net.s_addr ||
236  	    rt->dest.s_addr != (rt->iface->addr.s_addr & rt->iface->net.s_addr))
237  		rtm.hdr.rtm_flags |= RTF_STATIC;
238  	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
239  	if (rt->dest.s_addr == rt->gate.s_addr &&
240  	    rt->net.s_addr == INADDR_BROADCAST)
241  		rtm.hdr.rtm_flags |= RTF_HOST;
242  	else {
243  		rtm.hdr.rtm_addrs |= RTA_NETMASK;
244  		if (rtm.hdr.rtm_flags & RTF_STATIC)
245  			rtm.hdr.rtm_flags |= RTF_GATEWAY;
246  		if (action >= 0)
247  			rtm.hdr.rtm_addrs |= RTA_IFA;
248  	}
249  
250  	ADDADDR(&rt->dest);
251  	if (rtm.hdr.rtm_flags & RTF_HOST ||
252  	    !(rtm.hdr.rtm_flags & RTF_STATIC))
253  	{
254  		/* Make us a link layer socket for the host gateway */
255  		memset(&su, 0, sizeof(su));
256  		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
257  		link_addr(rt->iface->name, &su.sdl);
258  		ADDSU(su);
259  	} else
260  		ADDADDR(&rt->gate);
261  
262  	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
263  		ADDADDR(&rt->net);
264  
265  	if (rtm.hdr.rtm_addrs & RTA_IFA)
266  		ADDADDR(&rt->iface->addr);
267  
268  	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
269  	if (write(r_fd, &rtm, l) == -1)
270  		retval = -1;
271  	return retval;
272  }
273  
274  int
open_link_socket(void)275  open_link_socket(void)
276  {
277  	int fd;
278  
279  #ifdef DEBUG_MEMORY
280  	if (link_buf == NULL)
281  		atexit(cleanup);
282  #endif
283  
284  	fd = socket(PF_ROUTE, SOCK_RAW, 0);
285  	if (fd != -1) {
286  		set_cloexec(fd);
287  		set_nonblock(fd);
288  	}
289  	return fd;
290  }
291  
292  static void
get_addrs(int type,char * cp,struct sockaddr ** sa)293  get_addrs(int type, char *cp, struct sockaddr **sa)
294  {
295  	int i;
296  
297  	for (i = 0; i < RTAX_MAX; i++) {
298  		if (type & (1 << i)) {
299  			sa[i] = (struct sockaddr *)cp;
300  #ifdef DEBUG
301  			printf ("got %d %d %s\n", i, sa[i]->sa_family,
302  			    inet_ntoa(((struct sockaddr_in *)sa[i])->
303  				sin_addr));
304  #endif
305  			RT_ADVANCE(cp, sa[i]);
306  		} else
307  			sa[i] = NULL;
308  	}
309  }
310  
311  int
manage_link(int fd)312  manage_link(int fd)
313  {
314  	char *p, *e, *cp;
315  	char ifname[IF_NAMESIZE];
316  	ssize_t bytes;
317  	struct rt_msghdr *rtm;
318  	struct if_announcemsghdr *ifan;
319  	struct if_msghdr *ifm;
320  	struct ifa_msghdr *ifam;
321  	struct rt rt;
322  	struct sockaddr *sa, *rti_info[RTAX_MAX];
323  	int len;
324  #ifdef RTM_CHGADDR
325  	struct sockaddr_dl sdl;
326  	unsigned char *hwaddr;
327  #endif
328  
329  	for (;;) {
330  		if (ioctl(fd, FIONREAD, &len) == -1)
331  			return -1;
332  		if (link_buflen < len) {
333  			p = realloc(link_buf, len);
334  			if (p == NULL)
335  				return -1;
336  			link_buf = p;
337  			link_buflen = len;
338  		}
339  		bytes = read(fd, link_buf, link_buflen);
340  		if (bytes == -1) {
341  			if (errno == EAGAIN)
342  				return 0;
343  			if (errno == EINTR)
344  				continue;
345  			return -1;
346  		}
347  		e = link_buf + bytes;
348  		for (p = link_buf; p < e; p += rtm->rtm_msglen) {
349  			rtm = (struct rt_msghdr *)(void *)p;
350  			switch(rtm->rtm_type) {
351  #ifdef RTM_IFANNOUNCE
352  			case RTM_IFANNOUNCE:
353  				ifan = (struct if_announcemsghdr *)(void *)p;
354  				switch(ifan->ifan_what) {
355  				case IFAN_ARRIVAL:
356  					handle_interface(1, ifan->ifan_name);
357  					break;
358  				case IFAN_DEPARTURE:
359  					handle_interface(-1, ifan->ifan_name);
360  					break;
361  				}
362  				break;
363  #endif
364  			case RTM_IFINFO:
365  				ifm = (struct if_msghdr *)(void *)p;
366  				memset(ifname, 0, sizeof(ifname));
367  				if (!(if_indextoname(ifm->ifm_index, ifname)))
368  					break;
369  				switch (ifm->ifm_data.ifi_link_state) {
370  				case LINK_STATE_DOWN:
371  					len = -1;
372  					break;
373  				case LINK_STATE_UP:
374  					len = 1;
375  					break;
376  				default:
377  					/* handle_carrier will re-load
378  					 * the interface flags and check for
379  					 * IFF_RUNNING as some drivers that
380  					 * don't handle link state also don't
381  					 * set IFF_RUNNING when this routing
382  					 * message is generated.
383  					 * As such, it is a race ...*/
384  					len = 0;
385  					break;
386  				}
387  				handle_carrier(len, ifm->ifm_flags, ifname);
388  				break;
389  			case RTM_DELETE:
390  				if (~rtm->rtm_addrs &
391  				    (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
392  					break;
393  				if (rtm->rtm_pid == getpid())
394  					break;
395  				cp = (char *)(void *)(rtm + 1);
396  				sa = (struct sockaddr *)(void *)cp;
397  				if (sa->sa_family != AF_INET)
398  					break;
399  				get_addrs(rtm->rtm_addrs, cp, rti_info);
400  				rt.iface = NULL;
401  				rt.next = NULL;
402  				COPYOUT(rt.dest, rti_info[RTAX_DST]);
403  				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
404  				COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
405  				route_deleted(&rt);
406  				break;
407  #ifdef RTM_CHGADDR
408  			case RTM_CHGADDR:	/* FALLTHROUGH */
409  #endif
410  			case RTM_DELADDR:	/* FALLTHROUGH */
411  			case RTM_NEWADDR:
412  				ifam = (struct ifa_msghdr *)(void *)p;
413  				if (!if_indextoname(ifam->ifam_index, ifname))
414  					break;
415  				cp = (char *)(void *)(ifam + 1);
416  				get_addrs(ifam->ifam_addrs, cp, rti_info);
417  				if (rti_info[RTAX_IFA] == NULL)
418  					break;
419  				switch (rti_info[RTAX_IFA]->sa_family) {
420  #ifdef RTM_CHGADDR
421  				case AF_LINK:
422  					if (rtm->rtm_type != RTM_CHGADDR)
423  						break;
424  					memcpy(&sdl, rti_info[RTAX_IFA],
425  					    rti_info[RTAX_IFA]->sa_len);
426  					hwaddr = xmalloc(sdl.sdl_alen);
427  					memcpy(hwaddr, LLADDR(&sdl),
428  					    sdl.sdl_alen);
429  					handle_hwaddr(ifname, hwaddr,
430  					    sdl.sdl_alen);
431  					break;
432  #endif
433  				case AF_INET:
434  				case 255: /* FIXME: Why 255? */
435  					COPYOUT(rt.dest, rti_info[RTAX_IFA]);
436  					COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
437  					COPYOUT(rt.gate, rti_info[RTAX_BRD]);
438  					handle_ifa(rtm->rtm_type, ifname,
439  					    &rt.dest, &rt.net, &rt.gate);
440  					break;
441  				}
442  				break;
443  			}
444  		}
445  	}
446  }
447