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 #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
if_init(_unused struct interface * iface)80 if_init(_unused struct interface *iface)
81 {
82 /* BSD promotes secondary address by default */
83 return 0;
84 }
85
86 int
if_conf(_unused struct interface * iface)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
cleanup(void)95 cleanup(void)
96 {
97
98 free(link_buf);
99 }
100 #endif
101
102 int
init_sockets(void)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
getifssid(const char * ifname,char * ssid)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
if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)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
if_route(const struct rt * rt,int action)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
open_link_socket(void)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
get_addrs(int type,char * cp,struct sockaddr ** sa)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
manage_link(int fd)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