odhcpd.c 14 KB

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