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#ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */
39#  include <net/if_var.h>
40#endif
41#include <net/route.h>
42#include <netinet/in.h>
43#include <netinet6/in6_var.h>
44#ifdef __DragonFly__
45#  include <netproto/802_11/ieee80211_ioctl.h>
46#elif __APPLE__
47  /* FIXME: Add apple includes so we can work out SSID */
48#else
49#  include <net80211/ieee80211_ioctl.h>
50#endif
51
52#include <errno.h>
53#include <fnmatch.h>
54#include <stddef.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58#include <syslog.h>
59#include <unistd.h>
60
61#include "config.h"
62#include "common.h"
63#include "configure.h"
64#include "dhcp.h"
65#include "if-options.h"
66#include "ipv6.h"
67#include "net.h"
68
69#ifndef RT_ROUNDUP
70#define RT_ROUNDUP(a)							      \
71	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
72#define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len))
73#endif
74
75/* FIXME: Why do we need to check for sa_family 255 */
76#define COPYOUT(sin, sa)						      \
77	sin.s_addr = ((sa) != NULL) ?					      \
78	    (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
79
80static int r_fd = -1;
81static char *link_buf;
82static ssize_t link_buflen;
83
84int
85if_init(_unused struct interface *iface)
86{
87	/* BSD promotes secondary address by default */
88	return 0;
89}
90
91int
92if_conf(_unused struct interface *iface)
93{
94	/* No extra checks needed on BSD */
95	return 0;
96}
97
98#ifdef DEBUG_MEMORY
99static void
100cleanup(void)
101{
102
103	free(link_buf);
104}
105#endif
106
107int
108init_sockets(void)
109{
110	if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
111		return -1;
112	set_cloexec(socket_afnet);
113	if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
114		return -1;
115	set_cloexec(r_fd);
116	return 0;
117}
118
119int
120getifssid(const char *ifname, char *ssid)
121{
122	int retval = -1;
123#if defined(SIOCG80211NWID)
124	struct ifreq ifr;
125	struct ieee80211_nwid nwid;
126#elif defined(IEEE80211_IOC_SSID)
127	struct ieee80211req ireq;
128	char nwid[IEEE80211_NWID_LEN + 1];
129#endif
130
131#if defined(SIOCG80211NWID) /* NetBSD */
132	memset(&ifr, 0, sizeof(ifr));
133	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
134	memset(&nwid, 0, sizeof(nwid));
135	ifr.ifr_data = (void *)&nwid;
136	if (ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) {
137		retval = nwid.i_len;
138		memcpy(ssid, nwid.i_nwid, nwid.i_len);
139		ssid[nwid.i_len] = '\0';
140	}
141#elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
142	memset(&ireq, 0, sizeof(ireq));
143	strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
144	ireq.i_type = IEEE80211_IOC_SSID;
145	ireq.i_val = -1;
146	memset(nwid, 0, sizeof(nwid));
147	ireq.i_data = &nwid;
148	if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) {
149		retval = ireq.i_len;
150		memcpy(ssid, nwid, ireq.i_len);
151		ssid[ireq.i_len] = '\0';
152	}
153#endif
154	return retval;
155}
156
157int
158if_address(const struct interface *iface, const struct in_addr *address,
159    const struct in_addr *netmask, const struct in_addr *broadcast,
160    int action)
161{
162	struct ifaliasreq ifa;
163	union {
164		struct sockaddr *sa;
165		struct sockaddr_in *sin;
166	} _s;
167
168	memset(&ifa, 0, sizeof(ifa));
169	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));
170
171#define ADDADDR(_var, _addr) {						      \
172		_s.sa = &_var;						      \
173		_s.sin->sin_family = AF_INET;				      \
174		_s.sin->sin_len = sizeof(*_s.sin);			      \
175		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
176	}
177
178	ADDADDR(ifa.ifra_addr, address);
179	ADDADDR(ifa.ifra_mask, netmask);
180	if (action >= 0 && broadcast) {
181		ADDADDR(ifa.ifra_broadaddr, broadcast);
182	}
183#undef ADDADDR
184
185	return ioctl(socket_afnet,
186	    action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifa);
187}
188
189int
190if_route(const struct rt *rt, int action)
191{
192	union sockunion {
193		struct sockaddr sa;
194		struct sockaddr_in sin;
195		struct sockaddr_dl sdl;
196		struct sockaddr_storage ss;
197	} su;
198	struct rtm
199	{
200		struct rt_msghdr hdr;
201		char buffer[sizeof(su) * 4];
202	} rtm;
203	char *bp = rtm.buffer;
204	size_t l;
205	int retval = 0;
206
207#define ADDSU {								      \
208		l = RT_ROUNDUP(su.sa.sa_len);				      \
209		memcpy(bp, &su, l);					      \
210		bp += l;						      \
211	}
212#define ADDADDR(addr) {							      \
213		memset(&su, 0, sizeof(su));				      \
214		su.sin.sin_family = AF_INET;				      \
215		su.sin.sin_len = sizeof(su.sin);			      \
216		(&su.sin)->sin_addr = *addr;				      \
217		ADDSU;							      \
218	}
219
220	memset(&rtm, 0, sizeof(rtm));
221	rtm.hdr.rtm_version = RTM_VERSION;
222	rtm.hdr.rtm_seq = 1;
223	if (action == 0)
224		rtm.hdr.rtm_type = RTM_CHANGE;
225	else if (action > 0)
226		rtm.hdr.rtm_type = RTM_ADD;
227	else
228		rtm.hdr.rtm_type = RTM_DELETE;
229	rtm.hdr.rtm_flags = RTF_UP;
230	/* None interface subnet routes are static. */
231	if (rt->gate.s_addr != INADDR_ANY ||
232	    rt->net.s_addr != rt->iface->net.s_addr ||
233	    rt->dest.s_addr != (rt->iface->addr.s_addr & rt->iface->net.s_addr))
234		rtm.hdr.rtm_flags |= RTF_STATIC;
235	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
236	if (rt->dest.s_addr == rt->gate.s_addr &&
237	    rt->net.s_addr == INADDR_BROADCAST)
238		rtm.hdr.rtm_flags |= RTF_HOST;
239	else {
240		rtm.hdr.rtm_addrs |= RTA_NETMASK;
241		if (rtm.hdr.rtm_flags & RTF_STATIC)
242			rtm.hdr.rtm_flags |= RTF_GATEWAY;
243		if (action >= 0)
244			rtm.hdr.rtm_addrs |= RTA_IFA;
245	}
246
247	ADDADDR(&rt->dest);
248	if (rtm.hdr.rtm_flags & RTF_HOST ||
249	    !(rtm.hdr.rtm_flags & RTF_STATIC))
250	{
251		/* Make us a link layer socket for the host gateway */
252		memset(&su, 0, sizeof(su));
253		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
254		link_addr(rt->iface->name, &su.sdl);
255		ADDSU;
256	} else
257		ADDADDR(&rt->gate);
258
259	if (rtm.hdr.rtm_addrs & RTA_NETMASK)
260		ADDADDR(&rt->net);
261
262	/* IFP here if we need it */
263
264	if (rtm.hdr.rtm_addrs & RTA_IFA)
265		ADDADDR(&rt->iface->addr);
266
267#undef ADDADDR
268#undef ADDSU
269
270	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
271	if (write(r_fd, &rtm, l) == -1)
272		retval = -1;
273	return retval;
274}
275
276int
277if_address6(const struct interface *ifp, const struct ipv6_addr *a, int action)
278{
279	struct in6_aliasreq ifa;
280	struct in6_addr mask;
281
282	memset(&ifa, 0, sizeof(ifa));
283	strlcpy(ifa.ifra_name, ifp->name, sizeof(ifa.ifra_name));
284
285#define ADDADDR(v, addr) {						      \
286		(v)->sin6_family = AF_INET6;				      \
287		(v)->sin6_len = sizeof(*v);				      \
288		(v)->sin6_addr = *addr;					      \
289	}
290
291	ADDADDR(&ifa.ifra_addr, &a->addr);
292	ipv6_mask(&mask, a->prefix_len);
293	ADDADDR(&ifa.ifra_prefixmask, &mask);
294	ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
295	ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime;
296#undef ADDADDR
297
298	return ioctl(socket_afnet6,
299	    action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
300}
301
302int
303if_route6(const struct rt6 *rt, int action)
304{
305	union sockunion {
306		struct sockaddr sa;
307		struct sockaddr_in6 sin;
308		struct sockaddr_dl sdl;
309		struct sockaddr_storage ss;
310	} su;
311	struct rtm
312	{
313		struct rt_msghdr hdr;
314		char buffer[sizeof(su) * 4];
315	} rtm;
316	char *bp = rtm.buffer;
317	size_t l;
318	int retval = 0;
319
320/* KAME based systems want to store the scope inside the sin6_addr
321 * for link local addreses */
322#ifdef __KAME__
323#define SCOPE {								      \
324		if (IN6_IS_ADDR_LINKLOCAL(&su.sin.sin6_addr)) { 	      \
325			*(uint16_t *)(void *)&su.sin.sin6_addr.s6_addr[2] =   \
326			    htons(su.sin.sin6_scope_id); 		      \
327			su.sin.sin6_scope_id = 0; 			      \
328		} 							      \
329	}
330#else
331#define SCOPE
332#endif
333
334#define ADDSU {							     	      \
335		l = RT_ROUNDUP(su.sa.sa_len);				      \
336		memcpy(bp, &su, l);					      \
337		bp += l;						      \
338	}
339#define ADDADDRS(addr, scope) {						      \
340		memset(&su, 0, sizeof(su));				      \
341		su.sin.sin6_family = AF_INET6;				      \
342		su.sin.sin6_len = sizeof(su.sin);			      \
343		(&su.sin)->sin6_addr = *addr;				      \
344		su.sin.sin6_scope_id = scope;				      \
345		SCOPE;							      \
346		ADDSU;							      \
347	}
348#define ADDADDR(addr) ADDADDRS(addr, 0)
349
350	memset(&rtm, 0, sizeof(rtm));
351	rtm.hdr.rtm_version = RTM_VERSION;
352	rtm.hdr.rtm_seq = 1;
353	if (action == 0)
354		rtm.hdr.rtm_type = RTM_CHANGE;
355	else if (action > 0)
356		rtm.hdr.rtm_type = RTM_ADD;
357	else
358		rtm.hdr.rtm_type = RTM_DELETE;
359
360	rtm.hdr.rtm_flags = RTF_UP;
361	/* None interface subnet routes are static. */
362	if (IN6_IS_ADDR_UNSPECIFIED(&rt->dest) &&
363	    IN6_IS_ADDR_UNSPECIFIED(&rt->net))
364		rtm.hdr.rtm_flags |= RTF_GATEWAY;
365	else
366		rtm.hdr.rtm_flags |= RTF_CLONING;
367
368	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
369//	if (action >= 0)
370//		rtm.hdr.rtm_addrs |= RTA_IFA;
371
372	ADDADDR(&rt->dest);
373	if (rtm.hdr.rtm_flags & (RTF_HOST | RTF_CLONING)) {
374		/* Make us a link layer socket for the host gateway */
375		memset(&su, 0, sizeof(su));
376		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
377		link_addr(rt->iface->name, &su.sdl);
378		ADDSU;
379	} else
380		ADDADDRS(&rt->gate, rt->iface->index);
381
382	if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
383		if (rtm.hdr.rtm_flags & RTF_GATEWAY) {
384			memset(&su, 0, sizeof(su));
385			su.sin.sin6_family = AF_INET6;
386			ADDSU;
387		} else
388			ADDADDR(&rt->net);
389	}
390
391	/* IFP here if we need it */
392	/* IFA here if we need it */
393
394#undef ADDADDR
395#undef ADDSU
396#undef SCOPE
397
398	if (action >= 0 && rt->mtu) {
399		rtm.hdr.rtm_inits |= RTV_MTU;
400		rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
401	}
402
403	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
404	if (write(r_fd, &rtm, l) == -1)
405		retval = -1;
406	return retval;
407}
408
409int
410open_link_socket(void)
411{
412	int fd;
413
414#ifdef DEBUG_MEMORY
415	if (link_buf == NULL)
416		atexit(cleanup);
417#endif
418
419	fd = socket(PF_ROUTE, SOCK_RAW, 0);
420	if (fd != -1) {
421		set_cloexec(fd);
422		set_nonblock(fd);
423	}
424	return fd;
425}
426
427static void
428get_addrs(int type, char *cp, struct sockaddr **sa)
429{
430	int i;
431
432	for (i = 0; i < RTAX_MAX; i++) {
433		if (type & (1 << i)) {
434			sa[i] = (struct sockaddr *)cp;
435#ifdef DEBUG
436			printf ("got %d %d %s\n", i, sa[i]->sa_family,
437			    inet_ntoa(((struct sockaddr_in *)sa[i])->
438				sin_addr));
439#endif
440			RT_ADVANCE(cp, sa[i]);
441		} else
442			sa[i] = NULL;
443	}
444}
445
446int
447manage_link(int fd)
448{
449	char *p, *e, *cp;
450	char ifname[IF_NAMESIZE];
451	ssize_t bytes;
452	struct rt_msghdr *rtm;
453	struct if_announcemsghdr *ifan;
454	struct if_msghdr *ifm;
455	struct ifa_msghdr *ifam;
456	struct rt rt;
457	struct sockaddr *sa, *rti_info[RTAX_MAX];
458	int len;
459#ifdef RTM_CHGADDR
460	struct sockaddr_dl sdl;
461	unsigned char *hwaddr;
462#endif
463
464	for (;;) {
465		if (ioctl(fd, FIONREAD, &len) == -1)
466			return -1;
467		if (link_buflen < len) {
468			p = realloc(link_buf, len);
469			if (p == NULL)
470				return -1;
471			link_buf = p;
472			link_buflen = len;
473		}
474		bytes = read(fd, link_buf, link_buflen);
475		if (bytes == -1) {
476			if (errno == EAGAIN)
477				return 0;
478			if (errno == EINTR)
479				continue;
480			return -1;
481		}
482		e = link_buf + bytes;
483		for (p = link_buf; p < e; p += rtm->rtm_msglen) {
484			rtm = (struct rt_msghdr *)(void *)p;
485			switch(rtm->rtm_type) {
486#ifdef RTM_IFANNOUNCE
487			case RTM_IFANNOUNCE:
488				ifan = (struct if_announcemsghdr *)(void *)p;
489				switch(ifan->ifan_what) {
490				case IFAN_ARRIVAL:
491					handle_interface(1, ifan->ifan_name);
492					break;
493				case IFAN_DEPARTURE:
494					handle_interface(-1, ifan->ifan_name);
495					break;
496				}
497				break;
498#endif
499			case RTM_IFINFO:
500				ifm = (struct if_msghdr *)(void *)p;
501				memset(ifname, 0, sizeof(ifname));
502				if (!(if_indextoname(ifm->ifm_index, ifname)))
503					break;
504				switch (ifm->ifm_data.ifi_link_state) {
505				case LINK_STATE_DOWN:
506					len = -1;
507					break;
508				case LINK_STATE_UP:
509					len = 1;
510					break;
511				default:
512					/* handle_carrier will re-load
513					 * the interface flags and check for
514					 * IFF_RUNNING as some drivers that
515					 * don't handle link state also don't
516					 * set IFF_RUNNING when this routing
517					 * message is generated.
518					 * As such, it is a race ...*/
519					len = 0;
520					break;
521				}
522				handle_carrier(len, ifm->ifm_flags, ifname);
523				break;
524			case RTM_DELETE:
525				if (~rtm->rtm_addrs &
526				    (RTA_DST | RTA_GATEWAY | RTA_NETMASK))
527					break;
528				if (rtm->rtm_pid == getpid())
529					break;
530				cp = (char *)(void *)(rtm + 1);
531				sa = (struct sockaddr *)(void *)cp;
532				if (sa->sa_family != AF_INET)
533					break;
534				get_addrs(rtm->rtm_addrs, cp, rti_info);
535				rt.iface = NULL;
536				rt.next = NULL;
537				COPYOUT(rt.dest, rti_info[RTAX_DST]);
538				COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
539				COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
540				route_deleted(&rt);
541				break;
542#ifdef RTM_CHGADDR
543			case RTM_CHGADDR:	/* FALLTHROUGH */
544#endif
545			case RTM_DELADDR:	/* FALLTHROUGH */
546			case RTM_NEWADDR:
547				ifam = (struct ifa_msghdr *)(void *)p;
548				if (!if_indextoname(ifam->ifam_index, ifname))
549					break;
550				cp = (char *)(void *)(ifam + 1);
551				get_addrs(ifam->ifam_addrs, cp, rti_info);
552				if (rti_info[RTAX_IFA] == NULL)
553					break;
554				switch (rti_info[RTAX_IFA]->sa_family) {
555#ifdef RTM_CHGADDR
556				case AF_LINK:
557					if (rtm->rtm_type != RTM_CHGADDR)
558						break;
559					memcpy(&sdl, rti_info[RTAX_IFA],
560					    rti_info[RTAX_IFA]->sa_len);
561					hwaddr = xmalloc(sdl.sdl_alen);
562					memcpy(hwaddr, LLADDR(&sdl),
563					    sdl.sdl_alen);
564					handle_hwaddr(ifname, hwaddr,
565					    sdl.sdl_alen);
566					break;
567#endif
568				case AF_INET:
569				case 255: /* FIXME: Why 255? */
570					COPYOUT(rt.dest, rti_info[RTAX_IFA]);
571					COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
572					COPYOUT(rt.gate, rti_info[RTAX_BRD]);
573					handle_ifa(rtm->rtm_type, ifname,
574					    &rt.dest, &rt.net, &rt.gate);
575					break;
576				}
577				break;
578			}
579		}
580	}
581}
582