Home | History | Annotate | Line # | Download | only in ServiceRegistration
      1 /* icmp.c
      2  *
      3  * Copyright (c) 2019-2023 Apple Inc. All rights reserved.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     https://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  * This code implements ICMP I/O functions for the Thread border router.
     18  */
     19 
     20 #ifndef LINUX
     21 #include <netinet/in.h>
     22 #include <net/if.h>
     23 #include <netinet6/in6_var.h>
     24 #include <netinet6/nd6.h>
     25 #include <net/if_media.h>
     26 #include <sys/stat.h>
     27 #else
     28 #define _GNU_SOURCE
     29 #include <netinet/in.h>
     30 #include <fcntl.h>
     31 #include <bsd/stdlib.h>
     32 #include <net/if.h>
     33 #endif
     34 #include <sys/socket.h>
     35 #include <sys/ioctl.h>
     36 #include <net/route.h>
     37 #include <netinet/icmp6.h>
     38 #include <stdio.h>
     39 #include <unistd.h>
     40 #include <errno.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <ctype.h>
     44 #include <arpa/inet.h>
     45 #if !USE_SYSCTL_COMMAND_TO_ENABLE_FORWARDING
     46 #ifndef LINUX
     47 #include <sys/sysctl.h>
     48 #endif // LINUX
     49 #endif // !USE_SYSCTL_COMMAND_TO_ENABLE_FORWARDING
     50 #include <stdlib.h>
     51 #include <stddef.h>
     52 #include <dns_sd.h>
     53 #include <inttypes.h>
     54 #include <signal.h>
     55 
     56 #ifdef IOLOOP_MACOS
     57 #include <xpc/xpc.h>
     58 
     59 #include <TargetConditionals.h>
     60 #include <SystemConfiguration/SystemConfiguration.h>
     61 #include <SystemConfiguration/SCPrivate.h>
     62 #include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
     63 #include <SystemConfiguration/SCNetworkSignature.h>
     64 #include <network_information.h>
     65 
     66 #include <CoreUtils/CoreUtils.h>
     67 #endif // IOLOOP_MACOS
     68 
     69 #include "srp.h"
     70 #include "dns-msg.h"
     71 #include "ioloop.h"
     72 #include "cti-services.h"
     73 #include "srp-mdns-proxy.h"
     74 #include "route.h"
     75 #include "icmp.h"
     76 #include "state-machine.h"
     77 #include "thread-service.h"
     78 #include "omr-watcher.h"
     79 
     80 
     81 icmp_listener_t icmp_listener;
     82 
     83 void
     84 icmp_message_free(icmp_message_t *message)
     85 {
     86     if (message->options != NULL) {
     87         free(message->options);
     88     }
     89     if (message->wakeup != NULL) {
     90         ioloop_cancel_wake_event(message->wakeup);
     91         ioloop_wakeup_release(message->wakeup);
     92     }
     93     free(message);
     94 }
     95 
     96 void
     97 icmp_message_dump(icmp_message_t *message,
     98                   struct in6_addr *source_address, struct in6_addr *destination_address)
     99 {
    100     link_layer_address_t *lladdr;
    101     prefix_information_t *prefix_info;
    102     route_information_t *route_info;
    103     uint8_t *flags;
    104     int i;
    105     char retransmission_timer_buf[11]; // Maximum size of a uint32_t printed as decimal.
    106     char *retransmission_timer = "infinite";
    107 
    108     if (message->retransmission_timer != ND6_INFINITE_LIFETIME) {
    109         snprintf(retransmission_timer_buf, sizeof(retransmission_timer_buf), "%" PRIu32, message->retransmission_timer);
    110         retransmission_timer = retransmission_timer_buf;
    111     }
    112 
    113     SEGMENTED_IPv6_ADDR_GEN_SRP(source_address->s6_addr, src_addr_buf);
    114     SEGMENTED_IPv6_ADDR_GEN_SRP(destination_address->s6_addr, dst_addr_buf);
    115     if (message->type == icmp_type_router_advertisement) {
    116         INFO("router advertisement from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP
    117              " hop_limit %d on " PUB_S_SRP ": checksum = %x "
    118              "cur_hop_limit = %d flags = %x router_lifetime = %d reachable_time = %" PRIu32
    119              " retransmission_timer = " PUB_S_SRP,
    120              SEGMENTED_IPv6_ADDR_PARAM_SRP(source_address->s6_addr, src_addr_buf),
    121              SEGMENTED_IPv6_ADDR_PARAM_SRP(destination_address->s6_addr, dst_addr_buf),
    122              message->hop_limit, message->interface->name, message->checksum, message->cur_hop_limit, message->flags,
    123              message->router_lifetime, message->reachable_time, retransmission_timer);
    124     } else if (message->type == icmp_type_router_solicitation) {
    125         INFO("router solicitation from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP
    126              " hop_limit %d on " PUB_S_SRP ": code = %d checksum = %x",
    127              SEGMENTED_IPv6_ADDR_PARAM_SRP(source_address->s6_addr, src_addr_buf),
    128              SEGMENTED_IPv6_ADDR_PARAM_SRP(destination_address->s6_addr, dst_addr_buf),
    129              message->hop_limit, message->interface->name,
    130              message->code, message->checksum);
    131     } else {
    132         INFO("icmp message from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP " hop_limit %d on "
    133              PUB_S_SRP ": type = %d code = %d checksum = %x",
    134              SEGMENTED_IPv6_ADDR_PARAM_SRP(source_address->s6_addr, src_addr_buf),
    135              SEGMENTED_IPv6_ADDR_PARAM_SRP(destination_address->s6_addr, dst_addr_buf),
    136              message->hop_limit, message->interface->name, message->type,
    137              message->code, message->checksum);
    138     }
    139 
    140     for (i = 0; i < message->num_options; i++) {
    141         icmp_option_t *option = &message->options[i];
    142         switch(option->type) {
    143         case icmp_option_source_link_layer_address:
    144             lladdr = &option->option.link_layer_address;
    145             INFO("  source link layer address " PRI_MAC_ADDR_SRP, MAC_ADDR_PARAM_SRP(lladdr->address));
    146             break;
    147         case icmp_option_target_link_layer_address:
    148             lladdr = &option->option.link_layer_address;
    149             INFO("  destination link layer address " PRI_MAC_ADDR_SRP, MAC_ADDR_PARAM_SRP(lladdr->address));
    150             break;
    151         case icmp_option_prefix_information:
    152             prefix_info = &option->option.prefix_information;
    153             SEGMENTED_IPv6_ADDR_GEN_SRP(prefix_info->prefix.s6_addr, prefix_buf);
    154             INFO("  prefix info: " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d %x %" PRIu32 " %" PRIu32,
    155                  SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix_info->prefix.s6_addr, prefix_buf), prefix_info->length,
    156                  prefix_info->flags, prefix_info->valid_lifetime, prefix_info->preferred_lifetime);
    157             break;
    158         case icmp_option_route_information:
    159             route_info = &option->option.route_information;
    160                 SEGMENTED_IPv6_ADDR_GEN_SRP(route_info->prefix.s6_addr, router_prefix_buf);
    161             INFO("  route info: " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d %x %d",
    162                  SEGMENTED_IPv6_ADDR_PARAM_SRP(route_info->prefix.s6_addr, router_prefix_buf), route_info->length,
    163                  route_info->flags, route_info->route_lifetime);
    164             break;
    165         case icmp_option_ra_flags_extension:
    166             flags = option->option.ra_flags_extension;
    167             INFO("  ra flags extension: %x %x %x %x %x %x", flags[0], flags[1], flags[2], flags[3], flags[4], flags[5]);
    168             break;
    169         default:
    170             INFO("  option type %d", option->type);
    171             break;
    172         }
    173     }
    174 }
    175 
    176 static bool
    177 icmp_message_parse_options(icmp_message_t *message, uint8_t *icmp_buf, unsigned length, unsigned *offset)
    178 {
    179     uint8_t option_type, option_length_8;
    180     unsigned option_length;
    181     unsigned scan_offset = *offset;
    182     icmp_option_t *option;
    183     uint32_t reserved32;
    184     prefix_information_t *prefix_information;
    185     route_information_t *route_information;
    186 
    187     int prefix_bytes;
    188 
    189     // Count the options and validate the lengths
    190     message->num_options = 0;
    191     while (scan_offset < length) {
    192         if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_type)) {
    193             return false;
    194         }
    195         if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_length_8)) {
    196             return false;
    197         }
    198         if (option_length_8 == 0) { // RFC4191 section 4.6: The value 0 is invalid.
    199             ERROR("icmp_option_parse: option type %d length 0 is invalid.", option_type);
    200             return false;
    201         }
    202         if (scan_offset + option_length_8 * 8 - 2 > length) {
    203             ERROR("icmp_option_parse: option type %d length %d is longer than remaining available space %u",
    204                   option_type, option_length_8 * 8, length - scan_offset + 2);
    205             return false;
    206         }
    207         scan_offset += option_length_8 * 8 - 2;
    208         message->num_options++;
    209     }
    210     // If there are no options, we're done. No options is valid, so return true.
    211     if (message->num_options == 0) {
    212         return true;
    213     }
    214     message->options = calloc(message->num_options, sizeof(*message->options));
    215     if (message->options == NULL) {
    216         ERROR("No memory for icmp options.");
    217         return false;
    218     }
    219     option = message->options;
    220     while (*offset < length) {
    221         scan_offset = *offset;
    222         if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_type)) {
    223             return false;
    224         }
    225         if (!dns_u8_parse(icmp_buf, length, &scan_offset, &option_length_8)) {
    226             return false;
    227         }
    228         // We already validated the length in the previous pass.
    229         option->type = option_type;
    230         option_length = option_length_8 * 8;
    231 
    232         switch(option_type) {
    233         case icmp_option_source_link_layer_address:
    234         case icmp_option_target_link_layer_address:
    235             // At this juncture we are assuming that everything we care about looks like an
    236             // ethernet interface.  So for this case, length should be 8.
    237             if (option_length != 8) {
    238                 INFO("Ignoring unexpectedly long link layer address: %d", option_length);
    239                 // Don't store the option.
    240                 message->num_options--;
    241                 *offset += option_length;
    242                 continue;
    243             }
    244             option->option.link_layer_address.length = 6;
    245             memcpy(option->option.link_layer_address.address, &icmp_buf[scan_offset], 6);
    246             break;
    247         case icmp_option_prefix_information:
    248             prefix_information = &option->option.prefix_information;
    249             // Only a length of 32 is valid.  This is an invalid ICMP packet, not just misunderunderstood
    250             if (option_length != 32) {
    251                 return false;
    252             }
    253             // prefix length 8
    254             if (!dns_u8_parse(icmp_buf, length, &scan_offset, &prefix_information->length)) {
    255                 return false;
    256             }
    257             // flags 8a
    258             if (!dns_u8_parse(icmp_buf, length, &scan_offset, &prefix_information->flags)) {
    259                 return false;
    260             }
    261             // valid lifetime 32
    262             if (!dns_u32_parse(icmp_buf, length, &scan_offset,
    263                                &prefix_information->valid_lifetime)) {
    264                 return false;
    265             }
    266             // preferred lifetime 32
    267             if (!dns_u32_parse(icmp_buf, length, &scan_offset,
    268                                &prefix_information->preferred_lifetime)) {
    269                 return false;
    270             }
    271             // reserved2 32
    272             if (!dns_u32_parse(icmp_buf, length, &scan_offset, &reserved32)) {
    273                 return false;
    274             }
    275             // prefix 128
    276             in6prefix_copy_from_data(&prefix_information->prefix, &icmp_buf[scan_offset], 16);
    277             break;
    278         case icmp_option_route_information:
    279             route_information = &option->option.route_information;
    280 
    281             // route length 8
    282             if (!dns_u8_parse(icmp_buf, length, &scan_offset, &route_information->length)) {
    283                 return false;
    284             }
    285             switch(option_length) {
    286             case 8:
    287                 prefix_bytes = 0;
    288                 break;
    289             case 16:
    290                 prefix_bytes = 8;
    291                 break;
    292             case 24:
    293                 prefix_bytes = 16;
    294                 break;
    295             default:
    296                 ERROR("invalid route information option length %d for route length %d",
    297                       option_length, route_information->length);
    298                 return false;
    299             }
    300             // flags 8
    301             if (!dns_u8_parse(icmp_buf, length, &scan_offset, &route_information->flags)) {
    302                 return false;
    303             }
    304             // route lifetime 32
    305             if (!dns_u32_parse(icmp_buf, length, &scan_offset, &route_information->route_lifetime)) {
    306                 return false;
    307             }
    308             // route (64, 96 or 128)
    309             in6prefix_copy_from_data(&route_information->prefix, &icmp_buf[scan_offset], prefix_bytes);
    310             break;
    311         case icmp_option_ra_flags_extension:
    312             // The RA Flags extension as defined in RFC 5175 must have a length of 1 (meaning 8 bytes).
    313             // It's possible that a later spec will define a length > 1, but since we are implementing
    314             // RFC5175, we are required to silently ignore anything after the first 8 bytes. Since
    315             // we've already checked for length=0 (invalid), we can just take our six bytes of flags
    316             // and not bounds-check further.
    317             memcpy(option->option.ra_flags_extension, &icmp_buf[scan_offset], sizeof(option->option.ra_flags_extension));
    318             break;
    319         default:
    320         case icmp_option_mtu:
    321         case icmp_option_redirected_header:
    322             // don't care
    323             break;
    324         }
    325         *offset += option_length;
    326         option++;
    327     }
    328     return true;
    329 }
    330 
    331 
    332 static void
    333 icmp_message(route_state_t *route_state, uint8_t *icmp_buf, unsigned length, int ifindex, int hop_limit, addr_t *src, addr_t *dest)
    334 {
    335     unsigned offset = 0;
    336     uint32_t reserved32;
    337     interface_t *interface;
    338     icmp_message_t *message = calloc(1, sizeof(*message));
    339     if (message == NULL) {
    340         ERROR("Unable to allocate icmp_message_t for parsing");
    341         return;
    342     }
    343 
    344     message->source = src->sin6.sin6_addr;
    345     message->destination = dest->sin6.sin6_addr;
    346     message->hop_limit = hop_limit;
    347     for (interface = route_state->interfaces; interface; interface = interface->next) {
    348         if (interface->index == ifindex) {
    349             message->interface = interface;
    350             break;
    351         }
    352     }
    353     message->received_time = ioloop_timenow();
    354     message->received_time_already_adjusted = false;
    355     message->new_router = true;
    356     message->route_state = route_state;
    357 
    358     if (message->interface == NULL) {
    359         SEGMENTED_IPv6_ADDR_GEN_SRP(message->source.s6_addr, src_buf);
    360         SEGMENTED_IPv6_ADDR_GEN_SRP(message->destination.s6_addr, dst_buf);
    361         INFO("ICMP message type %d from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP
    362              " on interface index %d, which isn't listed.",
    363              icmp_buf[0], SEGMENTED_IPv6_ADDR_PARAM_SRP(message->source.s6_addr, src_buf),
    364              SEGMENTED_IPv6_ADDR_PARAM_SRP(message->destination.s6_addr, dst_buf), ifindex);
    365         icmp_message_free(message);
    366         return;
    367     }
    368 
    369     if (length < sizeof (struct icmp6_hdr)) {
    370         ERROR("Short ICMP message: length %d is shorter than ICMP header length %zd", length, sizeof(struct icmp6_hdr));
    371         icmp_message_free(message);
    372         return;
    373     }
    374     INFO("length %d", length);
    375 
    376     // The increasingly innaccurately named dns parse functions will work fine for this.
    377     if (!dns_u8_parse(icmp_buf, length, &offset, &message->type)) {
    378         goto out;
    379     }
    380     if (!dns_u8_parse(icmp_buf, length, &offset, &message->code)) {
    381         goto out;
    382     }
    383     // XXX check the checksum
    384     if (!dns_u16_parse(icmp_buf, length, &offset, &message->checksum)) {
    385         goto out;
    386     }
    387     switch(message->type) {
    388     case icmp_type_router_advertisement:
    389         if (!dns_u8_parse(icmp_buf, length, &offset, &message->cur_hop_limit)) {
    390             goto out;
    391         }
    392         if (!dns_u8_parse(icmp_buf, length, &offset, &message->flags)) {
    393             goto out;
    394         }
    395         if (!dns_u16_parse(icmp_buf, length, &offset, &message->router_lifetime)) {
    396             goto out;
    397         }
    398         if (!dns_u32_parse(icmp_buf, length, &offset, &message->reachable_time)) {
    399             goto out;
    400         }
    401         if (!dns_u32_parse(icmp_buf, length, &offset, &message->retransmission_timer)) {
    402             goto out;
    403         }
    404 
    405         if (!icmp_message_parse_options(message, icmp_buf, length, &offset)) {
    406             goto out;
    407         }
    408         icmp_message_dump(message, &message->source, &message->destination);
    409         router_advertisement(message);
    410         // router_advertisement() is given ownership of the message
    411         return;
    412 
    413     case icmp_type_router_solicitation:
    414         if (!dns_u32_parse(icmp_buf, length, &offset, &reserved32)) {
    415             goto out;
    416         }
    417         if (!icmp_message_parse_options(message, icmp_buf, length, &offset)) {
    418             goto out;
    419         }
    420         icmp_message_dump(message, &message->source, &message->destination);
    421         router_solicit(message);
    422         // router_solicit() is given ownership of the message.
    423         return;
    424 
    425     case icmp_type_neighbor_advertisement:
    426         icmp_message_dump(message, &message->source, &message->destination);
    427         neighbor_advertisement(message);
    428         break;
    429 
    430     case icmp_type_neighbor_solicitation:
    431     case icmp_type_echo_request:
    432     case icmp_type_echo_reply:
    433     case icmp_type_redirect:
    434         break;
    435     }
    436 
    437 out:
    438     icmp_message_free(message);
    439     return;
    440 }
    441 
    442 #ifndef FUZZING
    443 static
    444 #endif
    445 void
    446 icmp_callback(io_t *NONNULL io, void *UNUSED context)
    447 {
    448     ssize_t rv;
    449     uint8_t icmp_buf[1500];
    450     int ifindex = 0;
    451     addr_t src, dest;
    452     int hop_limit = 0;
    453 
    454 #ifndef FUZZING
    455     rv = ioloop_recvmsg(io->fd, &icmp_buf[0], sizeof(icmp_buf), &ifindex, &hop_limit, &src, &dest);
    456 #else
    457     rv = read(io->fd, &icmp_buf, sizeof(icmp_buf));
    458 #endif
    459     if (rv < 0) {
    460         ERROR("icmp_callback: can't read ICMP message: " PUB_S_SRP, strerror(errno));
    461         return;
    462     }
    463     for (route_state_t *route_state = route_states; route_state != NULL; route_state = route_state->next) {
    464         icmp_message(route_state, icmp_buf, (unsigned)rv, ifindex, hop_limit, &src, &dest); // rv will never be > sizeof(icmp_buf)
    465     }
    466 }
    467 
    468 static void
    469 route_information_to_wire(dns_towire_state_t *towire, void *prefix_data,
    470                           const char *source_interface, const char *dest_interface)
    471 {
    472     uint8_t *prefix = prefix_data;
    473 
    474 #ifndef ND_OPT_ROUTE_INFORMATION
    475 #define ND_OPT_ROUTE_INFORMATION 24
    476 #endif
    477     dns_u8_to_wire(towire, ND_OPT_ROUTE_INFORMATION);
    478     dns_u8_to_wire(towire, 2); // length / 8
    479     dns_u8_to_wire(towire, 64); // Interface prefixes are always 64 bits
    480     dns_u8_to_wire(towire, 0); // There's no reason at present to prefer one Thread BR over another
    481     dns_u32_to_wire(towire, BR_PREFIX_LIFETIME); // Route lifetime 1800 seconds (30 minutes)
    482     dns_rdata_raw_data_to_wire(towire, prefix, 8); // /64 requires 8 bytes.
    483     SEGMENTED_IPv6_ADDR_GEN_SRP(prefix, thread_prefix_buf);
    484     INFO("Sending route to " PRI_SEGMENTED_IPv6_ADDR_SRP "%%" PUB_S_SRP " on " PUB_S_SRP,
    485          SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix, thread_prefix_buf), source_interface, dest_interface);
    486 }
    487 
    488 static void
    489 icmp_send(uint8_t *message, size_t length, interface_t *interface, const struct in6_addr *destination)
    490 {
    491 #ifdef FUZZING
    492     char buffer[length];
    493     memcpy(buffer, message, length);
    494     return;
    495 #endif
    496     struct iovec iov;
    497     struct in6_pktinfo *packet_info;
    498     socklen_t cmsg_length = CMSG_SPACE(sizeof(*packet_info)) + CMSG_SPACE(sizeof (int));
    499     uint8_t *cmsg_buffer;
    500     struct msghdr msg_header;
    501     struct cmsghdr *cmsg_pointer;
    502     int hop_limit = 255;
    503     ssize_t rv;
    504     struct sockaddr_in6 dest;
    505 
    506     // Make space for the control message buffer.
    507     cmsg_buffer = calloc(1, cmsg_length);
    508     if (cmsg_buffer == NULL) {
    509         ERROR("Unable to construct ICMP Router Advertisement: no memory");
    510         return;
    511     }
    512 
    513     // Send the message
    514     memset(&dest, 0, sizeof(dest));
    515     dest.sin6_family = AF_INET6;
    516     dest.sin6_scope_id = interface->index;
    517 #ifndef NOT_HAVE_SA_LEN
    518     dest.sin6_len = sizeof(dest);
    519 #endif
    520     msg_header.msg_namelen = sizeof(dest);
    521     dest.sin6_addr = *destination;
    522 
    523     msg_header.msg_name = &dest;
    524     iov.iov_base = message;
    525     iov.iov_len = length;
    526     msg_header.msg_iov = &iov;
    527     msg_header.msg_iovlen = 1;
    528     msg_header.msg_control = cmsg_buffer;
    529     msg_header.msg_controllen = cmsg_length;
    530 
    531     // Specify the interface
    532     cmsg_pointer = CMSG_FIRSTHDR(&msg_header);
    533     cmsg_pointer->cmsg_level = IPPROTO_IPV6;
    534     cmsg_pointer->cmsg_type = IPV6_PKTINFO;
    535     cmsg_pointer->cmsg_len = CMSG_LEN(sizeof(*packet_info));
    536     packet_info = (struct in6_pktinfo *)CMSG_DATA(cmsg_pointer);
    537     memset(packet_info, 0, sizeof(*packet_info));
    538     packet_info->ipi6_ifindex = interface->index;
    539 
    540     // Router advertisements and solicitations have a hop limit of 255
    541     cmsg_pointer = CMSG_NXTHDR(&msg_header, cmsg_pointer);
    542     cmsg_pointer->cmsg_level = IPPROTO_IPV6;
    543     cmsg_pointer->cmsg_type = IPV6_HOPLIMIT;
    544     cmsg_pointer->cmsg_len = CMSG_LEN(sizeof(int));
    545     memcpy(CMSG_DATA(cmsg_pointer), &hop_limit, sizeof(hop_limit));
    546 
    547 
    548     // Send it
    549     rv = sendmsg(icmp_listener.io_state->fd, &msg_header, 0);
    550     if (rv < 0) {
    551         uint8_t *in6_addr_bytes = ((struct sockaddr_in6 *)(msg_header.msg_name))->sin6_addr.s6_addr;
    552         SEGMENTED_IPv6_ADDR_GEN_SRP(in6_addr_bytes, in6_addr_buf);
    553         ERROR("icmp_send: sending " PUB_S_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP " on interface " PUB_S_SRP
    554               " index %d: " PUB_S_SRP, message[0] == ND_ROUTER_SOLICIT ? "solicit" : "advertise",
    555               SEGMENTED_IPv6_ADDR_PARAM_SRP(in6_addr_bytes, in6_addr_buf),
    556               interface->name, interface->index, strerror(errno));
    557     } else if ((size_t)rv != iov.iov_len) {
    558         ERROR("icmp_send: short send to interface " PUB_S_SRP ": %zd < %zd", interface->name, rv, iov.iov_len);
    559     }
    560     free(cmsg_buffer);
    561 }
    562 
    563 void
    564 router_advertisement_send(interface_t *interface, const struct in6_addr *destination)
    565 {
    566     uint8_t *message;
    567     dns_towire_state_t towire;
    568     route_state_t *route_state = interface->route_state;
    569 
    570     // Thread blocks RAs so no point sending them.
    571     if (interface->inactive
    572 #ifndef RA_TESTER
    573         || interface->is_thread
    574 #endif
    575         ) {
    576         return;
    577     }
    578 
    579 #define MAX_ICMP_MESSAGE 1280
    580     message = malloc(MAX_ICMP_MESSAGE);
    581     if (message == NULL) {
    582         ERROR("router_advertisement_send: unable to construct ICMP Router Advertisement: no memory");
    583         return;
    584     }
    585 
    586     // Construct the ICMP header and options for each interface.
    587     memset(&towire, 0, sizeof towire);
    588     towire.p = message;
    589     towire.lim = message + MAX_ICMP_MESSAGE;
    590 
    591     // Construct the ICMP header.
    592     // We use the DNS message construction functions because it's easy; probably should just make
    593     // the towire functions more generic.
    594     dns_u8_to_wire(&towire, ND_ROUTER_ADVERT);  // icmp6_type
    595     dns_u8_to_wire(&towire, 0);                 // icmp6_code
    596     dns_u16_to_wire(&towire, 0);                // The kernel computes the checksum (we don't technically have it).
    597     dns_u8_to_wire(&towire, 0);                 // Hop limit, we don't set.
    598     dns_u8_to_wire(&towire, 0);                 // Flags.  We don't offer DHCP, so We set neither the M nor the O bit.
    599     // We are not a home agent, so no H bit.  Lifetime is 0, so Prf is 0.
    600 #ifdef ROUTER_LIFETIME_HACK
    601     dns_u16_to_wire(&towire, BR_PREFIX_LIFETIME); // Router lifetime, hacked.  This shouldn't ever be enabled.
    602 #else
    603 #ifdef RA_TESTER
    604     // Advertise a default route on the simulated thread network
    605     if (!strcmp(interface->name, route_state->thread_interface_name)) {
    606         dns_u16_to_wire(&towire, BR_PREFIX_LIFETIME); // Router lifetime for default route
    607     } else {
    608 #endif
    609         dns_u16_to_wire(&towire, 0);            // Router lifetime for non-default default route(s).
    610 #ifdef RA_TESTER
    611     }
    612 #endif // RA_TESTER
    613 #endif // ROUTER_LIFETIME_HACK
    614     dns_u32_to_wire(&towire, 0);                // Reachable time for NUD, we have no opinion on this.
    615     dns_u32_to_wire(&towire, 0);                // Retransmission timer, again we have no opinion.
    616 
    617 #ifndef RA_TESTER
    618     // Send MTU of 1280 for Thread?
    619     if (interface->is_thread) {
    620         dns_u8_to_wire(&towire, ND_OPT_MTU);
    621         dns_u8_to_wire(&towire, 1); // length / 8
    622         dns_u32_to_wire(&towire, 1280);
    623         INFO("advertising MTU of 1280 on " PUB_S_SRP, interface->name);
    624     }
    625 #endif
    626 
    627     // Send Prefix Information option if there's no IPv6 on the link.
    628     if (interface->our_prefix_advertised && !interface->suppress_ipv6_prefix && route_state->have_xpanid_prefix) {
    629         dns_u8_to_wire(&towire, ND_OPT_PREFIX_INFORMATION);
    630         dns_u8_to_wire(&towire, 4); // length / 8
    631         dns_u8_to_wire(&towire, 64); // On-link prefix is always 64 bits
    632         dns_u8_to_wire(&towire, ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO); // On link, autoconfig
    633         dns_u32_to_wire(&towire, interface->valid_lifetime);
    634         dns_u32_to_wire(&towire, interface->preferred_lifetime);
    635         dns_u32_to_wire(&towire, 0); // Reserved
    636         dns_rdata_raw_data_to_wire(&towire, &interface->ipv6_prefix, sizeof interface->ipv6_prefix);
    637         SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, ipv6_prefix_buf);
    638         INFO("advertising on-link prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP,
    639              SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, ipv6_prefix_buf), interface->name);
    640 
    641     }
    642 
    643     // In principle we can either send routes to links that are reachable by this router,
    644     // or just advertise a router to the entire ULA /48.   In theory it doesn't matter
    645     // which we do; if we support HNCP at some point we probably need to be specific, but
    646     // for now being general is fine because we have no way to share a ULA.
    647     // Unfortunately, some RIO implementations do not work with specific routes, so for now
    648     // We are doing it the easy way and just advertising the /48.
    649 #define SEND_INTERFACE_SPECIFIC_RIOS 1
    650 #ifdef SEND_INTERFACE_SPECIFIC_RIOS
    651 
    652     // If neither ROUTE_BETWEEN_NON_THREAD_LINKS nor RA_TESTER are defined, then we never want to
    653     // send an RIO other than for the thread network prefix.
    654 #if defined (ROUTE_BETWEEN_NON_THREAD_LINKS) || defined(RA_TESTER)
    655     interface_t *ifroute;
    656     // Send Route Information option for other interfaces.
    657     for (ifroute = route_state->interfaces; ifroute; ifroute = ifroute->next) {
    658         if (ifroute->inactive) {
    659             continue;
    660         }
    661         if (want_routing(route_state) &&
    662             ifroute->our_prefix_advertised &&
    663 #ifdef SEND_ON_LINK_ROUTE
    664             // In theory we don't want to send RIO for the on-link prefix, but there's this bug, see.
    665             true &&
    666 #else
    667             ifroute != interface &&
    668 #endif
    669 #ifdef RA_TESTER
    670             // For the RA tester, we don't need to send an RIO to the thread network because we're the
    671             // default router for that network.
    672             strcmp(interface->name, route_state->thread_interface_name)
    673 #else
    674             true
    675 #endif
    676             )
    677         {
    678             route_information_to_wire(&towire, &ifroute->ipv6_prefix, ifroute->name, interface->name);
    679         }
    680     }
    681 #endif // ROUTE_BETWEEN_NON_THREAD_LINKS || RA_TESTER
    682 
    683 #ifndef RA_TESTER
    684     // Send route information option for thread prefix
    685     if (route_state->omr_watcher != NULL) {
    686         omr_prefix_t *thread_prefixes = omr_watcher_prefixes_get(route_state->omr_watcher);
    687 
    688         // Send RIOs for any other prefixes that appear on the Thread network
    689         for (struct omr_prefix *prefix = thread_prefixes; prefix != NULL; prefix = prefix->next) {
    690             route_information_to_wire(&towire, &prefix->prefix, route_state->thread_interface_name, interface->name);
    691         }
    692     }
    693 #endif
    694 #else
    695 #ifndef SKIP_SLASH_48
    696     dns_u8_to_wire(&towire, ND_OPT_ROUTE_INFORMATION);
    697     dns_u8_to_wire(&towire, 3); // length / 8
    698     dns_u8_to_wire(&towire, 48); // ULA prefixes are always 48 bits
    699     dns_u8_to_wire(&towire, 0); // There's no reason at present to prefer one Thread BR over another
    700     dns_u32_to_wire(&towire, BR_PREFIX_LIFETIME); // Route lifetime 1800 seconds (30 minutes)
    701     dns_rdata_raw_data_to_wire(&towire, &route_state->srp_server->ula_prefix, 16); // /48 requires 16 bytes
    702 #endif // SKIP_SLASH_48
    703 #endif // SEND_INTERFACE_SPECIFIC_RIOS
    704 
    705     // Send the stub router flag
    706     dns_u8_to_wire(&towire, ND_OPT_RA_FLAGS_EXTENSION);
    707     dns_u8_to_wire(&towire, 1); // length / 8
    708     dns_u8_to_wire(&towire, RA_FLAGS1_STUB_ROUTER);
    709     dns_u8_to_wire(&towire, 0); // Five bytes of zero flag bits
    710     dns_u32_to_wire(&towire, 0);
    711 
    712     // Send Source link-layer address option
    713     if (interface->have_link_layer_address) {
    714         dns_u8_to_wire(&towire, ND_OPT_SOURCE_LINKADDR);
    715         dns_u8_to_wire(&towire, 1); // length / 8
    716         dns_rdata_raw_data_to_wire(&towire, &interface->link_layer, sizeof(interface->link_layer));
    717     }
    718 
    719     if (towire.error) {
    720         ERROR("No space in ICMP output buffer for " PUB_S_SRP " at route.c:%d", interface->name, towire.line);
    721         towire.error = 0;
    722     } else {
    723         SEGMENTED_IPv6_ADDR_GEN_SRP(destination->s6_addr, destination_buf);
    724         INFO("sending advertisement to " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP,
    725              SEGMENTED_IPv6_ADDR_PARAM_SRP(destination->s6_addr, destination_buf),
    726              interface->name);
    727         icmp_send(message, towire.p - message, interface, destination);
    728     }
    729     free(message);
    730 }
    731 
    732 void
    733 router_solicit_send(interface_t *interface)
    734 {
    735     uint8_t *message;
    736     dns_towire_state_t towire;
    737 
    738     // Thread blocks RSs so no point sending them.
    739     if (interface->inactive
    740 #ifndef RA_TESTER
    741         || interface->is_thread
    742 #endif
    743         ) {
    744         return;
    745     }
    746 #define MAX_ICMP_MESSAGE 1280
    747     message = malloc(MAX_ICMP_MESSAGE);
    748     if (message == NULL) {
    749         ERROR("Unable to construct ICMP Router Advertisement: no memory");
    750         return;
    751     }
    752 
    753     // Construct the ICMP header and options for each interface.
    754     memset(&towire, 0, sizeof towire);
    755     towire.p = message;
    756     towire.lim = message + MAX_ICMP_MESSAGE;
    757 
    758     // Construct the ICMP header.
    759     // We use the DNS message construction functions because it's easy; probably should just make
    760     // the towire functions more generic.
    761     dns_u8_to_wire(&towire, ND_ROUTER_SOLICIT);  // icmp6_type
    762     dns_u8_to_wire(&towire, 0);                  // icmp6_code
    763     dns_u16_to_wire(&towire, 0);                 // The kernel computes the checksum (we don't technically have it).
    764     dns_u32_to_wire(&towire, 0);                 // Reserved32
    765 
    766     // Send Source link-layer address option
    767     if (interface->have_link_layer_address) {
    768         dns_u8_to_wire(&towire, ND_OPT_SOURCE_LINKADDR);
    769         dns_u8_to_wire(&towire, 1); // length / 8
    770         dns_rdata_raw_data_to_wire(&towire, &interface->link_layer, sizeof(interface->link_layer));
    771     }
    772 
    773     if (towire.error) {
    774         ERROR("No space in ICMP output buffer for " PUB_S_SRP " at route.c:%d", interface->name, towire.line);
    775     } else {
    776         if (interface->have_link_layer_address) {
    777             INFO("sending router solicit on " PUB_S_SRP " to all routers with source " PRI_MAC_ADDR_SRP,
    778                  interface->name, MAC_ADDR_PARAM_SRP(interface->link_layer));
    779         } else {
    780             INFO("sending router solicit on " PUB_S_SRP " to all routers", interface->name);
    781         }
    782         icmp_send(message, towire.p - message, interface, &in6addr_linklocal_allrouters);
    783     }
    784     free(message);
    785 }
    786 
    787 void
    788 neighbor_solicit_send(interface_t *interface, struct in6_addr *destination)
    789 {
    790     uint8_t *message;
    791     dns_towire_state_t towire;
    792 
    793 #define MAX_ICMP_MESSAGE 1280
    794     message = malloc(MAX_ICMP_MESSAGE);
    795     if (message == NULL) {
    796         ERROR("Unable to construct ICMP Router Advertisement: no memory");
    797         return;
    798     }
    799 
    800     // Construct the ICMP header and options for each interface.
    801     memset(&towire, 0, sizeof towire);
    802     towire.p = message;
    803     towire.lim = message + MAX_ICMP_MESSAGE;
    804 
    805     // Construct the ICMP header.
    806     // We use the DNS message construction functions because it's easy; probably should just make
    807     // the towire functions more generic.
    808     dns_u8_to_wire(&towire, ND_NEIGHBOR_SOLICIT);  // icmp6_type
    809     dns_u8_to_wire(&towire, 0);                    // icmp6_code
    810     dns_u16_to_wire(&towire, 0);                   // The kernel computes the checksum (we don't technically have it).
    811     dns_u32_to_wire(&towire, 0);                   // Reserved32
    812     dns_rdata_raw_data_to_wire(&towire, destination, sizeof(*destination)); // Target address of solicit
    813 
    814     // Send Source link-layer address option
    815     if (interface->have_link_layer_address) {
    816         dns_u8_to_wire(&towire, ND_OPT_SOURCE_LINKADDR);
    817         dns_u8_to_wire(&towire, 1); // length / 8
    818         dns_rdata_raw_data_to_wire(&towire, &interface->link_layer, sizeof(interface->link_layer));
    819     }
    820 
    821     if (towire.error) {
    822         ERROR("No space in ICMP output buffer for " PUB_S_SRP " at route.c:%d", interface->name, towire.line);
    823     } else {
    824         SEGMENTED_IPv6_ADDR_GEN_SRP(destination, dest_buf);
    825         if (interface->have_link_layer_address) {
    826             INFO("sending neighbor solicit on " PUB_S_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP " with source " PRI_MAC_ADDR_SRP,
    827                  interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(destination, dest_buf), MAC_ADDR_PARAM_SRP(interface->link_layer));
    828         } else {
    829             INFO("sending neighbor solicit on " PUB_S_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP,
    830                  interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(destination, dest_buf));
    831         }
    832         icmp_send(message, towire.p - message, interface, destination);
    833     }
    834     free(message);
    835 }
    836 
    837 bool
    838 start_icmp_listener(void)
    839 {
    840 #ifndef SRP_TEST_SERVER
    841     int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
    842     int true_flag = 1;
    843 #ifdef CONFIGURE_STATIC_INTERFACE_ADDRESSES
    844     int false_flag = 0;
    845 #endif
    846     struct icmp6_filter filter;
    847     ssize_t rv;
    848 
    849     if (sock < 0) {
    850         ERROR("Unable to listen for icmp messages: " PUB_S_SRP, strerror(errno));
    851         close(sock);
    852         return false;
    853     }
    854 
    855     // Only accept router advertisements and router solicits.
    856     ICMP6_FILTER_SETBLOCKALL(&filter);
    857     ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter);
    858     ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filter);
    859     ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
    860     rv = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter));
    861     if (rv < 0) {
    862         ERROR("Can't set IPV6_RECVHOPLIMIT: " PUB_S_SRP ".", strerror(errno));
    863         close(sock);
    864         return false;
    865     }
    866 
    867     // We want a source address and interface index
    868     rv = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &true_flag, sizeof(true_flag));
    869     if (rv < 0) {
    870         ERROR("Can't set IPV6_RECVPKTINFO: " PUB_S_SRP ".", strerror(errno));
    871         close(sock);
    872         return false;
    873     }
    874 
    875     // We need to be able to reject RAs arriving from off-link.
    876     rv = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &true_flag, sizeof(true_flag));
    877     if (rv < 0) {
    878         ERROR("Can't set IPV6_RECVHOPLIMIT: " PUB_S_SRP ".", strerror(errno));
    879         close(sock);
    880         return false;
    881     }
    882 
    883 #ifdef CONFIGURE_STATIC_INTERFACE_ADDRESSES
    884     // Prevent our router advertisements from updating our routing table.
    885     rv = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &false_flag, sizeof(false_flag));
    886     if (rv < 0) {
    887         ERROR("Can't set IPV6_RECVHOPLIMIT: " PUB_S_SRP ".", strerror(errno));
    888         close(sock);
    889         return false;
    890     }
    891 #endif
    892 
    893     icmp_listener.io_state = ioloop_file_descriptor_create(sock, NULL, NULL);
    894     if (icmp_listener.io_state == NULL) {
    895         ERROR("No memory for ICMP I/O structure.");
    896         close(sock);
    897         return false;
    898     }
    899 
    900     // Beacon out a router advertisement every three minutes.
    901     icmp_listener.unsolicited_interval = 3 * 60 * 1000;
    902     ioloop_add_reader(icmp_listener.io_state, icmp_callback);
    903 #else
    904     (void)icmp_callback;
    905 #endif // !SRP_TEST_SERVER
    906 
    907     return true;
    908 }
    909 
    910 void
    911 icmp_interface_subscribe(interface_t *interface, bool added)
    912 {
    913     struct ipv6_mreq req;
    914     int rv;
    915 
    916     if (icmp_listener.io_state == NULL) {
    917         ERROR("Interface subscribe without ICMP listener.");
    918         return;
    919     }
    920 
    921     memset(&req, 0, sizeof req);
    922     if (interface->index == -1) {
    923         ERROR("icmp_interface_subscribe called before interface index fetch for " PUB_S_SRP, interface->name);
    924         return;
    925     }
    926 
    927     req.ipv6mr_multiaddr = in6addr_linklocal_allrouters;
    928     req.ipv6mr_interface = interface->index;
    929     rv = setsockopt(icmp_listener.io_state->fd, IPPROTO_IPV6, added ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &req,
    930                     sizeof req);
    931     if (rv < 0) {
    932         ERROR("Unable to " PUB_S_SRP " all-routers multicast group on " PUB_S_SRP ": " PUB_S_SRP,
    933               added ? "join" : "leave", interface->name, strerror(errno));
    934         return;
    935     } else {
    936         INFO(PUB_S_SRP "subscribed on interface " PUB_S_SRP, added ? "" : "un",
    937              interface->name);
    938     }
    939 
    940     req.ipv6mr_multiaddr = in6addr_linklocal_allnodes;
    941     req.ipv6mr_interface = interface->index;
    942     rv = setsockopt(icmp_listener.io_state->fd, IPPROTO_IPV6, added ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, &req,
    943                     sizeof req);
    944     if (rv < 0) {
    945         ERROR("Unable to " PUB_S_SRP " all-nodes multicast group on " PUB_S_SRP ": " PUB_S_SRP,
    946               added ? "join" : "leave", interface->name, strerror(errno));
    947         return;
    948     } else {
    949         INFO(PUB_S_SRP "subscribed on interface " PUB_S_SRP, added ? "" : "un",
    950              interface->name);
    951     }
    952 
    953 }
    954 
    955 
    956 // Local Variables:
    957 // mode: C
    958 // tab-width: 4
    959 // c-file-style: "bsd"
    960 // c-basic-offset: 4
    961 // fill-column: 120
    962 // indent-tabs-mode: nil
    963 // End:
    964