net.c revision 4c5a5fb53bccceff331bae70f748bf9b4609fe0a
1/* 2 * dhcpcd - DHCP client daemon 3 * Copyright 2006-2008 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/socket.h> 31#include <sys/time.h> 32 33#include <net/if.h> 34#include <net/if_arp.h> 35#include <arpa/inet.h> 36#include <netinet/in_systm.h> 37#ifdef __linux__ 38#include <netinet/ether.h> 39#include <netpacket/packet.h> 40#endif 41#include <netinet/in.h> 42#include <netinet/ip.h> 43#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */ 44#include <netinet/udp.h> 45#undef __FAVOR_BSD 46#ifdef SIOCGIFMEDIA 47#include <net/if_media.h> 48#endif 49#include <arpa/inet.h> 50#ifdef AF_LINK 51# include <net/if_dl.h> 52#endif 53 54#include <ctype.h> 55#include <errno.h> 56#include <stddef.h> 57#include <stdio.h> 58#include <stdlib.h> 59#include <string.h> 60#include <unistd.h> 61 62#include "config.h" 63#include "common.h" 64#include "dhcp.h" 65#include "logger.h" 66#include "net.h" 67#include "signals.h" 68 69int 70inet_ntocidr(struct in_addr address) 71{ 72 int cidr = 0; 73 uint32_t mask = htonl(address.s_addr); 74 75 while (mask) { 76 cidr++; 77 mask <<= 1; 78 } 79 80 return cidr; 81} 82 83int 84inet_cidrtoaddr(int cidr, struct in_addr *addr) 85{ 86 int ocets; 87 88 if (cidr < 0 || cidr > 32) { 89 errno = EINVAL; 90 return -1; 91 } 92 ocets = (cidr + 7) / 8; 93 94 addr->s_addr = 0; 95 if (ocets > 0) { 96 memset(&addr->s_addr, 255, (size_t)ocets - 1); 97 memset((unsigned char *)&addr->s_addr + (ocets - 1), 98 (256 - (1 << (32 - cidr) % 8)), 1); 99 } 100 101 return 0; 102} 103 104uint32_t 105get_netmask(uint32_t addr) 106{ 107 uint32_t dst; 108 109 if (addr == 0) 110 return 0; 111 112 dst = htonl(addr); 113 if (IN_CLASSA(dst)) 114 return ntohl(IN_CLASSA_NET); 115 if (IN_CLASSB (dst)) 116 return ntohl(IN_CLASSB_NET); 117 if (IN_CLASSC (dst)) 118 return ntohl(IN_CLASSC_NET); 119 120 return 0; 121} 122 123char * 124hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen) 125{ 126 static char buffer[(HWADDR_LEN * 3) + 1]; 127 char *p = buffer; 128 size_t i; 129 130 for (i = 0; i < hwlen && i < HWADDR_LEN; i++) { 131 if (i > 0) 132 *p ++= ':'; 133 p += snprintf(p, 3, "%.2x", hwaddr[i]); 134 } 135 136 *p ++= '\0'; 137 138 return buffer; 139} 140 141size_t 142hwaddr_aton(unsigned char *buffer, const char *addr) 143{ 144 char c[3]; 145 const char *p = addr; 146 unsigned char *bp = buffer; 147 size_t len = 0; 148 149 c[2] = '\0'; 150 while (*p) { 151 c[0] = *p++; 152 c[1] = *p++; 153 /* Ensure that digits are hex */ 154 if (isxdigit((unsigned char)c[0]) == 0 || 155 isxdigit((unsigned char)c[1]) == 0) 156 { 157 errno = EINVAL; 158 return 0; 159 } 160 /* We should have at least two entries 00:01 */ 161 if (len == 0 && *p == '\0') { 162 errno = EINVAL; 163 return 0; 164 } 165 /* Ensure that next data is EOL or a seperator with data */ 166 if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) { 167 errno = EINVAL; 168 return 0; 169 } 170 if (*p) 171 p++; 172 if (bp) 173 *bp++ = (unsigned char)strtol(c, NULL, 16); 174 len++; 175 } 176 return len; 177} 178 179int 180do_interface(const char *ifname, 181 _unused unsigned char *hwaddr, _unused size_t *hwlen, 182 struct in_addr *addr, struct in_addr *net, int get) 183{ 184 int s; 185 struct ifconf ifc; 186 int retval = 0, found = 0; 187 int len = 10 * sizeof(struct ifreq); 188 int lastlen = 0; 189 char *p; 190 union { 191 char *buffer; 192 struct ifreq *ifr; 193 } ifreqs; 194 struct sockaddr_in address; 195 struct ifreq *ifr; 196 struct sockaddr_in netmask; 197#ifdef AF_LINK 198 struct sockaddr_dl *sdl; 199#endif 200 201 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 202 return -1; 203 204 /* Not all implementations return the needed buffer size for 205 * SIOGIFCONF so we loop like so for all until it works */ 206 memset(&ifc, 0, sizeof(ifc)); 207 for (;;) { 208 ifc.ifc_len = len; 209 ifc.ifc_buf = xmalloc((size_t)len); 210 if (ioctl(s, SIOCGIFCONF, &ifc) == -1) { 211 if (errno != EINVAL || lastlen != 0) { 212 close(s); 213 free(ifc.ifc_buf); 214 return -1; 215 } 216 } else { 217 if (ifc.ifc_len == lastlen) 218 break; 219 lastlen = ifc.ifc_len; 220 } 221 222 free(ifc.ifc_buf); 223 ifc.ifc_buf = NULL; 224 len *= 2; 225 } 226 227 for (p = (char *)ifc.ifc_buf; p < (char *)ifc.ifc_buf + ifc.ifc_len;) { 228 /* Cast the ifc buffer to an ifreq cleanly */ 229 ifreqs.buffer = p; 230 ifr = ifreqs.ifr; 231 232#ifndef __linux__ 233 if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru)) 234 p += offsetof(struct ifreq, ifr_ifru) + 235 ifr->ifr_addr.sa_len; 236 else 237#endif 238 p += sizeof(*ifr); 239 240 if (strcmp(ifname, ifr->ifr_name) != 0) 241 continue; 242 243 found = 1; 244 245#ifdef AF_LINK 246 if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) { 247 sdl = xmalloc(ifr->ifr_addr.sa_len); 248 memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len); 249 *hwlen = sdl->sdl_alen; 250 memcpy(hwaddr, LLADDR(sdl), *hwlen); 251 free(sdl); 252 retval = 1; 253 break; 254 } 255#endif 256 257 if (ifr->ifr_addr.sa_family == AF_INET) { 258 memcpy(&address, &ifr->ifr_addr, sizeof(address)); 259 if (ioctl(s, SIOCGIFNETMASK, ifr) == -1) 260 continue; 261 memcpy(&netmask, &ifr->ifr_addr, sizeof(netmask)); 262 if (get) { 263 addr->s_addr = address.sin_addr.s_addr; 264 net->s_addr = netmask.sin_addr.s_addr; 265 retval = 1; 266 break; 267 } else { 268 if (address.sin_addr.s_addr == addr->s_addr && 269 (!net || 270 netmask.sin_addr.s_addr == net->s_addr)) 271 { 272 retval = 1; 273 break; 274 } 275 } 276 } 277 278 } 279 280 if (!found) 281 errno = ENXIO; 282 close(s); 283 free(ifc.ifc_buf); 284 return retval; 285} 286 287int 288up_interface(const char *ifname) 289{ 290 int s; 291 struct ifreq ifr; 292 int retval = -1; 293#ifdef __linux__ 294 char *p; 295#endif 296 297 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 298 return -1; 299 memset(&ifr, 0, sizeof(ifr)); 300 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 301#ifdef __linux__ 302 /* We can only bring the real interface up */ 303 if ((p = strchr(ifr.ifr_name, ':'))) 304 *p = '\0'; 305#endif 306 if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) { 307 if ((ifr.ifr_flags & IFF_UP)) 308 retval = 0; 309 else { 310 ifr.ifr_flags |= IFF_UP; 311 if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0) 312 retval = 0; 313 } 314 } 315 close(s); 316 return retval; 317} 318 319int 320carrier_status(const char *ifname) 321{ 322 int s; 323 struct ifreq ifr; 324 int retval = -1; 325#ifdef SIOCGIFMEDIA 326 struct ifmediareq ifmr; 327#endif 328#ifdef __linux__ 329 char *p; 330#endif 331 332 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 333 return -1; 334 memset(&ifr, 0, sizeof(ifr)); 335 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 336#ifdef __linux__ 337 /* We can only test the real interface up */ 338 if ((p = strchr(ifr.ifr_name, ':'))) 339 *p = '\0'; 340#endif 341 if ((retval = ioctl(s, SIOCGIFFLAGS, &ifr)) == 0) { 342 if (ifr.ifr_flags & IFF_UP && ifr.ifr_flags & IFF_RUNNING) 343 retval = 1; 344 else 345 retval = 0; 346 } 347 348#ifdef SIOCGIFMEDIA 349 if (retval == 1) { 350 memset(&ifmr, 0, sizeof(ifmr)); 351 strncpy(ifmr.ifm_name, ifr.ifr_name, sizeof(ifmr.ifm_name)); 352 if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 && 353 ifmr.ifm_status & IFM_AVALID) 354 { 355 if (!(ifmr.ifm_status & IFM_ACTIVE)) 356 retval = 0; 357 } 358 } 359#endif 360 close(s); 361 return retval; 362} 363 364struct interface * 365read_interface(const char *ifname, _unused int metric) 366{ 367 int s; 368 struct ifreq ifr; 369 struct interface *iface = NULL; 370 unsigned char *hwaddr = NULL; 371 size_t hwlen = 0; 372 sa_family_t family = 0; 373 374 memset(&ifr, 0, sizeof(ifr)); 375 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 376 377 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 378 return NULL; 379 380#ifdef __linux__ 381 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 382 if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) 383 goto eexit; 384 385 switch (ifr.ifr_hwaddr.sa_family) { 386 case ARPHRD_ETHER: 387 case ARPHRD_IEEE802: 388 hwlen = ETHER_ADDR_LEN; 389 break; 390 case ARPHRD_IEEE1394: 391 hwlen = EUI64_ADDR_LEN; 392 case ARPHRD_INFINIBAND: 393 hwlen = INFINIBAND_ADDR_LEN; 394 break; 395 } 396 397 hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN); 398 memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, hwlen); 399 family = ifr.ifr_hwaddr.sa_family; 400#else 401 ifr.ifr_metric = metric; 402 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 403 if (ioctl(s, SIOCSIFMETRIC, &ifr) == -1) 404 goto eexit; 405 406 hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN); 407 if (do_interface(ifname, hwaddr, &hwlen, NULL, NULL, 0) != 1) 408 goto eexit; 409 410 family = ARPHRD_ETHER; 411#endif 412 413 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 414 if (ioctl(s, SIOCGIFMTU, &ifr) == -1) 415 goto eexit; 416 417 /* Ensure that the MTU is big enough for DHCP */ 418 if (ifr.ifr_mtu < MTU_MIN) { 419 ifr.ifr_mtu = MTU_MIN; 420 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 421 if (ioctl(s, SIOCSIFMTU, &ifr) == -1) 422 goto eexit; 423 } 424 425 if (up_interface(ifname) != 0) 426 goto eexit; 427 428 iface = xzalloc(sizeof(*iface)); 429 strlcpy(iface->name, ifname, IF_NAMESIZE); 430 snprintf(iface->leasefile, PATH_MAX, LEASEFILE, ifname); 431 memcpy(&iface->hwaddr, hwaddr, hwlen); 432 iface->hwlen = hwlen; 433 434 iface->family = family; 435 iface->arpable = !(ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)); 436 437 /* 0 is a valid fd, so init to -1 */ 438 iface->raw_fd = -1; 439 iface->udp_fd = -1; 440 iface->arp_fd = -1; 441 iface->link_fd = -1; 442 443eexit: 444 close(s); 445 free(hwaddr); 446 return iface; 447} 448 449int 450do_mtu(const char *ifname, short int mtu) 451{ 452 struct ifreq ifr; 453 int r; 454 int s; 455 456 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 457 return -1; 458 459 memset(&ifr, 0, sizeof(ifr)); 460 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 461 ifr.ifr_mtu = mtu; 462 r = ioctl(s, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); 463 close(s); 464 if (r == -1) 465 return -1; 466 return ifr.ifr_mtu; 467} 468 469void 470free_routes(struct rt *routes) 471{ 472 struct rt *r; 473 474 while (routes) { 475 r = routes->next; 476 free(routes); 477 routes = r; 478 } 479} 480 481int 482open_udp_socket(struct interface *iface) 483{ 484 int s; 485 union sockunion { 486 struct sockaddr sa; 487 struct sockaddr_in sin; 488 } su; 489 int n; 490#ifdef SO_BINDTODEVICE 491 struct ifreq ifr; 492#endif 493 494 if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) 495 return -1; 496 497 n = 1; 498 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) 499 goto eexit; 500#ifdef SO_BINDTODEVICE 501 memset(&ifr, 0, sizeof(ifr)); 502 strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); 503 if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) 504 goto eexit; 505#endif 506 /* As we don't use this socket for receiving, set the 507 * receive buffer to 1 */ 508 n = 1; 509 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) 510 goto eexit; 511 memset(&su, 0, sizeof(su)); 512 su.sin.sin_family = AF_INET; 513 su.sin.sin_port = htons(DHCP_CLIENT_PORT); 514 su.sin.sin_addr.s_addr = iface->addr.s_addr; 515 if (bind(s, &su.sa, sizeof(su)) == -1) 516 goto eexit; 517 518 iface->udp_fd = s; 519 set_cloexec(s); 520 return 0; 521 522eexit: 523 close(s); 524 return -1; 525} 526 527ssize_t 528send_packet(const struct interface *iface, struct in_addr to, 529 const uint8_t *data, ssize_t len) 530{ 531 union sockunion { 532 struct sockaddr sa; 533 struct sockaddr_in sin; 534 } su; 535 536 memset(&su, 0, sizeof(su)); 537 su.sin.sin_family = AF_INET; 538 su.sin.sin_addr.s_addr = to.s_addr; 539 su.sin.sin_port = htons(DHCP_SERVER_PORT); 540 541 return sendto(iface->udp_fd, data, len, 0, &su.sa, sizeof(su)); 542} 543 544struct udp_dhcp_packet 545{ 546 struct ip ip; 547 struct udphdr udp; 548 struct dhcp_message dhcp; 549}; 550const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet); 551 552static uint16_t 553checksum(const void *data, uint16_t len) 554{ 555 const uint8_t *addr = data; 556 uint32_t sum = 0; 557 558 while (len > 1) { 559 sum += addr[0] * 256 + addr[1]; 560 addr += 2; 561 len -= 2; 562 } 563 564 if (len == 1) 565 sum += *addr * 256; 566 567 sum = (sum >> 16) + (sum & 0xffff); 568 sum += (sum >> 16); 569 570 sum = htons(sum); 571 572 return ~sum; 573} 574 575ssize_t 576make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length, 577 struct in_addr source, struct in_addr dest) 578{ 579 struct udp_dhcp_packet *udpp; 580 struct ip *ip; 581 struct udphdr *udp; 582 583 udpp = xzalloc(sizeof(*udpp)); 584 ip = &udpp->ip; 585 udp = &udpp->udp; 586 587 /* OK, this is important :) 588 * We copy the data to our packet and then create a small part of the 589 * ip structure and an invalid ip_len (basically udp length). 590 * We then fill the udp structure and put the checksum 591 * of the whole packet into the udp checksum. 592 * Finally we complete the ip structure and ip checksum. 593 * If we don't do the ordering like so then the udp checksum will be 594 * broken, so find another way of doing it! */ 595 596 memcpy(&udpp->dhcp, data, length); 597 598 ip->ip_p = IPPROTO_UDP; 599 ip->ip_src.s_addr = source.s_addr; 600 if (dest.s_addr == 0) 601 ip->ip_dst.s_addr = INADDR_BROADCAST; 602 else 603 ip->ip_dst.s_addr = dest.s_addr; 604 605 udp->uh_sport = htons(DHCP_CLIENT_PORT); 606 udp->uh_dport = htons(DHCP_SERVER_PORT); 607 udp->uh_ulen = htons(sizeof(*udp) + length); 608 ip->ip_len = udp->uh_ulen; 609 udp->uh_sum = checksum(udpp, sizeof(*udpp)); 610 611 ip->ip_v = IPVERSION; 612 ip->ip_hl = 5; 613 ip->ip_id = 0; 614 ip->ip_tos = IPTOS_LOWDELAY; 615 ip->ip_len = htons (sizeof(*ip) + sizeof(*udp) + length); 616 ip->ip_id = 0; 617 ip->ip_off = htons(IP_DF); /* Don't fragment */ 618 ip->ip_ttl = IPDEFTTL; 619 620 ip->ip_sum = checksum(ip, sizeof(*ip)); 621 622 *packet = (uint8_t *)udpp; 623 return sizeof(*ip) + sizeof(*udp) + length; 624} 625 626ssize_t 627get_udp_data(const uint8_t **data, const uint8_t *udp) 628{ 629 struct udp_dhcp_packet packet; 630 631 memcpy(&packet, udp, sizeof(packet)); 632 *data = udp + offsetof(struct udp_dhcp_packet, dhcp); 633 return ntohs(packet.ip.ip_len) - sizeof(packet.ip) - sizeof(packet.udp); 634} 635 636int 637valid_udp_packet(const uint8_t *data) 638{ 639 struct udp_dhcp_packet packet; 640 uint16_t bytes; 641 uint16_t ipsum; 642 uint16_t iplen; 643 uint16_t udpsum; 644 struct in_addr source; 645 struct in_addr dest; 646 int retval = 0; 647 648 memcpy(&packet, data, sizeof(packet)); 649 bytes = ntohs(packet.ip.ip_len); 650 ipsum = packet.ip.ip_sum; 651 iplen = packet.ip.ip_len; 652 udpsum = packet.udp.uh_sum; 653 654 if (0 != checksum(&packet.ip, sizeof(packet.ip))) { 655 errno = EINVAL; 656 return -1; 657 } 658 659 packet.ip.ip_sum = 0; 660 memcpy(&source, &packet.ip.ip_src, sizeof(packet.ip.ip_src)); 661 memcpy(&dest, &packet.ip.ip_dst, sizeof(packet.ip.ip_dst)); 662 memset(&packet.ip, 0, sizeof(packet.ip)); 663 packet.udp.uh_sum = 0; 664 665 packet.ip.ip_p = IPPROTO_UDP; 666 memcpy(&packet.ip.ip_src, &source, sizeof(packet.ip.ip_src)); 667 memcpy(&packet.ip.ip_dst, &dest, sizeof(packet.ip.ip_dst)); 668 packet.ip.ip_len = packet.udp.uh_ulen; 669 if (udpsum && udpsum != checksum(&packet, bytes)) { 670 errno = EINVAL; 671 retval = -1; 672 } 673 674 return retval; 675} 676 677int 678send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip) 679{ 680 struct arphdr *arp; 681 size_t arpsize; 682 uint8_t *p; 683 int retval; 684 685 arpsize = sizeof(*arp) + 2 * iface->hwlen + 2 * sizeof(sip); 686 arp = xmalloc(arpsize); 687 arp->ar_hrd = htons(iface->family); 688 arp->ar_pro = htons(ETHERTYPE_IP); 689 arp->ar_hln = iface->hwlen; 690 arp->ar_pln = sizeof(sip); 691 arp->ar_op = htons(op); 692 p = (uint8_t *)arp; 693 p += sizeof(*arp); 694 memcpy(p, iface->hwaddr, iface->hwlen); 695 p += iface->hwlen; 696 memcpy(p, &sip, sizeof(sip)); 697 p += sizeof(sip); 698 /* ARP requests should ignore this */ 699 retval = iface->hwlen; 700 while (retval--) 701 *p++ = '\0'; 702 memcpy(p, &tip, sizeof(tip)); 703 p += sizeof(tip); 704 retval = send_raw_packet(iface, ETHERTYPE_ARP, arp, arpsize); 705 free(arp); 706 return retval; 707} 708