1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2010 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 #define ROUNDUP(a) \ 65 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 66 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 67 68 /* FIXME: Why do we need to check for sa_family 255 */ 69 #define COPYOUT(sin, sa) \ 70 sin.s_addr = ((sa) != NULL) ? \ 71 (((struct sockaddr_in *)(void *)sa)->sin_addr).s_addr : 0 72 73 static int r_fd = -1; 74 static char *link_buf; 75 static ssize_t link_buflen; 76 77 int 78 if_init(_unused struct interface *iface) 79 { 80 /* BSD promotes secondary address by default */ 81 return 0; 82 } 83 84 int 85 if_conf(_unused struct interface *iface) 86 { 87 /* No extra checks needed on BSD */ 88 return 0; 89 } 90 91 int 92 init_sockets(void) 93 { 94 if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 95 return -1; 96 set_cloexec(socket_afnet); 97 if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 98 return -1; 99 set_cloexec(r_fd); 100 return 0; 101 } 102 103 int 104 getifssid(const char *ifname, char *ssid) 105 { 106 int retval = -1; 107 #if defined(SIOCG80211NWID) 108 struct ifreq ifr; 109 struct ieee80211_nwid nwid; 110 #elif defined(IEEE80211_IOC_SSID) 111 struct ieee80211req ireq; 112 char nwid[IEEE80211_NWID_LEN + 1]; 113 #endif 114 115 #if defined(SIOCG80211NWID) /* NetBSD */ 116 memset(&ifr, 0, sizeof(ifr)); 117 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 118 memset(&nwid, 0, sizeof(nwid)); 119 ifr.ifr_data = (void *)&nwid; 120 if (ioctl(socket_afnet, SIOCG80211NWID, &ifr) == 0) { 121 retval = nwid.i_len; 122 memcpy(ssid, nwid.i_nwid, nwid.i_len); 123 ssid[nwid.i_len] = '\0'; 124 } 125 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */ 126 memset(&ireq, 0, sizeof(ireq)); 127 strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); 128 ireq.i_type = IEEE80211_IOC_SSID; 129 ireq.i_val = -1; 130 ireq.i_data = &nwid; 131 if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) { 132 retval = ireq.i_len; 133 memcpy(ssid, nwid, ireq.i_len); 134 ssid[ireq.i_len] = '\0'; 135 } 136 #endif 137 return retval; 138 } 139 140 int 141 if_address(const struct interface *iface, const struct in_addr *address, 142 const struct in_addr *netmask, const struct in_addr *broadcast, 143 int action) 144 { 145 int retval; 146 struct ifaliasreq ifa; 147 union { 148 struct sockaddr *sa; 149 struct sockaddr_in *sin; 150 } _s; 151 152 memset(&ifa, 0, sizeof(ifa)); 153 strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name)); 154 155 #define ADDADDR(_var, _addr) { \ 156 _s.sa = &_var; \ 157 _s.sin->sin_family = AF_INET; \ 158 _s.sin->sin_len = sizeof(*_s.sin); \ 159 memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr)); \ 160 } 161 162 ADDADDR(ifa.ifra_addr, address); 163 ADDADDR(ifa.ifra_mask, netmask); 164 if (action >= 0 && broadcast) { 165 ADDADDR(ifa.ifra_broadaddr, broadcast); 166 } 167 #undef ADDADDR 168 169 if (action < 0) 170 retval = ioctl(socket_afnet, SIOCDIFADDR, &ifa); 171 else 172 retval = ioctl(socket_afnet, SIOCAIFADDR, &ifa); 173 return retval; 174 } 175 176 /* ARGSUSED4 */ 177 int 178 if_route(const struct interface *iface, const struct in_addr *dest, 179 const struct in_addr *net, const struct in_addr *gate, 180 _unused int metric, int action) 181 { 182 union sockunion { 183 struct sockaddr sa; 184 struct sockaddr_in sin; 185 #ifdef INET6 186 struct sockaddr_in6 sin6; 187 #endif 188 struct sockaddr_dl sdl; 189 struct sockaddr_storage ss; 190 } su; 191 struct rtm 192 { 193 struct rt_msghdr hdr; 194 char buffer[sizeof(su) * 4]; 195 } rtm; 196 char *bp = rtm.buffer, *p; 197 size_t l; 198 int retval = 0; 199 200 #define ADDSU(_su) { \ 201 l = ROUNDUP(_su.sa.sa_len); \ 202 memcpy(bp, &(_su), l); \ 203 bp += l; \ 204 } 205 #define ADDADDR(_a) { \ 206 memset (&su, 0, sizeof(su)); \ 207 su.sin.sin_family = AF_INET; \ 208 su.sin.sin_len = sizeof(su.sin); \ 209 memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr)); \ 210 ADDSU(su); \ 211 } 212 213 memset(&rtm, 0, sizeof(rtm)); 214 rtm.hdr.rtm_version = RTM_VERSION; 215 rtm.hdr.rtm_seq = 1; 216 if (action == 0) 217 rtm.hdr.rtm_type = RTM_CHANGE; 218 else if (action > 0) 219 rtm.hdr.rtm_type = RTM_ADD; 220 else 221 rtm.hdr.rtm_type = RTM_DELETE; 222 rtm.hdr.rtm_flags = RTF_UP; 223 /* None interface subnet routes are static. */ 224 if (gate->s_addr != INADDR_ANY || 225 net->s_addr != iface->net.s_addr || 226 dest->s_addr != (iface->addr.s_addr & iface->net.s_addr)) 227 rtm.hdr.rtm_flags |= RTF_STATIC; 228 rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; 229 if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST) 230 rtm.hdr.rtm_flags |= RTF_HOST; 231 else { 232 rtm.hdr.rtm_addrs |= RTA_NETMASK; 233 if (rtm.hdr.rtm_flags & RTF_STATIC) 234 rtm.hdr.rtm_flags |= RTF_GATEWAY; 235 if (action >= 0) 236 rtm.hdr.rtm_addrs |= RTA_IFA; 237 } 238 239 ADDADDR(dest); 240 if (rtm.hdr.rtm_flags & RTF_HOST || 241 !(rtm.hdr.rtm_flags & RTF_STATIC)) 242 { 243 /* Make us a link layer socket for the host gateway */ 244 memset(&su, 0, sizeof(su)); 245 su.sdl.sdl_len = sizeof(struct sockaddr_dl); 246 link_addr(iface->name, &su.sdl); 247 ADDSU(su); 248 } else 249 ADDADDR(gate); 250 251 if (rtm.hdr.rtm_addrs & RTA_NETMASK) { 252 /* Ensure that netmask is set correctly */ 253 memset(&su, 0, sizeof(su)); 254 su.sin.sin_family = AF_INET; 255 su.sin.sin_len = sizeof(su.sin); 256 memcpy(&su.sin.sin_addr, &net->s_addr, sizeof(su.sin.sin_addr)); 257 p = su.sa.sa_len + (char *)&su; 258 for (su.sa.sa_len = 0; p > (char *)&su;) 259 if (*--p != 0) { 260 su.sa.sa_len = 1 + p - (char *)&su; 261 break; 262 } 263 ADDSU(su); 264 } 265 266 if (rtm.hdr.rtm_addrs & RTA_IFA) 267 ADDADDR(&iface->addr); 268 269 rtm.hdr.rtm_msglen = l = bp - (char *)&rtm; 270 if (write(r_fd, &rtm, l) == -1) 271 retval = -1; 272 return retval; 273 } 274 275 int 276 open_link_socket(void) 277 { 278 int fd; 279 280 fd = socket(PF_ROUTE, SOCK_RAW, 0); 281 if (fd != -1) { 282 set_cloexec(fd); 283 set_nonblock(fd); 284 } 285 return fd; 286 } 287 288 static void 289 get_addrs(int type, char *cp, struct sockaddr **sa) 290 { 291 int i; 292 293 for (i = 0; i < RTAX_MAX; i++) { 294 if (type & (1 << i)) { 295 sa[i] = (struct sockaddr *)cp; 296 #ifdef DEBUG 297 printf ("got %d %d %s\n", i, sa[i]->sa_family, 298 inet_ntoa(((struct sockaddr_in *)sa[i])-> 299 sin_addr)); 300 #endif 301 ADVANCE(cp, sa[i]); 302 } else 303 sa[i] = NULL; 304 } 305 } 306 307 int 308 manage_link(int fd) 309 { 310 char *p, *e, *cp; 311 char ifname[IF_NAMESIZE]; 312 ssize_t bytes; 313 struct rt_msghdr *rtm; 314 struct if_announcemsghdr *ifan; 315 struct if_msghdr *ifm; 316 struct ifa_msghdr *ifam; 317 struct rt rt; 318 struct sockaddr *sa, *rti_info[RTAX_MAX]; 319 int len; 320 #ifdef RTM_CHGADDR 321 struct sockaddr_dl sdl; 322 unsigned char *hwaddr; 323 #endif 324 325 for (;;) { 326 if (ioctl(fd, FIONREAD, &len) == -1) 327 return -1; 328 if (link_buflen < len) { 329 p = realloc(link_buf, len); 330 if (p == NULL) 331 return -1; 332 link_buf = p; 333 link_buflen = len; 334 } 335 bytes = read(fd, link_buf, link_buflen); 336 if (bytes == -1) { 337 if (errno == EAGAIN) 338 return 0; 339 if (errno == EINTR) 340 continue; 341 return -1; 342 } 343 e = link_buf + bytes; 344 for (p = link_buf; p < e; p += rtm->rtm_msglen) { 345 rtm = (struct rt_msghdr *)(void *)p; 346 switch(rtm->rtm_type) { 347 #ifdef RTM_IFANNOUNCE 348 case RTM_IFANNOUNCE: 349 ifan = (struct if_announcemsghdr *)(void *)p; 350 switch(ifan->ifan_what) { 351 case IFAN_ARRIVAL: 352 handle_interface(1, ifan->ifan_name); 353 break; 354 case IFAN_DEPARTURE: 355 handle_interface(-1, ifan->ifan_name); 356 break; 357 } 358 break; 359 #endif 360 case RTM_IFINFO: 361 ifm = (struct if_msghdr *)(void *)p; 362 memset(ifname, 0, sizeof(ifname)); 363 if (if_indextoname(ifm->ifm_index, ifname)) 364 handle_interface(0, ifname); 365 break; 366 case RTM_DELETE: 367 if (!(rtm->rtm_addrs & RTA_DST) || 368 !(rtm->rtm_addrs & RTA_GATEWAY) || 369 !(rtm->rtm_addrs & RTA_NETMASK)) 370 break; 371 if (rtm->rtm_pid == getpid()) 372 break; 373 cp = (char *)(void *)(rtm + 1); 374 sa = (struct sockaddr *)(void *)cp; 375 if (sa->sa_family != AF_INET) 376 break; 377 get_addrs(rtm->rtm_addrs, cp, rti_info); 378 rt.iface = NULL; 379 rt.next = NULL; 380 COPYOUT(rt.dest, rti_info[RTAX_DST]); 381 COPYOUT(rt.net, rti_info[RTAX_NETMASK]); 382 COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]); 383 route_deleted(&rt); 384 break; 385 #ifdef RTM_CHGADDR 386 case RTM_CHGADDR: /* FALLTHROUGH */ 387 #endif 388 case RTM_DELADDR: /* FALLTHROUGH */ 389 case RTM_NEWADDR: 390 ifam = (struct ifa_msghdr *)(void *)p; 391 if (!if_indextoname(ifam->ifam_index, ifname)) 392 break; 393 cp = (char *)(void *)(ifam + 1); 394 get_addrs(ifam->ifam_addrs, cp, rti_info); 395 if (rti_info[RTAX_IFA] == NULL) 396 break; 397 switch (rti_info[RTAX_IFA]->sa_family) { 398 #ifdef RTM_CHGADDR 399 case AF_LINK: 400 if (rtm->rtm_type != RTM_CHGADDR) 401 break; 402 memcpy(&sdl, rti_info[RTAX_IFA], 403 rti_info[RTAX_IFA]->sa_len); 404 hwaddr = xmalloc(sdl.sdl_alen); 405 memcpy(hwaddr, LLADDR(&sdl), 406 sdl.sdl_alen); 407 handle_hwaddr(ifname, hwaddr, 408 sdl.sdl_alen); 409 break; 410 #endif 411 case AF_INET: 412 case 255: /* FIXME: Why 255? */ 413 COPYOUT(rt.dest, rti_info[RTAX_IFA]); 414 COPYOUT(rt.net, rti_info[RTAX_NETMASK]); 415 COPYOUT(rt.gate, rti_info[RTAX_BRD]); 416 handle_ifa(rtm->rtm_type, ifname, 417 &rt.dest, &rt.net, &rt.gate); 418 break; 419 } 420 break; 421 } 422 } 423 } 424 } 425