1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2010 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/types.h> 29 #include <sys/ioctl.h> 30 #include <sys/param.h> 31 #include <sys/socket.h> 32 #include <sys/time.h> 33 34 #include <arpa/inet.h> 35 #include <net/if.h> 36 #include <net/if_arp.h> 37 #ifdef AF_LINK 38 # include <net/if_dl.h> 39 # include <net/if_types.h> 40 #endif 41 #include <netinet/in_systm.h> 42 #include <netinet/in.h> 43 #include <netinet/ip.h> 44 #define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */ 45 #include <netinet/udp.h> 46 #undef __FAVOR_BSD 47 #ifdef AF_PACKET 48 # include <netpacket/packet.h> 49 #endif 50 #ifdef SIOCGIFMEDIA 51 # include <net/if_media.h> 52 #endif 53 54 #include <ctype.h> 55 #include <errno.h> 56 #include <ifaddrs.h> 57 #include <fnmatch.h> 58 #include <stddef.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <unistd.h> 63 64 #include "common.h" 65 #include "dhcp.h" 66 #include "if-options.h" 67 #include "net.h" 68 69 #include <rump/rump_syscalls.h> 70 71 static char hwaddr_buffer[(HWADDR_LEN * 3) + 1]; 72 73 int socket_afnet = -1; 74 75 int 76 inet_ntocidr(struct in_addr address) 77 { 78 int cidr = 0; 79 uint32_t mask = htonl(address.s_addr); 80 81 while (mask) { 82 cidr++; 83 mask <<= 1; 84 } 85 return cidr; 86 } 87 88 int 89 inet_cidrtoaddr(int cidr, struct in_addr *addr) 90 { 91 int ocets; 92 93 if (cidr < 1 || cidr > 32) { 94 errno = EINVAL; 95 return -1; 96 } 97 ocets = (cidr + 7) / 8; 98 99 addr->s_addr = 0; 100 if (ocets > 0) { 101 memset(&addr->s_addr, 255, (size_t)ocets - 1); 102 memset((unsigned char *)&addr->s_addr + (ocets - 1), 103 (256 - (1 << (32 - cidr) % 8)), 1); 104 } 105 106 return 0; 107 } 108 109 uint32_t 110 get_netmask(uint32_t addr) 111 { 112 uint32_t dst; 113 114 if (addr == 0) 115 return 0; 116 117 dst = htonl(addr); 118 if (IN_CLASSA(dst)) 119 return ntohl(IN_CLASSA_NET); 120 if (IN_CLASSB(dst)) 121 return ntohl(IN_CLASSB_NET); 122 if (IN_CLASSC(dst)) 123 return ntohl(IN_CLASSC_NET); 124 125 return 0; 126 } 127 128 char * 129 hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen) 130 { 131 char *p = hwaddr_buffer; 132 size_t i; 133 134 for (i = 0; i < hwlen && i < HWADDR_LEN; i++) { 135 if (i > 0) 136 *p ++= ':'; 137 p += snprintf(p, 3, "%.2x", hwaddr[i]); 138 } 139 140 *p ++= '\0'; 141 142 return hwaddr_buffer; 143 } 144 145 size_t 146 hwaddr_aton(unsigned char *buffer, const char *addr) 147 { 148 char c[3]; 149 const char *p = addr; 150 unsigned char *bp = buffer; 151 size_t len = 0; 152 153 c[2] = '\0'; 154 while (*p) { 155 c[0] = *p++; 156 c[1] = *p++; 157 /* Ensure that digits are hex */ 158 if (isxdigit((unsigned char)c[0]) == 0 || 159 isxdigit((unsigned char)c[1]) == 0) 160 { 161 errno = EINVAL; 162 return 0; 163 } 164 /* We should have at least two entries 00:01 */ 165 if (len == 0 && *p == '\0') { 166 errno = EINVAL; 167 return 0; 168 } 169 /* Ensure that next data is EOL or a separator with data */ 170 if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) { 171 errno = EINVAL; 172 return 0; 173 } 174 if (*p) 175 p++; 176 if (bp) 177 *bp++ = (unsigned char)strtol(c, NULL, 16); 178 len++; 179 } 180 return len; 181 } 182 183 struct interface * 184 init_interface(const char *ifname) 185 { 186 struct ifreq ifr; 187 struct interface *iface = NULL; 188 189 memset(&ifr, 0, sizeof(ifr)); 190 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 191 if (rump_sys_ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1) 192 goto eexit; 193 194 iface = xzalloc(sizeof(*iface)); 195 strlcpy(iface->name, ifname, sizeof(iface->name)); 196 iface->flags = ifr.ifr_flags; 197 /* We reserve the 100 range for virtual interfaces, if and when 198 * we can work them out. */ 199 iface->metric = 200 + if_nametoindex(iface->name); 200 if (getifssid(ifname, iface->ssid) != -1) { 201 iface->wireless = 1; 202 iface->metric += 100; 203 } 204 205 if (rump_sys_ioctl(socket_afnet, SIOCGIFMTU, &ifr) == -1) 206 goto eexit; 207 /* Ensure that the MTU is big enough for DHCP */ 208 if (ifr.ifr_mtu < MTU_MIN) { 209 ifr.ifr_mtu = MTU_MIN; 210 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 211 if (rump_sys_ioctl(socket_afnet, SIOCSIFMTU, &ifr) == -1) 212 goto eexit; 213 } 214 215 /* 0 is a valid fd, so init to -1 */ 216 iface->raw_fd = -1; 217 iface->udp_fd = -1; 218 iface->arp_fd = -1; 219 goto exit; 220 221 eexit: 222 free(iface); 223 iface = NULL; 224 exit: 225 return iface; 226 } 227 228 int 229 carrier_status(struct interface *iface) 230 { 231 int ret; 232 struct ifreq ifr; 233 #ifdef SIOCGIFMEDIA 234 struct ifmediareq ifmr; 235 #endif 236 #ifdef __linux__ 237 char *p; 238 #endif 239 240 memset(&ifr, 0, sizeof(ifr)); 241 strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 242 #ifdef __linux__ 243 /* We can only test the real interface up */ 244 if ((p = strchr(ifr.ifr_name, ':'))) 245 *p = '\0'; 246 #endif 247 248 if (rump_sys_ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1) 249 return -1; 250 iface->flags = ifr.ifr_flags; 251 252 ret = -1; 253 #ifdef SIOCGIFMEDIA 254 memset(&ifmr, 0, sizeof(ifmr)); 255 strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name)); 256 if (rump_sys_ioctl(socket_afnet, SIOCGIFMEDIA, &ifmr) != -1 && 257 ifmr.ifm_status & IFM_AVALID) 258 ret = (ifmr.ifm_status & IFM_ACTIVE) ? 1 : 0; 259 #endif 260 if (ret == -1) 261 ret = (ifr.ifr_flags & IFF_RUNNING) ? 1 : 0; 262 return ret; 263 } 264 265 int 266 up_interface(struct interface *iface) 267 { 268 struct ifreq ifr; 269 int retval = -1; 270 #ifdef __linux__ 271 char *p; 272 #endif 273 274 memset(&ifr, 0, sizeof(ifr)); 275 strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 276 #ifdef __linux__ 277 /* We can only bring the real interface up */ 278 if ((p = strchr(ifr.ifr_name, ':'))) 279 *p = '\0'; 280 #endif 281 if (rump_sys_ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == 0) { 282 if ((ifr.ifr_flags & IFF_UP)) 283 retval = 0; 284 else { 285 ifr.ifr_flags |= IFF_UP; 286 if (rump_sys_ioctl(socket_afnet, SIOCSIFFLAGS, &ifr) == 0) 287 retval = 0; 288 } 289 iface->flags = ifr.ifr_flags; 290 } 291 return retval; 292 } 293 294 int 295 do_address(const char *ifname, 296 struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act) 297 { 298 struct ifaddrs *ifaddrs, *ifa; 299 const struct sockaddr_in *a, *n, *d; 300 int retval; 301 302 if (getifaddrs(&ifaddrs) == -1) 303 return -1; 304 305 retval = 0; 306 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 307 if (ifa->ifa_addr == NULL || 308 ifa->ifa_addr->sa_family != AF_INET || 309 strcmp(ifa->ifa_name, ifname) != 0) 310 continue; 311 a = (const struct sockaddr_in *)(void *)ifa->ifa_addr; 312 n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask; 313 if (ifa->ifa_flags & IFF_POINTOPOINT) 314 d = (const struct sockaddr_in *)(void *) 315 ifa->ifa_dstaddr; 316 else 317 d = NULL; 318 if (act == 1) { 319 addr->s_addr = a->sin_addr.s_addr; 320 net->s_addr = n->sin_addr.s_addr; 321 if (dst) { 322 if (ifa->ifa_flags & IFF_POINTOPOINT) 323 dst->s_addr = d->sin_addr.s_addr; 324 else 325 dst->s_addr = INADDR_ANY; 326 } 327 retval = 1; 328 break; 329 } 330 if (addr->s_addr == a->sin_addr.s_addr && 331 (net == NULL || net->s_addr == n->sin_addr.s_addr)) 332 { 333 retval = 1; 334 break; 335 } 336 } 337 freeifaddrs(ifaddrs); 338 return retval; 339 } 340 341 int 342 do_mtu(const char *ifname, short int mtu) 343 { 344 struct ifreq ifr; 345 int r; 346 347 memset(&ifr, 0, sizeof(ifr)); 348 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 349 ifr.ifr_mtu = mtu; 350 r = rump_sys_ioctl(socket_afnet, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 351 if (r == -1) 352 return -1; 353 return ifr.ifr_mtu; 354 } 355 356 void 357 free_routes(struct rt *routes) 358 { 359 struct rt *r; 360 361 while (routes) { 362 r = routes->next; 363 free(routes); 364 routes = r; 365 } 366 } 367 368 struct udp_dhcp_packet 369 { 370 struct ip ip; 371 struct udphdr udp; 372 struct dhcp_message dhcp; 373 }; 374 const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet); 375 376 static uint16_t 377 checksum(const void *data, uint16_t len) 378 { 379 const uint8_t *addr = data; 380 uint32_t sum = 0; 381 382 while (len > 1) { 383 sum += addr[0] * 256 + addr[1]; 384 addr += 2; 385 len -= 2; 386 } 387 388 if (len == 1) 389 sum += *addr * 256; 390 391 sum = (sum >> 16) + (sum & 0xffff); 392 sum += (sum >> 16); 393 394 sum = htons(sum); 395 396 return ~sum; 397 } 398 399 ssize_t 400 make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length, 401 struct in_addr source, struct in_addr dest) 402 { 403 struct udp_dhcp_packet *udpp; 404 struct ip *ip; 405 struct udphdr *udp; 406 407 udpp = xzalloc(sizeof(*udpp)); 408 ip = &udpp->ip; 409 udp = &udpp->udp; 410 411 /* OK, this is important :) 412 * We copy the data to our packet and then create a small part of the 413 * ip structure and an invalid ip_len (basically udp length). 414 * We then fill the udp structure and put the checksum 415 * of the whole packet into the udp checksum. 416 * Finally we complete the ip structure and ip checksum. 417 * If we don't do the ordering like so then the udp checksum will be 418 * broken, so find another way of doing it! */ 419 420 memcpy(&udpp->dhcp, data, length); 421 422 ip->ip_p = IPPROTO_UDP; 423 ip->ip_src.s_addr = source.s_addr; 424 if (dest.s_addr == 0) 425 ip->ip_dst.s_addr = INADDR_BROADCAST; 426 else 427 ip->ip_dst.s_addr = dest.s_addr; 428 429 udp->uh_sport = htons(DHCP_CLIENT_PORT); 430 udp->uh_dport = htons(DHCP_SERVER_PORT); 431 udp->uh_ulen = htons(sizeof(*udp) + length); 432 ip->ip_len = udp->uh_ulen; 433 udp->uh_sum = checksum(udpp, sizeof(*udpp)); 434 435 ip->ip_v = IPVERSION; 436 ip->ip_hl = sizeof(*ip) >> 2; 437 ip->ip_id = arc4random() & UINT16_MAX; 438 ip->ip_ttl = IPDEFTTL; 439 ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length); 440 ip->ip_sum = checksum(ip, sizeof(*ip)); 441 442 *packet = (uint8_t *)udpp; 443 return sizeof(*ip) + sizeof(*udp) + length; 444 } 445 446 ssize_t 447 get_udp_data(const uint8_t **data, const uint8_t *udp) 448 { 449 struct udp_dhcp_packet packet; 450 451 memcpy(&packet, udp, sizeof(packet)); 452 *data = udp + offsetof(struct udp_dhcp_packet, dhcp); 453 return ntohs(packet.ip.ip_len) - 454 sizeof(packet.ip) - 455 sizeof(packet.udp); 456 } 457 458 int 459 valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from) 460 { 461 struct udp_dhcp_packet packet; 462 uint16_t bytes, udpsum; 463 464 if (data_len < sizeof(packet.ip)) { 465 if (from) 466 from->s_addr = INADDR_ANY; 467 errno = EINVAL; 468 return -1; 469 } 470 memcpy(&packet, data, MIN(data_len, sizeof(packet))); 471 if (from) 472 from->s_addr = packet.ip.ip_src.s_addr; 473 if (data_len > sizeof(packet)) { 474 errno = EINVAL; 475 return -1; 476 } 477 if (checksum(&packet.ip, sizeof(packet.ip)) != 0) { 478 errno = EINVAL; 479 return -1; 480 } 481 482 bytes = ntohs(packet.ip.ip_len); 483 if (data_len < bytes) { 484 errno = EINVAL; 485 return -1; 486 } 487 udpsum = packet.udp.uh_sum; 488 packet.udp.uh_sum = 0; 489 packet.ip.ip_hl = 0; 490 packet.ip.ip_v = 0; 491 packet.ip.ip_tos = 0; 492 packet.ip.ip_len = packet.udp.uh_ulen; 493 packet.ip.ip_id = 0; 494 packet.ip.ip_off = 0; 495 packet.ip.ip_ttl = 0; 496 packet.ip.ip_sum = 0; 497 if (udpsum && checksum(&packet, bytes) != udpsum) { 498 errno = EINVAL; 499 return -1; 500 } 501 502 return 0; 503 } 504