1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2011 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/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 <syslog.h> 63 #include <unistd.h> 64 65 #include "config.h" 66 #include "common.h" 67 #include "dhcp.h" 68 #include "if-options.h" 69 #include "ipv6rs.h" 70 #include "net.h" 71 #include "signals.h" 72 73 static char hwaddr_buffer[(HWADDR_LEN * 3) + 1]; 74 75 int socket_afnet = -1; 76 77 #if defined(__FreeBSD__) && defined(DEBUG_MEMORY) 78 /* FreeBSD does not zero the struct, causing valgrind errors */ 79 unsigned int 80 if_nametoindex(const char *ifname) 81 { 82 struct ifreq ifr; 83 84 memset(&ifr, 0, sizeof(ifr)); 85 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 86 if (ioctl(socket_afnet, SIOCGIFINDEX, &ifr) != -1) 87 return ifr.ifr_index; 88 return 0; 89 } 90 #endif 91 92 int 93 inet_ntocidr(struct in_addr address) 94 { 95 int cidr = 0; 96 uint32_t mask = htonl(address.s_addr); 97 98 while (mask) { 99 cidr++; 100 mask <<= 1; 101 } 102 return cidr; 103 } 104 105 int 106 inet_cidrtoaddr(int cidr, struct in_addr *addr) 107 { 108 int ocets; 109 110 if (cidr < 1 || cidr > 32) { 111 errno = EINVAL; 112 return -1; 113 } 114 ocets = (cidr + 7) / 8; 115 116 addr->s_addr = 0; 117 if (ocets > 0) { 118 memset(&addr->s_addr, 255, (size_t)ocets - 1); 119 memset((unsigned char *)&addr->s_addr + (ocets - 1), 120 (256 - (1 << (32 - cidr) % 8)), 1); 121 } 122 123 return 0; 124 } 125 126 uint32_t 127 get_netmask(uint32_t addr) 128 { 129 uint32_t dst; 130 131 if (addr == 0) 132 return 0; 133 134 dst = htonl(addr); 135 if (IN_CLASSA(dst)) 136 return ntohl(IN_CLASSA_NET); 137 if (IN_CLASSB(dst)) 138 return ntohl(IN_CLASSB_NET); 139 if (IN_CLASSC(dst)) 140 return ntohl(IN_CLASSC_NET); 141 142 return 0; 143 } 144 145 char * 146 hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen) 147 { 148 char *p = hwaddr_buffer; 149 size_t i; 150 151 for (i = 0; i < hwlen && i < HWADDR_LEN; i++) { 152 if (i > 0) 153 *p ++= ':'; 154 p += snprintf(p, 3, "%.2x", hwaddr[i]); 155 } 156 157 *p ++= '\0'; 158 159 return hwaddr_buffer; 160 } 161 162 size_t 163 hwaddr_aton(unsigned char *buffer, const char *addr) 164 { 165 char c[3]; 166 const char *p = addr; 167 unsigned char *bp = buffer; 168 size_t len = 0; 169 170 c[2] = '\0'; 171 while (*p) { 172 c[0] = *p++; 173 c[1] = *p++; 174 /* Ensure that digits are hex */ 175 if (isxdigit((unsigned char)c[0]) == 0 || 176 isxdigit((unsigned char)c[1]) == 0) 177 { 178 errno = EINVAL; 179 return 0; 180 } 181 /* We should have at least two entries 00:01 */ 182 if (len == 0 && *p == '\0') { 183 errno = EINVAL; 184 return 0; 185 } 186 /* Ensure that next data is EOL or a seperator with data */ 187 if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) { 188 errno = EINVAL; 189 return 0; 190 } 191 if (*p) 192 p++; 193 if (bp) 194 *bp++ = (unsigned char)strtol(c, NULL, 16); 195 len++; 196 } 197 return len; 198 } 199 200 struct interface * 201 init_interface(const char *ifname) 202 { 203 struct ifreq ifr; 204 struct interface *iface = NULL; 205 206 memset(&ifr, 0, sizeof(ifr)); 207 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 208 if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1) 209 goto eexit; 210 211 iface = xzalloc(sizeof(*iface)); 212 strlcpy(iface->name, ifname, sizeof(iface->name)); 213 iface->flags = ifr.ifr_flags; 214 /* We reserve the 100 range for virtual interfaces, if and when 215 * we can work them out. */ 216 iface->metric = 200 + if_nametoindex(iface->name); 217 if (getifssid(ifname, iface->ssid) != -1) { 218 iface->wireless = 1; 219 iface->metric += 100; 220 } 221 222 if (ioctl(socket_afnet, SIOCGIFMTU, &ifr) == -1) 223 goto eexit; 224 /* Ensure that the MTU is big enough for DHCP */ 225 if (ifr.ifr_mtu < MTU_MIN) { 226 ifr.ifr_mtu = MTU_MIN; 227 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 228 if (ioctl(socket_afnet, SIOCSIFMTU, &ifr) == -1) 229 goto eexit; 230 } 231 232 snprintf(iface->leasefile, sizeof(iface->leasefile), 233 LEASEFILE, ifname); 234 /* 0 is a valid fd, so init to -1 */ 235 iface->raw_fd = -1; 236 iface->udp_fd = -1; 237 iface->arp_fd = -1; 238 goto exit; 239 240 eexit: 241 free(iface); 242 iface = NULL; 243 exit: 244 return iface; 245 } 246 247 void 248 free_interface(struct interface *iface) 249 { 250 if (!iface) 251 return; 252 ipv6rs_free(iface); 253 if (iface->state) { 254 free_options(iface->state->options); 255 free(iface->state->old); 256 free(iface->state->new); 257 free(iface->state->offer); 258 free(iface->state); 259 } 260 free(iface->buffer); 261 free(iface->clientid); 262 free(iface); 263 } 264 265 int 266 carrier_status(struct interface *iface) 267 { 268 int ret; 269 struct ifreq ifr; 270 #ifdef SIOCGIFMEDIA 271 struct ifmediareq ifmr; 272 #endif 273 #ifdef __linux__ 274 char *p; 275 #endif 276 277 memset(&ifr, 0, sizeof(ifr)); 278 strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 279 #ifdef __linux__ 280 /* We can only test the real interface up */ 281 if ((p = strchr(ifr.ifr_name, ':'))) 282 *p = '\0'; 283 #endif 284 285 if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == -1) 286 return -1; 287 iface->flags = ifr.ifr_flags; 288 289 ret = -1; 290 #ifdef SIOCGIFMEDIA 291 memset(&ifmr, 0, sizeof(ifmr)); 292 strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name)); 293 if (ioctl(socket_afnet, SIOCGIFMEDIA, &ifmr) != -1 && 294 ifmr.ifm_status & IFM_AVALID) 295 ret = (ifmr.ifm_status & IFM_ACTIVE) ? 1 : 0; 296 #endif 297 if (ret == -1) 298 ret = (ifr.ifr_flags & IFF_RUNNING) ? 1 : 0; 299 return ret; 300 } 301 302 int 303 up_interface(struct interface *iface) 304 { 305 struct ifreq ifr; 306 int retval = -1; 307 #ifdef __linux__ 308 char *p; 309 #endif 310 311 memset(&ifr, 0, sizeof(ifr)); 312 strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 313 #ifdef __linux__ 314 /* We can only bring the real interface up */ 315 if ((p = strchr(ifr.ifr_name, ':'))) 316 *p = '\0'; 317 #endif 318 if (ioctl(socket_afnet, SIOCGIFFLAGS, &ifr) == 0) { 319 if ((ifr.ifr_flags & IFF_UP)) 320 retval = 0; 321 else { 322 ifr.ifr_flags |= IFF_UP; 323 if (ioctl(socket_afnet, SIOCSIFFLAGS, &ifr) == 0) 324 retval = 0; 325 } 326 iface->flags = ifr.ifr_flags; 327 } 328 return retval; 329 } 330 331 struct interface * 332 discover_interfaces(int argc, char * const *argv) 333 { 334 struct ifaddrs *ifaddrs, *ifa; 335 char *p; 336 int i, sdl_type; 337 struct interface *ifp, *ifs, *ifl; 338 #ifdef __linux__ 339 char ifn[IF_NAMESIZE]; 340 #endif 341 #ifdef AF_LINK 342 const struct sockaddr_dl *sdl; 343 #ifdef IFLR_ACTIVE 344 struct if_laddrreq iflr; 345 int socket_aflink; 346 347 socket_aflink = socket(AF_LINK, SOCK_DGRAM, 0); 348 if (socket_aflink == -1) 349 return NULL; 350 memset(&iflr, 0, sizeof(iflr)); 351 #endif 352 #elif AF_PACKET 353 const struct sockaddr_ll *sll; 354 #endif 355 356 if (getifaddrs(&ifaddrs) == -1) 357 return NULL; 358 359 ifs = ifl = NULL; 360 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 361 if (ifa->ifa_addr != NULL) { 362 #ifdef AF_LINK 363 if (ifa->ifa_addr->sa_family != AF_LINK) 364 continue; 365 #elif AF_PACKET 366 if (ifa->ifa_addr->sa_family != AF_PACKET) 367 continue; 368 #endif 369 } 370 371 /* It's possible for an interface to have >1 AF_LINK. 372 * For our purposes, we use the first one. */ 373 for (ifp = ifs; ifp; ifp = ifp->next) 374 if (strcmp(ifp->name, ifa->ifa_name) == 0) 375 break; 376 if (ifp) 377 continue; 378 if (argc > 0) { 379 for (i = 0; i < argc; i++) { 380 #ifdef __linux__ 381 /* Check the real interface name */ 382 strlcpy(ifn, argv[i], sizeof(ifn)); 383 p = strchr(ifn, ':'); 384 if (p) 385 *p = '\0'; 386 if (strcmp(ifn, ifa->ifa_name) == 0) 387 break; 388 #else 389 if (strcmp(argv[i], ifa->ifa_name) == 0) 390 break; 391 #endif 392 } 393 if (i == argc) 394 continue; 395 p = argv[i]; 396 } else { 397 /* -1 means we're discovering against a specific 398 * interface, but we still need the below rules 399 * to apply. */ 400 if (argc == -1 && strcmp(argv[0], ifa->ifa_name) != 0) 401 continue; 402 for (i = 0; i < ifdc; i++) 403 if (!fnmatch(ifdv[i], ifa->ifa_name, 0)) 404 break; 405 if (i < ifdc) 406 continue; 407 for (i = 0; i < ifac; i++) 408 if (!fnmatch(ifav[i], ifa->ifa_name, 0)) 409 break; 410 if (ifac && i == ifac) 411 continue; 412 p = ifa->ifa_name; 413 } 414 if ((ifp = init_interface(p)) == NULL) 415 continue; 416 417 /* Bring the interface up if not already */ 418 if (!(ifp->flags & IFF_UP) 419 #ifdef SIOCGIFMEDIA 420 && carrier_status(ifp) != -1 421 #endif 422 ) 423 { 424 if (up_interface(ifp) == 0) 425 options |= DHCPCD_WAITUP; 426 else 427 syslog(LOG_ERR, "%s: up_interface: %m", ifp->name); 428 } 429 430 sdl_type = 0; 431 /* Don't allow loopback unless explicit */ 432 if (ifp->flags & IFF_LOOPBACK) { 433 if (argc == 0 && ifac == 0) { 434 free_interface(ifp); 435 continue; 436 } 437 } else if (ifa->ifa_addr != NULL) { 438 #ifdef AF_LINK 439 sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr; 440 441 #ifdef IFLR_ACTIVE 442 /* We need to check for active address */ 443 strlcpy(iflr.iflr_name, ifp->name, 444 sizeof(iflr.iflr_name)); 445 memcpy(&iflr.addr, ifa->ifa_addr, 446 MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr))); 447 iflr.flags = IFLR_PREFIX; 448 iflr.prefixlen = sdl->sdl_alen * NBBY; 449 if (ioctl(socket_aflink, SIOCGLIFADDR, &iflr) == -1 || 450 !(iflr.flags & IFLR_ACTIVE)) 451 { 452 free_interface(ifp); 453 continue; 454 } 455 #endif 456 457 sdl_type = sdl->sdl_type; 458 switch(sdl->sdl_type) { 459 case IFT_BRIDGE: /* FALLTHROUGH */ 460 case IFT_L2VLAN: /* FALLTHOUGH */ 461 case IFT_L3IPVLAN: /* FALLTHROUGH */ 462 case IFT_ETHER: 463 ifp->family = ARPHRD_ETHER; 464 break; 465 case IFT_IEEE1394: 466 ifp->family = ARPHRD_IEEE1394; 467 break; 468 #ifdef IFT_INFINIBAND 469 case IFT_INFINIBAND: 470 ifp->family = ARPHRD_INFINIBAND; 471 break; 472 #endif 473 } 474 ifp->hwlen = sdl->sdl_alen; 475 #ifndef CLLADDR 476 # define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen)) 477 #endif 478 memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen); 479 #elif AF_PACKET 480 sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr; 481 ifp->family = sdl_type = sll->sll_hatype; 482 ifp->hwlen = sll->sll_halen; 483 if (ifp->hwlen != 0) 484 memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen); 485 #endif 486 } 487 488 /* We only work on ethernet by default */ 489 if (!(ifp->flags & IFF_POINTOPOINT) && 490 ifp->family != ARPHRD_ETHER) 491 { 492 if (argc == 0 && ifac == 0) { 493 free_interface(ifp); 494 continue; 495 } 496 switch (ifp->family) { 497 case ARPHRD_IEEE1394: /* FALLTHROUGH */ 498 case ARPHRD_INFINIBAND: 499 /* We don't warn for supported families */ 500 break; 501 default: 502 syslog(LOG_WARNING, 503 "%s: unsupported interface type %.2x" 504 ", falling back to ethernet", 505 ifp->name, sdl_type); 506 ifp->family = ARPHRD_ETHER; 507 break; 508 } 509 } 510 511 /* Handle any platform init for the interface */ 512 if (if_init(ifp) == -1) { 513 syslog(LOG_ERR, "%s: if_init: %m", p); 514 free_interface(ifp); 515 continue; 516 } 517 518 if (ifl) 519 ifl->next = ifp; 520 else 521 ifs = ifp; 522 ifl = ifp; 523 } 524 freeifaddrs(ifaddrs); 525 526 #ifdef IFLR_ACTIVE 527 close(socket_aflink); 528 #endif 529 530 return ifs; 531 } 532 533 int 534 do_address(const char *ifname, 535 struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act) 536 { 537 struct ifaddrs *ifaddrs, *ifa; 538 const struct sockaddr_in *a, *n, *d; 539 int retval; 540 541 if (getifaddrs(&ifaddrs) == -1) 542 return -1; 543 544 retval = 0; 545 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 546 if (ifa->ifa_addr == NULL || 547 ifa->ifa_addr->sa_family != AF_INET || 548 strcmp(ifa->ifa_name, ifname) != 0) 549 continue; 550 a = (const struct sockaddr_in *)(void *)ifa->ifa_addr; 551 n = (const struct sockaddr_in *)(void *)ifa->ifa_netmask; 552 if (ifa->ifa_flags & IFF_POINTOPOINT) 553 d = (const struct sockaddr_in *)(void *) 554 ifa->ifa_dstaddr; 555 else 556 d = NULL; 557 if (act == 1) { 558 addr->s_addr = a->sin_addr.s_addr; 559 net->s_addr = n->sin_addr.s_addr; 560 if (dst) { 561 /* TODO: Fix getifaddrs() */ 562 if ((ifa->ifa_flags & IFF_POINTOPOINT) && d) 563 dst->s_addr = d->sin_addr.s_addr; 564 else 565 dst->s_addr = INADDR_ANY; 566 } 567 retval = 1; 568 break; 569 } 570 if (addr->s_addr == a->sin_addr.s_addr && 571 (net == NULL || net->s_addr == n->sin_addr.s_addr)) 572 { 573 retval = 1; 574 break; 575 } 576 } 577 freeifaddrs(ifaddrs); 578 return retval; 579 } 580 581 int 582 do_mtu(const char *ifname, short int mtu) 583 { 584 struct ifreq ifr; 585 int r; 586 587 memset(&ifr, 0, sizeof(ifr)); 588 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 589 ifr.ifr_mtu = mtu; 590 r = ioctl(socket_afnet, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 591 if (r == -1) 592 return -1; 593 return ifr.ifr_mtu; 594 } 595 596 void 597 free_routes(struct rt *routes) 598 { 599 struct rt *r; 600 601 while (routes) { 602 r = routes->next; 603 free(routes); 604 routes = r; 605 } 606 } 607 608 int 609 open_udp_socket(struct interface *iface) 610 { 611 int s; 612 struct sockaddr_in sin; 613 int n; 614 #ifdef SO_BINDTODEVICE 615 struct ifreq ifr; 616 char *p; 617 #endif 618 619 if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 620 return -1; 621 622 n = 1; 623 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) 624 goto eexit; 625 #ifdef SO_BINDTODEVICE 626 memset(&ifr, 0, sizeof(ifr)); 627 strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 628 /* We can only bind to the real device */ 629 p = strchr(ifr.ifr_name, ':'); 630 if (p) 631 *p = '\0'; 632 if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, 633 sizeof(ifr)) == -1) 634 goto eexit; 635 #endif 636 /* As we don't use this socket for receiving, set the 637 * receive buffer to 1 */ 638 n = 1; 639 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) 640 goto eexit; 641 memset(&sin, 0, sizeof(sin)); 642 sin.sin_family = AF_INET; 643 sin.sin_port = htons(DHCP_CLIENT_PORT); 644 sin.sin_addr.s_addr = iface->addr.s_addr; 645 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) 646 goto eexit; 647 648 iface->udp_fd = s; 649 set_cloexec(s); 650 return 0; 651 652 eexit: 653 close(s); 654 return -1; 655 } 656 657 ssize_t 658 send_packet(const struct interface *iface, struct in_addr to, 659 const uint8_t *data, ssize_t len) 660 { 661 struct sockaddr_in sin; 662 663 memset(&sin, 0, sizeof(sin)); 664 sin.sin_family = AF_INET; 665 sin.sin_addr.s_addr = to.s_addr; 666 sin.sin_port = htons(DHCP_SERVER_PORT); 667 return sendto(iface->udp_fd, data, len, 0, 668 (struct sockaddr *)&sin, sizeof(sin)); 669 } 670 671 struct udp_dhcp_packet 672 { 673 struct ip ip; 674 struct udphdr udp; 675 struct dhcp_message dhcp; 676 }; 677 const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet); 678 679 static uint16_t 680 checksum(const void *data, uint16_t len) 681 { 682 const uint8_t *addr = data; 683 uint32_t sum = 0; 684 685 while (len > 1) { 686 sum += addr[0] * 256 + addr[1]; 687 addr += 2; 688 len -= 2; 689 } 690 691 if (len == 1) 692 sum += *addr * 256; 693 694 sum = (sum >> 16) + (sum & 0xffff); 695 sum += (sum >> 16); 696 697 sum = htons(sum); 698 699 return ~sum; 700 } 701 702 ssize_t 703 make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length, 704 struct in_addr source, struct in_addr dest) 705 { 706 struct udp_dhcp_packet *udpp; 707 struct ip *ip; 708 struct udphdr *udp; 709 710 udpp = xzalloc(sizeof(*udpp)); 711 ip = &udpp->ip; 712 udp = &udpp->udp; 713 714 /* OK, this is important :) 715 * We copy the data to our packet and then create a small part of the 716 * ip structure and an invalid ip_len (basically udp length). 717 * We then fill the udp structure and put the checksum 718 * of the whole packet into the udp checksum. 719 * Finally we complete the ip structure and ip checksum. 720 * If we don't do the ordering like so then the udp checksum will be 721 * broken, so find another way of doing it! */ 722 723 memcpy(&udpp->dhcp, data, length); 724 725 ip->ip_p = IPPROTO_UDP; 726 ip->ip_src.s_addr = source.s_addr; 727 if (dest.s_addr == 0) 728 ip->ip_dst.s_addr = INADDR_BROADCAST; 729 else 730 ip->ip_dst.s_addr = dest.s_addr; 731 732 udp->uh_sport = htons(DHCP_CLIENT_PORT); 733 udp->uh_dport = htons(DHCP_SERVER_PORT); 734 udp->uh_ulen = htons(sizeof(*udp) + length); 735 ip->ip_len = udp->uh_ulen; 736 udp->uh_sum = checksum(udpp, sizeof(*udpp)); 737 738 ip->ip_v = IPVERSION; 739 ip->ip_hl = sizeof(*ip) >> 2; 740 ip->ip_id = arc4random() & UINT16_MAX; 741 ip->ip_ttl = IPDEFTTL; 742 ip->ip_len = htons(sizeof(*ip) + sizeof(*udp) + length); 743 ip->ip_sum = checksum(ip, sizeof(*ip)); 744 745 *packet = (uint8_t *)udpp; 746 return sizeof(*ip) + sizeof(*udp) + length; 747 } 748 749 ssize_t 750 get_udp_data(const uint8_t **data, const uint8_t *udp) 751 { 752 struct udp_dhcp_packet packet; 753 754 memcpy(&packet, udp, sizeof(packet)); 755 *data = udp + offsetof(struct udp_dhcp_packet, dhcp); 756 return ntohs(packet.ip.ip_len) - 757 sizeof(packet.ip) - 758 sizeof(packet.udp); 759 } 760 761 int 762 valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from, 763 int noudpcsum) 764 { 765 struct udp_dhcp_packet packet; 766 uint16_t bytes, udpsum; 767 768 if (data_len < sizeof(packet.ip)) { 769 if (from) 770 from->s_addr = INADDR_ANY; 771 errno = EINVAL; 772 return -1; 773 } 774 memcpy(&packet, data, MIN(data_len, sizeof(packet))); 775 if (from) 776 from->s_addr = packet.ip.ip_src.s_addr; 777 if (data_len > sizeof(packet)) { 778 errno = EINVAL; 779 return -1; 780 } 781 if (checksum(&packet.ip, sizeof(packet.ip)) != 0) { 782 errno = EINVAL; 783 return -1; 784 } 785 786 bytes = ntohs(packet.ip.ip_len); 787 if (data_len < bytes) { 788 errno = EINVAL; 789 return -1; 790 } 791 792 if (noudpcsum == 0) { 793 udpsum = packet.udp.uh_sum; 794 packet.udp.uh_sum = 0; 795 packet.ip.ip_hl = 0; 796 packet.ip.ip_v = 0; 797 packet.ip.ip_tos = 0; 798 packet.ip.ip_len = packet.udp.uh_ulen; 799 packet.ip.ip_id = 0; 800 packet.ip.ip_off = 0; 801 packet.ip.ip_ttl = 0; 802 packet.ip.ip_sum = 0; 803 if (udpsum && checksum(&packet, bytes) != udpsum) { 804 errno = EINVAL; 805 return -1; 806 } 807 } 808 809 return 0; 810 } 811