Home | History | Annotate | Line # | Download | only in ServiceRegistration
      1 /* route.c
      2  *
      3  * Copyright (c) 2019-2024 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 adds border router support to 3rd party HomeKit Routers as part of Apples commitment to the CHIP project.
     18  *
     19  * This file contains an implementation of Thread Border Router routing.
     20  * The state of the Thread network is tracked, the state of the infrastructure
     21  * network is tracked, and policy decisions are made as to what to advertise
     22  * on both networks.
     23  */
     24 
     25 #ifndef LINUX
     26 #include <netinet/in.h>
     27 #include <net/if.h>
     28 #include <netinet6/in6_var.h>
     29 #include <netinet6/nd6.h>
     30 #include <net/if_media.h>
     31 #include <sys/stat.h>
     32 #else
     33 #define _GNU_SOURCE
     34 #include <netinet/in.h>
     35 #include <fcntl.h>
     36 #include <bsd/stdlib.h>
     37 #include <net/if.h>
     38 #endif
     39 #include <sys/socket.h>
     40 #include <sys/ioctl.h>
     41 #include <net/route.h>
     42 #include <netinet/icmp6.h>
     43 #include <stdio.h>
     44 #include <unistd.h>
     45 #include <errno.h>
     46 #include <stdlib.h>
     47 #include <string.h>
     48 #include <ctype.h>
     49 #include <arpa/inet.h>
     50 #if !USE_SYSCTL_COMMAND_TO_ENABLE_FORWARDING
     51 #ifndef LINUX
     52 #include <sys/sysctl.h>
     53 #endif // LINUX
     54 #endif // !USE_SYSCTL_COMMAND_TO_ENABLE_FORWARDING
     55 #include <stdlib.h>
     56 #include <stddef.h>
     57 #include <dns_sd.h>
     58 #include <inttypes.h>
     59 #include <signal.h>
     60 
     61 #ifdef IOLOOP_MACOS
     62 #include <xpc/xpc.h>
     63 
     64 #include <TargetConditionals.h>
     65 #include <SystemConfiguration/SystemConfiguration.h>
     66 #include <SystemConfiguration/SCPrivate.h>
     67 #include <SystemConfiguration/SCNetworkConfigurationPrivate.h>
     68 #include <SystemConfiguration/SCNetworkSignature.h>
     69 #include <network_information.h>
     70 
     71 #include <CoreUtils/CoreUtils.h>
     72 #endif // IOLOOP_MACOS
     73 
     74 #include "srp.h"
     75 #include "dns-msg.h"
     76 #include "ioloop.h"
     77 #include "srp-crypto.h"
     78 #include "srp-gw.h"
     79 #include "srp-mdns-proxy.h"
     80 #include "adv-ctl-server.h"
     81 #include "srp-replication.h"
     82 
     83 
     84 # define THREAD_DATA_DIR "/var/lib/openthread"
     85 # define THREAD_ULA_FILE THREAD_DATA_DIR "/thread-mesh-ula"
     86 
     87 #if STUB_ROUTER // Stub Router is true if we're building a Thread Border router or an RA tester.
     88 #ifdef THREAD_BORDER_ROUTER
     89 #include "cti-services.h"
     90 #endif
     91 #include "srp-gw.h"
     92 #include "srp-proxy.h"
     93 #include "srp-mdns-proxy.h"
     94 #include "dnssd-proxy.h"
     95 #if SRP_FEATURE_NAT64
     96 #include "nat64-macos.h"
     97 #endif
     98 #include "srp-proxy.h"
     99 #include "route.h"
    100 #include "nat64.h"
    101 
    102 #include "state-machine.h"
    103 #include "thread-service.h"
    104 #include "service-tracker.h"
    105 #include "omr-watcher.h"
    106 #include "omr-publisher.h"
    107 #include "route-tracker.h"
    108 #include "icmp.h"
    109 
    110 
    111 #ifdef LINUX
    112 #define CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IFCONFIG 1
    113 #endif
    114 
    115 #ifdef LINUX
    116 struct in6_addr in6addr_linklocal_allnodes = {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    117                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}};
    118 struct in6_addr in6addr_linklocal_allrouters = {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    119                                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}};
    120 #endif
    121 
    122 route_state_t *route_states;
    123 
    124 #define CONFIGURE_STATIC_INTERFACE_ADDRESSES 1
    125 
    126 #define interface_create(route_state, name, iface) interface_create_(route_state, name, iface, __FILE__, __LINE__)
    127 interface_t *NULLABLE interface_create_(route_state_t *NONNULL route_state, const char *NONNULL name, int ifindex,
    128                                         const char *NONNULL file, int line);
    129 
    130 static void interface_beacon_schedule(interface_t *NONNULL interface, unsigned when);
    131 static void interface_prefix_configure(struct in6_addr prefix, interface_t *NONNULL interface);
    132 static void interface_prefix_evaluate(interface_t *interface);
    133 static void start_router_solicit(interface_t *interface);
    134 #ifndef RA_TESTER
    135 static void attempt_wpan_reconnect(void *context);
    136 static void routing_policy_evaluate_all_interfaces(route_state_t *route_state, bool assume_changed);
    137 #endif
    138 static void routing_policy_evaluate(interface_t *interface, bool assume_changed);
    139 static void post_solicit_policy_evaluate(void *context);
    140 static void schedule_next_router_probe(interface_t *interface);
    141 
    142 #ifndef RA_TESTER
    143 static void thread_network_startup(route_state_t *route_state);
    144 static void thread_network_shutdown(route_state_t *route_state);
    145 static void thread_network_shutdown_start(route_state_t *route_state);
    146 static void partition_state_reset(route_state_t *route_state);
    147 static void partition_utun0_address_changed(route_state_t *route_state, const struct in6_addr *NONNULL addr, enum interface_address_change change);
    148 static void partition_utun0_pick_listener_address(route_state_t *route_state);
    149 static void partition_got_tunnel_name(route_state_t *route_state);
    150 static void partition_remove_service_done(void *UNUSED NULLABLE context, cti_status_t status);
    151 static void partition_stop_advertising_service(route_state_t *route_state);
    152 static void partition_proxy_listener_ready(void *UNUSED NULLABLE context, uint16_t port);
    153 static void partition_maybe_advertise_service(route_state_t *route_state);
    154 static void partition_service_set_changed(void *context);
    155 static void partition_maybe_enable_services(route_state_t *route_state);
    156 static void partition_disable_service(route_state_t *route_state);
    157 void partition_discontinue_srp_service(route_state_t *route_state);
    158 static void partition_schedule_service_add_wakeup(route_state_t *route_state);
    159 static void partition_schedule_anycast_service_add_wakeup(route_state_t *route_state);
    160 #endif
    161 
    162 route_state_t *
    163 route_state_create(srp_server_t *server_state, const char *name)
    164 {
    165     route_state_t *new_route_state = calloc(1, sizeof(*new_route_state));
    166     if (new_route_state == NULL || (new_route_state->name = strdup(name)) == NULL) {
    167         free(new_route_state);
    168         ERROR("no memory for route state.");
    169         return NULL;
    170     }
    171 #if !defined(RA_TESTER)
    172     new_route_state->thread_network_running = false;
    173     new_route_state->partition_may_offer_service = false;
    174     new_route_state->partition_settle_satisfied = true;
    175     new_route_state->current_thread_state = kCTI_NCPState_Uninitialized;
    176 #endif
    177     new_route_state->have_non_thread_interface = false;
    178     new_route_state->ula_serial = 1;
    179     new_route_state->have_xpanid_prefix = false;
    180     new_route_state->have_thread_prefix = false;
    181     new_route_state->config_enable_dhcpv6_prefixes = false;
    182     new_route_state->srp_server = server_state; // temporarily communicate the server_state object to route.c with a static assignment.
    183     new_route_state->next = route_states;
    184     route_states = new_route_state;
    185     return new_route_state;
    186 }
    187 
    188 static void
    189 interface_finalize(void *context)
    190 {
    191     interface_t *interface = context;
    192     if (interface->name != NULL) {
    193         free(interface->name);
    194     }
    195     if (interface->beacon_wakeup != NULL) {
    196         ioloop_wakeup_release(interface->beacon_wakeup);
    197     }
    198     if (interface->post_solicit_wakeup != NULL) {
    199         ioloop_wakeup_release(interface->post_solicit_wakeup);
    200     }
    201     if (interface->stale_evaluation_wakeup != NULL) {
    202         ioloop_wakeup_release(interface->stale_evaluation_wakeup);
    203     }
    204     if (interface->router_solicit_wakeup != NULL) {
    205         ioloop_wakeup_release(interface->router_solicit_wakeup);
    206     }
    207     if (interface->deconfigure_wakeup != NULL) {
    208         ioloop_wakeup_release(interface->deconfigure_wakeup);
    209     }
    210     if (interface->neighbor_solicit_wakeup != NULL) {
    211         ioloop_wakeup_release(interface->neighbor_solicit_wakeup);
    212     }
    213     if (interface->router_probe_wakeup != NULL) {
    214         ioloop_wakeup_release(interface->router_probe_wakeup);
    215     }
    216     free(interface);
    217 }
    218 
    219 interface_t *
    220 interface_create_(route_state_t *route_state, const char *name, int ifindex, const char *file, int line)
    221 {
    222     interface_t *ret;
    223 
    224     if (name == NULL) {
    225         ERROR("interface_create: missing name");
    226         return NULL;
    227     }
    228 
    229     ret = calloc(1, sizeof(*ret));
    230     if (ret) {
    231         RETAIN(ret, interface);
    232         ret->name = strdup(name);
    233         if (ret->name == NULL) {
    234             ERROR("interface_create: no memory for name");
    235             RELEASE(ret, interface);
    236             return NULL;
    237         }
    238         ret->deconfigure_wakeup = ioloop_wakeup_create();
    239         if (ret->deconfigure_wakeup == NULL) {
    240             ERROR("No memory for interface deconfigure wakeup on " PUB_S_SRP ".", ret->name);
    241             RELEASE(ret, interface);
    242             return NULL;
    243         }
    244 
    245         ret->route_state = route_state;
    246         ret->index = ifindex;
    247         ret->previously_inactive = true;
    248         ret->inactive = true;
    249         ret->previously_ineligible = true;
    250         if (!strcmp(name, "lo") || !strcmp(name, "wpan0")) {
    251             ret->ineligible = true;
    252         } else {
    253             ret->ineligible = false;
    254         }
    255     }
    256     return ret;
    257 }
    258 
    259 void interface_retain_(interface_t *NONNULL interface, const char *file, int line)
    260 {
    261     RETAIN(interface, interface);
    262 }
    263 
    264 void interface_release_(interface_t *NONNULL interface, const char *file, int line)
    265 {
    266     RELEASE(interface, interface);
    267 }
    268 
    269 #ifndef RA_TESTER
    270 #endif // RA_TESTER
    271 
    272 static void
    273 interface_prefix_deconfigure(void *context)
    274 {
    275     interface_t *interface = context;
    276     INFO("post solicit wakeup.");
    277 
    278     if (interface->preferred_lifetime != 0) {
    279         INFO("PUT PREFIX DECONFIGURE CODE HERE!!");
    280         interface->valid_lifetime = 0;
    281     }
    282     interface->deprecate_deadline = 0;
    283 }
    284 
    285 static bool
    286 want_routing(route_state_t *route_state)
    287 {
    288 #ifdef RA_TESTER
    289     (void)route_state;
    290     return true;
    291 #else
    292     return (route_state->partition_can_provide_routing &&
    293             route_state->partition_has_xpanid);
    294 #endif
    295 }
    296 
    297 static void
    298 interface_beacon_send(interface_t *interface, const struct in6_addr *destination)
    299 {
    300     uint64_t now = ioloop_timenow();
    301 #ifndef RA_TESTER
    302     route_state_t *route_state = interface->route_state;
    303 #endif
    304 
    305     INFO(PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP PUB_S_SRP,
    306          interface->deprecate_deadline > now ? " ddl>now" : "",
    307 #ifdef RA_TESTER
    308          "", "", "",
    309 #else
    310          route_state->partition_can_provide_routing ? " canpr" : " !canpr",
    311          route_state->partition_has_xpanid ? " havexp" : " !havexp",
    312          interface->suppress_ipv6_prefix ? " suppress" : " !suppress",
    313 #endif
    314          interface->our_prefix_advertised ? " advert" : " !advert",
    315          interface->sent_first_beacon ? "" : " first beacon");
    316 
    317     if (interface->deprecate_deadline > now) {
    318         // The remaining valid and preferred lifetimes is the time left until the deadline.
    319         interface->valid_lifetime = (uint32_t)((interface->deprecate_deadline - now) / 1000);
    320         interface->preferred_lifetime = 0;
    321         if (interface->valid_lifetime < icmp_listener.unsolicited_interval / 1000) {
    322             SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
    323             INFO("prefix valid life time is less than the unsolicited interval, stop advertising it "
    324                  "and prepare to deconfigure the prefix - ifname: " PUB_S_SRP "prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP
    325                  ", preferred time: %" PRIu32 ", valid time: %" PRIu32 ", unsolicited interval: %" PRIu32,
    326                  interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf),
    327                  interface->preferred_lifetime, interface->valid_lifetime, icmp_listener.unsolicited_interval / 1000);
    328             interface->our_prefix_advertised = false;
    329             ioloop_add_wake_event(interface->deconfigure_wakeup,
    330                                   interface, interface_prefix_deconfigure,
    331                                   NULL, interface->valid_lifetime * 1000);
    332         }
    333     }
    334 
    335 #ifndef RA_TESTER
    336     // If we have been beaconing, and router mode has been disabled, and we don't have
    337     // an on-link prefix to advertise, discontinue beaconing.
    338     if (want_routing(route_state) || interface->our_prefix_advertised) {
    339 #endif
    340 
    341     // Send an RA.
    342         router_advertisement_send(interface, destination);
    343         if (destination == &in6addr_linklocal_allnodes) {
    344             interface->sent_first_beacon = true;
    345             interface->last_beacon = ioloop_timenow();;
    346         }
    347 #ifndef CONTINUE_ADVERTISING_DURING_DEPRECATION
    348         // If we are deprecating, just send the initial deprecation to shorten the preferred lifetime, and then go silent.
    349         if (interface->deprecate_deadline > now && !interface->suppress_ipv6_prefix) {
    350             INFO("suppressing ipv6 prefix on " PUB_S_SRP, interface->name);
    351             interface->suppress_ipv6_prefix = true;
    352         }
    353 #endif
    354 
    355 #ifndef RA_TESTER
    356     } else {
    357         INFO("didn't send: " PUB_S_SRP PUB_S_SRP PUB_S_SRP,
    358              route_state->partition_can_provide_routing ? "canpr" : "!canpr",
    359              route_state->partition_has_xpanid ? " route_state->xpanid" : " !route_state->xpanid",
    360              interface->our_prefix_advertised ? " advert" : " !advert");
    361     }
    362 #endif
    363     if (destination == &in6addr_linklocal_allnodes) {
    364         if (interface->num_beacons_sent < MAX_RA_RETRANSMISSION - 1) {
    365             // Schedule a beacon for between 8 and 16 seconds in the future (<MAX_INITIAL_RTR_ADVERT_INTERVAL)
    366             interface_beacon_schedule(interface, 8000 + srp_random16() % 8000);
    367         } else {
    368             interface_beacon_schedule(interface, icmp_listener.unsolicited_interval);
    369         }
    370         interface->num_beacons_sent++;
    371     }
    372 }
    373 
    374 static void
    375 interface_beacon(void *context)
    376 {
    377     interface_t *interface = context;
    378     interface_beacon_send(interface, &in6addr_linklocal_allnodes);
    379 }
    380 
    381 static void
    382 interface_beacon_schedule(interface_t *interface, unsigned when)
    383 {
    384     uint64_t now = ioloop_timenow();
    385     unsigned interval;
    386 
    387 
    388     // Make sure we haven't send an RA too recently.
    389     if (when < MIN_DELAY_BETWEEN_RAS && now - interface->last_beacon < MIN_DELAY_BETWEEN_RAS) {
    390         when = MIN_DELAY_BETWEEN_RAS;
    391     }
    392     // Add up to a second of jitter.
    393     when += srp_random16() % 1024;
    394     interface->next_beacon = now + when;
    395     if (interface->beacon_wakeup == NULL) {
    396         interface->beacon_wakeup = ioloop_wakeup_create();
    397         if (interface->beacon_wakeup == NULL) {
    398             ERROR("Unable to allocate beacon wakeup for " PUB_S_SRP, interface->name);
    399             return;
    400         }
    401     } else {
    402         // We can reschedule a beacon for sooner if we get a router solicit; in this case, we
    403         // need to cancel the existing beacon wakeup, and if there is none scheduled, this will
    404         // be a no-op.
    405         ioloop_cancel_wake_event(interface->beacon_wakeup);
    406     }
    407     if (interface->next_beacon - now > UINT_MAX) {
    408         interval = UINT_MAX;
    409     } else {
    410         interval = (unsigned)(interface->next_beacon - now);
    411     }
    412     INFO("Scheduling " PUB_S_SRP "beacon on " PUB_S_SRP " for %u milliseconds in the future",
    413          interface->sent_first_beacon ? "" : "first ", interface->name, interval);
    414     ioloop_add_wake_event(interface->beacon_wakeup, interface, interface_beacon, NULL, interval);
    415 }
    416 
    417 static void
    418 router_discovery_start(interface_t *interface)
    419 {
    420     INFO("Starting router discovery on " PUB_S_SRP, interface->name);
    421 
    422     // Immediately when an interface shows up, start doing router solicits.
    423     start_router_solicit(interface);
    424 
    425     if (interface->post_solicit_wakeup == NULL) {
    426         interface->post_solicit_wakeup = ioloop_wakeup_create();
    427         if (interface->post_solicit_wakeup == NULL) {
    428             ERROR("No memory for post-solicit RA wakeup on " PUB_S_SRP ".", interface->name);
    429         }
    430     } else {
    431         ioloop_cancel_wake_event(interface->post_solicit_wakeup);
    432     }
    433 
    434     // In 20 seconds, check the results of router discovery and update policy as needed.
    435     if (interface->post_solicit_wakeup) {
    436         ioloop_add_wake_event(interface->post_solicit_wakeup, interface, post_solicit_policy_evaluate,
    437                               NULL, 20 * 1000);
    438     }
    439     interface->router_discovery_in_progress = true;
    440     interface->router_discovery_started = true;
    441 }
    442 
    443 static void
    444 flush_routers(interface_t *interface, uint64_t now)
    445 {
    446     icmp_message_t *router, **p_router;
    447 
    448     // Flush stale routers (or all routers).
    449     for (p_router = &interface->routers; *p_router != NULL; ) {
    450         router = *p_router;
    451         if (now == 0 || now - router->received_time > MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE)  {
    452             *p_router = router->next;
    453             SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_addr_buf);
    454             INFO("flushing stale router - ifname: " PUB_S_SRP
    455                  ", router src: " PRI_SEGMENTED_IPv6_ADDR_SRP, interface->name,
    456                  SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_addr_buf));
    457             icmp_message_free(router);
    458         } else {
    459             p_router = &(*p_router)->next;
    460         }
    461     }
    462 }
    463 
    464 static void
    465 router_discovery_cancel(interface_t *interface)
    466 {
    467     if (interface->router_solicit_wakeup != NULL) {
    468         ioloop_cancel_wake_event(interface->router_solicit_wakeup);
    469     }
    470     if (interface->post_solicit_wakeup != NULL) {
    471         ioloop_cancel_wake_event(interface->post_solicit_wakeup);
    472     }
    473 #if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
    474     if (interface->vicarious_discovery_complete != NULL) {
    475         ioloop_cancel_wake_event(interface->vicarious_discovery_complete);
    476         INFO("stopping vicarious router discovery on " PUB_S_SRP, interface->name);
    477     }
    478     interface->vicarious_router_discovery_in_progress = false;
    479 #endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
    480 }
    481 
    482 static void
    483 router_discovery_stop(interface_t *interface, uint64_t now)
    484 {
    485     if (!interface->router_discovery_started) {
    486         INFO("router discovery not yet started.");
    487         return;
    488     }
    489     if (!interface->router_discovery_complete) {
    490         INFO("stopping router discovery on " PUB_S_SRP, interface->name);
    491     }
    492     router_discovery_cancel(interface);
    493     interface->router_discovery_complete = true;
    494     interface->router_discovery_in_progress = false;
    495     // clear out need_reconfigure_prefix when router_discovery_complete is set back to true.
    496     interface->need_reconfigure_prefix = false;
    497 #ifdef FLUSH_STALE_ROUTERS
    498     flush_routers(interface, now);
    499 #else
    500     (void)now;
    501 #endif // FLUSH_STALE_ROUTERS
    502 
    503     // See if we need a new prefix on the interface.
    504     interface_prefix_evaluate(interface);
    505 }
    506 
    507 #if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
    508 static void
    509 adjust_router_received_time(interface_t *const interface, const uint64_t now, const int64_t time_adjusted)
    510 {
    511     icmp_message_t *router;
    512 
    513     if (interface->routers == NULL) {
    514         if (interface->our_prefix_advertised) {
    515             SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __ipv6_prefix);
    516             INFO("No router information available for the interface - "
    517                  "ifname: " PUB_S_SRP ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
    518                  interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __ipv6_prefix));
    519         } else {
    520             INFO("No router information available for the interface - "
    521                  "ifname: " PUB_S_SRP, interface->name);
    522         }
    523 
    524         goto exit;
    525     }
    526 
    527     for (router = interface->routers; router != NULL; router = router->next) {
    528         SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_addr_buf);
    529         // Only adjust the received time once.
    530         if (router->received_time_already_adjusted) {
    531             INFO("received time already adjusted - remaining time: %llu, "
    532                   "router src: " PRI_SEGMENTED_IPv6_ADDR_SRP, (now - router->received_time) / MSEC_PER_SEC,
    533                  SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_addr_buf));
    534             continue;
    535         }
    536         require_action_quiet(
    537             (time_adjusted > 0 && (UINT64_MAX - now) > (uint64_t)time_adjusted) ||
    538             (time_adjusted < 0 && now > ((uint64_t)-time_adjusted)), exit,
    539             ERROR("adjust_router_received_time: invalid adjusted values is causing overflow - "
    540                   "now: %" PRIu64 ", time_adjusted: %" PRId64, now, time_adjusted));
    541         router->received_time = now + time_adjusted;
    542         router->received_time_already_adjusted = true; // Only adjust the icmp message received time once.
    543         INFO("router received time is adjusted - router src: " PRI_SEGMENTED_IPv6_ADDR_SRP
    544               ", adjusted value: %" PRId64,
    545              SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_addr_buf), time_adjusted);
    546     }
    547 
    548 exit:
    549     return;
    550 }
    551 
    552 static void
    553 make_all_routers_nearly_stale(interface_t *interface, uint64_t now)
    554 {
    555     // Make every router go stale in 19.999 seconds.   This means that if we don't get a response
    556     // to our solicit in 20 seconds, then when the timeout callback is called, there will be no
    557     // routers on the interface that aren't stale, which will trigger router discovery.
    558     adjust_router_received_time(interface, now, 19999 - 600 * MSEC_PER_SEC);
    559 }
    560 
    561 static void
    562 vicarious_discovery_callback(void *context)
    563 {
    564     interface_t *interface = context;
    565     INFO("Vicarious router discovery finished on " PUB_S_SRP ".", interface->name);
    566     interface->vicarious_router_discovery_in_progress = false;
    567     // At this point, policy evaluate will show all the routes that were present before vicarious
    568     // discovery as stale, so policy_evaluate will start router discovery if we didn't get any
    569     // RAs containing on-link prefixes.
    570     routing_policy_evaluate(interface, false);
    571 }
    572 #endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
    573 
    574 #ifndef RA_TESTER
    575 static void
    576 routing_policy_evaluate_all_interfaces(route_state_t *route_state, bool assume_changed)
    577 {
    578     interface_t *interface;
    579 
    580     for (interface = route_state->interfaces; interface; interface = interface->next) {
    581         routing_policy_evaluate(interface, assume_changed);
    582     }
    583 }
    584 #endif
    585 
    586 #ifdef FLUSH_STALE_ROUTERS
    587 static void
    588 stale_router_policy_evaluate(void *context)
    589 {
    590     interface_t *interface = context;
    591     INFO("Evaluating stale routers on " PUB_S_SRP, interface->name);
    592 
    593     flush_routers(interface, ioloop_timenow());
    594 
    595     // See if we need a new prefix on the interface.
    596     interface_prefix_evaluate(interface);
    597 
    598     routing_policy_evaluate(interface, true);
    599 }
    600 #endif // FLUSH_STALE_ROUTERS
    601 
    602 static bool
    603 prefix_usable(interface_t *interface, route_state_t *route_state, icmp_message_t *router, prefix_information_t *prefix)
    604 {
    605     SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
    606     SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_addr_buf);
    607     // It needs to be on link, autoconfiguration enabled, or have the managed flag set and we are allowing DHCPv6-only
    608     // prefixes (not by default). And the preferred lifetime needs to be >0 (maybe should be >= 1800?)
    609     if (!((prefix->flags & ND_OPT_PI_FLAG_ONLINK) &&
    610           ((prefix->flags & ND_OPT_PI_FLAG_AUTO) ||
    611            (route_state->config_enable_dhcpv6_prefixes && (router->flags & ND_RA_FLAG_MANAGED))) &&
    612           prefix->preferred_lifetime > 300))
    613     {
    614         INFO("Router " PRI_SEGMENTED_IPv6_ADDR_SRP
    615              " is advertising prefix " PRI_SEGMENTED_IPv6_ADDR_SRP ": %sonlink, %sautoconf, %sdhcp, preferred = %d",
    616              SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    617              SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_addr_buf),
    618              bool_str(prefix->flags & ND_OPT_PI_FLAG_ONLINK),
    619              bool_str(prefix->flags & ND_OPT_PI_FLAG_AUTO),
    620              bool_str(route_state->config_enable_dhcpv6_prefixes && (router->flags & ND_RA_FLAG_MANAGED)),
    621              prefix->preferred_lifetime);
    622         return false;
    623     }
    624     int cmp = in6prefix_compare(&prefix->prefix, &route_state->xpanid_prefix, 8);
    625     if (!cmp)
    626     {
    627         INFO("Router " PRI_SEGMENTED_IPv6_ADDR_SRP
    628              " is advertising xpanid prefix " PRI_SEGMENTED_IPv6_ADDR_SRP ": not considering it usable",
    629              SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    630              SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_addr_buf));
    631         // If it's the xpanid prefix, we will also advertise the xpanid prefix
    632         return false;
    633     }
    634 
    635     // If this is a stub router, and we are advertising our own prefix, and the PIO it is advertising is greater than
    636     // the one we are advertising, then we keep advertising ours.
    637     if (interface->our_prefix_advertised && router->stub_router && cmp > 0) {
    638         INFO("Router " PRI_SEGMENTED_IPv6_ADDR_SRP
    639              " is a stub router advertising prefix " PRI_SEGMENTED_IPv6_ADDR_SRP ", which loses the election and is not usable",
    640              SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    641              SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_addr_buf));
    642         return false;
    643     }
    644     INFO("Router " PRI_SEGMENTED_IPv6_ADDR_SRP
    645          " is " PUB_S_SRP "advertising prefix " PRI_SEGMENTED_IPv6_ADDR_SRP ", which is usable",
    646          SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    647          router->stub_router ? "a stub router " : "",
    648          SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_addr_buf));
    649     return true;
    650 }
    651 
    652 static void
    653 routing_policy_evaluate(interface_t *interface, bool assume_changed)
    654 {
    655     icmp_message_t *router;
    656     bool new_prefix = false;    // new prefix means that srp-mdns-proxy received a new prefix from the wire, which it
    657                                 // did not know before.
    658     bool on_link_prefix_present = false;
    659     bool something_changed = assume_changed;
    660     uint64_t now = ioloop_timenow();
    661     bool stale_routers_exist = false;
    662     uint64_t stale_refresh_time = 0;
    663     route_state_t *route_state = interface->route_state;
    664 
    665     // No action on interfaces that aren't eligible for routing or that isn't currently active.
    666     if (interface->ineligible || interface->inactive) {
    667         INFO("not evaluating policy on " PUB_S_SRP " because it's " PUB_S_SRP, interface->name,
    668              interface->ineligible ? "ineligible" : "inactive");
    669         return;
    670     }
    671 
    672     // We can't tell whether any particular prefix is usable until we've gotten the xpanid.
    673     if (route_state->have_xpanid_prefix) {
    674         // Look at all the router advertisements we've seen to see if any contain a usable prefix which is not the
    675         // prefix we'd advertise. Routers advertising that prefix are all Thread BRs, and it's fine for more than
    676         // one router to advertise a prefix, so we will also advertise it for redundancy.
    677         for (router = interface->routers; router; router = router->next) {
    678             icmp_option_t *option = router->options;
    679             int i;
    680             bool usable = false;
    681             for (i = 0; i < router->num_options; i++, option++) {
    682                 if (option->type == icmp_option_prefix_information) {
    683                     prefix_information_t *prefix = &option->option.prefix_information;
    684 #ifndef RA_TESTER
    685                     omr_publisher_check_prefix(route_state->omr_publisher, &prefix->prefix, prefix->length);
    686 #endif
    687                     if (prefix_usable(interface, route_state, router, prefix)) {
    688                         // We don't consider the prefix we would advertise to be infrastructure-provided if we see it
    689                         // advertised by another router, because that router is also a Thread BR, and we don't want
    690                         // to get into dueling prefixes with it.
    691                         if (in6prefix_compare(&option->option.prefix_information.prefix, &route_state->xpanid_prefix, 8))
    692                         {
    693                             uint32_t preferred_lifetime_offset = MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE / MSEC_PER_SEC;
    694                             uint32_t preferred_lifetime = prefix->preferred_lifetime;
    695 
    696                             // Infinite preferred lifetime. Bogus.
    697                             if (preferred_lifetime == UINT32_MAX) {
    698                                 preferred_lifetime = 60 * 60;   // One hour
    699                             }
    700 
    701                             // If the remaining time on this prefix is less than the stale time gap, use an offset that's the
    702                             // valid lifetime minus sixty seconds so that we have time if the prefix expires.
    703                             if (preferred_lifetime < preferred_lifetime_offset + 60) {
    704                                 // If the preferred lifetime is less than a minute, we're not going to count this as a valid
    705                                 // on-link prefix.
    706                                 if (preferred_lifetime < 60) {
    707                                     SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
    708                                     SEGMENTED_IPv6_ADDR_GEN_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf);
    709                                     INFO("router " PRI_SEGMENTED_IPv6_ADDR_SRP " advertising " PRI_SEGMENTED_IPv6_ADDR_SRP
    710                                          " has a preferred lifetime of %d, which is not enough to count as usable.",
    711                                          SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    712                                          SEGMENTED_IPv6_ADDR_PARAM_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf),
    713                                          preferred_lifetime);
    714                                     continue;
    715                                 }
    716                                 preferred_lifetime_offset = preferred_lifetime - 60;
    717                             }
    718 
    719                             // Lifetimes are in seconds, but henceforth we will compare with clock times, which are in ms.
    720                             preferred_lifetime_offset *= MSEC_PER_SEC;
    721 
    722                             // If the prefix' preferred lifetime plus the time received is in the past, the prefix doesn't
    723                             // count as an on-link prefix that's present.
    724                             if (router->received_time + preferred_lifetime_offset < now) {
    725                                 SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
    726                                 SEGMENTED_IPv6_ADDR_GEN_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf);
    727                                 INFO("router " PRI_SEGMENTED_IPv6_ADDR_SRP " advertising " PRI_SEGMENTED_IPv6_ADDR_SRP
    728                                      " was received %d seconds ago with a preferred lifetime of %d.",
    729                                      SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    730                                      SEGMENTED_IPv6_ADDR_PARAM_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf),
    731                                      (int)((now - router->received_time) / 1000), preferred_lifetime);
    732 
    733                                 continue;
    734                             }
    735 
    736                             // This prefix is in principle usable. It may not actually be usable if it is stale, but we mark it usable so it
    737                             // will continue to be probed.
    738                             usable = true;
    739 
    740                             // router->reachable will be true immediately after receiving a router advertisement until we do a
    741                             // probe and don't get a response. It will become true again if, during a later probe, we get a
    742                             // response.
    743                             if (!router->reachable) {
    744                                 SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
    745                                 SEGMENTED_IPv6_ADDR_GEN_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf);
    746                                 INFO("router %p " PRI_SEGMENTED_IPv6_ADDR_SRP " advertising %d %p " PRI_SEGMENTED_IPv6_ADDR_SRP
    747                                      " was last known to be reachable %d seconds ago.",
    748                                      router,
    749                                      SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
    750                                      i, option,
    751                                      SEGMENTED_IPv6_ADDR_PARAM_SRP(option->option.prefix_information.prefix.s6_addr, pref_buf),
    752                                      (int)((now - router->latest_na) / 1000));
    753                                 continue;
    754                             }
    755 
    756                             // Otherwise, if this router's on-link prefix will expire later than any other we've seen
    757                             if (stale_refresh_time < router->received_time + preferred_lifetime_offset) {
    758                                 stale_refresh_time = router->received_time + preferred_lifetime_offset;
    759                             }
    760 
    761                             // If this is a new icmp_message received now and contains PIO.
    762                             if (router->new_router) {
    763                                 new_prefix = true;
    764                                 router->new_router = false; // clear the bit since srp-mdns-proxy already processed it.
    765                             }
    766 
    767                             // This router has a usable prefix.
    768                             usable = true;
    769 
    770                             // Right now all we need is to see if there is an on-link prefix.
    771                             on_link_prefix_present = true;
    772                             SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_add_buf);
    773                             SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, __pio_prefix_buf);
    774                             INFO("router has usable PIO - ifname: " PUB_S_SRP ", router src: " PRI_SEGMENTED_IPv6_ADDR_SRP
    775                                  ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
    776                                  interface->name,
    777                                  SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_add_buf),
    778                                  SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, __pio_prefix_buf));
    779                         } else {
    780                             SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
    781                             INFO("Router " PRI_SEGMENTED_IPv6_ADDR_SRP
    782                                  " is advertising the xpanid prefix: not counting as usable ",
    783                                  SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf));
    784                         }
    785                     } else {
    786                         SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, __router_src_add_buf);
    787                         SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, __pio_prefix_buf);
    788                         INFO("router has unusable PIO - ifname: " PUB_S_SRP ", router src: " PRI_SEGMENTED_IPv6_ADDR_SRP
    789                              ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
    790                              interface->name,
    791                              SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, __router_src_add_buf),
    792                              SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, __pio_prefix_buf));
    793                     }
    794                 }
    795             }
    796             // Remember whether or not this router has a usable prefix.
    797             router->usable = usable;
    798         }
    799     }
    800 
    801     INFO("policy on " PUB_S_SRP ": " PUB_S_SRP "stale " /* stale_routers_exist ? */
    802          PUB_S_SRP "started " /* interface->router_discovery_started ? */
    803          PUB_S_SRP "disco " /* interface->router_discovery_complete ? */
    804          PUB_S_SRP "present " /* on_link_prefix_present ? */
    805          PUB_S_SRP "advert " /* interface->our_prefix_advertised ? */
    806          PUB_S_SRP "conf " /* interface->on_link_prefix_configured ? */
    807          PUB_S_SRP "new_prefix " /* new_prefix ? */
    808          "preferred = %" PRIu32 " valid = %" PRIu32 " deadline = %" PRIu64,
    809          interface->name, stale_routers_exist ? "" : "!", interface->router_discovery_started ? "" : "!",
    810          interface->router_discovery_complete ? "" : "!",
    811          on_link_prefix_present ? "" : "!", interface->our_prefix_advertised ? "" : "!",
    812          interface->on_link_prefix_configured ? "" : "!", new_prefix ? "" : "!",
    813          interface->preferred_lifetime, interface->valid_lifetime, interface->deprecate_deadline);
    814 
    815     // If there are stale routers, start doing router discovery again to see if we can get them to respond.
    816     // Note that doing router discover just because we haven't seen an RA is actually not allowed in RFC 4861,
    817     // so this shouldn't be enabled.
    818     // Also, if we have not yet done router discovery, do it now.
    819     if ((!interface->router_discovery_started || !interface->router_discovery_complete
    820 #if SRP_FEATURE_STALE_ROUTER_DISCOVERY
    821          || stale_routers_exist
    822 #endif //SRP_FEATURE_STALE_ROUTER_DISCOVERY
    823             ) && !on_link_prefix_present) {
    824         if (!interface->router_discovery_in_progress) {
    825             // Start router discovery.
    826             INFO("starting router discovery");
    827             router_discovery_start(interface);
    828         } else {
    829             INFO("router discovery in progress");
    830         }
    831     }
    832     // If we are advertising a prefix and there's another on-link prefix, deprecate the one we are
    833     // advertising.
    834     else if (interface->our_prefix_advertised && on_link_prefix_present) {
    835         // If we have been advertising a preferred prefix, deprecate it.
    836         SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
    837         if (interface->preferred_lifetime == BR_PREFIX_LIFETIME) {
    838             INFO("routing_policy_evaluate: deprecating interface prefix in 30 minutes - prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
    839                  SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
    840             interface->deprecate_deadline = now + BR_PREFIX_LIFETIME * 1000;
    841             something_changed = true;
    842             interface->preferred_lifetime = 0;
    843         } else {
    844             INFO("prefix deprecating in progress - prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
    845                  SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
    846         }
    847     }
    848     // If there is no on-link prefix and we aren't advertising, or have deprecated, start advertising
    849     // again (or for the first time).
    850     else if (!on_link_prefix_present && interface->router_discovery_complete && route_state->have_xpanid_prefix &&
    851              (!interface->our_prefix_advertised || interface->deprecate_deadline != 0 ||
    852               interface->preferred_lifetime == 0)) {
    853 
    854         SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
    855         INFO("advertising prefix again - ifname: " PUB_S_SRP
    856              ", prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP, interface->name,
    857              SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
    858 
    859         // If we were deprecating, stop.
    860         ioloop_cancel_wake_event(interface->deconfigure_wakeup);
    861         interface->deprecate_deadline = 0;
    862 
    863         // Start advertising immediately, 30 minutes.
    864         interface->preferred_lifetime = interface->valid_lifetime = BR_PREFIX_LIFETIME;
    865 
    866         // If the on-link prefix isn't configured on the interface, do that.
    867         if (!interface->on_link_prefix_configured) {
    868 #ifndef RA_TESTER
    869             if (!interface->is_thread) {
    870 #endif
    871                 interface_prefix_configure(interface->ipv6_prefix, interface);
    872 #ifndef RA_TESTER
    873             } else {
    874                 INFO("Not setting up " PUB_S_SRP " because it is the thread interface", interface->name);
    875             }
    876 #endif
    877         } else {
    878             // Configuring the on-link prefix takes a while, so we want to re-evaluate after it's finished.
    879             interface->our_prefix_advertised = true;
    880             something_changed = true;
    881         }
    882     }
    883     // If there is no on-link prefix present, and srp-mdns-proxy itself is advertising the prefix, and it has configured
    884     // an on-link prefix, and the interface is not thread interface, and it just got an interface address removal event,
    885     // it is possible that the IPv6 routing has been flushed due to loss of address in configd, so here we explicitly
    886     // reconfigure the IPv6 prefix and the routing.
    887     else if (interface->need_reconfigure_prefix && !on_link_prefix_present && interface->our_prefix_advertised &&
    888              interface->on_link_prefix_configured && !interface->is_thread) {
    889         SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf);
    890         INFO("reconfigure ipv6 prefix due to possible network changes -"
    891              " prefix: " PRI_SEGMENTED_IPv6_ADDR_SRP,
    892              SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, __prefix_buf));
    893         interface_prefix_configure(interface->ipv6_prefix, interface);
    894         interface->need_reconfigure_prefix = false;
    895     }
    896 
    897     // If the on-link prefix goes away, stop suppressing the one we've been advertising (if it's still valid).
    898     if (!on_link_prefix_present && interface->suppress_ipv6_prefix) {
    899         INFO("un-suppressing ipv6 prefix.");
    900         interface->suppress_ipv6_prefix = false;
    901     }
    902 
    903     // If we've been looking to see if there's an on-link prefix, and we got one from the new router advertisement,
    904     // stop looking for new one.
    905     if (new_prefix) {
    906         router_discovery_stop(interface, now);
    907     }
    908 
    909     // If anything changed, do an immediate beacon; otherwise wait until the next one.
    910     // Also when something changed, set the number of transmissions back to zero so that
    911     // we send a few initial beacons quickly for reliability.
    912     if (something_changed) {
    913         INFO("change on " PUB_S_SRP ": " PUB_S_SRP "started " PUB_S_SRP "disco " PUB_S_SRP "present " PUB_S_SRP "advert " PUB_S_SRP
    914              "conf preferred = %" PRIu32 " valid = %" PRIu32 " deadline = %" PRIu64,
    915              interface->name, interface->router_discovery_started ? "" : "!",
    916              interface->router_discovery_complete ? "" : "!", on_link_prefix_present ? "" : "!",
    917              interface->our_prefix_advertised ? "" : "!", interface->on_link_prefix_configured ? "" : "!",
    918              interface->preferred_lifetime,
    919              interface->valid_lifetime, interface->deprecate_deadline);
    920         interface->num_beacons_sent = 0;
    921         interface_beacon_schedule(interface, 0);
    922     }
    923 
    924     // It's possible for us to start configuring the interface because there's no on-link prefix, and then see
    925     // an advertisement for an on-link prefix before interface configuration completes. When this happens, we
    926     // need to delete the address we just configured, because we're not going to be advertising it. We always
    927     // get a policy re-evaluation event when interface configuration completes, so this will happen immediately.
    928     // At this point we have not yet sent a router advertisement with the prefix, so even though it has a preferred
    929     // lifetime of about 1800 seconds here, we can safely set it to zero without leaving stale information
    930     // in any host's routing table.
    931     if (!interface->our_prefix_advertised && interface->on_link_prefix_configured) {
    932         INFO("on-link prefix appeared during interface configuration. removing");
    933         interface->preferred_lifetime = 0;
    934         interface_prefix_deconfigure(interface);
    935     }
    936 
    937 #ifdef FLUSH_STALE_ROUTERS
    938     // If we have an on-link prefix, schedule a policy re-evaluation at the stale router interval.
    939     if (on_link_prefix_present) {
    940         if (stale_refresh_time < now) {
    941             ERROR("Stale refresh time is in the past: %" PRIu64 "!", stale_refresh_time);
    942         } else {
    943             // The math used to compute refresh timeout guarantees that refresh_timeout will be <10 minutes.
    944             int refresh_timeout = (int)(stale_refresh_time - now);
    945 
    946             if (interface->stale_evaluation_wakeup == NULL) {
    947                 interface->stale_evaluation_wakeup = ioloop_wakeup_create();
    948                 if (interface->stale_evaluation_wakeup == NULL) {
    949                     ERROR("No memory for stale router evaluation wakeup on " PUB_S_SRP ".", interface->name);
    950                 }
    951             } else {
    952                 ioloop_cancel_wake_event(interface->stale_evaluation_wakeup);
    953             }
    954             ioloop_add_wake_event(interface->stale_evaluation_wakeup,
    955                                   interface, stale_router_policy_evaluate, NULL, refresh_timeout);
    956         }
    957     }
    958 #endif // FLUSH_STALE_ROUTERS
    959 
    960     // Once router discovery is complete, start doing aliveness checks on whatever we discovered (if anything).
    961     if (interface->last_router_probe == 0 && interface->router_discovery_started && interface->router_discovery_complete) {
    962         schedule_next_router_probe(interface);
    963     }
    964 
    965 #ifndef RA_TESTER
    966     if (route_state->route_tracker != NULL) {
    967         route_tracker_route_state_changed(route_state->route_tracker, interface);
    968     }
    969 #endif
    970 }
    971 
    972 #if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
    973 static void
    974 start_vicarious_router_discovery_if_appropriate(interface_t *const interface)
    975 {
    976     if (!interface->our_prefix_advertised &&
    977         !interface->vicarious_router_discovery_in_progress && !interface->router_discovery_in_progress)
    978     {
    979         if (interface->vicarious_discovery_complete == NULL) {
    980             interface->vicarious_discovery_complete = ioloop_wakeup_create();
    981         } else {
    982             ioloop_cancel_wake_event(interface->vicarious_discovery_complete);
    983         }
    984         if (interface->vicarious_discovery_complete != NULL) {
    985             ioloop_add_wake_event(interface->vicarious_discovery_complete,
    986                                   interface, vicarious_discovery_callback, NULL, 20 * 1000);
    987             interface->vicarious_router_discovery_in_progress = true;
    988         }
    989         // In order for vicarious router discovery to be useful, we need all of the routers
    990         // that were present when the first solicit was received to be stale when we give up
    991         // on vicarious discovery.  If we got any router advertisements, these will not be
    992         // stale, and that means vicarious discovery succeeded.
    993         make_all_routers_nearly_stale(interface, ioloop_timenow());
    994         INFO("Starting vicarious router discovery on " PUB_S_SRP,
    995              interface->name);
    996     }
    997 }
    998 #endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
    999 
   1000 static void
   1001 retransmit_unicast_beacon(void *context)
   1002 {
   1003     icmp_message_t *message = context;
   1004 
   1005     // Schedule retranmsission
   1006     interface_beacon_send(message->interface, &message->source);
   1007     ioloop_add_wake_event(message->wakeup, message, retransmit_unicast_beacon, NULL,
   1008                           MIN_DELAY_BETWEEN_RAS + srp_random16() % RA_FUZZ_TIME);
   1009 
   1010     // Discontinue retransmission after the third we've sent.
   1011     if (message->messages_sent++ > 2) {
   1012         icmp_message_t **sp = &message->interface->solicits;
   1013         while (*sp != NULL) {
   1014             if (*sp == message) {
   1015                 *sp = message->next;
   1016                 icmp_message_free(message);
   1017                 break;
   1018             } else {
   1019                 sp = &(*sp)->next;
   1020             }
   1021         }
   1022     }
   1023 }
   1024 
   1025 // This gets called to check to see if any of the usable routers are still responding. It gets called whenever
   1026 // we get a router solicit, to ensure that the solicit gets a quick response, and also gets called once every
   1027 // minute so that we quickly notice when a router becomes unreachable.
   1028 
   1029 static void
   1030 send_router_probes(void *context)
   1031 {
   1032     interface_t *interface = context;
   1033 
   1034     // After sending three probes, do a policy evaluation.
   1035     if (interface->num_solicits_sent++ > MAX_NS_RETRANSMISSIONS - 1) {
   1036         // Mark routers from which we received neighbor advertises during the probe as reachable. Routers
   1037         // that did not respond are no longer reachable.
   1038         for (icmp_message_t *router = interface->routers; router != NULL; router = router->next) {
   1039             SEGMENTED_IPv6_ADDR_GEN_SRP(router->source.s6_addr, router_src_addr_buf);
   1040             INFO("router (%p) " PRI_SEGMENTED_IPv6_ADDR_SRP " was " PUB_S_SRP "reached during probing.", router,
   1041                  SEGMENTED_IPv6_ADDR_PARAM_SRP(router->source.s6_addr, router_src_addr_buf),
   1042                  router->reached ? "" : "not ");
   1043             router->reachable = router->reached;
   1044         }
   1045         routing_policy_evaluate(interface, false);
   1046         schedule_next_router_probe(interface);
   1047         return;
   1048     }
   1049 
   1050     // Send Neighbor Solicits to any usable routers that haven't responded yet and schedule the next call to
   1051     // send_router_probes...
   1052     for (icmp_message_t *router = interface->routers; router != NULL; router = router->next) {
   1053         // Don't probe routers that aren't usable, and don't re-probe a router that's already responded in this probe cycle.
   1054         if (!router->usable || router->reached) {
   1055             continue;
   1056         }
   1057         neighbor_solicit_send(router->interface, &router->source);
   1058     }
   1059     ioloop_add_wake_event(interface->neighbor_solicit_wakeup, interface, send_router_probes, NULL,
   1060                           MIN_DELAY_BETWEEN_RAS + srp_random16() % RA_FUZZ_TIME);
   1061 }
   1062 
   1063 static void
   1064 check_router_aliveness(void *context)
   1065 {
   1066     interface_t *interface = context;
   1067 
   1068     if (!interface->probing) {
   1069         interface->probing = true;
   1070         if (interface->neighbor_solicit_wakeup == NULL) {
   1071             interface->neighbor_solicit_wakeup = ioloop_wakeup_create();
   1072         }
   1073         if (interface->neighbor_solicit_wakeup != NULL) {
   1074             interface->num_solicits_sent = 0;
   1075             // Clear the reached flag on all routers
   1076             for (icmp_message_t *router = interface->routers; router != NULL; router = router->next) {
   1077                 router->reached = false;
   1078             }
   1079             send_router_probes(interface);
   1080         }
   1081     }
   1082 }
   1083 
   1084 static void
   1085 schedule_next_router_probe(interface_t *interface)
   1086 {
   1087     if (interface->router_probe_wakeup == NULL) {
   1088         interface->router_probe_wakeup = ioloop_wakeup_create();
   1089     }
   1090     if (interface->router_probe_wakeup != NULL) {
   1091         INFO("scheduling router probe in 60 seconds.");
   1092         ioloop_add_wake_event(interface->router_probe_wakeup, interface, check_router_aliveness, NULL, 60 * 1000);
   1093         interface->probing = false;
   1094         interface->last_router_probe = ioloop_timenow();
   1095     }
   1096 }
   1097 
   1098 void
   1099 router_solicit(icmp_message_t *message)
   1100 {
   1101     interface_t *iface, *interface;
   1102     bool is_retransmission = false;
   1103 
   1104 
   1105     // Further validate the message
   1106     if (message->hop_limit != 255 || message->code != 0) {
   1107         ERROR("Invalid router solicitation, hop limit = %d, code = %d", message->hop_limit, message->code);
   1108         goto out;
   1109     }
   1110     if (IN6_IS_ADDR_UNSPECIFIED(&message->source)) {
   1111         icmp_option_t *option = message->options;
   1112         int i;
   1113         for (i = 0; i < message->num_options; i++) {
   1114             if (option->type == icmp_option_source_link_layer_address) {
   1115                 ERROR("source link layer address in router solicitation from unspecified IP address");
   1116                 goto out;
   1117             }
   1118             option++;
   1119         }
   1120     } else {
   1121         // Make sure it's not from this host
   1122         for (iface = message->route_state->interfaces; iface; iface = iface->next) {
   1123             if (iface->have_link_layer_address && !in6addr_compare(&message->source, &iface->link_local)) {
   1124                 INFO("dropping router solicitation sent from this host.");
   1125                 goto out;
   1126             }
   1127         }
   1128     }
   1129     interface = message->interface;
   1130 
   1131     SEGMENTED_IPv6_ADDR_GEN_SRP(message->source.s6_addr, source_buf);
   1132     INFO(PUB_S_SRP " solicit on " PUB_S_SRP ": source address is " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1133          is_retransmission ? "retransmitted" : "initial",
   1134          message->interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(message->source.s6_addr, source_buf));
   1135 
   1136     // See if this is a retransmission...
   1137     icmp_message_t **sp;
   1138     sp = &interface->solicits;
   1139     while (*sp != NULL) {
   1140         icmp_message_t *solicit = *sp;
   1141         // Same source? Not already found?
   1142         if (!is_retransmission && !in6addr_compare(&message->source, &solicit->source)) {
   1143             uint64_t now = ioloop_timenow();
   1144             // RFC 4861 limits RS transmissions to 3, separated by four seconds. Allowing for a bit of slop,
   1145             // if it was received in the past 15 seconds, this is a retransmission.
   1146             if (now - solicit->received_time > 15 * 1000) {
   1147                 *sp = solicit->next;
   1148                 icmp_message_free(solicit);
   1149             } else {
   1150                 solicit->retransmissions_received++;
   1151                 is_retransmission = true;
   1152 
   1153                 // Since this is a retransmission, that hints that there might not be any live routers
   1154                 // on this link, so check to see if the routers we are aware of are alive.
   1155                 check_router_aliveness(interface);
   1156 
   1157                 sp = &(*sp)->next;
   1158             }
   1159         } else {
   1160             sp = &(*sp)->next;
   1161         }
   1162     }
   1163 
   1164     // Schedule an immediate send. If this is a retransmission, just let our retransmission schedule
   1165     // dictate when to send the next one.
   1166     if (!is_retransmission && !interface->ineligible && !interface->inactive) {
   1167         message->wakeup = ioloop_wakeup_create();
   1168         if (message->wakeup == NULL) {
   1169             ERROR("no memory for solicit wakeup.");
   1170         } else {
   1171             // Save the message for later
   1172             *sp = message;
   1173             // Start the unicast RA transmission train for this RS.
   1174             retransmit_unicast_beacon(message);
   1175             message = NULL;
   1176         }
   1177     } else {
   1178         INFO("not sending a router advertisement.");
   1179     }
   1180 
   1181 #if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
   1182     // When we receive a router solicit, it means that a host is looking for a router.   We should
   1183     // expect to hear replies if they are multicast.   If we hear no replies, it could mean there is
   1184     // no on-link prefix.   In this case, we restart our own router discovery process.  There is no
   1185     // need to do this if we are the one advertising a prefix.
   1186     start_vicarious_router_discovery_if_appropriate(interface);
   1187 #endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
   1188 out:
   1189     if (message != NULL) {
   1190         icmp_message_free(message);
   1191     }
   1192 }
   1193 
   1194 void
   1195 router_advertisement(icmp_message_t *message)
   1196 {
   1197     interface_t *iface;
   1198     icmp_message_t *router, **rp;
   1199     if (message->hop_limit != 255 || message->code != 0 || !IN6_IS_ADDR_LINKLOCAL(&message->source)) {
   1200         ERROR("Invalid router advertisement, hop limit = %d, code = %d", message->hop_limit, message->code);
   1201         icmp_message_free(message);
   1202         return;
   1203     }
   1204     for (iface = message->route_state->interfaces; iface != NULL; iface = iface->next) {
   1205         if (iface->have_link_layer_address && !in6addr_compare(&message->source, &iface->link_local)) {
   1206             INFO("dropping router advertisement sent from this host.");
   1207             icmp_message_free(message);
   1208             return;
   1209         }
   1210     }
   1211 
   1212     // See if we've had a previous advertisement from this router. Note that routers can send more than one
   1213     // RA to advertise more data than will fit in one RA, but in practice routers tend not to do this, and how
   1214     // this is supposed to work is not clearly specified. From RFC4861:
   1215     //
   1216     //    If including all options causes the size of an advertisement to
   1217     //    exceed the link MTU, multiple advertisements can be sent, each
   1218     //    containing a subset of the options.
   1219     //
   1220     // If this happens, we're going to wind up using the last RA in the sequence. Ideally we'd do some work to marshal
   1221     // RA trains. This is too much work to do in a current milestone. The issue is tracked in rdar://105200987
   1222     // (Restructure handling of incoming router advertisements so as to marshal the data in case we get more than one RA
   1223     // from the same router with different data.)
   1224     for (rp = &message->interface->routers; *rp != NULL; rp = &(*rp)->next) {
   1225         router = *rp;
   1226         // The new RA is from the same router as this previous RA.
   1227         if (!in6addr_compare(&router->source, &message->source)) {
   1228             message->next = router->next;
   1229             *rp = message;
   1230             icmp_message_free(router);
   1231             break;
   1232         }
   1233     }
   1234     // If we got rid of the old RA, *rp will be non-NULL. If we didn't find a match for the old RA, or if we
   1235     // need to keep the old RA, then *rp will be NULL, meaning that we should keep the new RA.
   1236     if (*rp == NULL) {
   1237         *rp = message;
   1238     }
   1239 
   1240     // When we receive an RA, we can assume that the router is reachable, and skip immediately probing with a
   1241     // neighbor solicit.
   1242     message->latest_na = message->received_time;
   1243     message->reachable = true;
   1244     message->reached = true;
   1245 
   1246     // Check for the stub router flag here so that we have it when scanning PIOs for usability.
   1247     for (int i = 0; i < message->num_options; i++) {
   1248         icmp_option_t *option = &message->options[i];
   1249         if (option->type == icmp_option_ra_flags_extension) {
   1250             if (option->option.ra_flags_extension[0] & RA_FLAGS1_STUB_ROUTER) {
   1251                 message->stub_router = true;
   1252             }
   1253         }
   1254     }
   1255     // Something may have changed, so do a policy recalculation for this interface
   1256     routing_policy_evaluate(message->interface, false);
   1257 }
   1258 
   1259 void
   1260 neighbor_advertisement(icmp_message_t *message)
   1261 {
   1262     if (message->hop_limit != 255 || message->code != 0) {
   1263         ERROR("Invalid neighbor advertisement, hop limit = %d, code = %d", message->hop_limit, message->code);
   1264         return;
   1265     }
   1266 
   1267     // If this NA matches a router that has advertised a usable prefix, mark the router as alive by setting the
   1268     // "latest_na" value to the current time. We don't care about NAs for routers that are not advertising a usable
   1269     // prefix.
   1270     for (icmp_message_t *router = message->interface->routers; router != NULL; router = router->next) {
   1271         if (!in6addr_compare(&message->source, &router->source)) {
   1272             // Only log for usable routers, to avoid a lot of extra noise. However, we don't actually probe routers that
   1273             // aren't usable, so generally speaking this test will always be true.
   1274             if (router->usable) {
   1275                 SEGMENTED_IPv6_ADDR_GEN_SRP(message->source.s6_addr, source_buf);
   1276                 INFO("usable neighbor advertisement recieved on " PUB_S_SRP " from " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1277                      message->interface->name, SEGMENTED_IPv6_ADDR_PARAM_SRP(message->source.s6_addr, source_buf));
   1278             }
   1279             router->latest_na = ioloop_timenow();
   1280             router->reached = true;
   1281             router->reachable = true;
   1282         }
   1283     }
   1284     return;
   1285 }
   1286 
   1287 #if   defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IPCONFIG) || \
   1288       defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IFCONFIG)
   1289 static void
   1290 link_route_done(void *context, int status, const char *error)
   1291 {
   1292     interface_t *interface = context;
   1293 
   1294     if (error != NULL) {
   1295         ERROR("link_route_done on " PUB_S_SRP ": " PUB_S_SRP, interface->name, error);
   1296     } else {
   1297         INFO("link_route_done on " PUB_S_SRP ": %d.", interface->name, status);
   1298     }
   1299     ioloop_subproc_release(interface->link_route_adder_process);
   1300     interface->link_route_adder_process = NULL;
   1301     // Now that the on-link prefix is configured, time for a policy re-evaluation.
   1302     interface->on_link_prefix_configured = true;
   1303     routing_policy_evaluate(interface, true);
   1304 }
   1305 #endif
   1306 
   1307 static void
   1308 interface_prefix_configure(struct in6_addr prefix, interface_t *interface)
   1309 {
   1310     int sock;
   1311     route_state_t *route_state = interface->route_state;
   1312 
   1313     sock = socket(PF_INET6, SOCK_DGRAM, 0);
   1314     if (sock < 0) {
   1315         ERROR("interface_prefix_configure: socket(PF_INET6, SOCK_DGRAM, 0) failed " PUB_S_SRP ": " PUB_S_SRP,
   1316               interface->name, strerror(errno));
   1317         return;
   1318     }
   1319 #ifdef CONFIGURE_STATIC_INTERFACE_ADDRESSES
   1320     struct in6_addr interface_address = prefix;
   1321     char addrbuf[INET6_ADDRSTRLEN + 4];
   1322     // Use our ULA prefix as the host identifier.
   1323     memcpy(&interface_address.s6_addr[10], &route_state->srp_server->ula_prefix.s6_addr[0], 6);
   1324     interface_address.s6_addr[8] = (interface->index >> 8) & 255;
   1325     interface_address.s6_addr[9] = interface->index & 255;
   1326     inet_ntop(AF_INET6, &interface_address, addrbuf, INET6_ADDRSTRLEN);
   1327 #if   defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IPCONFIG)
   1328     char *args[] = { "set", interface->name, "MANUAL-V6", addrbuf, "64" };
   1329 
   1330     if (interface->link_route_adder_process != NULL) {
   1331         ERROR("interface_prefix_configure: " PUB_S_SRP " already configuring the route.", interface->name);
   1332         return;
   1333     }
   1334     INFO("/sbin/ipconfig " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " " PUB_S_SRP " "
   1335          PUB_S_SRP, args[0], args[1], args[2], args[3], args[4]);
   1336     interface->link_route_adder_process = ioloop_subproc("/usr/sbin/ipconfig", args, 5, link_route_done, interface, NULL);
   1337     if (interface->link_route_adder_process == NULL) {
   1338         ERROR("interface_prefix_configure: unable to set interface address for %s to %s.", interface->name, addrbuf);
   1339     }
   1340 #elif defined(CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IFCONFIG)
   1341     char *eos = addrbuf + strlen(addrbuf);
   1342     if (sizeof(addrbuf) - (eos - addrbuf) < 4) {
   1343         ERROR("interface_prefix_configure: this shouldn't happen: no space in addrbuf");
   1344         return;
   1345     }
   1346     strcpy(eos, "/64");
   1347     char *args[] = { interface->name, "add", addrbuf };
   1348 
   1349     if (interface->link_route_adder_process != NULL) {
   1350         ERROR("interface_prefix_configure: " PUB_S_SRP " already configuring the route.", interface->name);
   1351         return;
   1352     }
   1353     INFO("/sbin/ifconfig %s %s %s", args[0], args[1], args[2]);
   1354     interface->link_route_adder_process = ioloop_subproc("/sbin/ifconfig", args, 3, link_route_done, NULL, interface);
   1355     if (interface->link_route_adder_process == NULL) {
   1356         SEGMENTED_IPv6_ADDR_GEN_SRP(interface_address.s6_addr, if_addr_buf);
   1357         ERROR("interface_prefix_configure: unable to set interface address for " PUB_S_SRP " to "
   1358               PRI_SEGMENTED_IPv6_ADDR_SRP ".", interface->name,
   1359               SEGMENTED_IPv6_ADDR_PARAM_SRP(interface_address.s6_addr, if_addr_buf));
   1360     }
   1361 #else
   1362     struct in6_aliasreq alias_request;
   1363     int ret;
   1364 
   1365     memset(&alias_request, 0, sizeof(alias_request));
   1366     strlcpy(alias_request.ifra_name, interface->name, IFNAMSIZ);
   1367     alias_request.ifra_addr.sin6_family = AF_INET6;
   1368     alias_request.ifra_addr.sin6_len = sizeof(alias_request.ifra_addr);
   1369     memcpy(&alias_request.ifra_addr.sin6_addr, &interface_address, sizeof(alias_request.ifra_addr.sin6_addr));
   1370     alias_request.ifra_prefixmask.sin6_len = sizeof(alias_request.ifra_addr);
   1371     alias_request.ifra_prefixmask.sin6_family = AF_INET6;
   1372     memset(&alias_request.ifra_prefixmask.sin6_addr, 0xff, 8); // /64.
   1373     alias_request.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; // seconds, I hope?
   1374     alias_request.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; // seconds, I hope?
   1375 
   1376     ret = ioctl(sock, SIOCAIFADDR_IN6, &alias_request);
   1377     if (ret < 0) {
   1378         SEGMENTED_IPv6_ADDR_GEN_SRP(interface_address.s6_addr, if_addr_buf);
   1379         ERROR("interface_prefix_configure: can't configure static address " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP
   1380               ": " PUB_S_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(interface_address.s6_addr, if_addr_buf), interface->name,
   1381               strerror(errno));
   1382     } else {
   1383         SEGMENTED_IPv6_ADDR_GEN_SRP(interface_address.s6_addr, if_addr_buf);
   1384         INFO("added address " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PUB_S_SRP,
   1385              SEGMENTED_IPv6_ADDR_PARAM_SRP(interface_address.s6_addr, if_addr_buf), interface->name);
   1386     }
   1387 #endif // CONFIGURE_STATIC_INTERFACE_ADDRESSES_WITH_IPCONFIG
   1388 #else
   1389     (void)prefix;
   1390 #endif // CONFIGURE_STATIC_INTERFACE_ADDRESSES
   1391     close(sock);
   1392 }
   1393 
   1394 #ifndef RA_TESTER
   1395 static void
   1396 set_thread_forwarding(void)
   1397 {
   1398 #ifdef LINUX
   1399     const char *procfile = "/proc/sys/net/ipv6/conf/all/forwarding";
   1400     int fd = open(procfile, O_WRONLY);
   1401     if (fd < 0) {
   1402         ERROR("%s: %s", procfile, strerror(errno));
   1403     } else {
   1404         ssize_t ret = write(fd, "1", 1);
   1405         if (ret < 0) {
   1406             ERROR("write: %s", strerror(errno));
   1407         } else if (ret != 1) {
   1408             ERROR("invalid write: %zd", ret);
   1409         }
   1410         close(fd);
   1411     }
   1412 #else
   1413     int wun = 1;
   1414     int ret = sysctlbyname("net.inet6.ip6.forwarding", NULL, 0, &wun, sizeof(wun));
   1415     if (ret < 0) {
   1416         ERROR(PUB_S_SRP, strerror(errno));
   1417     } else {
   1418         INFO("Enabled IPv6 forwarding.");
   1419     }
   1420 #endif
   1421 }
   1422 #endif // RA_TESTER
   1423 
   1424 #ifdef NEED_THREAD_RTI_SETTER
   1425 static void
   1426 thread_rti_done(void *UNUSED context, int status, const char *error)
   1427 {
   1428     route_state_t *route_state = context;
   1429 
   1430     if (error != NULL) {
   1431         ERROR("thread_rti_done: " PUB_S_SRP, error);
   1432     } else {
   1433         INFO("%d.", status);
   1434     }
   1435     ioloop_subproc_release(route_state->thread_rti_setter_process);
   1436     route_state->thread_rti_setter_process = NULL;
   1437 }
   1438 
   1439 static void
   1440 set_thread_rti(route_state_t *route_state)
   1441 {
   1442     char *args[] = { "-w", "net.inet6.icmp6.nd6_process_rti=1" };
   1443     route_state->thread_rti_setter_process = ioloop_subproc("/usr/sbin/sysctl", args, 2, thread_rti_done,
   1444                                                NULL, route_state);
   1445     if (route_state->thread_rti_setter_process == NULL) {
   1446         ERROR("Unable to set thread rti enabled.");
   1447     }
   1448 }
   1449 #endif
   1450 
   1451 #if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
   1452 #ifdef ADD_PREFIX_WITH_WPANCTL
   1453 static void
   1454 thread_prefix_done(void *context, int status, const char *error)
   1455 {
   1456     route_state_t *route_state = context;
   1457 
   1458     if (error != NULL) {
   1459         ERROR("thread_prefix_done: " PUB_S_SRP, error);
   1460     } else {
   1461         interface_t *interface;
   1462 
   1463         INFO("%d.", status);
   1464         for (interface = route_state->interfaces; interface; interface = interface->next) {
   1465             if (!interface->inactive) {
   1466                 interface_beacon_schedule(interface, 0);
   1467             }
   1468         }
   1469     }
   1470     ioloop_subproc_release(route_state->thread_prefix_adder_process);
   1471     route_state->thread_prefix_adder_process = NULL;
   1472 }
   1473 #endif
   1474 #endif // THREAD_BORDER_ROUTRER && !RA_TESTER
   1475 
   1476 static void
   1477 post_solicit_policy_evaluate(void *context)
   1478 {
   1479     interface_t *interface = context;
   1480     INFO("Done waiting for router discovery to finish on " PUB_S_SRP, interface->name);
   1481     interface->router_discovery_complete = true;
   1482     interface->router_discovery_in_progress = false;
   1483 #ifdef FLUSH_STALE_ROUTERS
   1484     flush_routers(interface, ioloop_timenow());
   1485 #endif // FLUSH_STALE_ROUTERS
   1486 
   1487     // See if we need a new prefix on the interface.
   1488     interface_prefix_evaluate(interface);
   1489 
   1490     routing_policy_evaluate(interface, true);
   1491     // Always clear out need_reconfigure_prefix when router_discovery_complete is set to true.
   1492     interface->need_reconfigure_prefix = false;
   1493 }
   1494 
   1495 static void
   1496 ula_record(const char *ula_printable)
   1497 {
   1498     size_t len = strlen(ula_printable);
   1499     if (access(THREAD_DATA_DIR, F_OK) < 0) {
   1500         if (mkdir(THREAD_DATA_DIR, 0700) < 0) {
   1501             ERROR("ula_record: " THREAD_DATA_DIR " not present and can't be created: %s", strerror(errno));
   1502             return;
   1503         }
   1504     }
   1505     srp_store_file_data(NULL, THREAD_ULA_FILE, (uint8_t *)ula_printable, len);
   1506 }
   1507 
   1508 void
   1509 route_ula_generate(route_state_t *route_state)
   1510 {
   1511     char ula_prefix_buffer[INET6_ADDRSTRLEN];
   1512     struct in6_addr ula_prefix, old_ula_prefix;
   1513     bool prefix_changed;
   1514 
   1515     // Already have a prefix?
   1516     if (route_state->srp_server->ula_prefix.s6_addr[0] == 0xfd) {
   1517         old_ula_prefix = route_state->srp_server->ula_prefix;
   1518         prefix_changed = true;
   1519     } else {
   1520         prefix_changed = false;
   1521     }
   1522 
   1523     in6addr_zero(&ula_prefix);
   1524     srp_randombytes(&ula_prefix.s6_addr[1], 5);
   1525     ula_prefix.s6_addr[0] = 0xfd;
   1526 
   1527     inet_ntop(AF_INET6, &ula_prefix, ula_prefix_buffer, sizeof ula_prefix_buffer);
   1528 
   1529     ula_record(ula_prefix_buffer);
   1530     if (prefix_changed) {
   1531         SEGMENTED_IPv6_ADDR_GEN_SRP(old_ula_prefix.s6_addr, old_prefix_buf);
   1532         SEGMENTED_IPv6_ADDR_GEN_SRP(ula_prefix.s6_addr, new_prefix_buf);
   1533         INFO("ula-generate: prefix changed from " PRI_SEGMENTED_IPv6_ADDR_SRP " to " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1534              SEGMENTED_IPv6_ADDR_PARAM_SRP(old_ula_prefix.s6_addr, old_prefix_buf),
   1535              SEGMENTED_IPv6_ADDR_PARAM_SRP(ula_prefix.s6_addr, new_prefix_buf));
   1536     } else {
   1537         SEGMENTED_IPv6_ADDR_GEN_SRP(ula_prefix.s6_addr, new_prefix_buf);
   1538         INFO("ula-generate: generated ULA prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1539              SEGMENTED_IPv6_ADDR_PARAM_SRP(ula_prefix.s6_addr, new_prefix_buf));
   1540     }
   1541 
   1542     // Set up the thread prefix.
   1543     route_state->my_thread_ula_prefix = ula_prefix;
   1544     route_state->srp_server->ula_prefix = ula_prefix;
   1545     route_state->have_thread_prefix = true;
   1546 #if SRP_FEATURE_NAT64
   1547     if (route_state->srp_server->srp_nat64_enabled) {
   1548         nat64_set_ula_prefix(&ula_prefix);
   1549     }
   1550 #endif
   1551 }
   1552 
   1553 void
   1554 route_ula_setup(route_state_t *route_state)
   1555 {
   1556     bool have_stored_ula_prefix = false;
   1557 
   1558     char ula_buf[INET6_ADDRSTRLEN];
   1559     uint16_t length;
   1560     if (srp_load_file_data(NULL, THREAD_ULA_FILE, (uint8_t *)ula_buf, &length, sizeof(ula_buf) - 1)) {
   1561         ula_buf[length] = 0;
   1562         if (inet_pton(AF_INET6, ula_buf, &route_state->srp_server->ula_prefix)) {
   1563             have_stored_ula_prefix = true;
   1564         } else {
   1565             INFO("ula prefix %.*s is not valid", length, ula_buf);
   1566         }
   1567     } else {
   1568         INFO("Couldn't open ULA file " THREAD_ULA_FILE ".");
   1569     }
   1570 
   1571     // If we didn't already successfully fetch a stored prefix, try to store one.
   1572     if (!have_stored_ula_prefix) {
   1573         route_ula_generate(route_state);
   1574     } else {
   1575         // Set up the thread prefix.
   1576         route_state->my_thread_ula_prefix = route_state->srp_server->ula_prefix;
   1577         route_state->have_thread_prefix = true;
   1578 #if SRP_FEATURE_NAT64
   1579         if (route_state->srp_server->srp_nat64_enabled) {
   1580             nat64_set_ula_prefix(&route_state->srp_server->ula_prefix);
   1581         }
   1582 #endif
   1583     }
   1584 }
   1585 
   1586 static void
   1587 router_solicit_callback(void *context)
   1588 {
   1589     interface_t *interface = context;
   1590     if (interface->is_thread) {
   1591         INFO("discontinuing router solicitations on thread interface " PUB_S_SRP, interface->name);
   1592         return;
   1593     }
   1594     if (interface->num_solicits_sent >= 3) {
   1595         INFO("Done sending router solicitations on " PUB_S_SRP ".", interface->name);
   1596         return;
   1597     }
   1598     INFO("sending router solicitation on " PUB_S_SRP , interface->name);
   1599     router_solicit_send(interface);
   1600 
   1601     interface->num_solicits_sent++;
   1602     ioloop_add_wake_event(interface->router_solicit_wakeup,
   1603                           interface, router_solicit_callback, NULL,
   1604                           RTR_SOLICITATION_INTERVAL * 1000 + srp_random16() % 1024);
   1605 }
   1606 
   1607 static void
   1608 start_router_solicit(interface_t *interface)
   1609 {
   1610     if (interface->router_solicit_wakeup == NULL) {
   1611         interface->router_solicit_wakeup = ioloop_wakeup_create();
   1612         if (interface->router_solicit_wakeup == 0) {
   1613             ERROR("No memory for router solicit wakeup on " PUB_S_SRP ".", interface->name);
   1614             return;
   1615         }
   1616     } else {
   1617         ioloop_cancel_wake_event(interface->router_solicit_wakeup);
   1618     }
   1619     interface->num_solicits_sent = 0;
   1620     ioloop_add_wake_event(interface->router_solicit_wakeup, interface, router_solicit_callback,
   1621                           NULL, 128 + srp_random16() % 896);
   1622 }
   1623 
   1624 static interface_t *
   1625 find_interface(route_state_t *route_state, const char *name, int ifindex)
   1626 {
   1627     interface_t **p_interface, *interface = NULL;
   1628 
   1629     for (p_interface = &route_state->interfaces; *p_interface; p_interface = &(*p_interface)->next) {
   1630         interface = *p_interface;
   1631         if (!strcmp(name, interface->name)) {
   1632             if (ifindex != -1 && interface->index != ifindex) {
   1633                 INFO("interface name " PUB_S_SRP " index changed from %d to %d", name, interface->index, ifindex);
   1634                 interface->index = ifindex;
   1635             }
   1636             break;
   1637         }
   1638     }
   1639 
   1640     // If it's a new interface, make a structure.
   1641     // We could do a callback, but don't have a use case
   1642     if (*p_interface == NULL) {
   1643         interface = interface_create(route_state, name, ifindex);
   1644         if (interface != NULL) {
   1645             if (route_state->thread_interface_name != NULL && !strcmp(name, route_state->thread_interface_name)) {
   1646                 interface->is_thread = true;
   1647             }
   1648             *p_interface = interface;
   1649         }
   1650     }
   1651     return interface;
   1652 }
   1653 
   1654 
   1655 static void
   1656 interface_shutdown(interface_t *interface)
   1657 {
   1658     icmp_message_t *router, *next;
   1659     INFO("Interface " PUB_S_SRP " went away.", interface->name);
   1660     if (interface->beacon_wakeup != NULL) {
   1661         ioloop_cancel_wake_event(interface->beacon_wakeup);
   1662     }
   1663     if (interface->post_solicit_wakeup != NULL) {
   1664         ioloop_cancel_wake_event(interface->post_solicit_wakeup);
   1665     }
   1666     if (interface->stale_evaluation_wakeup != NULL) {
   1667         ioloop_cancel_wake_event(interface->stale_evaluation_wakeup);
   1668     }
   1669     if (interface->router_solicit_wakeup != NULL) {
   1670         ioloop_cancel_wake_event(interface->router_solicit_wakeup);
   1671     }
   1672     if (interface->deconfigure_wakeup != NULL) {
   1673         ioloop_cancel_wake_event(interface->deconfigure_wakeup);
   1674     }
   1675 #if SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
   1676     if (interface->vicarious_discovery_complete != NULL) {
   1677         ioloop_cancel_wake_event(interface->vicarious_discovery_complete);
   1678     }
   1679     interface->vicarious_router_discovery_in_progress = false;
   1680 #endif // SRP_FEATURE_VICARIOUS_ROUTER_DISCOVERY
   1681     for (router = interface->routers; router; router = next) {
   1682         next = router->next;
   1683         icmp_message_free(router);
   1684     }
   1685     interface->routers = NULL;
   1686     interface->last_beacon = interface->next_beacon = 0;
   1687     interface->deprecate_deadline = 0;
   1688     interface->preferred_lifetime = interface->valid_lifetime = 0;
   1689     interface->num_solicits_sent = 0;
   1690     interface->inactive = true;
   1691     interface->ineligible = true;
   1692     interface->our_prefix_advertised = false;
   1693     interface->suppress_ipv6_prefix = false;
   1694     interface->have_link_layer_address = false;
   1695     interface->on_link_prefix_configured = false;
   1696     interface->sent_first_beacon = false;
   1697     interface->num_beacons_sent = 0;
   1698     interface->router_discovery_started = false;
   1699     interface->router_discovery_complete = false;
   1700     interface->router_discovery_in_progress = false;
   1701     interface->need_reconfigure_prefix = false;
   1702 }
   1703 
   1704 static void
   1705 interface_prefix_evaluate(interface_t *interface)
   1706 {
   1707     route_state_t *route_state = interface->route_state;
   1708     // Set up the interface prefix using the prefix number for the link.
   1709     interface->ipv6_prefix = route_state->xpanid_prefix;
   1710 }
   1711 
   1712 
   1713 #ifndef RA_TESTER
   1714 static bool
   1715 router_is_advertising(icmp_message_t *router, const struct in6_addr *prefix, int preflen)
   1716 {
   1717     for (int i = 0; i < router->num_options; i++) {
   1718         icmp_option_t *option = &router->options[i];
   1719         if (option->type == icmp_option_prefix_information) {
   1720             prefix_information_t *pio = &option->option.prefix_information;
   1721             if (pio->length != 64) {
   1722                 SEGMENTED_IPv6_ADDR_GEN_SRP(&pio->prefix, prefix_buf);
   1723                 INFO("invalid IP address prefix length: " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d",
   1724                      SEGMENTED_IPv6_ADDR_PARAM_SRP(&pio->prefix, prefix_buf), preflen);
   1725                 continue;
   1726             }
   1727             if (!in6prefix_compare(prefix, &pio->prefix, 8)) {
   1728                 SEGMENTED_IPv6_ADDR_GEN_SRP(&pio->prefix, prefix_buf);
   1729                 SEGMENTED_IPv6_ADDR_GEN_SRP(&router->source, router_buf);
   1730                 INFO("router at " PRI_SEGMENTED_IPv6_ADDR_SRP " advertised prefix " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d",
   1731                      SEGMENTED_IPv6_ADDR_PARAM_SRP(&router->source, router_buf),
   1732                      SEGMENTED_IPv6_ADDR_PARAM_SRP(&pio->prefix, prefix_buf), preflen);
   1733                 return true;
   1734             }
   1735         }
   1736     }
   1737     return false;
   1738 }
   1739 
   1740 static void
   1741 route_remove_routers_advertising_prefix(interface_t *interface, const struct in6_addr *prefix, int preflen)
   1742 {
   1743     if (preflen != 64) {
   1744         SEGMENTED_IPv6_ADDR_GEN_SRP(prefix, prefix_buf);
   1745         INFO("invalid IP address prefix length: " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d",
   1746              SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix, prefix_buf), preflen);
   1747         return;
   1748     }
   1749     for (icmp_message_t **rp = &interface->routers; *rp != NULL; ) {
   1750         icmp_message_t *router = *rp;
   1751         if (router_is_advertising(router, prefix, preflen)) {
   1752             *rp = router->next;
   1753             router->next = NULL;
   1754             icmp_message_free(router);
   1755         } else {
   1756             rp = &router->next;
   1757         }
   1758     }
   1759 }
   1760 #endif // RA_TESTER
   1761 
   1762 static void
   1763 ifaddr_callback(srp_server_t *server_state, void *context, const char *name, const addr_t *address,
   1764                 const addr_t *mask, unsigned flags, enum interface_address_change change)
   1765 {
   1766     char addrbuf[INET6_ADDRSTRLEN];
   1767     const uint8_t *addrbytes, *maskbytes, *prefp;
   1768     int preflen, i;
   1769     interface_t *interface;
   1770     route_state_t *route_state = context;
   1771 
   1772 #ifndef POSIX_BUILD
   1773     interface = find_interface(route_state, name, -1);
   1774 #else
   1775     interface = find_interface(route_state, name, if_nametoindex(name));
   1776 #endif
   1777     if (interface == NULL) {
   1778         ERROR("find_interface returned NULL for " PUB_S_SRP, name);
   1779         return;
   1780     }
   1781 
   1782     const bool is_thread_interface = interface->is_thread;
   1783 
   1784     if (address->sa.sa_family == AF_INET) {
   1785         addrbytes = (uint8_t *)&address->sin.sin_addr;
   1786         maskbytes = (uint8_t *)&mask->sin.sin_addr;
   1787         prefp = maskbytes + 3;
   1788         preflen = 32;
   1789         if (change == interface_address_added) {
   1790             // Just got an IPv4 address?
   1791             if (!interface->num_ipv4_addresses) {
   1792                 if (!(flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
   1793                     interface_prefix_evaluate(interface);
   1794                 }
   1795             }
   1796             interface->num_ipv4_addresses++;
   1797         } else if (change == interface_address_deleted) {
   1798             interface->num_ipv4_addresses--;
   1799             // Just lost our last IPv4 address?
   1800             if (!(flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
   1801                 if (!interface->num_ipv4_addresses) {
   1802                     interface_prefix_evaluate(interface);
   1803                 }
   1804             }
   1805         }
   1806     } else if (address->sa.sa_family == AF_INET6) {
   1807         if (change == interface_address_added) {
   1808             interface->num_ipv6_addresses++;
   1809         } else if (change == interface_address_deleted) {
   1810             interface->num_ipv6_addresses--;
   1811         }
   1812         addrbytes = (uint8_t *)&address->sin6.sin6_addr;
   1813         maskbytes = (uint8_t *)&mask->sin6.sin6_addr;
   1814         prefp = maskbytes + 15;
   1815         preflen = 128;
   1816 #ifndef LINUX
   1817     } else if (address->sa.sa_family == AF_LINK) {
   1818         snprintf(addrbuf, sizeof addrbuf, "%02x:%02x:%02x:%02x:%02x:%02x",
   1819                  address->ether_addr.addr[0], address->ether_addr.addr[1],
   1820                  address->ether_addr.addr[2], address->ether_addr.addr[3],
   1821                  address->ether_addr.addr[4], address->ether_addr.addr[5]);
   1822         prefp = (uint8_t *)&addrbuf[0]; maskbytes = prefp + 1; // Skip prefix length calculation
   1823         preflen = 0;
   1824         addrbytes = NULL;
   1825 #endif
   1826     } else {
   1827         INFO("Unknown address type %d", address->sa.sa_family);
   1828         return;
   1829     }
   1830 
   1831     if (change != interface_address_unchanged) {
   1832 #ifndef LINUX
   1833         if (address->sa.sa_family == AF_LINK) {
   1834             if (!interface->ineligible) {
   1835                 INFO("interface " PUB_S_SRP PUB_S_SRP " " PUB_S_SRP " " PRI_MAC_ADDR_SRP " flags %x",
   1836                      name, is_thread_interface ? " (thread)" : "",
   1837                      change == interface_address_added ? "added" : "removed",
   1838                      MAC_ADDR_PARAM_SRP(address->ether_addr.addr), flags);
   1839             }
   1840         } else {
   1841 #endif
   1842             for (; prefp >= maskbytes; prefp--) {
   1843                 if (*prefp) {
   1844                     break;
   1845                 }
   1846                 preflen -= 8;
   1847             }
   1848             for (i = 0; i < 8; i++) {
   1849                 if (*prefp & (1<<i)) {
   1850                     break;
   1851                 }
   1852                 --preflen;
   1853             }
   1854             inet_ntop(address->sa.sa_family, addrbytes, addrbuf, sizeof addrbuf);
   1855             if (!interface->ineligible) {
   1856                 if (address->sa.sa_family == AF_INET) {
   1857                     IPv4_ADDR_GEN_SRP(addrbytes, addr_buf);
   1858                     INFO("interface " PUB_S_SRP PUB_S_SRP " " PUB_S_SRP " " PRI_IPv4_ADDR_SRP
   1859                          "/%d flags %x", name, is_thread_interface ? " (thread)" : "",
   1860                          change == interface_address_added ? "added" : "removed",
   1861                          IPv4_ADDR_PARAM_SRP(addrbytes, addr_buf), preflen, flags);
   1862                 } else if (address->sa.sa_family == AF_INET6) {
   1863                     SEGMENTED_IPv6_ADDR_GEN_SRP(addrbytes, addr_buf);
   1864                     INFO("interface " PUB_S_SRP PUB_S_SRP " " PUB_S_SRP " " PRI_SEGMENTED_IPv6_ADDR_SRP
   1865                          "/%d flags %x", name, is_thread_interface ? " (thread)" : "",
   1866                          change == interface_address_added ? "added" : "removed",
   1867                          SEGMENTED_IPv6_ADDR_PARAM_SRP(addrbytes, addr_buf), preflen, flags);
   1868 #ifndef RA_TESTER
   1869                     if (change == interface_address_deleted) {
   1870                         route_remove_routers_advertising_prefix(interface, &address->sin6.sin6_addr, preflen);
   1871                         if (route_state->route_tracker != NULL) {
   1872                             route_tracker_route_state_changed(route_state->route_tracker, interface);
   1873                         }
   1874                     }
   1875 #endif
   1876                 } else {
   1877                     INFO("invalid sa_family: %d", address->sa.sa_family);
   1878                 }
   1879 
   1880                 // Only notify dnssd-proxy when srp-mdns-proxy and dnssd-proxy is combined together.
   1881 #if !defined(RA_TESTER) && (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
   1882                 // Notify dnssd-proxy that address is added or removed.
   1883                 if (!is_thread_interface) {
   1884                     if (change == interface_address_added) {
   1885                         if (!interface->inactive) {
   1886                             dnssd_proxy_ifaddr_callback(server_state, context, name, address, mask, flags, change);
   1887                         }
   1888                     } else { // change == interface_address_removed
   1889                         dnssd_proxy_ifaddr_callback(server_state, context, name, address, mask, flags, change);
   1890                     }
   1891                 }
   1892 #endif // #if !defined(RA_TESTER) && (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY)
   1893 
   1894                 // When new IP address is removed, it is possible that the existing router information, such as
   1895                 // PIO and RIO is no longer valid since srp-mdns-proxy is losing its IP address. In order to let it to
   1896                 // flush the stale router information as soon as possible, we mark all the router as stale immediately,
   1897                 // by setting the router received time to a value which is 601s ago (router will be stale if the router
   1898                 // information is received for more than 600s). And then do router discovery for 20s, so we can ensure
   1899                 // that all the stale router information will be updated during the discovery, or flushed away. If all
   1900                 // routers are flushed, then srp-mdns-proxy will advertise its own prefix and configure the new IPv6
   1901                 // address.
   1902                 if (address->sa.sa_family == AF_INET6 &&                                       // An IPv6 address
   1903                     change == interface_address_deleted &&                                     // went away
   1904                     in6prefix_compare(&address->sin6.sin6_addr, &interface->ipv6_prefix, 8) && // not one of ours
   1905                     !is_thread_mesh_synthetic_or_link_local(&address->sin6.sin6_addr))         // not link-local
   1906                 {
   1907 
   1908                     INFO("clearing router discovery complete flag because address deleted.");
   1909 #ifdef VICARIOUS_ROUTER_DISCOVERY
   1910                     INFO("making all routers stale and start router discovery due to removed address");
   1911                     adjust_router_received_time(interface, ioloop_timenow(),
   1912                                                 -(MAX_ROUTER_RECEIVED_TIME_GAP_BEFORE_STALE + MSEC_PER_SEC));
   1913 #endif
   1914                     // Explicitly set router_discovery_complete to false so we can ensure that srp-mdns-proxy will start
   1915                     // the router discovery immediately.
   1916                     interface->router_discovery_complete = false;
   1917                     interface->router_discovery_started = false;
   1918                     // Set need_reconfigure_prefix to true to let routing_policy_evaluate know that the router discovery
   1919                     // is caused by interface removal event, so when the router discovery finished and nothing changes,
   1920                     // it can reconfigure the IPv6 routing in case configured does not handle it correctly.
   1921                     interface->need_reconfigure_prefix = true;
   1922                     routing_policy_evaluate(interface, false);
   1923                 }
   1924             }
   1925 #ifndef LINUX
   1926         }
   1927 #endif
   1928     }
   1929 
   1930     // Not a broadcast interface
   1931     if (flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) {
   1932         // Not the thread interface
   1933         if (!is_thread_interface) {
   1934             return;
   1935         }
   1936     }
   1937 
   1938     // 169.254.*
   1939     if (address->sa.sa_family == AF_INET && IN_LINKLOCAL(address->sin.sin_addr.s_addr)) {
   1940         return;
   1941     }
   1942 
   1943     if (interface->index == -1) {
   1944         interface->index = address->ether_addr.index;
   1945     }
   1946 
   1947 #if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
   1948     if (is_thread_interface && address->sa.sa_family == AF_INET6) {
   1949         partition_utun0_address_changed(route_state, &address->sin6.sin6_addr, change);
   1950     }
   1951 #endif
   1952 
   1953     if (address->sa.sa_family == AF_INET) {
   1954     } else if (address->sa.sa_family == AF_INET6) {
   1955         if (IN6_IS_ADDR_LINKLOCAL(&address->sin6.sin6_addr)) {
   1956             interface->link_local = address->sin6.sin6_addr;
   1957         }
   1958 #ifndef LINUX
   1959     } else if (address->sa.sa_family == AF_LINK) {
   1960         if (address->ether_addr.len == 6) {
   1961             if (change != interface_address_deleted) {
   1962                 memcpy(interface->link_layer, address->ether_addr.addr, 6);
   1963                 INFO("setting link layer address for " PUB_S_SRP " to " PRI_MAC_ADDR_SRP, interface->name,
   1964                      MAC_ADDR_PARAM_SRP(interface->link_layer));
   1965                 interface->have_link_layer_address = true;
   1966             } else {
   1967                 INFO("resetting link layer address for " PUB_S_SRP " (was " PRI_MAC_ADDR_SRP ")", interface->name,
   1968                      MAC_ADDR_PARAM_SRP(interface->link_layer));
   1969                 memset(interface->link_layer, 0, 6);
   1970                 interface->have_link_layer_address = false;
   1971             }
   1972         }
   1973 #endif
   1974     }
   1975 #if defined(POSIX_BUILD)
   1976     interface_active_state_evaluate(interface, true, true);
   1977 #endif
   1978 }
   1979 
   1980 #ifndef RA_TESTER
   1981 static void
   1982 route_get_mesh_local_prefix_callback(void *context, const char *prefix_string, cti_status_t status)
   1983 {
   1984     route_state_t *route_state = context;
   1985     char prefix_buf[INET6_ADDRSTRLEN];
   1986 
   1987     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   1988         INFO("disconnected");
   1989         attempt_wpan_reconnect(route_state);
   1990         goto fail;
   1991     }
   1992 
   1993     INFO(PRI_S_SRP " %d", prefix_string != NULL ? prefix_string : "<null>", status);
   1994     if (status != kCTIStatus_NoError) {
   1995         INFO("error %d", status);
   1996     }
   1997     if (prefix_string == NULL) {
   1998         INFO("NULL prefix string");
   1999         goto fail;
   2000     }
   2001 
   2002     const char *prefix_addr_string;
   2003     char *slash = strchr(prefix_string, '/');
   2004     if (slash != NULL) {
   2005         size_t len = slash - prefix_string;
   2006         if (len == 0) {
   2007             ERROR("bogus prefix: " PRI_S_SRP, prefix_string);
   2008             goto fail;
   2009         }
   2010         if (len - 1 > sizeof(prefix_buf)) {
   2011             ERROR("prefix too long: " PRI_S_SRP, prefix_string);
   2012             goto fail;
   2013         }
   2014         memcpy(prefix_buf, prefix_string, len);
   2015         prefix_buf[len] = 0;
   2016         prefix_addr_string = prefix_buf;
   2017     } else {
   2018         prefix_addr_string = prefix_string;
   2019     }
   2020     if (!inet_pton(AF_INET6, prefix_addr_string, &route_state->thread_mesh_local_prefix)) {
   2021         ERROR("prefix syntax incorrect: " PRI_S_SRP, prefix_addr_string);
   2022         goto fail;
   2023     }
   2024     SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->thread_mesh_local_prefix.s6_addr, ml_prefix_buf);
   2025     INFO(PRI_SEGMENTED_IPv6_ADDR_SRP PUB_S_SRP,
   2026          SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->thread_mesh_local_prefix.s6_addr, ml_prefix_buf),
   2027          slash ? slash : "");
   2028     route_state->have_mesh_local_prefix = true;
   2029     return;
   2030 fail:
   2031     route_state->have_mesh_local_prefix = false;
   2032     return;
   2033 }
   2034 #endif // RA_TESTER
   2035 
   2036 void
   2037 route_refresh_interface_list(route_state_t *route_state)
   2038 {
   2039     interface_t *interface;
   2040     bool UNUSED have_active = false;
   2041     // We sometimes do not get "interface down" notifications when moving from one WiFi SSID to the next. To detect that
   2042     // this has happened, see if we go from nonzero IPv6 addresses to zero after scanning the interface addresses
   2043     for (interface = route_state->interfaces; interface != NULL; interface = interface->next) {
   2044         interface->old_num_ipv6_addresses = interface->num_ipv6_addresses;
   2045     }
   2046     ioloop_map_interface_addresses_here(route_state->srp_server, &route_state->interface_addresses, NULL, route_state, ifaddr_callback);
   2047 
   2048     for (interface = route_state->interfaces; interface; interface = interface->next) {
   2049 #if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
   2050         if (interface->is_thread) {
   2051             partition_utun0_pick_listener_address(route_state);
   2052         }
   2053 #endif
   2054         if (!interface->ineligible && !interface->inactive) {
   2055             have_active = true;
   2056         }
   2057 
   2058         if (!interface->ineligible && !interface->inactive &&
   2059             interface->num_ipv6_addresses == 0 && interface->old_num_ipv6_addresses != 0)
   2060         {
   2061             flush_routers(interface, 0);
   2062         }
   2063     }
   2064 
   2065 #ifndef RA_TESTER
   2066     // Notice if we have lost or gained infrastructure.
   2067     if (have_active && !route_state->have_non_thread_interface) {
   2068         INFO("we have an active interface");
   2069         route_state->have_non_thread_interface = true;
   2070         route_state->partition_can_advertise_service = true;
   2071         partition_maybe_advertise_anycast_service(route_state);
   2072     } else if (!have_active && route_state->have_non_thread_interface) {
   2073         INFO("we no longer have an active interface");
   2074         route_state->have_non_thread_interface = false;
   2075         route_state->partition_can_advertise_service = false;
   2076         // Stop advertising the service, if we are doing so.
   2077         partition_discontinue_all_srp_service(route_state);
   2078     }
   2079 #endif // RA_TESTER
   2080 }
   2081 
   2082 
   2083 #if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
   2084 #if defined(POSIX_BUILD)
   2085 static void
   2086 wpan_reconnect_wakeup_callback(void *context)
   2087 {
   2088     route_state_t *route_state = context;
   2089     if (route_state->wpan_reconnect_wakeup != NULL) {
   2090         ioloop_wakeup_release(route_state->wpan_reconnect_wakeup);
   2091         route_state->wpan_reconnect_wakeup = NULL;
   2092     }
   2093     // Attempt to restart the thread network...
   2094     infrastructure_network_startup(context);
   2095 }
   2096 #endif // POSIX_BUILD
   2097 
   2098 static void
   2099 attempt_wpan_reconnect(void *context)
   2100 {
   2101     route_state_t *route_state = context;
   2102 #if defined(POSIX_BUILD)
   2103     if (route_state->wpan_reconnect_wakeup == NULL) {
   2104         route_state->wpan_reconnect_wakeup = ioloop_wakeup_create();
   2105         if (route_state->wpan_reconnect_wakeup == NULL) {
   2106             ERROR("can't allocate wpan reconnect wait wakeup.");
   2107             return;
   2108         }
   2109         INFO("delaying for ten seconds before attempt to reconnect to thread daemon.");
   2110         ioloop_add_wake_event(route_state->wpan_reconnect_wakeup, NULL,
   2111                               wpan_reconnect_wakeup_callback, NULL, 10 * 1000);
   2112         partition_state_reset(route_state);
   2113 #endif
   2114     }
   2115 }
   2116 
   2117 static void
   2118 cti_get_tunnel_name_callback(void *context, const char *name, cti_status_t status)
   2119 {
   2120     route_state_t *route_state = context;
   2121     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   2122         INFO("disconnected");
   2123         attempt_wpan_reconnect(route_state);
   2124         return;
   2125     }
   2126 
   2127     INFO(PUB_S_SRP " %d", name != NULL ? name : "<null>", status);
   2128     if (status != kCTIStatus_NoError) {
   2129         return;
   2130     }
   2131     route_state->num_thread_interfaces = 1;
   2132     if (route_state->thread_interface_name != NULL) {
   2133         free(route_state->thread_interface_name);
   2134     }
   2135     route_state->thread_interface_name = strdup(name);
   2136     if (route_state->thread_interface_name == NULL) {
   2137         ERROR("No memory to save thread interface name " PUB_S_SRP, name);
   2138         return;
   2139     }
   2140     INFO("Thread interface at " PUB_S_SRP, route_state->thread_interface_name);
   2141     partition_got_tunnel_name(route_state);
   2142 }
   2143 
   2144 static void
   2145 cti_get_role_callback(void *context, cti_network_node_type_t role, cti_status_t status)
   2146 {
   2147     route_state_t *route_state = context;
   2148     bool am_thread_router = false;
   2149 
   2150     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   2151         INFO("disconnected");
   2152         attempt_wpan_reconnect(route_state);
   2153         return;
   2154     }
   2155 
   2156     if (status == kCTIStatus_NoError) {
   2157         route_state->partition_last_role_change = ioloop_timenow();
   2158 
   2159         if (role == kCTI_NetworkNodeType_Router || role == kCTI_NetworkNodeType_Leader) {
   2160             am_thread_router = true;
   2161         }
   2162 
   2163         INFO("role is: " PUB_S_SRP " (%d)\n ", am_thread_router ? "router" : "not router", role);
   2164     } else {
   2165         ERROR("cti_get_role_callback: nonzero status %d", status);
   2166     }
   2167 
   2168     // Our thread role doesn't actually matter, but it's useful to report it in the logs.
   2169 }
   2170 
   2171 static void
   2172 cti_get_state_callback(void *context, cti_network_state_t state, cti_status_t status)
   2173 {
   2174     route_state_t *route_state = context;
   2175     bool associated = false;
   2176 
   2177     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   2178         INFO("disconnected");
   2179         attempt_wpan_reconnect(context);
   2180         return;
   2181     }
   2182 
   2183     route_state->partition_last_state_change = ioloop_timenow();
   2184 
   2185     if (status == kCTIStatus_NoError) {
   2186         if ((state == kCTI_NCPState_Associated)     || (state == kCTI_NCPState_Isolated) ||
   2187             (state == kCTI_NCPState_NetWake_Asleep) || (state == kCTI_NCPState_NetWake_Waking))
   2188         {
   2189             associated = true;
   2190         }
   2191 
   2192         INFO("state is: " PUB_S_SRP " (%d)\n ", associated ? "associated" : "not associated", state);
   2193     } else {
   2194         ERROR("cti_get_state_callback: nonzero status %d", status);
   2195     }
   2196 
   2197     if (route_state->current_thread_state != state) {
   2198         if (associated) {
   2199             route_state->current_thread_state = state;
   2200             partition_maybe_enable_services(route_state); // but probably not
   2201         } else {
   2202             route_state->current_thread_state = state;
   2203             partition_disable_service(route_state);
   2204         }
   2205     }
   2206 }
   2207 
   2208 static void
   2209 re_evaluate_interfaces(route_state_t *route_state)
   2210 {
   2211     for (interface_t *interface = route_state->interfaces; interface != NULL; interface = interface->next) {
   2212         interface_prefix_evaluate(interface);
   2213     }
   2214 
   2215     partition_maybe_enable_services(route_state);
   2216 }
   2217 
   2218 static void
   2219 route_get_xpanid_callback(void *context, uint64_t new_xpanid, cti_status_t status)
   2220 {
   2221     route_state_t *route_state = context;
   2222     if (status == kCTIStatus_Disconnected || status == kCTIStatus_DaemonNotRunning) {
   2223         INFO("disconnected");
   2224         attempt_wpan_reconnect(route_state);
   2225         return;
   2226     }
   2227 
   2228     if (status == kCTIStatus_NoError) {
   2229         if (route_state->partition_has_xpanid) {
   2230             ERROR("Unexpected change to XPANID from %" PRIu64 " to %" PRIu64,
   2231                   route_state->srp_server->xpanid, new_xpanid);
   2232         } else {
   2233             INFO("XPANID is now %" PRIu64, new_xpanid);
   2234         }
   2235     } else {
   2236         ERROR("nonzero status %d", status);
   2237         return;
   2238     }
   2239 
   2240     route_state->srp_server->xpanid = new_xpanid;
   2241     route_state->partition_has_xpanid = true;
   2242     in6addr_zero(&route_state->xpanid_prefix);
   2243     route_state->xpanid_prefix.s6_addr[0] = 0xfd;
   2244     for (int i = 1; i < 8; i++) {
   2245         route_state->xpanid_prefix.s6_addr[i] = ((route_state->srp_server->xpanid >> ((8 - i) * 8)) & 0xFFU);
   2246     }
   2247     route_state->have_xpanid_prefix = true;
   2248 
   2249 #if SRP_FEATURE_REPLICATION
   2250     if (route_state->srp_server->srp_replication_enabled) {
   2251         INFO("start srp replication.");
   2252         srpl_startup(route_state->srp_server);
   2253     }
   2254 #endif // SRP_FEATURE_REPLICATION
   2255 
   2256     re_evaluate_interfaces(route_state);
   2257 }
   2258 
   2259 void
   2260 adv_ctl_add_prefix(route_state_t *route_state, const uint8_t *const data)
   2261 {
   2262     if (route_state->omr_watcher != NULL) {
   2263         omr_prefix_t *thread_prefixes = omr_watcher_prefixes_get(route_state->omr_watcher);
   2264         omr_prefix_t *prefix = NULL;
   2265 
   2266         for (prefix = thread_prefixes; prefix != NULL; prefix = prefix->next) {
   2267             if (!memcmp(&prefix->prefix, data, BR_PREFIX_SLASH_64_BYTES)) {
   2268                 SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
   2269                 INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " already there",
   2270                       SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
   2271                 break;
   2272             }
   2273         }
   2274         if (prefix == NULL) {
   2275             SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
   2276             INFO("adding prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   2277                  SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
   2278             if (!omr_watcher_prefix_add(route_state->omr_watcher, (struct in6_addr *)data, BR_PREFIX_SLASH_64_BYTES, omr_prefix_priority_low)) {
   2279                 INFO("failed");
   2280             }
   2281         }
   2282     }
   2283 }
   2284 
   2285 void
   2286 adv_ctl_remove_prefix(route_state_t *route_state, const uint8_t *const data)
   2287 {
   2288     if (route_state->omr_watcher != NULL) {
   2289         omr_prefix_t *thread_prefixes = omr_watcher_prefixes_get(route_state->omr_watcher);
   2290         omr_prefix_t *prefix = NULL;
   2291 
   2292         for (prefix = thread_prefixes; prefix != NULL; prefix = prefix->next) {
   2293             if (!memcmp(&prefix->prefix, data, BR_PREFIX_SLASH_64_BYTES)) {
   2294                 break;
   2295             }
   2296         }
   2297         if (prefix == NULL) {
   2298             SEGMENTED_IPv6_ADDR_GEN_SRP(data, prefix_buf);
   2299             INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " not present",
   2300                  SEGMENTED_IPv6_ADDR_PARAM_SRP(data, prefix_buf));
   2301         } else {
   2302             SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf);
   2303             INFO("removing prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   2304                  SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf));
   2305             if (!omr_watcher_prefix_remove(route_state->omr_watcher, data, BR_PREFIX_SLASH_64_BYTES)) {
   2306                 INFO("no prefix removed.");
   2307             }
   2308         }
   2309     }
   2310 }
   2311 
   2312 static void
   2313 route_rloc16_callback(void *context, uint16_t rloc16, cti_status_t status)
   2314 {
   2315     route_state_t *route_state = context;
   2316 
   2317     if (status != kCTIStatus_NoError) {
   2318         ERROR("%d", status);
   2319     } else {
   2320         route_state->srp_server->rloc16 = rloc16;
   2321         route_state->have_rloc16 = true;
   2322         INFO("server_state->rloc16 updated to %d", route_state->srp_server->rloc16);
   2323         // whenever the local rloc16 is updated, we should re-evaluate if anycast
   2324         // service should be advertised.
   2325         partition_maybe_advertise_anycast_service(route_state);
   2326     }
   2327 }
   2328 #endif // THREAD_BORDER_ROUTER && !RA_TESTER
   2329 
   2330 void
   2331 infrastructure_network_startup(route_state_t *route_state)
   2332 {
   2333     INFO("Thread network started.");
   2334 
   2335 //    ioloop_network_watcher_start(network_watch_event);
   2336 #ifndef RA_TESTER
   2337     set_thread_forwarding();
   2338 #endif
   2339 }
   2340 
   2341 #if defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
   2342 static void
   2343 route_omr_watcher_event(route_state_t *route_state, void *UNUSED context, omr_watcher_event_type_t event_type,
   2344                         omr_prefix_t *UNUSED prefixes, omr_prefix_t *UNUSED prefix)
   2345 {
   2346     // Whenever we get an update to the prefix list, we should check our interface addresses.
   2347     if (event_type == omr_watcher_event_prefix_update_finished) {
   2348         route_refresh_interface_list(route_state);
   2349         int num_prefixes = 0;
   2350         for (omr_prefix_t *prf = prefixes; prf != NULL; prf = prf->next) {
   2351             num_prefixes++;
   2352         }
   2353         if (num_prefixes != route_state->num_thread_prefixes) {
   2354             int old_num_prefixes = route_state->num_thread_prefixes;
   2355             INFO("%d prefixes instead of %d, evaluating policy", num_prefixes, route_state->num_thread_prefixes);
   2356             routing_policy_evaluate_all_interfaces(route_state, true);
   2357             route_state->num_thread_prefixes = num_prefixes;
   2358             if (old_num_prefixes == 0 && num_prefixes > 0) {
   2359                 INFO("thread prefix available, may advertise anycast");
   2360                 partition_maybe_advertise_anycast_service(route_state);
   2361             }
   2362             if (old_num_prefixes > 0 && num_prefixes == 0) {
   2363                 INFO("all thread prefixes are gone, stop advertising anycast service");
   2364                 partition_stop_advertising_anycast_service(route_state, route_state->thread_sequence_number);
   2365             }
   2366         }
   2367     }
   2368 }
   2369 
   2370 static void
   2371 thread_network_startup(route_state_t *route_state)
   2372 {
   2373     if (route_state->thread_network_shutting_down) {
   2374         INFO("thread network still shutting down--canceling");
   2375         ioloop_cancel_wake_event(route_state->thread_network_shutdown_wakeup);
   2376         route_state->thread_network_shutting_down = false;
   2377         return;
   2378     }
   2379     int status = cti_get_state(route_state->srp_server, &route_state->thread_state_context, route_state,
   2380                                cti_get_state_callback, NULL);
   2381     if (status == kCTIStatus_NoError) {
   2382         status = cti_get_network_node_type(route_state->srp_server, &route_state->thread_role_context, route_state,
   2383                                            cti_get_role_callback, NULL);
   2384     }
   2385     srp_server_t *server_state = route_state->srp_server;
   2386     server_state->service_tracker = service_tracker_create(server_state);
   2387     if (server_state->service_tracker != NULL) {
   2388         service_tracker_callback_add(server_state->service_tracker,
   2389                                      partition_service_set_changed, NULL, route_state);
   2390         service_tracker_start(server_state->service_tracker);
   2391     }
   2392     if (status == kCTIStatus_NoError) {
   2393         status = cti_get_tunnel_name(route_state->srp_server, route_state, cti_get_tunnel_name_callback, NULL);
   2394     }
   2395     if (status == kCTIStatus_NoError) {
   2396         status = cti_get_extended_pan_id(route_state->srp_server, &route_state->thread_xpanid_context, route_state,
   2397                                          route_get_xpanid_callback, NULL);
   2398     }
   2399     if (status == kCTIStatus_NoError) {
   2400         status = cti_get_rloc16(route_state->srp_server, &route_state->thread_rloc16_context, route_state,
   2401                                 route_rloc16_callback, NULL);
   2402     }
   2403     if (status == kCTIStatus_NoError) {
   2404         status = cti_get_mesh_local_prefix(route_state->srp_server, route_state,
   2405                                            route_get_mesh_local_prefix_callback, NULL);
   2406     }
   2407     if (status != kCTIStatus_NoError) {
   2408         if (status == kCTIStatus_DaemonNotRunning) {
   2409             attempt_wpan_reconnect(route_state);
   2410         } else {
   2411             ERROR("initial network setup failed");
   2412         }
   2413     }
   2414 #if SRP_FEATURE_NAT64
   2415     INFO("start nat64.");
   2416     nat64_start(route_state);
   2417 #endif
   2418     route_state->omr_watcher = omr_watcher_create(route_state, attempt_wpan_reconnect);
   2419     if (route_state->omr_watcher == NULL) {
   2420         ERROR("omr_watcher create failed");
   2421         return;
   2422     }
   2423     route_state->omr_watcher_callback = omr_watcher_callback_add(route_state->omr_watcher,
   2424                                                                  route_omr_watcher_event, NULL, route_state);
   2425     if (route_state->omr_watcher_callback == NULL) {
   2426         ERROR("omr_watcher_callback add failed");
   2427         return;
   2428     }
   2429     route_state->omr_publisher = omr_publisher_create(route_state, "main");
   2430     if (route_state->omr_publisher == NULL) {
   2431         ERROR("omr_publisher create failed");
   2432         return;
   2433     }
   2434     omr_publisher_set_omr_watcher(route_state->omr_publisher, route_state->omr_watcher);
   2435     omr_publisher_set_reconnect_callback(route_state->omr_publisher, attempt_wpan_reconnect);
   2436     omr_publisher_start(route_state->omr_publisher);
   2437     omr_watcher_start(route_state->omr_watcher);
   2438     route_state->thread_network_running = true;
   2439 }
   2440 #endif //  defined(THREAD_BORDER_ROUTER) && !defined(RA_TESTER)
   2441 
   2442 #ifndef RA_TESTER
   2443 static void
   2444 thread_network_shutdown_wakeup_callback(void *context)
   2445 {
   2446     route_state_t *route_state = context;
   2447     INFO("shutdown timer expired, shutting down.");
   2448     thread_network_shutdown(route_state);
   2449 }
   2450 
   2451 static void
   2452 thread_network_shutdown_start(route_state_t *route_state)
   2453 {
   2454     if (route_state->thread_network_shutdown_wakeup == NULL) {
   2455         route_state->thread_network_shutdown_wakeup = ioloop_wakeup_create();
   2456     }
   2457     if (route_state->thread_network_shutdown_wakeup == NULL) {
   2458         INFO("no memory for wakeup object");
   2459         thread_network_shutdown(route_state);
   2460     } else {
   2461         INFO("scheduling shutdown in ten seconds");
   2462         route_state->thread_network_shutting_down = true;
   2463         ioloop_add_wake_event(route_state->thread_network_shutdown_wakeup,
   2464                               route_state, thread_network_shutdown_wakeup_callback, NULL, 10 * 1000);
   2465     }
   2466 }
   2467 
   2468 static void
   2469 thread_network_shutdown(route_state_t *route_state)
   2470 {
   2471     // If we get an explicit shutdown after getting a "shut down if nothing improves", cancel the scheduled shutdown.
   2472     // This code also runs when we're called from the shutdown wakeup callback and serves to cancel that state.
   2473     if (route_state->thread_network_shutdown_wakeup != NULL) {
   2474         ioloop_cancel_wake_event(route_state->thread_network_shutdown_wakeup);
   2475     }
   2476     route_state->thread_network_shutting_down = false;
   2477     if (route_state->thread_state_context != NULL) {
   2478         INFO("discontinuing state events");
   2479         cti_events_discontinue(route_state->thread_state_context);
   2480         route_state->thread_state_context = NULL;
   2481     }
   2482     if (route_state->thread_role_context != NULL) {
   2483         INFO("discontinuing role events");
   2484         cti_events_discontinue(route_state->thread_role_context);
   2485         route_state->thread_role_context = NULL;
   2486     }
   2487     if (route_state->thread_route_context != NULL) {
   2488         INFO("discontinuing route events");
   2489         cti_events_discontinue(route_state->thread_route_context);
   2490         route_state->thread_route_context = NULL;
   2491     }
   2492     if (route_state->thread_xpanid_context != NULL) {
   2493         INFO("discontinuing xpanid events");
   2494         cti_events_discontinue(route_state->thread_xpanid_context);
   2495         route_state->thread_xpanid_context = NULL;
   2496     }
   2497     if (route_state->thread_rloc16_context != NULL) {
   2498         INFO("discontinuing rloc16 events");
   2499         cti_events_discontinue(route_state->thread_rloc16_context);
   2500         route_state->thread_rloc16_context = NULL;
   2501     }
   2502     if (route_state->thread_ml_prefix_connection != NULL) {
   2503         INFO("discontinuing route events");
   2504         cti_events_discontinue(route_state->thread_ml_prefix_connection);
   2505         route_state->thread_ml_prefix_connection = NULL;
   2506     }
   2507     srp_mdns_flush(route_state->srp_server);
   2508 #if SRP_FEATURE_REPLICATION
   2509     INFO("stop srp replication.");
   2510     srpl_shutdown(route_state->srp_server);
   2511 #endif
   2512 #if SRP_FEATURE_NAT64
   2513     INFO("stop nat64.");
   2514     nat64_stop(route_state);
   2515 #endif
   2516     partition_state_reset(route_state);
   2517     route_state->thread_network_running = false;
   2518 }
   2519 #endif // RA_TESTER
   2520 
   2521 void
   2522 infrastructure_network_shutdown(route_state_t *route_state)
   2523 {
   2524     interface_t *interface;
   2525 
   2526 #ifndef RA_TESTER
   2527     if (route_state->thread_network_running) {
   2528         thread_network_shutdown(route_state);
   2529     }
   2530 #endif
   2531     INFO("Infrastructure network shutdown.");
   2532     // Stop all activity on interfaces.
   2533     for (interface = route_state->interfaces; interface; interface = interface->next) {
   2534         interface_shutdown(interface);
   2535     }
   2536     // Whatever non-thread interface we may have had we just shut down, so mark it down so that we can
   2537     // start it up later.
   2538     route_state->have_non_thread_interface = false;
   2539 }
   2540 
   2541 #ifndef RA_TESTER
   2542 static void
   2543 partition_state_reset(route_state_t *route_state)
   2544 {
   2545     if (route_state->omr_watcher) {
   2546         if (route_state->omr_watcher_callback != NULL) {
   2547             INFO("canceling omr watcher callback");
   2548             omr_watcher_callback_cancel(route_state->omr_watcher, route_state->omr_watcher_callback);
   2549             route_state->omr_watcher_callback = NULL;
   2550         }
   2551         INFO("discontinuing omr watcher");
   2552         omr_watcher_cancel(route_state->omr_watcher);
   2553         omr_watcher_release(route_state->omr_watcher);
   2554 
   2555         route_state->omr_watcher = NULL;
   2556     }
   2557     if (route_state->omr_publisher) {
   2558         INFO("discontinuing omr publisher");
   2559         omr_publisher_cancel(route_state->omr_publisher);
   2560         omr_publisher_release(route_state->omr_publisher);
   2561         route_state->omr_publisher = NULL;
   2562     }
   2563     if (route_state->route_tracker) {
   2564         INFO("discontinuing route tracker");
   2565         route_tracker_cancel(route_state->route_tracker);
   2566         route_tracker_release(route_state->route_tracker);
   2567         route_state->route_tracker = NULL;
   2568     }
   2569     srp_server_t *server_state = route_state->srp_server;
   2570     if (server_state->service_tracker != NULL) {
   2571         service_tracker_cancel(server_state->service_tracker);
   2572         service_tracker_release(server_state->service_tracker);
   2573         server_state->service_tracker = NULL;
   2574     }
   2575 
   2576     route_state->current_thread_state = kCTI_NCPState_Uninitialized;
   2577     route_state->partition_last_prefix_set_change = 0;
   2578     route_state->partition_last_pref_id_set_change = 0;
   2579     route_state->partition_last_role_change = 0;
   2580     route_state->partition_last_state_change = 0;
   2581     route_state->partition_settle_start = 0;
   2582     route_state->partition_service_last_add_time = 0;
   2583     route_state->partition_have_prefix_list = false;
   2584     route_state->partition_have_pref_id_list = false;
   2585     route_state->partition_tunnel_name_is_known = false;
   2586     route_state->partition_can_advertise_service = false;
   2587     route_state->partition_can_advertise_anycast_service = false;
   2588     route_state->srp_server->srp_anycast_service_blocked = false;
   2589     route_state->srp_server->srp_unicast_service_blocked = false;
   2590     route_state->partition_can_provide_routing = false;
   2591     route_state->partition_has_xpanid = false;
   2592     route_state->partition_may_offer_service = false;
   2593     route_state->partition_settle_satisfied = true;
   2594     route_state->have_rloc16 = false;
   2595     route_state->advertising_srp_anycast_service = false;
   2596 
   2597     if (route_state->partition_settle_wakeup != NULL) {
   2598         ioloop_cancel_wake_event(route_state->partition_settle_wakeup);
   2599     }
   2600 
   2601     if (route_state->partition_post_partition_wakeup != NULL) {
   2602         ioloop_cancel_wake_event(route_state->partition_post_partition_wakeup);
   2603     }
   2604 
   2605     if (route_state->partition_pref_id_wait_wakeup != NULL) {
   2606         ioloop_cancel_wake_event(route_state->partition_pref_id_wait_wakeup);
   2607     }
   2608 
   2609     if (route_state->partition_service_add_pending_wakeup != NULL) {
   2610         ioloop_cancel_wake_event(route_state->partition_service_add_pending_wakeup);
   2611     }
   2612 
   2613     if (route_state->partition_anycast_service_add_pending_wakeup != NULL) {
   2614         ioloop_cancel_wake_event(route_state->partition_service_add_pending_wakeup);
   2615     }
   2616 
   2617     if (route_state->service_set_changed_wakeup != NULL) {
   2618         ioloop_cancel_wake_event(route_state->service_set_changed_wakeup);
   2619     }
   2620 }
   2621 
   2622 static void
   2623 partition_proxy_listener_ready(void *context, uint16_t port)
   2624 {
   2625     srp_server_t *server_state = context;
   2626     route_state_t *route_state = server_state->route_state;
   2627 
   2628     INFO("listening on port %d", port);
   2629     route_state->srp_service_listen_port = port;
   2630     if (route_state->have_non_thread_interface) {
   2631         route_state->partition_can_advertise_service = true;
   2632         partition_maybe_advertise_service(route_state);
   2633     } else {
   2634         partition_discontinue_srp_service(route_state);
   2635     }
   2636 }
   2637 
   2638 static void
   2639 partition_srp_listener_canceled(comm_t *listener, void *context)
   2640 {
   2641     srp_server_t *server_state = context;
   2642     route_state_t *route_state = server_state->route_state;
   2643 
   2644     INFO("listener is %p", listener);
   2645     if (route_state->srp_listener == listener) {
   2646         ioloop_comm_release(route_state->srp_listener);
   2647         route_state->srp_listener = NULL;
   2648 
   2649         if (!server_state->srp_unicast_service_blocked) {
   2650             partition_discontinue_srp_service(route_state);
   2651         }
   2652     }
   2653 }
   2654 
   2655 static void
   2656 partition_stop_srp_listener(route_state_t *route_state)
   2657 {
   2658     if (route_state->srp_listener != NULL) {
   2659         INFO("discontinuing SRP service on port %d", route_state->srp_service_listen_port);
   2660         ioloop_listener_cancel(route_state->srp_listener);
   2661         ioloop_comm_release(route_state->srp_listener);
   2662         route_state->srp_listener = NULL;
   2663     }
   2664 }
   2665 
   2666 void
   2667 partition_start_srp_listener(route_state_t *route_state)
   2668 {
   2669 #define max_avoid_ports 100
   2670     uint16_t avoid_ports[max_avoid_ports];
   2671     int num_avoid_ports = 0;
   2672     thread_service_t *service;
   2673 
   2674     for (service = service_tracker_services_get(route_state->srp_server->service_tracker);
   2675          service != NULL; service = service->next)
   2676     {
   2677         if (service->service_type == unicast_service) {
   2678             // Track the port regardless.
   2679             if (num_avoid_ports < max_avoid_ports) {
   2680                 avoid_ports[num_avoid_ports] = (service->u.unicast.port[0] << 8) | (service->u.unicast.port[1]);
   2681                 num_avoid_ports++;
   2682             }
   2683         }
   2684     }
   2685 
   2686     // Make sure we don't overwrite the listener without stopping it.
   2687     partition_stop_srp_listener(route_state);
   2688 
   2689     INFO("starting listener.");
   2690     route_state->srp_listener = srp_proxy_listen(avoid_ports, num_avoid_ports, NULL, partition_proxy_listener_ready,
   2691                                                  partition_srp_listener_canceled, NULL, NULL, route_state->srp_server);
   2692     if (route_state->srp_listener == NULL) {
   2693         ERROR("Unable to start SRP listener, so can't advertise it");
   2694         return;
   2695     }
   2696 }
   2697 
   2698 void
   2699 partition_discontinue_srp_service(route_state_t *route_state)
   2700 {
   2701     partition_stop_srp_listener(route_state);
   2702 
   2703     // Won't match
   2704     in6addr_zero(&route_state->srp_listener_ip_address);
   2705     route_state->srp_service_listen_port = 0;
   2706 
   2707     // Stop advertising the service, if we are doing so.
   2708     partition_stop_advertising_service(route_state);
   2709 }
   2710 
   2711 void
   2712 partition_discontinue_all_srp_service(route_state_t *route_state)
   2713 {
   2714     partition_discontinue_srp_service(route_state);
   2715     partition_stop_advertising_anycast_service(route_state, route_state->thread_sequence_number);
   2716 }
   2717 
   2718 // An address on utun0 has changed.  Evaluate what to do with our listener service.
   2719 // This gets called from ifaddr_callback().   If we don't yet have a thread service configured,
   2720 // it should be called for unchanged addresses as well as changed.
   2721 static void
   2722 partition_utun0_address_changed(route_state_t *route_state, const struct in6_addr *addr,
   2723                                 enum interface_address_change change)
   2724 {
   2725     SEGMENTED_IPv6_ADDR_GEN_SRP(addr, addr_buf);
   2726 
   2727     // Is this the address we are currently using?
   2728     if (!in6addr_compare(&route_state->srp_listener_ip_address, addr)) {
   2729         route_state->seen_listener_address = true;
   2730 
   2731         // Did it go away?   If so, drop the listener.
   2732         if (change == interface_address_deleted) {
   2733             INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": listener address removed.",
   2734                  SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2735             if (route_state->srp_listener != NULL) {
   2736                 INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": canceling listener on removed address.",
   2737                      SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2738                 partition_discontinue_srp_service(route_state);
   2739             }
   2740         } else {
   2741             // This should never happen.
   2742             if (change == interface_address_added) {
   2743                 ERROR(PRI_SEGMENTED_IPv6_ADDR_SRP ": address we're listening on was added.",
   2744                       SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2745             } else {
   2746                 INFO("still listening on " PRI_SEGMENTED_IPv6_ADDR_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2747             }
   2748         }
   2749 
   2750         // Nothing more to do for this address.
   2751         return;
   2752     }
   2753 
   2754     // No point in looking at addresses if we don't have prerequisites.
   2755     if (!route_state->have_mesh_local_prefix || !route_state->have_non_thread_interface) {
   2756         return;
   2757     }
   2758 
   2759     // Otherwise, we don't care about deleted addresses, but added and existing addresses matter.
   2760     if (change != interface_address_deleted) {
   2761         // If this address isn't an address we're already listening on, check if it's an anycast address; if so,
   2762         // skip it as a candidate to listen on.
   2763         if (is_thread_mesh_synthetic_address(addr)) {
   2764             INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": thread anycast address.",
   2765                  SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2766         }
   2767 
   2768         // If it's not an anycast address, do an election on it against the previously-seen addresses in this
   2769         // iteration of ioloop_map_interface_addresses(). Numerically lowest address wins. Note that this means
   2770         // that a link-local address will always lose, and if we have any anycast address we at least have a
   2771         // mesh-local address, and that's fine to use if it happens to win. If we could figure out what our
   2772         // mesh-local prefix was, we'd actually prefer this address since it never changes.
   2773         else {
   2774             // Don't use the mesh-local prefix
   2775             if (!in6prefix_compare(addr, &route_state->thread_mesh_local_prefix, 8)) {
   2776                 INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": is our mesh-local address, skipping",
   2777                      SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2778             }
   2779             // RFC4297: Link-Scoped Unicast address range FE80::/10
   2780             else if (addr->s6_addr[0] == 0xfe && (addr->s6_addr[1] & 0xc0) == 0x80) {
   2781                 INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": is our link-local address, skipping",
   2782                      SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2783             }
   2784             // If the address is not on the list of prefixes we know about, let's not use it.
   2785             else if (route_state->omr_watcher == NULL ||
   2786                      !omr_watcher_prefix_exists(route_state->omr_watcher, addr, 64))
   2787             {
   2788                 INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": is unknown, skipping",
   2789                      SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2790             }
   2791             // Otherwise it's legit and we can use it
   2792             else {
   2793                 if (!route_state->have_proposed_srp_listener_address ||
   2794                     in6addr_compare(&route_state->proposed_srp_listener_address, addr) > 0)
   2795                 {
   2796                     if (route_state->have_proposed_srp_listener_address) {
   2797                         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": wins over previous winner.",
   2798                              SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2799                     } else {
   2800                         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": wins by being first.",
   2801                              SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2802                     }
   2803                     in6addr_copy(&route_state->proposed_srp_listener_address, addr);
   2804                     route_state->have_proposed_srp_listener_address = true;
   2805                 }
   2806             }
   2807         }
   2808     } else {
   2809         INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": removed.", SEGMENTED_IPv6_ADDR_PARAM_SRP(addr, addr_buf));
   2810     }
   2811 }
   2812 
   2813 static void
   2814 partition_utun0_pick_listener_address(route_state_t *route_state)
   2815 {
   2816     if (route_state->have_mesh_local_prefix && route_state->advertising_srp_anycast_service &&
   2817         route_state->have_non_thread_interface && route_state->have_proposed_srp_listener_address)
   2818     {
   2819         if (route_state->srp_listener == NULL) {
   2820             SEGMENTED_IPv6_ADDR_GEN_SRP(&route_state->proposed_srp_listener_address, addr_buf);
   2821             INFO("starting listener on" PRI_SEGMENTED_IPv6_ADDR_SRP,
   2822                  SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->proposed_srp_listener_address, addr_buf));
   2823 
   2824             // Copy the winning proposed listener IP address to the listener IP address
   2825             in6addr_copy(&route_state->srp_listener_ip_address, &route_state->proposed_srp_listener_address);
   2826 
   2827             // Set up a listener.
   2828             route_state->srp_service_listen_port = 0;
   2829             partition_start_srp_listener(route_state);
   2830         } else {
   2831             SEGMENTED_IPv6_ADDR_GEN_SRP(&route_state->srp_listener_ip_address, addr_buf);
   2832             if (!route_state->seen_listener_address) {
   2833                 FAULT("didn't see listener address " PRI_SEGMENTED_IPv6_ADDR_SRP,
   2834                       SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf));
   2835             } else {
   2836                 INFO("already listening on" PRI_SEGMENTED_IPv6_ADDR_SRP,
   2837                      SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf));
   2838             }
   2839         }
   2840     } else {
   2841         INFO(PUB_S_SRP "advertising anycast service; " PUB_S_SRP " proposed listener address; "
   2842              PUB_S_SRP " non-thread interface; " PUB_S_SRP " mesh-local prefix; " PUB_S_SRP " listener",
   2843              route_state->advertising_srp_anycast_service    ? "" : "not ",
   2844              route_state->have_proposed_srp_listener_address ? "have" : "no",
   2845              route_state->have_non_thread_interface          ? "have" : "no",
   2846              route_state->have_mesh_local_prefix             ? "have" : "no",
   2847              route_state->srp_listener != NULL               ? "have" : "no");
   2848         // In common cases, if we are not advertising anycast service due to replication failure,
   2849         // we can not advertise unicast either. One exception is that we manually block the anycast
   2850         // service for testing purpose. Unicast service should not be affected in this case.
   2851         if (route_state->srp_listener != NULL && !route_state->advertising_srp_anycast_service &&
   2852             !route_state->srp_server->srp_anycast_service_blocked) {
   2853             SEGMENTED_IPv6_ADDR_GEN_SRP(&route_state->srp_listener_ip_address, addr_buf);
   2854             INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": canceling listener.",
   2855                  SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf));
   2856             partition_discontinue_srp_service(route_state);
   2857         }
   2858     }
   2859 
   2860     // Clear all of the election state.
   2861     route_state->seen_listener_address = false;
   2862     route_state->have_proposed_srp_listener_address = false;
   2863     in6addr_zero(&route_state->proposed_srp_listener_address);
   2864 }
   2865 
   2866 static void
   2867 partition_got_tunnel_name(route_state_t *route_state)
   2868 {
   2869     route_state->partition_tunnel_name_is_known = true;
   2870     for (interface_t *interface = route_state->interfaces; interface; interface = interface->next) {
   2871         if (!strcmp(interface->name, route_state->thread_interface_name)) {
   2872             interface->is_thread = true;
   2873             break;
   2874         }
   2875     }
   2876     route_refresh_interface_list(route_state);
   2877 }
   2878 
   2879 static void
   2880 partition_remove_service_done(void *context, cti_status_t status)
   2881 {
   2882     route_state_t *route_state = context;
   2883     INFO("%d", status);
   2884 
   2885     // Flush any advertisements we're currently doing, since the accessories that advertised them will
   2886     // notice the service is gone and start advertising with a different service.
   2887 #if defined(SRP_FEATURE_REPLICATION)
   2888     if (!route_state->srp_server->srp_replication_enabled) {
   2889 #endif
   2890         srp_mdns_flush(route_state->srp_server);
   2891 #if defined(SRP_FEATURE_REPLICATION)
   2892     }
   2893 #endif
   2894 }
   2895 
   2896 static bool
   2897 route_maybe_restart_service_tracker(route_state_t *route_state, int *reset, int *increment)
   2898 {
   2899     *reset = 0;
   2900     (*increment)++;
   2901     if (*increment > 5) {
   2902         if (route_state->srp_server->service_tracker != NULL) {
   2903             service_tracker_start(route_state->srp_server->service_tracker);
   2904         } else {
   2905             FAULT("service tracker not present when restarting.");
   2906         }
   2907         *increment = 0;
   2908         return true;
   2909     }
   2910     return false;
   2911 }
   2912 
   2913 static void
   2914 partition_stop_advertising_service(route_state_t *route_state)
   2915 {
   2916     // This should remove any copy of the service that this BR is advertising.
   2917     INFO("%" PRIu64 "/%x", THREAD_ENTERPRISE_NUMBER, THREAD_SRP_SERVER_OPTION);
   2918     uint8_t service_info[] = { 0, 0, 0, 1 };
   2919     int status;
   2920 
   2921     if (route_maybe_restart_service_tracker(route_state, &route_state->times_advertised_unicast, &route_state->times_unadvertised_unicast)) {
   2922         INFO("restarted service tracker.");
   2923     }
   2924     service_info[0] = THREAD_SRP_SERVER_OPTION & 255;
   2925     status = cti_remove_service(route_state->srp_server, route_state, partition_remove_service_done, NULL,
   2926                                 THREAD_ENTERPRISE_NUMBER, service_info, 1);
   2927     if (status != kCTIStatus_NoError) {
   2928         INFO("status %d", status);
   2929     }
   2930     route_state->advertising_srp_unicast_service = false;
   2931 }
   2932 
   2933 void
   2934 partition_stop_advertising_anycast_service(route_state_t *route_state, uint8_t sequence_number)
   2935 {
   2936     // This should remove any copy of the service that this BR is advertising.
   2937     INFO("%" PRIu64 "/%x %x", THREAD_ENTERPRISE_NUMBER, THREAD_SRP_SERVER_ANYCAST_OPTION, sequence_number);
   2938     uint8_t service_info[] = { 0, 0, 0, 1 };
   2939     int status;
   2940 
   2941     if (route_maybe_restart_service_tracker(route_state, &route_state->times_advertised_anycast, &route_state->times_unadvertised_anycast)) {
   2942         INFO("restarted service tracker.");
   2943     }
   2944     service_info[0] = THREAD_SRP_SERVER_ANYCAST_OPTION & 255;
   2945     service_info[1] = sequence_number;
   2946     status = cti_remove_service(route_state->srp_server, route_state, partition_remove_service_done, NULL,
   2947                                 THREAD_ENTERPRISE_NUMBER, service_info, 2);
   2948     if (status != kCTIStatus_NoError) {
   2949         INFO("status %d", status);
   2950     }
   2951     route_state->advertising_srp_anycast_service = false;
   2952     if (route_state->route_tracker != NULL) {
   2953         INFO("discontinuing route tracker");
   2954         route_tracker_cancel(route_state->route_tracker);
   2955         route_tracker_release(route_state->route_tracker);
   2956         route_state->route_tracker = NULL;
   2957     }
   2958     route_refresh_interface_list(route_state);
   2959 }
   2960 
   2961 static void
   2962 partition_add_service_callback(void *context, cti_status_t status)
   2963 {
   2964     route_state_t *UNUSED route_state = context;
   2965     if (status != kCTIStatus_NoError) {
   2966         INFO("status = %d", status);
   2967     } else {
   2968         INFO("status = %d", status);
   2969     }
   2970 }
   2971 
   2972 static void
   2973 partition_start_advertising_service(route_state_t *route_state)
   2974 {
   2975     uint8_t service_info[] = {0, 0, 0, 1};
   2976     uint8_t server_info[18];
   2977     int ret;
   2978 
   2979     if (route_maybe_restart_service_tracker(route_state, &route_state->times_unadvertised_unicast, &route_state->times_advertised_unicast)) {
   2980         INFO("restarted service tracker.");
   2981     }
   2982     memcpy(&server_info, &route_state->srp_listener_ip_address, 16);
   2983     server_info[16] = (route_state->srp_service_listen_port >> 8) & 255;
   2984     server_info[17] = route_state->srp_service_listen_port & 255;
   2985 
   2986     SEGMENTED_IPv6_ADDR_GEN_SRP(route_state->srp_listener_ip_address.s6_addr, server_ip_buf);
   2987     service_info[0] = THREAD_SRP_SERVER_OPTION & 255;
   2988     INFO("%" PRIu64 "/%02x/" PRI_SEGMENTED_IPv6_ADDR_SRP ":%d" ,
   2989          THREAD_ENTERPRISE_NUMBER, service_info[0],
   2990          SEGMENTED_IPv6_ADDR_PARAM_SRP(route_state->srp_listener_ip_address.s6_addr, server_ip_buf),
   2991          route_state->srp_service_listen_port);
   2992 
   2993     ret = cti_add_service(route_state->srp_server, route_state, partition_add_service_callback, NULL,
   2994                           THREAD_ENTERPRISE_NUMBER, service_info, 1, server_info, sizeof server_info);
   2995     if (ret != kCTIStatus_NoError) {
   2996         INFO("status %d", ret);
   2997     }
   2998 
   2999     // Wait a while for the service add to be reflected in an event.
   3000     partition_schedule_service_add_wakeup(route_state);
   3001     route_state->advertising_srp_unicast_service = true;
   3002 }
   3003 
   3004 static void
   3005 partition_start_advertising_anycast_service(route_state_t *route_state)
   3006 {
   3007     uint8_t service_info[] = {0, 0, 0, 1};
   3008     int ret;
   3009 
   3010     if (route_maybe_restart_service_tracker(route_state, &route_state->times_unadvertised_anycast, &route_state->times_advertised_anycast)) {
   3011         INFO("restarted service tracker.");
   3012     }
   3013     service_info[0] = THREAD_SRP_SERVER_ANYCAST_OPTION & 255;
   3014     service_info[1] = route_state->thread_sequence_number;
   3015     INFO("%" PRIu64 "/%02x/ %x", THREAD_ENTERPRISE_NUMBER, service_info[0], route_state->thread_sequence_number);
   3016 
   3017     ret = cti_add_service(route_state->srp_server, route_state, partition_add_service_callback, NULL,
   3018                           THREAD_ENTERPRISE_NUMBER, service_info, 2, NULL, 0);
   3019     if (ret != kCTIStatus_NoError) {
   3020         INFO("status %d", ret);
   3021     }
   3022 
   3023     // Wait a while for the service add to be reflected in an event.
   3024     partition_schedule_anycast_service_add_wakeup(route_state);
   3025     route_state->advertising_srp_anycast_service = true;
   3026     route_refresh_interface_list(route_state);
   3027 
   3028     if (route_state->route_tracker == NULL) {
   3029         route_state->route_tracker = route_tracker_create(route_state, "main");
   3030         if (route_state->route_tracker == NULL) {
   3031             ERROR("route_tracker create failed");
   3032             return;
   3033         }
   3034         route_tracker_set_reconnect_callback(route_state->route_tracker, attempt_wpan_reconnect);
   3035         route_tracker_start(route_state->route_tracker);
   3036     } else {
   3037         INFO("route tracker already running.");
   3038     }
   3039 }
   3040 
   3041 static void
   3042 partition_service_add_wakeup(void *context)
   3043 {
   3044     route_state_t *route_state = context;
   3045     route_state->partition_service_last_add_time = 0;
   3046     partition_maybe_advertise_service(route_state);
   3047 }
   3048 
   3049 static void
   3050 partition_anycast_service_add_wakeup(void *context)
   3051 {
   3052     route_state_t *route_state = context;
   3053     route_state->partition_service_last_add_time = 0;
   3054     partition_maybe_advertise_anycast_service(route_state);
   3055 }
   3056 
   3057 static void
   3058 partition_schedule_service_add_wakeup(route_state_t *route_state)
   3059 {
   3060     if (route_state->partition_service_add_pending_wakeup == NULL) {
   3061         route_state->partition_service_add_pending_wakeup = ioloop_wakeup_create();
   3062         if (route_state->partition_service_add_pending_wakeup == NULL) {
   3063             ERROR("Can't schedule service add pending wakeup: no memory!");
   3064             return;
   3065         }
   3066     } else {
   3067         ioloop_cancel_wake_event(route_state->partition_service_add_pending_wakeup);
   3068     }
   3069     // Wait thirty seconds.
   3070     ioloop_add_wake_event(route_state->partition_service_add_pending_wakeup, route_state,
   3071                           partition_service_add_wakeup, NULL, 30 * 1000);
   3072 }
   3073 
   3074 static void
   3075 partition_schedule_anycast_service_add_wakeup(route_state_t *route_state)
   3076 {
   3077     if (route_state->partition_anycast_service_add_pending_wakeup == NULL) {
   3078         route_state->partition_anycast_service_add_pending_wakeup = ioloop_wakeup_create();
   3079         if (route_state->partition_anycast_service_add_pending_wakeup == NULL) {
   3080             ERROR("Can't schedule anycast service add pending wakeup: no memory!");
   3081             return;
   3082         }
   3083     } else {
   3084         ioloop_cancel_wake_event(route_state->partition_anycast_service_add_pending_wakeup);
   3085     }
   3086     // Wait thirty seconds.
   3087     ioloop_add_wake_event(route_state->partition_anycast_service_add_pending_wakeup, route_state,
   3088                           partition_anycast_service_add_wakeup, NULL, 30 * 1000);
   3089 }
   3090 
   3091 static void
   3092 partition_maybe_advertise_service(route_state_t *route_state)
   3093 {
   3094     thread_service_t *service;
   3095     int num_lower_services = 0;
   3096     int num_other_services = 0;
   3097     int num_legacy_services = 0;
   3098     int i;
   3099     int64_t last_add_time;
   3100     bool advertising_service = false;
   3101 
   3102     // If we aren't ready to advertise a service, there's nothing to do.
   3103     if (!route_state->partition_can_advertise_service) {
   3104         INFO("no service to advertise yet.");
   3105         return;
   3106     }
   3107 
   3108     if (route_state->srp_server->srp_unicast_service_blocked) {
   3109         INFO("service advertising is disabled.");
   3110         return;
   3111     }
   3112 
   3113     for (i = 0; i < 16; i++) {
   3114         if (route_state->srp_listener_ip_address.s6_addr[i] != 0) {
   3115             break;
   3116         }
   3117     }
   3118     if (i == 16) {
   3119         INFO("no listener.");
   3120         return;
   3121     }
   3122 
   3123     // The add service function requires a remove prior to the add, so if we are doing an add, we need to wait
   3124     // for things to stabilize before allowing the removal of a service to trigger a re-evaluation.
   3125     // Therefore, if we've done an add in the past ten seconds, wait ten seconds before trying another add.
   3126     last_add_time = ioloop_timenow() - route_state->partition_service_last_add_time;
   3127     INFO("last_add_time = %" PRId64, last_add_time);
   3128     if (last_add_time < 10 * 1000) {
   3129     schedule_wakeup:
   3130         partition_schedule_service_add_wakeup(route_state);
   3131         return;
   3132     }
   3133 
   3134     // Count how many services are numerically lower than the listener address
   3135     for (service = service_tracker_services_get(route_state->srp_server->service_tracker);
   3136          service; service = service->next)
   3137     {
   3138         if (service->ignore || service->service_type != unicast_service) {
   3139             continue;
   3140         }
   3141 
   3142         if ((service->user || (route_state->have_rloc16 && service->rloc16 == route_state->srp_server->rloc16)) &&
   3143             (in6addr_compare(&service->u.unicast.address, &route_state->srp_listener_ip_address) ||
   3144              ((service->u.unicast.port[0] << 8) | service->u.unicast.port[1]) != route_state->srp_service_listen_port))
   3145         {
   3146             thread_service_note("Rtr0", service, "is ours, but stale");
   3147             partition_stop_advertising_service(route_state);
   3148             goto schedule_wakeup;
   3149         }
   3150 
   3151         // See if host advertising this unicast service is also advertising an anycast service; if not, then this
   3152         // unicast service doesn't count (much).
   3153         bool anycast_present = false;
   3154         for (thread_service_t *aservice = service_tracker_services_get(route_state->srp_server->service_tracker);
   3155              aservice != NULL; aservice = aservice->next)
   3156         {
   3157             if (aservice->ignore || aservice->service_type != anycast_service) {
   3158                 continue;
   3159             }
   3160             if (service->rloc16 == aservice->rloc16) {
   3161                 anycast_present = true;
   3162                 break;
   3163             }
   3164         }
   3165         if (!anycast_present) {
   3166             num_legacy_services++;
   3167             route_state->seen_legacy_service = true;
   3168             continue;
   3169         }
   3170 
   3171         int cmp = in6addr_compare(&service->u.unicast.address, &route_state->srp_listener_ip_address);
   3172         SEGMENTED_IPv6_ADDR_GEN_SRP(&service->u.unicast.address, addr_buf);
   3173         INFO(PUB_S_SRP PRI_SEGMENTED_IPv6_ADDR_SRP ": is " PUB_S_SRP " listener address.",
   3174              anycast_present ? "legacy service " : "service ",
   3175              SEGMENTED_IPv6_ADDR_PARAM_SRP(&service->u.unicast.address, addr_buf),
   3176              cmp < 0 ? "less than" : cmp > 0 ? "greater than" : "equal to");
   3177         if (cmp < 0) {
   3178             num_lower_services++;
   3179         } else if (cmp == 0) {
   3180             advertising_service = true;
   3181         } else {
   3182             num_other_services++;
   3183         }
   3184     }
   3185 
   3186     // We only want to advertise our service if there are no services being advertised on addresses that are lower than
   3187     // ours. Also, if we notice that a service is being advertised by our rloc16 with a different IP address than the
   3188     // listener address, it's a stale address, so remove it. If we have seen a legacy service, and there is only one
   3189     // other non-legacy service, continue to advertise a second service, since cooperating services are preferable.
   3190     if ((num_lower_services > 0  && !route_state->seen_legacy_service) || num_lower_services > 1) {
   3191         if (advertising_service) {
   3192             SEGMENTED_IPv6_ADDR_GEN_SRP(&route_state->srp_listener_ip_address, addr_buf);
   3193             INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": stopping advertising unicast service.",
   3194                  SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf));
   3195             partition_stop_advertising_service(route_state);
   3196             route_state->partition_service_last_add_time = ioloop_timenow();
   3197         } else {
   3198             INFO("not advertising unicast service.");
   3199         }
   3200     }
   3201     // If there is not some other service published, and we are not publishing, publish.  If there is a legacy (no
   3202     // anycast) service published, publish a second service so as to encourage the legacy service to withdraw, because
   3203     // cooperating services are preferable to competing services.
   3204     else if (num_other_services < 1 || (num_other_services < 2 && route_state->seen_legacy_service)) {
   3205         if (num_legacy_services > 1 && num_other_services > 1) {
   3206             ERROR("%d legacy services present!", num_legacy_services);
   3207         } else if (!advertising_service) {
   3208             SEGMENTED_IPv6_ADDR_GEN_SRP(&route_state->srp_listener_ip_address, addr_buf);
   3209             INFO(PRI_SEGMENTED_IPv6_ADDR_SRP ": starting advertising unicast service.",
   3210                  SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf));
   3211             partition_start_advertising_service(route_state);
   3212             route_state->partition_service_last_add_time = ioloop_timenow();
   3213         } else {
   3214             INFO("already advertising unicast service.");
   3215         }
   3216     }
   3217     // There is some other service published.
   3218     else {
   3219         INFO("another service is present, no need to advertise.");
   3220     }
   3221 }
   3222 
   3223 void
   3224 partition_maybe_advertise_anycast_service(route_state_t *route_state)
   3225 {
   3226     int64_t last_add_time;
   3227     bool publish = false;
   3228 
   3229     // If we aren't ready to advertise a service, there's nothing to do.
   3230     if (!route_state->have_non_thread_interface) {
   3231         INFO("no active interface.");
   3232         return;
   3233     }
   3234 
   3235     if (!route_state->partition_can_advertise_service) {
   3236         INFO("service advertisements are blocked.");
   3237         return;
   3238     }
   3239 
   3240     if (!route_state->partition_can_advertise_anycast_service) {
   3241         INFO("no service to advertise yet.");
   3242         return;
   3243     }
   3244 
   3245     if (route_state->srp_server->srp_anycast_service_blocked) {
   3246         INFO("service advertising is disabled.");
   3247         return;
   3248     }
   3249 
   3250     if (route_state->num_thread_prefixes == 0) {
   3251         INFO("OMR prefix is not yet advertised.");
   3252         return;
   3253     }
   3254 
   3255     // The add service function requires a remove prior to the add, so if we are doing an add, we need to wait
   3256     // for things to stabilize before allowing the removal of a service to trigger a re-evaluation.
   3257     // Therefore, if we've done an add in the past ten seconds, wait ten seconds before trying another add.
   3258     last_add_time = ioloop_timenow() - route_state->partition_service_last_add_time;
   3259     INFO("last_add_time = %" PRId64, last_add_time);
   3260     if (last_add_time < 10 * 1000) {
   3261     schedule_wakeup:
   3262         partition_schedule_anycast_service_add_wakeup(route_state);
   3263         return;
   3264     }
   3265 
   3266     // Find the highest (two's complement math) sequence number
   3267     uint8_t winning_seq = route_state->thread_sequence_number;
   3268     for (thread_service_t *service = service_tracker_services_get(route_state->srp_server->service_tracker); service;
   3269          service = service->next)
   3270     {
   3271         if (service->service_type != anycast_service) {
   3272             continue;
   3273         }
   3274         struct thread_anycast_service *aservice = &service->u.anycast;
   3275         // Eliminate stale services before doing anything else.
   3276         if ((service->user || (route_state->have_rloc16 && service->rloc16 == route_state->srp_server->rloc16)) &&
   3277             (aservice->sequence_number != route_state->thread_sequence_number ||
   3278             !route_state->advertising_srp_anycast_service))
   3279         {
   3280             thread_service_note("Rtr0", service, "is ours, but stale");
   3281             partition_stop_advertising_anycast_service(route_state, aservice->sequence_number);
   3282             goto schedule_wakeup;
   3283         }
   3284 #ifdef PING_ANYCAST_SERVICE
   3285         if (service->ignore) {
   3286             continue;
   3287         }
   3288         route_ping_aservice(route_state, service);
   3289 #endif
   3290         uint8_t service_seq = aservice->sequence_number;
   3291         int8_t distance = service_seq - winning_seq;
   3292         if (distance > 0) {
   3293             winning_seq = service_seq;
   3294         }
   3295         if (distance == -128) {
   3296             if ((int8_t)service_seq > (int8_t)winning_seq) {
   3297                 winning_seq = service_seq;
   3298             }
   3299         }
   3300     }
   3301 
   3302     if (winning_seq != route_state->thread_sequence_number) {
   3303         INFO("our sequence number (0x%02x) loses the election to 0x%02x", route_state->thread_sequence_number, winning_seq);
   3304         goto publication;
   3305     }
   3306 
   3307     // Count how many services on our anycast sequence number have lower RLOCs
   3308     int num_less = 0;
   3309     for (thread_service_t *service = service_tracker_services_get(route_state->srp_server->service_tracker); service;
   3310          service = service->next)
   3311     {
   3312         struct thread_anycast_service *aservice = &service->u.anycast;
   3313         if (aservice->sequence_number == winning_seq) {
   3314             if (service->rloc16 < route_state->srp_server->rloc16) {
   3315                 num_less++;
   3316             }
   3317         }
   3318     }
   3319 
   3320     if (num_less >= MAX_ANYCAST_NUM) {
   3321         INFO("our sequence number (0x%02x) wins, but there are %d other services published already",
   3322              route_state->thread_sequence_number, num_less);
   3323         goto publication;
   3324     }
   3325 
   3326     INFO("our sequence number (0x%02x) wins, and there are %d (<5) other services published already",
   3327          route_state->thread_sequence_number, num_less);
   3328     publish = true;
   3329 publication:
   3330     if (publish) {
   3331         if (!route_state->advertising_srp_anycast_service) {
   3332             INFO("advertising our anycast service with sequence number 0x%02x", route_state->thread_sequence_number);
   3333             partition_start_advertising_anycast_service(route_state);
   3334             route_state->partition_service_last_add_time = ioloop_timenow();
   3335         } else {
   3336             INFO("already advertising our anycast service with sequence number 0x%x",
   3337                  route_state->thread_sequence_number);
   3338         }
   3339     } else {
   3340         if (!route_state->advertising_srp_anycast_service) {
   3341             INFO("not advertising our anycast service with sequence number 0x%02x",
   3342                  route_state->thread_sequence_number);
   3343         } else {
   3344             INFO("withdrawing our anycast service advertisement with sequence number 0x%02x",
   3345                  route_state->thread_sequence_number);
   3346             partition_stop_advertising_anycast_service(route_state, route_state->thread_sequence_number);
   3347             route_state->partition_service_last_add_time = ioloop_timenow();
   3348         }
   3349     }
   3350 }
   3351 
   3352 static void
   3353 partition_service_set_changed_callback(void *context)
   3354 {
   3355     route_state_t *route_state = context;
   3356     service_tracker_t *tracker = route_state->srp_server->service_tracker;
   3357 
   3358     // If we discover an advertised service with our rloc, but listening address or port does not
   3359     // match, we need to remove it.
   3360     for (thread_service_t *service = service_tracker_services_get(tracker); service != NULL; service = service->next) {
   3361         if (service->ignore) {
   3362             continue;
   3363         }
   3364         if (service->service_type == unicast_service) {
   3365             if (service->user || (route_state->srp_server->have_rloc16 && service->rloc16 == route_state->srp_server->rloc16)) {
   3366                 uint16_t port = (service->u.unicast.port[0] << 8) | service->u.unicast.port[1];
   3367                 if (in6addr_compare(&service->u.unicast.address, &route_state->srp_listener_ip_address) ||
   3368                     port != route_state->srp_service_listen_port)
   3369                 {
   3370                     service_tracker_thread_service_note(tracker, service, "is ours, but stale");
   3371                     partition_stop_advertising_service(route_state);
   3372                     service->ignore = true;
   3373                 }
   3374             }
   3375         } else if (service->service_type == anycast_service) {
   3376             // If we discover an advertised service with our rloc, and either we aren't advertising an anycast service,
   3377             // or the sequence number isn't the one we're supposed to be advertising, we need to remove it.
   3378             if ((service->user || (route_state->srp_server->have_rloc16 && service->rloc16 == route_state->srp_server->rloc16)) &&
   3379                 (!route_state->advertising_srp_anycast_service ||
   3380                  service->u.anycast.sequence_number != route_state->thread_sequence_number))
   3381             {
   3382                 service_tracker_thread_service_note(tracker, service, "is ours, but stale");
   3383                 partition_stop_advertising_anycast_service(route_state, service->u.anycast.sequence_number);
   3384                 service->ignore = true;
   3385             }
   3386         }
   3387     }
   3388 
   3389     partition_maybe_advertise_service(route_state);
   3390     partition_maybe_advertise_anycast_service(route_state);
   3391 }
   3392 
   3393 static void
   3394 partition_service_set_changed(void *context)
   3395 {
   3396     route_state_t *route_state = context;
   3397     if (route_state->service_set_changed_wakeup == NULL) {
   3398         route_state->service_set_changed_wakeup = ioloop_wakeup_create();
   3399         if (route_state->service_set_changed_wakeup == NULL) {
   3400             ERROR("Can't schedule service list change wakeup: no memory!");
   3401             return;
   3402         }
   3403     } else {
   3404         ioloop_cancel_wake_event(route_state->service_set_changed_wakeup);
   3405     }
   3406     int timeout = srp_random16() % 20000; // Randomly wait between zero and twenty seconds
   3407     INFO("waiting %d milliseconds before processing service state change.", timeout);
   3408     ioloop_add_wake_event(route_state->service_set_changed_wakeup, route_state,
   3409                           partition_service_set_changed_callback, NULL, timeout);
   3410 }
   3411 
   3412 static void partition_maybe_enable_services(route_state_t *route_state)
   3413 {
   3414     bool am_associated = route_state->current_thread_state == kCTI_NCPState_Associated;
   3415     if (am_associated) {
   3416         bool restart = false;
   3417         INFO("Enabling service, which was disabled because of the thread role or state.");
   3418         route_state->partition_may_offer_service = true;
   3419         route_state->partition_can_provide_routing = true;
   3420         route_refresh_interface_list(route_state);
   3421         routing_policy_evaluate_all_interfaces(route_state, true);
   3422         if (route_state->omr_watcher == NULL) {
   3423             if (route_state->omr_publisher != NULL) {
   3424                 omr_publisher_cancel(route_state->omr_publisher);
   3425                 omr_publisher_release(route_state->omr_publisher);
   3426                 route_state->omr_publisher = NULL;
   3427             }
   3428             route_state->omr_watcher = omr_watcher_create(route_state, attempt_wpan_reconnect);
   3429             if (route_state->omr_watcher == NULL) {
   3430                 ERROR("omr_watcher create failed");
   3431                 return;
   3432             }
   3433             route_state->omr_watcher_callback = omr_watcher_callback_add(route_state->omr_watcher,
   3434                                                                          route_omr_watcher_event, NULL, route_state);
   3435             if (route_state->omr_watcher_callback == NULL) {
   3436                 ERROR("omr_watcher_callback add failed");
   3437                 return;
   3438             }
   3439             restart = true;
   3440         }
   3441         if (route_state->omr_publisher == NULL) {
   3442             route_state->omr_publisher = omr_publisher_create(route_state, "main");
   3443             if (route_state->omr_publisher == NULL) {
   3444                 ERROR("omr_publisher create failed");
   3445                 return;
   3446             }
   3447             omr_publisher_set_omr_watcher(route_state->omr_publisher, route_state->omr_watcher);
   3448             omr_publisher_set_reconnect_callback(route_state->omr_publisher, attempt_wpan_reconnect);
   3449             restart = true;
   3450         }
   3451         if (restart) {
   3452             omr_publisher_start(route_state->omr_publisher);
   3453             omr_watcher_start(route_state->omr_watcher);
   3454         }
   3455     } else {
   3456         INFO("Not enabling service: " PUB_S_SRP,
   3457              am_associated ? "associated" : "!associated");
   3458     }
   3459 }
   3460 
   3461 static void partition_disable_service(route_state_t *route_state)
   3462 {
   3463     bool done_something = false;
   3464 
   3465     // When our node type or state is such that we should no longer be publishing a prefix, the NCP will
   3466     // automatically remove the published prefix.  In case this happens, we do not want to remember the
   3467     // prefix as already having been published.  So drop our recollection of the published
   3468     // prefix; this will get cleaned up when the network comes back if there's an inconsistency.
   3469     if (route_state->omr_publisher != NULL) {
   3470         omr_publisher_cancel(route_state->omr_publisher);
   3471         omr_publisher_release(route_state->omr_publisher);
   3472         route_state->omr_publisher = NULL;
   3473         done_something = true;
   3474     }
   3475     if (route_state->omr_watcher != NULL) {
   3476         if (route_state->omr_watcher_callback != NULL) {
   3477             omr_watcher_callback_cancel(route_state->omr_watcher, route_state->omr_watcher_callback);
   3478             route_state->omr_watcher_callback = NULL;
   3479         }
   3480         omr_watcher_cancel(route_state->omr_watcher);
   3481         omr_watcher_release(route_state->omr_watcher);
   3482         route_state->omr_watcher = NULL;
   3483         done_something = true;
   3484     }
   3485 
   3486     // We want to always say something when we pass through this state.
   3487     if (done_something) {
   3488         INFO("did something");
   3489     } else {
   3490         INFO("did nothing.");
   3491     }
   3492 
   3493     route_state->partition_may_offer_service = false;
   3494     route_state->partition_can_provide_routing = false;
   3495 }
   3496 
   3497 void partition_block_anycast_service(route_state_t *route_state, bool block)
   3498 {
   3499     if (block) {
   3500         if (!route_state->srp_server->srp_anycast_service_blocked) {
   3501             route_state->srp_server->srp_anycast_service_blocked = block;
   3502             partition_stop_advertising_anycast_service(route_state, route_state->thread_sequence_number);
   3503         }
   3504     } else {
   3505         if (route_state->srp_server->srp_anycast_service_blocked) {
   3506             route_state->srp_server->srp_anycast_service_blocked = block;
   3507             partition_maybe_advertise_anycast_service(route_state);
   3508         }
   3509     }
   3510 }
   3511 
   3512 #endif // RA_TESTER
   3513 
   3514 #if SRP_FEATURE_LOCAL_DISCOVERY
   3515 int
   3516 route_get_current_infra_interface_index(void)
   3517 {
   3518     extern srp_server_t *srp_servers;
   3519     if (srp_servers == NULL) {
   3520         INFO("no SRP servers");
   3521         return -1;
   3522     }
   3523     route_state_t *route_state = srp_servers->route_state;
   3524     if (route_state == NULL) {
   3525         INFO("no route state");
   3526         return -1;
   3527     }
   3528     for (interface_t *interface = route_state->interfaces; interface != NULL; interface = interface->next) {
   3529         if (!interface->inactive && !interface->is_thread) {
   3530             return (int)interface->index; // real interface indexes are always positive integers
   3531         }
   3532     }
   3533     return -1;
   3534 }
   3535 #endif // SRP_FEATURE_LOCAL_DISCOVERY
   3536 #endif // STUB_ROUTER
   3537 
   3538 // Local Variables:
   3539 // mode: C
   3540 // tab-width: 4
   3541 // c-file-style: "bsd"
   3542 // c-basic-offset: 4
   3543 // fill-column: 120
   3544 // indent-tabs-mode: nil
   3545 // End:
   3546