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 175 /* Forwards a packet on a specific interface */ 176 ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest, 177 struct iovec *iov, size_t iov_len, 178 const struct interface *iface) 179 { 180 /* Construct headers */ 181 uint8_t cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {0}; 182 struct msghdr msg = { 183 .msg_name = (void *) dest, 184 .msg_namelen = sizeof(*dest), 185 .msg_iov = iov, 186 .msg_iovlen = iov_len, 187 .msg_control = cmsg_buf, 188 .msg_controllen = sizeof(cmsg_buf), 189 .msg_flags = 0 190 }; 191 192 /* Set control data (define destination interface) */ 193 struct cmsghdr *chdr = CMSG_FIRSTHDR(&msg); 194 chdr->cmsg_level = IPPROTO_IPV6; 195 chdr->cmsg_type = IPV6_PKTINFO; 196 chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 197 struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(chdr); 198 pktinfo->ipi6_ifindex = iface->ifindex; 199 200 /* Also set scope ID if link-local */ 201 if (IN6_IS_ADDR_LINKLOCAL(&dest->sin6_addr) 202 || IN6_IS_ADDR_MC_LINKLOCAL(&dest->sin6_addr)) 203 dest->sin6_scope_id = iface->ifindex; 204 205 char ipbuf[INET6_ADDRSTRLEN]; 206 inet_ntop(AF_INET6, &dest->sin6_addr, ipbuf, sizeof(ipbuf)); 207 208 ssize_t sent = sendmsg(socket, &msg, MSG_DONTWAIT); 209 if (sent < 0) 210 syslog(LOG_ERR, "Failed to send to %s%%%s@%s (%m)", 211 ipbuf, iface->name, iface->ifname); 212 else 213 syslog(LOG_DEBUG, "Sent %zd bytes to %s%%%s@%s", 214 sent, ipbuf, iface->name, iface->ifname); 215 return sent; 216 } 217 218 219 static int odhcpd_get_linklocal_interface_address(int ifindex, struct in6_addr *lladdr) 220 { 221 int ret = -1; 222 struct sockaddr_in6 addr; 223 socklen_t alen = sizeof(addr); 224 int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 225 226 if (sock < 0) 227 return -1; 228 229 memset(&addr, 0, sizeof(addr)); 230 addr.sin6_family = AF_INET6; 231 inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &addr.sin6_addr); 232 addr.sin6_scope_id = ifindex; 233 234 if (!connect(sock, (struct sockaddr*)&addr, sizeof(addr)) && 235 !getsockname(sock, (struct sockaddr*)&addr, &alen)) { 236 *lladdr = addr.sin6_addr; 237 ret = 0; 238 } 239 240 close(sock); 241 return ret; 242 } 243 244 /* 245 * DNS address selection criteria order : 246 * - use IPv6 address with valid lifetime if none is yet selected 247 * - use IPv6 address with a preferred lifetime if the already selected IPv6 address is deprecated 248 * - use an IPv6 ULA address if the already selected IPv6 address is not an ULA address 249 * - use the IPv6 address with the longest preferred lifetime 250 */ 251 int odhcpd_get_interface_dns_addr(const struct interface *iface, struct in6_addr *addr) 252 { 253 time_t now = odhcpd_time(); 254 ssize_t m = -1; 255 256 if (!iface->dns_service) 257 return -1; 258 259 for (size_t i = 0; i < iface->addr6_len; ++i) { 260 if (iface->addr6[i].valid <= (uint32_t)now) 261 continue; 262 263 if (m < 0) { 264 m = i; 265 continue; 266 } 267 268 if (iface->addr6[m].preferred >= (uint32_t)now && 269 iface->addr6[i].preferred < (uint32_t)now) 270 continue; 271 272 if (IN6_IS_ADDR_ULA(&iface->addr6[i].addr.in6)) { 273 if (!IN6_IS_ADDR_ULA(&iface->addr6[m].addr.in6)) { 274 m = i; 275 continue; 276 } 277 } else if (IN6_IS_ADDR_ULA(&iface->addr6[m].addr.in6)) 278 continue; 279 280 if (iface->addr6[i].preferred > iface->addr6[m].preferred) 281 m = i; 282 } 283 284 if (m >= 0) { 285 *addr = iface->addr6[m].addr.in6; 286 return 0; 287 } 288 289 return odhcpd_get_linklocal_interface_address(iface->ifindex, addr); 290 } 291 292 struct interface* odhcpd_get_interface_by_index(int ifindex) 293 { 294 struct interface *iface; 295 296 avl_for_each_element(&interfaces, iface, avl) { 297 if (iface->ifindex == ifindex) 298 return iface; 299 } 300 301 return NULL; 302 } 303 304 /* Convenience function to receive and do basic validation of packets */ 305 static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int events) 306 { 307 struct odhcpd_event *e = container_of(u, struct odhcpd_event, uloop); 308 309 uint8_t data_buf[8192], cmsg_buf[128]; 310 union { 311 struct sockaddr_in6 in6; 312 struct sockaddr_in in; 313 struct sockaddr_ll ll; 314 struct sockaddr_nl nl; 315 } addr; 316 317 if (u->error) { 318 int ret = -1; 319 socklen_t ret_len = sizeof(ret); 320 321 u->error = false; 322 if (e->handle_error && getsockopt(u->fd, SOL_SOCKET, SO_ERROR, &ret, &ret_len) == 0) 323 e->handle_error(e, ret); 324 } 325 326 if (e->recv_msgs) { 327 e->recv_msgs(e); 328 return; 329 } 330 331 while (true) { 332 struct iovec iov = {data_buf, sizeof(data_buf)}; 333 struct msghdr msg = { 334 .msg_name = (void *) &addr, 335 .msg_namelen = sizeof(addr), 336 .msg_iov = &iov, 337 .msg_iovlen = 1, 338 .msg_control = cmsg_buf, 339 .msg_controllen = sizeof(cmsg_buf), 340 .msg_flags = 0 341 }; 342 343 ssize_t len = recvmsg(u->fd, &msg, MSG_DONTWAIT); 344 if (len < 0) { 345 if (errno == EAGAIN) 346 break; 347 else 348 continue; 349 } 350 351 352 /* Extract destination interface */ 353 int destiface = 0; 354 int *hlim = NULL; 355 void *dest = NULL; 356 struct in6_pktinfo *pktinfo; 357 struct in_pktinfo *pkt4info; 358 for (struct cmsghdr *ch = CMSG_FIRSTHDR(&msg); ch != NULL; ch = CMSG_NXTHDR(&msg, ch)) { 359 if (ch->cmsg_level == IPPROTO_IPV6 && 360 ch->cmsg_type == IPV6_PKTINFO) { 361 pktinfo = (struct in6_pktinfo*)CMSG_DATA(ch); 362 destiface = pktinfo->ipi6_ifindex; 363 dest = &pktinfo->ipi6_addr; 364 } else if (ch->cmsg_level == IPPROTO_IP && 365 ch->cmsg_type == IP_PKTINFO) { 366 pkt4info = (struct in_pktinfo*)CMSG_DATA(ch); 367 destiface = pkt4info->ipi_ifindex; 368 dest = &pkt4info->ipi_addr; 369 } else if (ch->cmsg_level == IPPROTO_IPV6 && 370 ch->cmsg_type == IPV6_HOPLIMIT) { 371 hlim = (int*)CMSG_DATA(ch); 372 } 373 } 374 375 /* Check hoplimit if received */ 376 if (hlim && *hlim != 255) 377 continue; 378 379 /* Detect interface for packet sockets */ 380 if (addr.ll.sll_family == AF_PACKET) 381 destiface = addr.ll.sll_ifindex; 382 383 char ipbuf[INET6_ADDRSTRLEN] = "kernel"; 384 if (addr.ll.sll_family == AF_PACKET && 385 len >= (ssize_t)sizeof(struct ip6_hdr)) 386 inet_ntop(AF_INET6, &data_buf[8], ipbuf, sizeof(ipbuf)); 387 else if (addr.in6.sin6_family == AF_INET6) 388 inet_ntop(AF_INET6, &addr.in6.sin6_addr, ipbuf, sizeof(ipbuf)); 389 else if (addr.in.sin_family == AF_INET) 390 inet_ntop(AF_INET, &addr.in.sin_addr, ipbuf, sizeof(ipbuf)); 391 392 /* From netlink */ 393 if (addr.nl.nl_family == AF_NETLINK) { 394 syslog(LOG_DEBUG, "Received %zd Bytes from %s%%netlink", len, 395 ipbuf); 396 e->handle_dgram(&addr, data_buf, len, NULL, dest); 397 return; 398 } else if (destiface != 0) { 399 struct interface *iface; 400 401 avl_for_each_element(&interfaces, iface, avl) { 402 if (iface->ifindex != destiface) 403 continue; 404 405 syslog(LOG_DEBUG, "Received %zd Bytes from %s%%%s@%s", len, 406 ipbuf, iface->name, iface->ifname); 407 408 e->handle_dgram(&addr, data_buf, len, iface, dest); 409 } 410 } 411 412 413 } 414 } 415 416 /* Register events for the multiplexer */ 417 int odhcpd_register(struct odhcpd_event *event) 418 { 419 event->uloop.cb = odhcpd_receive_packets; 420 return uloop_fd_add(&event->uloop, ULOOP_READ | 421 ((event->handle_error) ? ULOOP_ERROR_CB : 0)); 422 } 423 424 int odhcpd_deregister(struct odhcpd_event *event) 425 { 426 event->uloop.cb = NULL; 427 return uloop_fd_delete(&event->uloop); 428 } 429 430 void odhcpd_process(struct odhcpd_event *event) 431 { 432 odhcpd_receive_packets(&event->uloop, 0); 433 } 434 435 int odhcpd_urandom(void *data, size_t len) 436 { 437 return read(urandom_fd, data, len); 438 } 439 440 441 time_t odhcpd_time(void) 442 { 443 struct timespec ts; 444 clock_gettime(CLOCK_MONOTONIC, &ts); 445 return ts.tv_sec; 446 } 447 448 449 static const char hexdigits[] = "0123456789abcdef"; 450 static const int8_t hexvals[] = { 451 -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1, 452 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 453 -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 454 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 455 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 456 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 457 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 458 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 459 }; 460 461 ssize_t odhcpd_unhexlify(uint8_t *dst, size_t len, const char *src) 462 { 463 size_t c; 464 for (c = 0; c < len && src[0] && src[1]; ++c) { 465 int8_t x = (int8_t)*src++; 466 int8_t y = (int8_t)*src++; 467 if (x < 0 || (x = hexvals[x]) < 0 468 || y < 0 || (y = hexvals[y]) < 0) 469 return -1; 470 dst[c] = x << 4 | y; 471 while (((int8_t)*src) < 0 || 472 (*src && hexvals[(uint8_t)*src] < 0)) 473 src++; 474 } 475 476 return c; 477 } 478 479 480 void odhcpd_hexlify(char *dst, const uint8_t *src, size_t len) 481 { 482 for (size_t i = 0; i < len; ++i) { 483 *dst++ = hexdigits[src[i] >> 4]; 484 *dst++ = hexdigits[src[i] & 0x0f]; 485 } 486 *dst = 0; 487 } 488 489 const char *odhcpd_print_mac(const uint8_t *mac, const size_t len) 490 { 491 static char buf[32]; 492 493 snprintf(buf, sizeof(buf), "%02x", mac[0]); 494 for (size_t i = 1, j = 2; i < len && j < sizeof(buf); i++, j += 3) 495 snprintf(buf + j, sizeof(buf) - j, ":%02x", mac[i]); 496 497 return buf; 498 } 499 500 int odhcpd_bmemcmp(const void *av, const void *bv, size_t bits) 501 { 502 const uint8_t *a = av, *b = bv; 503 size_t bytes = bits / 8; 504 bits %= 8; 505 506 int res = memcmp(a, b, bytes); 507 if (res == 0 && bits > 0) 508 res = (a[bytes] >> (8 - bits)) - (b[bytes] >> (8 - bits)); 509 510 return res; 511 } 512 513 514 void odhcpd_bmemcpy(void *av, const void *bv, size_t bits) 515 { 516 uint8_t *a = av; 517 const uint8_t *b = bv; 518 519 size_t bytes = bits / 8; 520 bits %= 8; 521 memcpy(a, b, bytes); 522 523 if (bits > 0) { 524 uint8_t mask = (1 << (8 - bits)) - 1; 525 a[bytes] = (a[bytes] & mask) | ((~mask) & b[bytes]); 526 } 527 } 528 529 530 int odhcpd_netmask2bitlen(bool inet6, void *mask) 531 { 532 int bits; 533 struct in_addr *v4; 534 struct in6_addr *v6; 535 536 if (inet6) 537 for (bits = 0, v6 = mask; 538 bits < 128 && (v6->s6_addr[bits / 8] << (bits % 8)) & 128; 539 bits++); 540 else 541 for (bits = 0, v4 = mask; 542 bits < 32 && (ntohl(v4->s_addr) << bits) & 0x80000000; 543 bits++); 544 545 return bits; 546 } 547 548 bool odhcpd_bitlen2netmask(bool inet6, unsigned int bits, void *mask) 549 { 550 uint8_t b; 551 struct in_addr *v4; 552 struct in6_addr *v6; 553 554 if (inet6) 555 { 556 if (bits > 128) 557 return false; 558 559 v6 = mask; 560 561 for (unsigned int i = 0; i < sizeof(v6->s6_addr); i++) 562 { 563 b = (bits > 8) ? 8 : bits; 564 v6->s6_addr[i] = (uint8_t)(0xFF << (8 - b)); 565 bits -= b; 566 } 567 } 568 else 569 { 570 if (bits > 32) 571 return false; 572 573 v4 = mask; 574 v4->s_addr = bits ? htonl(~((1 << (32 - bits)) - 1)) : 0; 575 } 576 577 return true; 578 } 579 580 bool odhcpd_valid_hostname(const char *name) 581 { 582 #define MAX_LABEL 63 583 const char *c, *label, *label_end; 584 int label_sz = 0; 585 586 for (c = name, label_sz = 0, label = name, label_end = name + strcspn(name, ".") - 1; 587 *c && label_sz <= MAX_LABEL; c++) { 588 if ((*c >= '' && *c <= '9') || 589 (*c >= 'A' && *c <= 'Z') || 590 (*c >= 'a' && *c <= 'z')) { 591 label_sz++; 592 continue; 593 } 594 595 if ((*c == '_' || *c == '-') && c != label && c != label_end) { 596 label_sz++; 597 continue; 598 } 599 600 if (*c == '.') { 601 if (*(c + 1)) { 602 label = c + 1; 603 label_end = label + strcspn(label, ".") - 1; 604 label_sz = 0; 605 } 606 continue; 607 } 608 609 return false; 610 } 611 612 return (label_sz && label_sz <= MAX_LABEL ? true : false); 613 } 614
This page was automatically generated by LXR 0.3.1. • OpenWrt