1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2012 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 #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 80 if_init(_unused struct interface *iface) 81 { 82 /* BSD promotes secondary address by default */ 83 return 0; 84 } 85 86 int 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 95 cleanup(void) 96 { 97 98 free(link_buf); 99 } 100 #endif 101 102 int 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 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 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 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 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 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 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