1 /** 2 * Copyright (C) 2012-2013 Steven Barth <steven@midlink.org> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License v2 as published by 6 * the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15 #include <time.h> 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <stdio.h> 19 #include <resolv.h> 20 #include <getopt.h> 21 #include <stddef.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <unistd.h> 25 #include <signal.h> 26 #include <stdbool.h> 27 #include <syslog.h> 28 #include <alloca.h> 29 30 #include <arpa/inet.h> 31 #include <net/if.h> 32 #include <netinet/ip6.h> 33 #include <netpacket/packet.h> 34 #include <linux/netlink.h> 35 36 #include <sys/socket.h> 37 #include <sys/ioctl.h> 38 #include <sys/epoll.h> 39 #include <sys/types.h> 40 #include <sys/wait.h> 41 #include <sys/syscall.h> 42 43 #include <libubox/uloop.h> 44 #include "odhcpd.h" 45 46 static int ioctl_sock = -1; 47 static int urandom_fd = -1; 48 49 static void sighandler(_unused int signal) 50 { 51 uloop_end(); 52 } 53 54 static void print_usage(const char *app) 55 { 56 printf( 57 "== %s Usage ==\n\n" 58 " -h, --help Print this help\n" 59 " -l level Specify log level 0..7 (default %d)\n", 60 app, config.log_level 61 ); 62 } 63 64 static bool ipv6_enabled(void) 65 { 66 int fd = socket(AF_INET6, SOCK_DGRAM, 0); 67 68 if (fd < 0) 69 return false; 70 71 close(fd); 72 73 return true; 74 } 75 76 int main(int argc, char **argv) 77 { 78 openlog("odhcpd", LOG_PERROR | LOG_PID, LOG_DAEMON); 79 int opt; 80 81 while ((opt = getopt(argc, argv, "hl:")) != -1) { 82 switch (opt) { 83 case 'h': 84 print_usage(argv[0]); 85 return 0; 86 case 'l': 87 config.log_level = (atoi(optarg) & LOG_PRIMASK); 88 fprintf(stderr, "Log level set to %d\n", config.log_level); 89 break; 90 } 91 } 92 setlogmask(LOG_UPTO(config.log_level)); 93 uloop_init(); 94 95 if (getuid() != 0) { 96 syslog(LOG_ERR, "Must be run as root!"); 97 return 2; 98 } 99 100 ioctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 101 102 if (ioctl_sock < 0) 103 return 4; 104 105 if ((urandom_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) < 0) 106 return 4; 107 108 signal(SIGUSR1, SIG_IGN); 109 signal(SIGINT, sighandler); 110 signal(SIGTERM, sighandler); 111 112 if (netlink_init()) 113 return 4; 114 115 if (ipv6_enabled()) { 116 if (router_init()) 117 return 4; 118 119 if (dhcpv6_init()) 120 return 4; 121 122 if (ndp_init()) 123 return 4; 124 } 125 #ifndef DHCPV4_SUPPORT 126 else 127 return 4; 128 #else 129 if (dhcpv4_init()) 130 return 4; 131 #endif 132 133 odhcpd_run(); 134 return 0; 135 } 136 137 138 /* Read IPv6 MTU for interface */ 139 int odhcpd_get_interface_config(const char *ifname, const char *what) 140 { 141 char buf[64]; 142 143 snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/%s", ifname, what); 144 145 int fd = open(buf, O_RDONLY); 146 if (fd < 0) 147 return -1; 148 149 ssize_t len = read(fd, buf, sizeof(buf) - 1); 150 close(fd); 151 152 if (len < 0) 153 return -1; 154 155 buf[len] = 0; 156 return atoi(buf); 157 } 158 159 160 /* Read IPv6 MAC for interface */ 161 int odhcpd_get_mac(const struct interface *iface, uint8_t mac[6]) 162 { 163 struct ifreq ifr; 164 165 memset(&ifr, 0, sizeof(ifr)); 166 strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name) - 1); 167 if (ioctl(ioctl_sock, SIOCGIFHWADDR, &ifr) < 0) 168 return -1; 169 170 memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); 171 return 0; 172 } 173 174 int odhcpd_get_flags(const struct interface *iface) 175 { 176 struct ifreq ifr; 177 178 memset(&ifr, 0, sizeof(ifr)); 179 strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name) - 1); 180 if (ioctl(ioctl_sock, SIOCGIFFLAGS, &ifr) < 0) 181 return -1; 182 183 return ifr.ifr_flags; 184 } 185 186 187 /* Forwards a packet on a specific interface */ 188 ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest, 189 struct iovec *iov, size_t iov_len, 190 const struct interface *iface) 191 { 192 /* Construct headers */ 193 uint8_t cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {0}; 194 struct msghdr msg = { 195 .msg_name = (void *) dest, 196 .msg_namelen = sizeof(*dest), 197 .msg_iov = iov, 198 .msg_iovlen = iov_len, 199 .msg_control = cmsg_buf, 200 .msg_controllen = sizeof(cmsg_buf), 201 .msg_flags = 0 202 }; 203 204 /* Set control data (define destination interface) */ 205 struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg); 206 chdr->cmsg_level = IPPROTO_IPV6; 207 chdr->cmsg_type = IPV6_PKTINFO; 208 chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 209 struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(chdr); 210 pktinfo->ipi6_ifindex = iface->ifindex; 211 212 /* Also set scope ID if link-local */ 213 if (IN6_IS_ADDR_LINKLOCAL(&dest->sin6_addr) 214 || IN6_IS_ADDR_MC_LINKLOCAL(&dest->sin6_addr)) 215 dest->sin6_scope_id = iface->ifindex; 216 217 char ipbuf[INET6_ADDRSTRLEN]; 218 inet_ntop(AF_INET6, &dest->sin6_addr, ipbuf, sizeof(ipbuf)); 219 220 ssize_t sent = sendmsg(socket, &msg, MSG_DONTWAIT); 221 if (sent < 0) 222 syslog(LOG_ERR, "Failed to send to %s%%%s@%s (%m)", 223 ipbuf, iface->name, iface->ifname); 224 else 225 syslog(LOG_DEBUG, "Sent %zd bytes to %s%%%s@%s", 226 sent, ipbuf, iface->name, iface->ifname); 227 return sent; 228 } 229 230 231 static int odhcpd_get_linklocal_interface_address(int ifindex, struct in6_addr *lladdr) 232 { 233 int ret = -1; 234 struct sockaddr_in6 addr; 235 socklen_t alen = sizeof(addr); 236 int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 237 238 if (sock < 0) 239 return -1; 240 241 memset(&addr, 0, sizeof(addr)); 242 addr.sin6_family = AF_INET6; 243 inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &addr.sin6_addr); 244 addr.sin6_scope_id = ifindex; 245 246 if (!connect(sock, (struct sockaddr*)&addr, sizeof(addr)) && 247 !getsockname(sock, (struct sockaddr*)&addr, &alen)) { 248 *lladdr = addr.sin6_addr; 249 ret = 0; 250 } 251 252 close(sock); 253 return ret; 254 } 255 256 /* 257 * DNS address selection criteria order : 258 * - use IPv6 address with valid lifetime if none is yet selected 259 * - use IPv6 address with a preferred lifetime if the already selected IPv6 address is deprecated 260 * - use an IPv6 ULA address if the already selected IPv6 address is not an ULA address 261 * - use the IPv6 address with the longest preferred lifetime 262 */ 263 int odhcpd_get_interface_dns_addr(const struct interface *iface, struct in6_addr *addr) 264 { 265 time_t now = odhcpd_time(); 266 ssize_t m = -1; 267 268 if (!iface->dns_service) 269 return -1; 270 271 for (size_t i = 0; i < iface->addr6_len; ++i) { 272 if (iface->addr6[i].valid_lt <= (uint32_t)now) 273 continue; 274 275 if (m < 0) { 276 m = i; 277 continue; 278 } 279 280 if (iface->addr6[m].preferred_lt >= (uint32_t)now && 281 iface->addr6[i].preferred_lt < (uint32_t)now) 282 continue; 283 284 if (IN6_IS_ADDR_ULA(&iface->addr6[i].addr.in6)) { 285 if (!IN6_IS_ADDR_ULA(&iface->addr6[m].addr.in6)) { 286 m = i; 287 continue; 288 } 289 } else if (IN6_IS_ADDR_ULA(&iface->addr6[m].addr.in6)) 290 continue; 291 292 if (iface->addr6[i].preferred_lt > iface->addr6[m].preferred_lt) 293 m = i; 294 } 295 296 if (m >= 0) { 297 *addr = iface->addr6[m].addr.in6; 298 return 0; 299 } 300 301 return odhcpd_get_linklocal_interface_address(iface->ifindex, addr); 302 } 303 304 struct interface* odhcpd_get_interface_by_index(int ifindex) 305 { 306 struct interface *iface; 307 308 avl_for_each_element(&interfaces, iface, avl) { 309 if (iface->ifindex == ifindex) 310 return iface; 311 } 312 313 return NULL; 314 } 315 316 /* Convenience function to receive and do basic validation of packets */ 317 static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int events) 318 { 319 struct odhcpd_event *e = container_of(u, struct odhcpd_event, uloop); 320 321 uint8_t data_buf[8192], cmsg_buf[128]; 322 union { 323 struct sockaddr_in6 in6; 324 struct sockaddr_in in; 325 struct sockaddr_ll ll; 326 struct sockaddr_nl nl; 327 } addr; 328 329 if (u->error) { 330 int ret = -1; 331 socklen_t ret_len = sizeof(ret); 332 333 u->error = false; 334 if (e->handle_error && getsockopt(u->fd, SOL_SOCKET, SO_ERROR, &ret, &ret_len) == 0) 335 e->handle_error(e, ret); 336 } 337 338 if (e->recv_msgs) { 339 e->recv_msgs(e); 340 return; 341 } 342 343 while (true) { 344 struct iovec iov = {data_buf, sizeof(data_buf)}; 345 struct msghdr msg = { 346 .msg_name = (void *) &addr, 347 .msg_namelen = sizeof(addr), 348 .msg_iov = &iov, 349 .msg_iovlen = 1, 350 .msg_control = cmsg_buf, 351 .msg_controllen = sizeof(cmsg_buf), 352 .msg_flags = 0 353 }; 354 355 ssize_t len = recvmsg(u->fd, &msg, MSG_DONTWAIT); 356 if (len < 0) { 357 if (errno == EAGAIN) 358 break; 359 else 360 continue; 361 } 362 363 364 /* Extract destination interface */ 365 int destiface = 0; 366 int *hlim = NULL; 367 void *dest = NULL; 368 struct in6_pktinfo *pktinfo; 369 struct in_pktinfo *pkt4info; 370 for (struct cmsghdr *ch = CMSG_FIRSTHDR(&msg); ch != NULL; ch = CMSG_NXTHDR(&msg, ch)) { 371 if (ch->cmsg_level == IPPROTO_IPV6 && 372 ch->cmsg_type == IPV6_PKTINFO) { 373 pktinfo = (struct in6_pktinfo*)CMSG_DATA(ch); 374 destiface = pktinfo->ipi6_ifindex; 375 dest = &pktinfo->ipi6_addr; 376 } else if (ch->cmsg_level == IPPROTO_IP && 377 ch->cmsg_type == IP_PKTINFO) { 378 pkt4info = (struct in_pktinfo*)CMSG_DATA(ch); 379 destiface = pkt4info->ipi_ifindex; 380 dest = &pkt4info->ipi_addr; 381 } else if (ch->cmsg_level == IPPROTO_IPV6 && 382 ch->cmsg_type == IPV6_HOPLIMIT) { 383 hlim = (int*)CMSG_DATA(ch); 384 } 385 } 386 387 /* Check hoplimit if received */ 388 if (hlim && *hlim != 255) 389 continue; 390 391 /* Detect interface for packet sockets */ 392 if (addr.ll.sll_family == AF_PACKET) 393 destiface = addr.ll.sll_ifindex; 394 395 char ipbuf[INET6_ADDRSTRLEN] = "kernel"; 396 if (addr.ll.sll_family == AF_PACKET && 397 len >= (ssize_t)sizeof(struct ip6_hdr)) 398 inet_ntop(AF_INET6, &data_buf[8], ipbuf, sizeof(ipbuf)); 399 else if (addr.in6.sin6_family == AF_INET6) 400 inet_ntop(AF_INET6, &addr.in6.sin6_addr, ipbuf, sizeof(ipbuf)); 401 else if (addr.in.sin_family == AF_INET) 402 inet_ntop(AF_INET, &addr.in.sin_addr, ipbuf, sizeof(ipbuf)); 403 404 /* From netlink */ 405 if (addr.nl.nl_family == AF_NETLINK) { 406 syslog(LOG_DEBUG, "Received %zd Bytes from %s%%netlink", len, 407 ipbuf); 408 e->handle_dgram(&addr, data_buf, len, NULL, dest); 409 return; 410 } else if (destiface != 0) { 411 struct interface *iface; 412 413 avl_for_each_element(&interfaces, iface, avl) { 414 if (iface->ifindex != destiface) 415 continue; 416 417 syslog(LOG_DEBUG, "Received %zd Bytes from %s%%%s@%s", len, 418 ipbuf, iface->name, iface->ifname); 419 420 e->handle_dgram(&addr, data_buf, len, iface, dest); 421 } 422 } 423 424 425 } 426 } 427 428 /* Register events for the multiplexer */ 429 int odhcpd_register(struct odhcpd_event *event) 430 { 431 event->uloop.cb = odhcpd_receive_packets; 432 return uloop_fd_add(&event->uloop, ULOOP_READ | 433 ((event->handle_error) ? ULOOP_ERROR_CB : 0)); 434 } 435 436 int odhcpd_deregister(struct odhcpd_event *event) 437 { 438 event->uloop.cb = NULL; 439 return uloop_fd_delete(&event->uloop); 440 } 441 442 void odhcpd_process(struct odhcpd_event *event) 443 { 444 odhcpd_receive_packets(&event->uloop, 0); 445 } 446 447 int odhcpd_urandom(void *data, size_t len) 448 { 449 return read(urandom_fd, data, len); 450 } 451 452 453 time_t odhcpd_time(void) 454 { 455 struct timespec ts; 456 clock_gettime(CLOCK_MONOTONIC, &ts); 457 return ts.tv_sec; 458 } 459 460 461 static const char hexdigits[] = "0123456789abcdef"; 462 static const int8_t hexvals[] = { 463 -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, 464 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 465 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 466 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 467 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 468 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 469 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 470 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 471 }; 472 473 ssize_t odhcpd_unhexlify(uint8_t *dst, size_t len, const char *src) 474 { 475 size_t c; 476 for (c = 0; c < len && src[0] && src[1]; ++c) { 477 int8_t x = (int8_t)*src++; 478 int8_t y = (int8_t)*src++; 479 if (x < 0 || (x = hexvals[x]) < 0 480 || y < 0 || (y = hexvals[y]) < 0) 481 return -1; 482 dst[c] = x << 4 | y; 483 while (((int8_t)*src) < 0 || 484 (*src && hexvals[(uint8_t)*src] < 0)) 485 src++; 486 } 487 488 return c; 489 } 490 491 492 void odhcpd_hexlify(char *dst, const uint8_t *src, size_t len) 493 { 494 for (size_t i = 0; i < len; ++i) { 495 *dst++ = hexdigits[src[i] >> 4]; 496 *dst++ = hexdigits[src[i] & 0x0f]; 497 } 498 *dst = 0; 499 } 500 501 const char *odhcpd_print_mac(const uint8_t *mac, const size_t len) 502 { 503 static char buf[32]; 504 505 snprintf(buf, sizeof(buf), "%02x", mac[0]); 506 for (size_t i = 1, j = 2; i < len && j < sizeof(buf); i++, j += 3) 507 snprintf(buf + j, sizeof(buf) - j, ":%02x", mac[i]); 508 509 return buf; 510 } 511 512 int odhcpd_bmemcmp(const void *av, const void *bv, size_t bits) 513 { 514 const uint8_t *a = av, *b = bv; 515 size_t bytes = bits / 8; 516 bits %= 8; 517 518 int res = memcmp(a, b, bytes); 519 if (res == 0 && bits > 0) 520 res = (a[bytes] >> (8 - bits)) - (b[bytes] >> (8 - bits)); 521 522 return res; 523 } 524 525 526 void odhcpd_bmemcpy(void *av, const void *bv, size_t bits) 527 { 528 uint8_t *a = av; 529 const uint8_t *b = bv; 530 531 size_t bytes = bits / 8; 532 bits %= 8; 533 memcpy(a, b, bytes); 534 535 if (bits > 0) { 536 uint8_t mask = (1 << (8 - bits)) - 1; 537 a[bytes] = (a[bytes] & mask) | ((~mask) & b[bytes]); 538 } 539 } 540 541 542 int odhcpd_netmask2bitlen(bool inet6, void *mask) 543 { 544 int bits; 545 struct in_addr *v4; 546 struct in6_addr *v6; 547 548 if (inet6) 549 for (bits = 0, v6 = mask; 550 bits < 128 && (v6->s6_addr[bits / 8] << (bits % 8)) & 128; 551 bits++); 552 else 553 for (bits = 0, v4 = mask; 554 bits < 32 && (ntohl(v4->s_addr) << bits) & 0x80000000; 555 bits++); 556 557 return bits; 558 } 559 560 bool odhcpd_bitlen2netmask(bool inet6, unsigned int bits, void *mask) 561 { 562 uint8_t b; 563 struct in_addr *v4; 564 struct in6_addr *v6; 565 566 if (inet6) 567 { 568 if (bits > 128) 569 return false; 570 571 v6 = mask; 572 573 for (unsigned int i = 0; i < sizeof(v6->s6_addr); i++) 574 { 575 b = (bits > 8) ? 8 : bits; 576 v6->s6_addr[i] = (uint8_t)(0xFF << (8 - b)); 577 bits -= b; 578 } 579 } 580 else 581 { 582 if (bits > 32) 583 return false; 584 585 v4 = mask; 586 v4->s_addr = bits ? htonl(~((1 << (32 - bits)) - 1)) : 0; 587 } 588 589 return true; 590 } 591 592 bool odhcpd_valid_hostname(const char *name) 593 { 594 #define MAX_LABEL 63 595 const char *c, *label, *label_end; 596 int label_sz = 0; 597 598 for (c = name, label_sz = 0, label = name, label_end = name + strcspn(name, ".") - 1; 599 *c && label_sz <= MAX_LABEL; c++) { 600 if ((*c >= '' && *c <= '9') || 601 (*c >= 'A' && *c <= 'Z') || 602 (*c >= 'a' && *c <= 'z')) { 603 label_sz++; 604 continue; 605 } 606 607 if ((*c == '_' || *c == '-') && c != label && c != label_end) { 608 label_sz++; 609 continue; 610 } 611 612 if (*c == '.') { 613 if (*(c + 1)) { 614 label = c + 1; 615 label_end = label + strcspn(label, ".") - 1; 616 label_sz = 0; 617 } 618 continue; 619 } 620 621 return false; 622 } 623 624 return (label_sz && label_sz <= MAX_LABEL ? true : false); 625 } 626
This page was automatically generated by LXR 0.3.1. • OpenWrt