Home | History | Annotate | Download | only in dhcpcd
      1 /*
      2  * dhcpcd - DHCP client daemon
      3  * Copyright (c) 2006-2010 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 #define ROUNDUP(a)							      \
     65 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
     66 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
     67 
     68 /* FIXME: Why do we need to check for sa_family 255 */
     69 #define COPYOUT(sin, sa)						      \
     70 	sin.s_addr = ((sa) != NULL) ?					      \
     71 	    (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
     72 
     73 static int r_fd = -1;
     74 static char *link_buf;
     75 static ssize_t link_buflen;
     76 
     77 int
     78 if_init(_unused struct interface *iface)
     79 {
     80 	/* BSD promotes secondary address by default */
     81 	return 0;
     82 }
     83 
     84 int
     85 if_conf(_unused struct interface *iface)
     86 {
     87 	/* No extra checks needed on BSD */
     88 	return 0;
     89 }
     90 
     91 int
     92 init_sockets(void)
     93 {
     94 	if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
     95 		return -1;
     96 	set_cloexec(socket_afnet);
     97 	if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
     98 		return -1;
     99 	set_cloexec(r_fd);
    100 	return 0;
    101 }
    102 
    103 int
    104 getifssid(const char *ifname, char *ssid)
    105 {
    106 	int retval = -1;
    107 #if defined(SIOCG80211NWID)
    108 	struct ifreq ifr;
    109 	struct ieee80211_nwid nwid;
    110 #elif defined(IEEE80211_IOC_SSID)
    111 	struct ieee80211req ireq;
    112 	char nwid[IEEE80211_NWID_LEN + 1];
    113 #endif
    114 
    115 #if defined(SIOCG80211NWID) /* NetBSD */
    116 	memset(&ifr, 0, sizeof(ifr));
    117 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
    118 	memset(&nwid, 0, sizeof(nwid));
    119 	ifr.ifr_data = (void *)&nwid;
    120 	if (ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) {
    121 		retval = nwid.i_len;
    122 		memcpy(ssid, nwid.i_nwid, nwid.i_len);
    123 		ssid[nwid.i_len] = '\0';
    124 	}
    125 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
    126 	memset(&ireq, 0, sizeof(ireq));
    127 	strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
    128 	ireq.i_type = IEEE80211_IOC_SSID;
    129 	ireq.i_val = -1;
    130 	ireq.i_data = &nwid;
    131 	if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) {
    132 		retval = ireq.i_len;
    133 		memcpy(ssid, nwid, ireq.i_len);
    134 		ssid[ireq.i_len] = '\0';
    135 	}
    136 #endif
    137 	return retval;
    138 }
    139 
    140 int
    141 if_address(const struct interface *iface, const struct in_addr *address,
    142     const struct in_addr *netmask, const struct in_addr *broadcast,
    143     int action)
    144 {
    145 	int retval;
    146 	struct ifaliasreq ifa;
    147 	union {
    148 		struct sockaddr *sa;
    149 		struct sockaddr_in *sin;
    150 	} _s;
    151 
    152 	memset(&ifa, 0, sizeof(ifa));
    153 	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));
    154 
    155 #define ADDADDR(_var, _addr) {						      \
    156 		_s.sa = &_var;						      \
    157 		_s.sin->sin_family = AF_INET;				      \
    158 		_s.sin->sin_len = sizeof(*_s.sin);			      \
    159 		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
    160 	}
    161 
    162 	ADDADDR(ifa.ifra_addr, address);
    163 	ADDADDR(ifa.ifra_mask, netmask);
    164 	if (action >= 0 && broadcast) {
    165 		ADDADDR(ifa.ifra_broadaddr, broadcast);
    166 	}
    167 #undef ADDADDR
    168 
    169 	if (action < 0)
    170 		retval = ioctl(socket_afnet, SIOCDIFADDR, &ifa);
    171 	else
    172 		retval = ioctl(socket_afnet, SIOCAIFADDR, &ifa);
    173 	return retval;
    174 }
    175 
    176 /* ARGSUSED4 */
    177 int
    178 if_route(const struct interface *iface, const struct in_addr *dest,
    179     const struct in_addr *net, const struct in_addr *gate,
    180     _unused int metric, int action)
    181 {
    182 	union sockunion {
    183 		struct sockaddr sa;
    184 		struct sockaddr_in sin;
    185 #ifdef INET6
    186 		struct sockaddr_in6 sin6;
    187 #endif
    188 		struct sockaddr_dl sdl;
    189 		struct sockaddr_storage ss;
    190 	} su;
    191 	struct rtm
    192 	{
    193 		struct rt_msghdr hdr;
    194 		char buffer[sizeof(su) * 4];
    195 	} rtm;
    196 	char *bp = rtm.buffer, *p;
    197 	size_t l;
    198 	int retval = 0;
    199 
    200 #define ADDSU(_su) {							      \
    201 		l = ROUNDUP(_su.sa.sa_len);				      \
    202 		memcpy(bp, &(_su), l);					      \
    203 		bp += l;						      \
    204 	}
    205 #define ADDADDR(_a) {							      \
    206 		memset (&su, 0, sizeof(su));				      \
    207 		su.sin.sin_family = AF_INET;				      \
    208 		su.sin.sin_len = sizeof(su.sin);			      \
    209 		memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr));	      \
    210 		ADDSU(su);						      \
    211 	}
    212 
    213 	memset(&rtm, 0, sizeof(rtm));
    214 	rtm.hdr.rtm_version = RTM_VERSION;
    215 	rtm.hdr.rtm_seq = 1;
    216 	if (action == 0)
    217 		rtm.hdr.rtm_type = RTM_CHANGE;
    218 	else if (action > 0)
    219 		rtm.hdr.rtm_type = RTM_ADD;
    220 	else
    221 		rtm.hdr.rtm_type = RTM_DELETE;
    222 	rtm.hdr.rtm_flags = RTF_UP;
    223 	/* None interface subnet routes are static. */
    224 	if (gate->s_addr != INADDR_ANY ||
    225 	    net->s_addr != iface->net.s_addr ||
    226 	    dest->s_addr != (iface->addr.s_addr & iface->net.s_addr))
    227 		rtm.hdr.rtm_flags |= RTF_STATIC;
    228 	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
    229 	if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST)
    230 		rtm.hdr.rtm_flags |= RTF_HOST;
    231 	else {
    232 		rtm.hdr.rtm_addrs |= RTA_NETMASK;
    233 		if (rtm.hdr.rtm_flags & RTF_STATIC)
    234 			rtm.hdr.rtm_flags |= RTF_GATEWAY;
    235 		if (action >= 0)
    236 			rtm.hdr.rtm_addrs |= RTA_IFA;
    237 	}
    238 
    239 	ADDADDR(dest);
    240 	if (rtm.hdr.rtm_flags & RTF_HOST ||
    241 	    !(rtm.hdr.rtm_flags & RTF_STATIC))
    242 	{
    243 		/* Make us a link layer socket for the host gateway */
    244 		memset(&su, 0, sizeof(su));
    245 		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
    246 		link_addr(iface->name, &su.sdl);
    247 		ADDSU(su);
    248 	} else
    249 		ADDADDR(gate);
    250 
    251 	if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
    252 		/* Ensure that netmask is set correctly */
    253 		memset(&su, 0, sizeof(su));
    254 		su.sin.sin_family = AF_INET;
    255 		su.sin.sin_len = sizeof(su.sin);
    256 		memcpy(&su.sin.sin_addr, &net->s_addr, sizeof(su.sin.sin_addr));
    257 		p = su.sa.sa_len + (char *)&su;
    258 		for (su.sa.sa_len = 0; p > (char *)&su;)
    259 			if (*--p != 0) {
    260 				su.sa.sa_len = 1 + p - (char *)&su;
    261 				break;
    262 			}
    263 		ADDSU(su);
    264 	}
    265 
    266 	if (rtm.hdr.rtm_addrs & RTA_IFA)
    267 		ADDADDR(&iface->addr);
    268 
    269 	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
    270 	if (write(r_fd, &rtm, l) == -1)
    271 		retval = -1;
    272 	return retval;
    273 }
    274 
    275 int
    276 open_link_socket(void)
    277 {
    278 	int fd;
    279 
    280 	fd = socket(PF_ROUTE, SOCK_RAW, 0);
    281 	if (fd != -1) {
    282 		set_cloexec(fd);
    283 		set_nonblock(fd);
    284 	}
    285 	return fd;
    286 }
    287 
    288 static void
    289 get_addrs(int type, char *cp, struct sockaddr **sa)
    290 {
    291 	int i;
    292 
    293 	for (i = 0; i < RTAX_MAX; i++) {
    294 		if (type & (1 << i)) {
    295 			sa[i] = (struct sockaddr *)cp;
    296 #ifdef DEBUG
    297 			printf ("got %d %d %s\n", i, sa[i]->sa_family,
    298 			    inet_ntoa(((struct sockaddr_in *)sa[i])->
    299 				sin_addr));
    300 #endif
    301 			ADVANCE(cp, sa[i]);
    302 		} else
    303 			sa[i] = NULL;
    304 	}
    305 }
    306 
    307 int
    308 manage_link(int fd)
    309 {
    310 	char *p, *e, *cp;
    311 	char ifname[IF_NAMESIZE];
    312 	ssize_t bytes;
    313 	struct rt_msghdr *rtm;
    314 	struct if_announcemsghdr *ifan;
    315 	struct if_msghdr *ifm;
    316 	struct ifa_msghdr *ifam;
    317 	struct rt rt;
    318 	struct sockaddr *sa, *rti_info[RTAX_MAX];
    319 	int len;
    320 #ifdef RTM_CHGADDR
    321 	struct sockaddr_dl sdl;
    322 	unsigned char *hwaddr;
    323 #endif
    324 
    325 	for (;;) {
    326 		if (ioctl(fd, FIONREAD, &len) == -1)
    327 			return -1;
    328 		if (link_buflen < len) {
    329 			p = realloc(link_buf, len);
    330 			if (p == NULL)
    331 				return -1;
    332 			link_buf = p;
    333 			link_buflen = len;
    334 		}
    335 		bytes = read(fd, link_buf, link_buflen);
    336 		if (bytes == -1) {
    337 			if (errno == EAGAIN)
    338 				return 0;
    339 			if (errno == EINTR)
    340 				continue;
    341 			return -1;
    342 		}
    343 		e = link_buf + bytes;
    344 		for (p = link_buf; p < e; p += rtm->rtm_msglen) {
    345 			rtm = (struct rt_msghdr *)(void *)p;
    346 			switch(rtm->rtm_type) {
    347 #ifdef RTM_IFANNOUNCE
    348 			case RTM_IFANNOUNCE:
    349 				ifan = (struct if_announcemsghdr *)(void *)p;
    350 				switch(ifan->ifan_what) {
    351 				case IFAN_ARRIVAL:
    352 					handle_interface(1, ifan->ifan_name);
    353 					break;
    354 				case IFAN_DEPARTURE:
    355 					handle_interface(-1, ifan->ifan_name);
    356 					break;
    357 				}
    358 				break;
    359 #endif
    360 			case RTM_IFINFO:
    361 				ifm = (struct if_msghdr *)(void *)p;
    362 				memset(ifname, 0, sizeof(ifname));
    363 				if (if_indextoname(ifm->ifm_index, ifname))
    364 					handle_interface(0, ifname);
    365 				break;
    366 			case RTM_DELETE:
    367 				if (!(rtm->rtm_addrs & RTA_DST) ||
    368 				    !(rtm->rtm_addrs & RTA_GATEWAY) ||
    369 				    !(rtm->rtm_addrs & RTA_NETMASK))
    370 					break;
    371 				if (rtm->rtm_pid == getpid())
    372 					break;
    373 				cp = (char *)(void *)(rtm + 1);
    374 				sa = (struct sockaddr *)(void *)cp;
    375 				if (sa->sa_family != AF_INET)
    376 					break;
    377 				get_addrs(rtm->rtm_addrs, cp, rti_info);
    378 				rt.iface = NULL;
    379 				rt.next = NULL;
    380 				COPYOUT(rt.dest, rti_info[RTAX_DST]);
    381 				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
    382 				COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
    383 				route_deleted(&rt);
    384 				break;
    385 #ifdef RTM_CHGADDR
    386 			case RTM_CHGADDR:	/* FALLTHROUGH */
    387 #endif
    388 			case RTM_DELADDR:	/* FALLTHROUGH */
    389 			case RTM_NEWADDR:
    390 				ifam = (struct ifa_msghdr *)(void *)p;
    391 				if (!if_indextoname(ifam->ifam_index, ifname))
    392 					break;
    393 				cp = (char *)(void *)(ifam + 1);
    394 				get_addrs(ifam->ifam_addrs, cp, rti_info);
    395 				if (rti_info[RTAX_IFA] == NULL)
    396 					break;
    397 				switch (rti_info[RTAX_IFA]->sa_family) {
    398 #ifdef RTM_CHGADDR
    399 				case AF_LINK:
    400 					if (rtm->rtm_type != RTM_CHGADDR)
    401 						break;
    402 					memcpy(&sdl, rti_info[RTAX_IFA],
    403 					    rti_info[RTAX_IFA]->sa_len);
    404 					hwaddr = xmalloc(sdl.sdl_alen);
    405 					memcpy(hwaddr, LLADDR(&sdl),
    406 					    sdl.sdl_alen);
    407 					handle_hwaddr(ifname, hwaddr,
    408 					    sdl.sdl_alen);
    409 					break;
    410 #endif
    411 				case AF_INET:
    412 				case 255: /* FIXME: Why 255? */
    413 					COPYOUT(rt.dest, rti_info[RTAX_IFA]);
    414 					COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
    415 					COPYOUT(rt.gate, rti_info[RTAX_BRD]);
    416 					handle_ifa(rtm->rtm_type, ifname,
    417 					    &rt.dest, &rt.net, &rt.gate);
    418 					break;
    419 				}
    420 				break;
    421 			}
    422 		}
    423 	}
    424 }
    425