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