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