ra.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /**
  2. * Copyright (C) 2012-2014 Steven Barth <steven@midlink.org>
  3. * Copyright (C) 2017-2018 Hans Dedecker <dedeckeh@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License v2 as published by
  7. * the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <stdio.h>
  18. #include <signal.h>
  19. #include <string.h>
  20. #include <stddef.h>
  21. #include <stdbool.h>
  22. #include <syslog.h>
  23. #include <unistd.h>
  24. #include <resolv.h>
  25. #include <alloca.h>
  26. #include <net/if.h>
  27. #include <arpa/inet.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/socket.h>
  30. #include <sys/types.h>
  31. #include <netinet/in.h>
  32. #include <netinet/icmp6.h>
  33. #include <linux/rtnetlink.h>
  34. #ifndef SOL_NETLINK
  35. #define SOL_NETLINK 270
  36. #endif
  37. #ifndef NETLINK_ADD_MEMBERSHIP
  38. #define NETLINK_ADD_MEMBERSHIP 1
  39. #endif
  40. #ifndef IFF_LOWER_UP
  41. #define IFF_LOWER_UP 0x10000
  42. #endif
  43. #include "odhcp6c.h"
  44. #include "ra.h"
  45. static bool nocarrier = false;
  46. static bool ptp_link = false;
  47. static int sock = -1, rtnl = -1;
  48. static int if_index = 0;
  49. static char if_name[IF_NAMESIZE] = {0};
  50. static volatile int rs_attempt = 0;
  51. static struct in6_addr lladdr = IN6ADDR_ANY_INIT;
  52. static unsigned int ra_options = 0;
  53. static unsigned int ra_holdoff_interval = 0;
  54. static int ra_hoplimit = 0;
  55. static int ra_mtu = 0;
  56. static int ra_reachable = 0;
  57. static int ra_retransmit = 0;
  58. struct {
  59. struct icmp6_hdr hdr;
  60. struct icmpv6_opt lladdr;
  61. } rs = {
  62. .hdr = {ND_ROUTER_SOLICIT, 0, 0, {{0}}},
  63. .lladdr = {ND_OPT_SOURCE_LINKADDR, 1, {0}},
  64. };
  65. static void ra_send_rs(int signal __attribute__((unused)));
  66. int ra_init(const char *ifname, const struct in6_addr *ifid,
  67. unsigned int options, unsigned int holdoff_interval)
  68. {
  69. struct ifreq ifr;
  70. ra_options = options;
  71. ra_holdoff_interval = holdoff_interval;
  72. const pid_t ourpid = getpid();
  73. sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, IPPROTO_ICMPV6);
  74. if (sock < 0)
  75. goto failure;
  76. memset(&ifr, 0, sizeof(ifr));
  77. strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
  78. if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0)
  79. goto failure;
  80. ptp_link = !!(ifr.ifr_flags & IFF_POINTOPOINT);
  81. memset(&ifr, 0, sizeof(ifr));
  82. strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
  83. if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
  84. goto failure;
  85. if_index = ifr.ifr_ifindex;
  86. lladdr = *ifid;
  87. rtnl = socket(AF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
  88. if (rtnl < 0)
  89. goto failure;
  90. struct sockaddr_nl rtnl_kernel = { .nl_family = AF_NETLINK };
  91. if (connect(rtnl, (const struct sockaddr*)&rtnl_kernel, sizeof(rtnl_kernel)) < 0)
  92. goto failure;
  93. int val = RTNLGRP_LINK;
  94. if (setsockopt(rtnl, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &val, sizeof(val)) < 0)
  95. goto failure;
  96. if (fcntl(rtnl, F_SETOWN, ourpid) < 0)
  97. goto failure;
  98. if (fcntl(rtnl, F_SETFL, fcntl(sock, F_GETFL) | O_ASYNC) < 0)
  99. goto failure;
  100. struct {
  101. struct nlmsghdr hdr;
  102. struct ifinfomsg ifi;
  103. } req = {
  104. .hdr = {sizeof(req), RTM_GETLINK, NLM_F_REQUEST, 1, 0},
  105. .ifi = {.ifi_index = if_index}
  106. };
  107. if (send(rtnl, &req, sizeof(req), 0) < 0)
  108. goto failure;
  109. ra_link_up();
  110. // Filter ICMPv6 package types
  111. struct icmp6_filter filt;
  112. ICMP6_FILTER_SETBLOCKALL(&filt);
  113. ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
  114. if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)) < 0)
  115. goto failure;
  116. // Bind to all-nodes
  117. struct ipv6_mreq an = {ALL_IPV6_NODES, if_index};
  118. if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &an, sizeof(an)) < 0)
  119. goto failure;
  120. // Let the kernel compute our checksums
  121. val = 2;
  122. if (setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val)) < 0)
  123. goto failure;
  124. // This is required by RFC 4861
  125. val = 255;
  126. if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val)) < 0)
  127. goto failure;
  128. // Receive multicast hops
  129. val = 1;
  130. if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &val, sizeof(val)) < 0)
  131. goto failure;
  132. // Bind to one device
  133. if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0)
  134. goto failure;
  135. // Add async-mode
  136. if (fcntl(sock, F_SETOWN, ourpid) < 0)
  137. goto failure;
  138. val = fcntl(sock, F_GETFL);
  139. if (val < 0)
  140. goto failure;
  141. if (fcntl(sock, F_SETFL, val | O_ASYNC) < 0)
  142. goto failure;
  143. // Send RS
  144. signal(SIGALRM, ra_send_rs);
  145. ra_send_rs(SIGALRM);
  146. return 0;
  147. failure:
  148. if (sock >= 0)
  149. close(sock);
  150. if (rtnl >= 0)
  151. close(rtnl);
  152. return -1;
  153. }
  154. static void ra_send_rs(int signal __attribute__((unused)))
  155. {
  156. const struct sockaddr_in6 dest = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
  157. const struct icmpv6_opt llnull = {ND_OPT_SOURCE_LINKADDR, 1, {0}};
  158. size_t len;
  159. if ((rs_attempt % 2 == 0) && memcmp(&rs.lladdr, &llnull, sizeof(llnull)))
  160. len = sizeof(rs);
  161. else
  162. len = sizeof(struct icmp6_hdr);
  163. if (sendto(sock, &rs, len, MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
  164. syslog(LOG_ERR, "Failed to send RS (%s)", strerror(errno));
  165. if (++rs_attempt <= 3)
  166. alarm(4);
  167. }
  168. static int16_t pref_to_priority(uint8_t flags)
  169. {
  170. flags = (flags >> 3) & 0x03;
  171. return (flags == 0x0) ? 512 : (flags == 0x1) ? 384 :
  172. (flags == 0x3) ? 640 : -1;
  173. }
  174. bool ra_link_up(void)
  175. {
  176. static bool firstcall = true;
  177. struct {
  178. struct nlmsghdr hdr;
  179. struct ifinfomsg msg;
  180. uint8_t pad[4000];
  181. } resp;
  182. bool ret = false;
  183. ssize_t read;
  184. do {
  185. read = recv(rtnl, &resp, sizeof(resp), MSG_DONTWAIT);
  186. if (read < 0 || !NLMSG_OK(&resp.hdr, (size_t)read) ||
  187. resp.hdr.nlmsg_type != RTM_NEWLINK ||
  188. resp.msg.ifi_index != if_index)
  189. continue;
  190. ssize_t alen = NLMSG_PAYLOAD(&resp.hdr, sizeof(resp.msg));
  191. for (struct rtattr *rta = (struct rtattr*)(resp.pad);
  192. RTA_OK(rta, alen); rta = RTA_NEXT(rta, alen)) {
  193. if (rta->rta_type == IFLA_ADDRESS &&
  194. RTA_PAYLOAD(rta) >= sizeof(rs.lladdr.data))
  195. memcpy(rs.lladdr.data, RTA_DATA(rta), sizeof(rs.lladdr.data));
  196. }
  197. bool hascarrier = resp.msg.ifi_flags & IFF_LOWER_UP;
  198. if (!firstcall && nocarrier != !hascarrier)
  199. ret = true;
  200. nocarrier = !hascarrier;
  201. firstcall = false;
  202. } while (read > 0);
  203. if (ret) {
  204. syslog(LOG_NOTICE, "carrier => %i event on %s", (int)!nocarrier, if_name);
  205. rs_attempt = 0;
  206. ra_send_rs(SIGALRM);
  207. }
  208. return ret;
  209. }
  210. static bool ra_icmpv6_valid(struct sockaddr_in6 *source, int hlim, uint8_t *data, size_t len)
  211. {
  212. struct icmp6_hdr *hdr = (struct icmp6_hdr*)data;
  213. struct icmpv6_opt *opt, *end = (struct icmpv6_opt*)&data[len];
  214. if (hlim != 255 || len < sizeof(*hdr) || hdr->icmp6_code)
  215. return false;
  216. switch (hdr->icmp6_type) {
  217. case ND_ROUTER_ADVERT:
  218. if (!IN6_IS_ADDR_LINKLOCAL(&source->sin6_addr))
  219. return false;
  220. opt = (struct icmpv6_opt*)((struct nd_router_advert*)data + 1);
  221. break;
  222. default:
  223. return false;
  224. }
  225. icmpv6_for_each_option(opt, opt, end)
  226. ;
  227. return opt == end;
  228. }
  229. static bool ra_set_hoplimit(int val)
  230. {
  231. if (val > 0 && val != ra_hoplimit) {
  232. ra_hoplimit = val;
  233. return true;
  234. }
  235. return false;
  236. }
  237. static bool ra_set_mtu(int val)
  238. {
  239. if (val >= 1280 && val <= 65535 && ra_mtu != val) {
  240. ra_mtu = val;
  241. return true;
  242. }
  243. return false;
  244. }
  245. static bool ra_set_reachable(int val)
  246. {
  247. if (val > 0 && val <= 3600000 && ra_reachable != val) {
  248. ra_reachable = val;
  249. return true;
  250. }
  251. return false;
  252. }
  253. static bool ra_set_retransmit(int val)
  254. {
  255. if (val > 0 && val <= 60000 && ra_retransmit != val) {
  256. ra_retransmit = val;
  257. return true;
  258. }
  259. return false;
  260. }
  261. int ra_get_hoplimit(void)
  262. {
  263. return ra_hoplimit;
  264. }
  265. int ra_get_mtu(void)
  266. {
  267. return ra_mtu;
  268. }
  269. int ra_get_reachable(void)
  270. {
  271. return ra_reachable;
  272. }
  273. int ra_get_retransmit(void)
  274. {
  275. return ra_retransmit;
  276. }
  277. bool ra_process(void)
  278. {
  279. bool found = false;
  280. bool changed = false;
  281. uint8_t buf[1500] _aligned(4);
  282. union {
  283. struct cmsghdr hdr;
  284. uint8_t buf[CMSG_SPACE(sizeof(int))];
  285. } cmsg_buf;
  286. struct nd_router_advert *adv = (struct nd_router_advert*)buf;
  287. struct odhcp6c_entry *entry = alloca(sizeof(*entry) + 256);
  288. const struct in6_addr any = IN6ADDR_ANY_INIT;
  289. memset(entry, 0, sizeof(*entry));
  290. if (IN6_IS_ADDR_UNSPECIFIED(&lladdr)) {
  291. struct sockaddr_in6 addr = {AF_INET6, 0, 0, ALL_IPV6_ROUTERS, if_index};
  292. socklen_t alen = sizeof(addr);
  293. int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
  294. if (sock >= 0) {
  295. if (!connect(sock, (struct sockaddr*)&addr, sizeof(addr)) &&
  296. !getsockname(sock, (struct sockaddr*)&addr, &alen))
  297. lladdr = addr.sin6_addr;
  298. close(sock);
  299. }
  300. }
  301. while (true) {
  302. struct sockaddr_in6 from;
  303. struct iovec iov = {buf, sizeof(buf)};
  304. struct msghdr msg = {
  305. .msg_name = (void *) &from,
  306. .msg_namelen = sizeof(from),
  307. .msg_iov = &iov,
  308. .msg_iovlen = 1,
  309. .msg_control = cmsg_buf.buf,
  310. .msg_controllen = sizeof(cmsg_buf),
  311. .msg_flags = 0
  312. };
  313. struct icmpv6_opt *opt;
  314. uint32_t router_valid;
  315. int hlim = 0;
  316. ssize_t len = recvmsg(sock, &msg, MSG_DONTWAIT);
  317. if (len <= 0)
  318. break;
  319. if (IN6_IS_ADDR_UNSPECIFIED(&lladdr))
  320. continue;
  321. for (struct cmsghdr *ch = CMSG_FIRSTHDR(&msg); ch != NULL;
  322. ch = CMSG_NXTHDR(&msg, ch))
  323. if (ch->cmsg_level == IPPROTO_IPV6 &&
  324. ch->cmsg_type == IPV6_HOPLIMIT)
  325. memcpy(&hlim, CMSG_DATA(ch), sizeof(hlim));
  326. if (!ra_icmpv6_valid(&from, hlim, buf, len))
  327. continue;
  328. if (!found) {
  329. odhcp6c_expire(false);
  330. found = true;
  331. }
  332. router_valid = ntohs(adv->nd_ra_router_lifetime);
  333. /* RFC4861 §6.3.7
  334. * Once the host sends a Router Solicitation, and receives a valid
  335. * Router Advertisement with a non-zero Router Lifetime, the host MUST
  336. * desist from sending additional solicitations on that interface
  337. * Moreover, a host SHOULD send at least one solicitation in the case
  338. * where an advertisement is received prior to having sent a solicitation.
  339. */
  340. if (rs_attempt > 0 && router_valid > 0) {
  341. alarm(0);
  342. rs_attempt = 0;
  343. }
  344. // Parse default route
  345. entry->target = any;
  346. entry->length = 0;
  347. entry->router = from.sin6_addr;
  348. entry->priority = pref_to_priority(adv->nd_ra_flags_reserved);
  349. if (entry->priority < 0)
  350. entry->priority = pref_to_priority(0);
  351. entry->valid = router_valid;
  352. entry->preferred = entry->valid;
  353. changed |= odhcp6c_update_entry(STATE_RA_ROUTE, entry,
  354. 0, ra_holdoff_interval);
  355. // Parse hoplimit
  356. changed |= ra_set_hoplimit(adv->nd_ra_curhoplimit);
  357. // Parse ND parameters
  358. changed |= ra_set_reachable(ntohl(adv->nd_ra_reachable));
  359. changed |= ra_set_retransmit(ntohl(adv->nd_ra_retransmit));
  360. // Evaluate options
  361. icmpv6_for_each_option(opt, &adv[1], &buf[len]) {
  362. if (opt->type == ND_OPT_MTU) {
  363. uint32_t *mtu = (uint32_t*)&opt->data[2];
  364. changed |= ra_set_mtu(ntohl(*mtu));
  365. } else if (opt->type == ND_OPT_ROUTE_INFORMATION && opt->len <= 3) {
  366. struct icmpv6_opt_route_info *ri = (struct icmpv6_opt_route_info *)opt;
  367. if (ri->prefix_len > 128) {
  368. continue;
  369. } else if (ri->prefix_len > 64) {
  370. if (ri->len < 2)
  371. continue;
  372. } else if (ri->prefix_len > 0) {
  373. if (ri->len < 1)
  374. continue;
  375. }
  376. entry->router = from.sin6_addr;
  377. entry->target = any;
  378. entry->priority = pref_to_priority(ri->flags);
  379. entry->length = ri->prefix_len;
  380. entry->valid = ntohl(ri->lifetime);
  381. memcpy(&entry->target, ri->prefix, (ri->len - 1) * 8);
  382. if (IN6_IS_ADDR_LINKLOCAL(&entry->target)
  383. || IN6_IS_ADDR_LOOPBACK(&entry->target)
  384. || IN6_IS_ADDR_MULTICAST(&entry->target))
  385. continue;
  386. if (entry->priority > 0)
  387. changed |= odhcp6c_update_entry(STATE_RA_ROUTE, entry,
  388. 0, ra_holdoff_interval);
  389. } else if (opt->type == ND_OPT_PREFIX_INFORMATION && opt->len == 4) {
  390. struct nd_opt_prefix_info *pinfo = (struct nd_opt_prefix_info*)opt;
  391. entry->router = any;
  392. entry->target = pinfo->nd_opt_pi_prefix;
  393. entry->priority = 256;
  394. entry->length = pinfo->nd_opt_pi_prefix_len;
  395. entry->valid = ntohl(pinfo->nd_opt_pi_valid_time);
  396. entry->preferred = ntohl(pinfo->nd_opt_pi_preferred_time);
  397. if (entry->length > 128 || IN6_IS_ADDR_LINKLOCAL(&entry->target)
  398. || IN6_IS_ADDR_LOOPBACK(&entry->target)
  399. || IN6_IS_ADDR_MULTICAST(&entry->target)
  400. || entry->valid < entry->preferred)
  401. continue;
  402. if ((pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) &&
  403. !ptp_link)
  404. changed |= odhcp6c_update_entry(STATE_RA_ROUTE, entry,
  405. 7200, ra_holdoff_interval);
  406. if (!(pinfo->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) ||
  407. pinfo->nd_opt_pi_prefix_len != 64)
  408. continue;
  409. entry->target.s6_addr32[2] = lladdr.s6_addr32[2];
  410. entry->target.s6_addr32[3] = lladdr.s6_addr32[3];
  411. changed |= odhcp6c_update_entry(STATE_RA_PREFIX, entry,
  412. 7200, ra_holdoff_interval);
  413. } else if (opt->type == ND_OPT_RECURSIVE_DNS && opt->len > 2) {
  414. entry->router = from.sin6_addr;
  415. entry->priority = 0;
  416. entry->length = 128;
  417. uint32_t *valid = (uint32_t*)&opt->data[2];
  418. entry->valid = ntohl(*valid);
  419. entry->preferred = 0;
  420. for (ssize_t i = 0; i < (opt->len - 1) / 2; ++i) {
  421. memcpy(&entry->target, &opt->data[6 + i * sizeof(entry->target)],
  422. sizeof(entry->target));
  423. changed |= odhcp6c_update_entry(STATE_RA_DNS, entry,
  424. 0, ra_holdoff_interval);
  425. }
  426. } else if (opt->type == ND_OPT_DNSSL && opt->len > 1) {
  427. uint32_t *valid = (uint32_t*)&opt->data[2];
  428. uint8_t *buf = &opt->data[6];
  429. uint8_t *end = &buf[(opt->len - 1) * 8];
  430. entry->router = from.sin6_addr;
  431. entry->valid = ntohl(*valid);
  432. while (buf < end) {
  433. int len = dn_expand(buf, end, buf, (char*)entry->auxtarget, 256);
  434. if (len < 1)
  435. break;
  436. buf = &buf[len];
  437. entry->auxlen = strlen((char*)entry->auxtarget);
  438. if (entry->auxlen == 0)
  439. continue;
  440. changed |= odhcp6c_update_entry(STATE_RA_SEARCH, entry,
  441. 0, ra_holdoff_interval);
  442. entry->auxlen = 0;
  443. }
  444. }
  445. }
  446. if (ra_options & RA_RDNSS_DEFAULT_LIFETIME) {
  447. int states[2] = {STATE_RA_DNS, STATE_RA_SEARCH};
  448. for (size_t i = 0; i < 2; ++i) {
  449. size_t ra_dns_len;
  450. uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len);
  451. for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start;
  452. (uint8_t*)c < &start[ra_dns_len] &&
  453. (uint8_t*)odhcp6c_next_entry(c) <= &start[ra_dns_len];
  454. c = odhcp6c_next_entry(c)) {
  455. if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) &&
  456. c->valid > router_valid)
  457. c->valid = router_valid;
  458. }
  459. }
  460. }
  461. }
  462. if (found)
  463. odhcp6c_expire(false);
  464. return found && changed;
  465. }