Home | History | Annotate | Download | only in dhcpcd
      1 /*
      2  * dhcpcd - DHCP client daemon
      3  * Copyright (c) 2006-2012 Roy Marples <roy (at) 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
     80 if_init(_unused struct interface *iface)
     81 {
     82 	/* BSD promotes secondary address by default */
     83 	return 0;
     84 }
     85 
     86 int
     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
     95 cleanup(void)
     96 {
     97 
     98 	free(link_buf);
     99 }
    100 #endif
    101 
    102 int
    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
    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
    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
    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
    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
    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
    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