xref: /netbsd-src/usr.bin/rump_dhcpclient/if-bsd.c (revision 0ce325d8e41d32f35d5828bd1c83bed509801cf9)
1e9639606Spooka /*
2e9639606Spooka  * dhcpcd - DHCP client daemon
3e9639606Spooka  * Copyright (c) 2006-2010 Roy Marples <roy@marples.name>
4e9639606Spooka  * All rights reserved
5e9639606Spooka 
6e9639606Spooka  * Redistribution and use in source and binary forms, with or without
7e9639606Spooka  * modification, are permitted provided that the following conditions
8e9639606Spooka  * are met:
9e9639606Spooka  * 1. Redistributions of source code must retain the above copyright
10e9639606Spooka  *    notice, this list of conditions and the following disclaimer.
11e9639606Spooka  * 2. Redistributions in binary form must reproduce the above copyright
12e9639606Spooka  *    notice, this list of conditions and the following disclaimer in the
13e9639606Spooka  *    documentation and/or other materials provided with the distribution.
14e9639606Spooka  *
15e9639606Spooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e9639606Spooka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e9639606Spooka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e9639606Spooka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e9639606Spooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e9639606Spooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e9639606Spooka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e9639606Spooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e9639606Spooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e9639606Spooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e9639606Spooka  * SUCH DAMAGE.
26e9639606Spooka  */
27e9639606Spooka 
28e9639606Spooka #include <sys/ioctl.h>
29e9639606Spooka #include <sys/param.h>
30e9639606Spooka #include <sys/socket.h>
31e9639606Spooka #include <sys/stat.h>
32e9639606Spooka #include <sys/sysctl.h>
33e9639606Spooka #include <sys/types.h>
34e9639606Spooka 
35e9639606Spooka #include <arpa/inet.h>
36e9639606Spooka #include <net/if.h>
37e9639606Spooka #include <net/if_dl.h>
38e9639606Spooka #include <net/route.h>
39e9639606Spooka #include <netinet/in.h>
40e9639606Spooka #ifdef __DragonFly__
41e9639606Spooka #  include <netproto/802_11/ieee80211_ioctl.h>
42e9639606Spooka #elif __APPLE__
43e9639606Spooka   /* FIXME: Add apple includes so we can work out SSID */
44e9639606Spooka #else
45e9639606Spooka #  include <net80211/ieee80211_ioctl.h>
46e9639606Spooka #endif
47e9639606Spooka 
48e9639606Spooka #include <errno.h>
49e9639606Spooka #include <fnmatch.h>
50e9639606Spooka #include <stddef.h>
51e9639606Spooka #include <stdio.h>
52e9639606Spooka #include <stdlib.h>
53e9639606Spooka #include <string.h>
54e9639606Spooka #include <unistd.h>
55e9639606Spooka 
56e9639606Spooka #include <rump/rump.h>
57e9639606Spooka #include <rump/rump_syscalls.h>
58e9639606Spooka 
59e9639606Spooka #include "common.h"
60e9639606Spooka #include "configure.h"
61e9639606Spooka #include "dhcp.h"
62e9639606Spooka #include "if-options.h"
63e9639606Spooka #include "net.h"
64e9639606Spooka 
65e9639606Spooka /* FIXME: Why do we need to check for sa_family 255 */
66e9639606Spooka #define COPYOUT(sin, sa)						      \
67e9639606Spooka 	sin.s_addr = ((sa) != NULL) ?					      \
68e9639606Spooka 	    (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0
69e9639606Spooka 
70e9639606Spooka static int r_fd = -1;
71e9639606Spooka 
72e9639606Spooka int
if_init(_unused struct interface * iface)73e9639606Spooka if_init(_unused struct interface *iface)
74e9639606Spooka {
75e9639606Spooka 	/* BSD promotes secondary address by default */
76e9639606Spooka 	return 0;
77e9639606Spooka }
78e9639606Spooka 
79e9639606Spooka int
if_conf(_unused struct interface * iface)80e9639606Spooka if_conf(_unused struct interface *iface)
81e9639606Spooka {
82e9639606Spooka 	/* No extra checks needed on BSD */
83e9639606Spooka 	return 0;
84e9639606Spooka }
85e9639606Spooka 
86e9639606Spooka int
init_sockets(void)87e9639606Spooka init_sockets(void)
88e9639606Spooka {
89e9639606Spooka 
90e9639606Spooka 	if ((socket_afnet = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)) == -1)
91e9639606Spooka 		return -1;
92e9639606Spooka 	if ((r_fd = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
93e9639606Spooka 		return -1;
94e9639606Spooka 	return 0;
95e9639606Spooka }
96e9639606Spooka 
97e9639606Spooka int
getifssid(const char * ifname,char * ssid)98e9639606Spooka getifssid(const char *ifname, char *ssid)
99e9639606Spooka {
100e9639606Spooka 	int retval = -1;
101e9639606Spooka #if defined(SIOCG80211NWID)
102e9639606Spooka 	struct ifreq ifr;
103e9639606Spooka 	struct ieee80211_nwid nwid;
104e9639606Spooka #elif defined(IEEE80211_IOC_SSID)
105e9639606Spooka 	struct ieee80211req ireq;
106e9639606Spooka 	char nwid[IEEE80211_NWID_LEN + 1];
107e9639606Spooka #endif
108e9639606Spooka 
109e9639606Spooka #if defined(SIOCG80211NWID) /* NetBSD */
110e9639606Spooka 	memset(&ifr, 0, sizeof(ifr));
111e9639606Spooka 	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
112e9639606Spooka 	memset(&nwid, 0, sizeof(nwid));
113e9639606Spooka 	ifr.ifr_data = (void *)&nwid;
114e9639606Spooka 	if (rump_sys_ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) {
115e9639606Spooka 		retval = nwid.i_len;
116e9639606Spooka 		memcpy(ssid, nwid.i_nwid, nwid.i_len);
117e9639606Spooka 		ssid[nwid.i_len] = '\0';
118e9639606Spooka 	}
119e9639606Spooka #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
120e9639606Spooka 	memset(&ireq, 0, sizeof(ireq));
121e9639606Spooka 	strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
122e9639606Spooka 	ireq.i_type = IEEE80211_IOC_SSID;
123e9639606Spooka 	ireq.i_val = -1;
124e9639606Spooka 	ireq.i_data = &nwid;
125e9639606Spooka 	if (rump_sys_ioctl(socket_afnet, SIOCG80211, &ireq) == 0) {
126e9639606Spooka 		retval = ireq.i_len;
127e9639606Spooka 		memcpy(ssid, nwid, ireq.i_len);
128e9639606Spooka 		ssid[ireq.i_len] = '\0';
129e9639606Spooka 	}
130e9639606Spooka #endif
131e9639606Spooka 	return retval;
132e9639606Spooka }
133e9639606Spooka 
134e9639606Spooka int
if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)135e9639606Spooka if_address(const struct interface *iface, const struct in_addr *address,
136e9639606Spooka     const struct in_addr *netmask, const struct in_addr *broadcast,
137e9639606Spooka     int action)
138e9639606Spooka {
139e9639606Spooka 	int retval;
140e9639606Spooka 	struct ifaliasreq ifa;
141e9639606Spooka 	union {
142e9639606Spooka 		struct sockaddr *sa;
143e9639606Spooka 		struct sockaddr_in *sin;
144e9639606Spooka 	} _s;
145e9639606Spooka 
146e9639606Spooka 	memset(&ifa, 0, sizeof(ifa));
147e9639606Spooka 	strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));
148e9639606Spooka 
149e9639606Spooka #define ADDADDR(_var, _addr) {						      \
150e9639606Spooka 		_s.sa = &_var;						      \
151e9639606Spooka 		_s.sin->sin_family = AF_INET;				      \
152e9639606Spooka 		_s.sin->sin_len = sizeof(*_s.sin);			      \
153e9639606Spooka 		memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr));   \
154e9639606Spooka 	}
155e9639606Spooka 
156e9639606Spooka 	ADDADDR(ifa.ifra_addr, address);
157e9639606Spooka 	ADDADDR(ifa.ifra_mask, netmask);
158e9639606Spooka 	if (action >= 0 && broadcast) {
159e9639606Spooka 		ADDADDR(ifa.ifra_broadaddr, broadcast);
160e9639606Spooka 	}
161e9639606Spooka #undef ADDADDR
162e9639606Spooka 
163e9639606Spooka 	if (action < 0)
164e9639606Spooka 		retval = rump_sys_ioctl(socket_afnet, SIOCDIFADDR, &ifa);
165e9639606Spooka 	else
166e9639606Spooka 		retval = rump_sys_ioctl(socket_afnet, SIOCAIFADDR, &ifa);
167e9639606Spooka 	return retval;
168e9639606Spooka }
169e9639606Spooka 
170e9639606Spooka /* ARGSUSED4 */
171e9639606Spooka int
if_route(const struct interface * iface,const struct in_addr * dest,const struct in_addr * net,const struct in_addr * gate,_unused int metric,int action)172e9639606Spooka if_route(const struct interface *iface, const struct in_addr *dest,
173e9639606Spooka     const struct in_addr *net, const struct in_addr *gate,
174e9639606Spooka     _unused int metric, int action)
175e9639606Spooka {
176e9639606Spooka 	union sockunion {
177e9639606Spooka 		struct sockaddr sa;
178e9639606Spooka 		struct sockaddr_in sin;
179e9639606Spooka #ifdef INET6
180e9639606Spooka 		struct sockaddr_in6 sin6;
181e9639606Spooka #endif
182e9639606Spooka 		struct sockaddr_dl sdl;
183e9639606Spooka 		struct sockaddr_storage ss;
184e9639606Spooka 	} su;
185e9639606Spooka 	struct rtm
186e9639606Spooka 	{
187e9639606Spooka 		struct rt_msghdr hdr;
188e9639606Spooka 		char buffer[sizeof(su) * 4];
189e9639606Spooka 	} rtm;
190e9639606Spooka 	char *bp = rtm.buffer, *p;
191e9639606Spooka 	size_t l;
192e9639606Spooka 	int retval = 0;
193e9639606Spooka 
194e9639606Spooka #define ADDSU(_su) {							      \
195*0ce325d8Sroy 		l = RT_ROUNDUP(_su.sa.sa_len);				      \
196e9639606Spooka 		memcpy(bp, &(_su), l);					      \
197e9639606Spooka 		bp += l;						      \
198e9639606Spooka 	}
199e9639606Spooka #define ADDADDR(_a) {							      \
200e9639606Spooka 		memset (&su, 0, sizeof(su));				      \
201e9639606Spooka 		su.sin.sin_family = AF_INET;				      \
202e9639606Spooka 		su.sin.sin_len = sizeof(su.sin);			      \
203e9639606Spooka 		memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr));	      \
204e9639606Spooka 		ADDSU(su);						      \
205e9639606Spooka 	}
206e9639606Spooka 
207e9639606Spooka 	memset(&rtm, 0, sizeof(rtm));
208e9639606Spooka 	rtm.hdr.rtm_version = RTM_VERSION;
209e9639606Spooka 	rtm.hdr.rtm_seq = 1;
210e9639606Spooka 	if (action == 0)
211e9639606Spooka 		rtm.hdr.rtm_type = RTM_CHANGE;
212e9639606Spooka 	else if (action > 0)
213e9639606Spooka 		rtm.hdr.rtm_type = RTM_ADD;
214e9639606Spooka 	else
215e9639606Spooka 		rtm.hdr.rtm_type = RTM_DELETE;
216e9639606Spooka 	rtm.hdr.rtm_flags = RTF_UP;
217e9639606Spooka 	/* None interface subnet routes are static. */
218e9639606Spooka 	if (gate->s_addr != INADDR_ANY ||
219e9639606Spooka 	    net->s_addr != iface->net.s_addr ||
220e9639606Spooka 	    dest->s_addr != (iface->addr.s_addr & iface->net.s_addr))
221e9639606Spooka 		rtm.hdr.rtm_flags |= RTF_STATIC;
222e9639606Spooka 	rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
223e9639606Spooka 	if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST)
224e9639606Spooka 		rtm.hdr.rtm_flags |= RTF_HOST;
225e9639606Spooka 	else {
226e9639606Spooka 		rtm.hdr.rtm_addrs |= RTA_NETMASK;
227e9639606Spooka 		if (rtm.hdr.rtm_flags & RTF_STATIC)
228e9639606Spooka 			rtm.hdr.rtm_flags |= RTF_GATEWAY;
229e9639606Spooka 		if (action >= 0)
230e9639606Spooka 			rtm.hdr.rtm_addrs |= RTA_IFA;
231e9639606Spooka 	}
232e9639606Spooka 
233e9639606Spooka 	ADDADDR(dest);
234e9639606Spooka 	if (rtm.hdr.rtm_flags & RTF_HOST ||
235e9639606Spooka 	    !(rtm.hdr.rtm_flags & RTF_STATIC))
236e9639606Spooka 	{
237e9639606Spooka 		/* Make us a link layer socket for the host gateway */
238e9639606Spooka 		memset(&su, 0, sizeof(su));
239e9639606Spooka 		su.sdl.sdl_len = sizeof(struct sockaddr_dl);
240e9639606Spooka 		link_addr(iface->name, &su.sdl);
241e9639606Spooka 		ADDSU(su);
242e9639606Spooka 	} else
243e9639606Spooka 		ADDADDR(gate);
244e9639606Spooka 
245e9639606Spooka 	if (rtm.hdr.rtm_addrs & RTA_NETMASK) {
246e9639606Spooka 		/* Ensure that netmask is set correctly */
247e9639606Spooka 		memset(&su, 0, sizeof(su));
248e9639606Spooka 		su.sin.sin_family = AF_INET;
249e9639606Spooka 		su.sin.sin_len = sizeof(su.sin);
250e9639606Spooka 		memcpy(&su.sin.sin_addr, &net->s_addr, sizeof(su.sin.sin_addr));
251e9639606Spooka 		p = su.sa.sa_len + (char *)&su;
252e9639606Spooka 		for (su.sa.sa_len = 0; p > (char *)&su;)
253e9639606Spooka 			if (*--p != 0) {
254e9639606Spooka 				su.sa.sa_len = 1 + p - (char *)&su;
255e9639606Spooka 				break;
256e9639606Spooka 			}
257e9639606Spooka 		ADDSU(su);
258e9639606Spooka 	}
259e9639606Spooka 
260e9639606Spooka 	if (rtm.hdr.rtm_addrs & RTA_IFA)
261e9639606Spooka 		ADDADDR(&iface->addr);
262e9639606Spooka 
263e9639606Spooka 	rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
264e9639606Spooka 	if (rump_sys_write(r_fd, &rtm, l) == -1)
265e9639606Spooka 		retval = -1;
266e9639606Spooka 	return retval;
267e9639606Spooka }
268