Home | History | Annotate | Line # | Download | only in ServiceRegistration
nat64.c revision 1.1
      1 /* nat64.c
      2  *
      3  * Copyright (c) 2022-2023 Apple Inc. All rights reserved.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     https://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include <netinet/in.h>
     19 #include "srp-log.h"
     20 #include "dns-msg.h"
     21 #include "ioloop.h"
     22 #include "srp-mdns-proxy.h"
     23 #include "nat64.h"
     24 #include "nat64-macos.h"
     25 #include "state-machine.h"
     26 #include "thread-service.h"
     27 #include "omr-watcher.h"
     28 #include "omr-publisher.h"
     29 
     30 #if SRP_FEATURE_NAT64
     31 static void nat64_infra_prefix_publisher_event_init(nat64_infra_prefix_publisher_event_t *event, nat64_infra_prefix_publisher_event_type_t event_type);
     32 static void nat64_infra_prefix_publisher_event_deliver(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t *event);
     33 static void nat64_br_prefix_publisher_event_init(nat64_br_prefix_publisher_event_t *event, nat64_br_prefix_publisher_event_type_t event_type);
     34 static void nat64_br_prefix_publisher_event_deliver(nat64_br_prefix_publisher_t *state_machine, nat64_br_prefix_publisher_event_t *event);
     35 static void nat64_add_prefix_to_update_queue(nat64_t *nat64, nat64_prefix_t *prefix, nat64_prefix_action action);
     36 static void nat64_prefix_start_next_update(nat64_t *nat64);
     37 static bool nat64_query_prefix_on_infra(nat64_infra_prefix_monitor_t *state_machine);
     38 
     39 static void
     40 nat64_prefix_finalize(nat64_prefix_t *prefix)
     41 {
     42     free(prefix);
     43 }
     44 
     45 static void
     46 nat64_finalize(nat64_t *nat64)
     47 {
     48     free(nat64);
     49 }
     50 
     51 static nat64_ipv4_default_route_monitor_t *
     52 nat64_ipv4_default_route_monitor_create(nat64_t *nat64)
     53 {
     54     nat64_ipv4_default_route_monitor_t *monitor = calloc(1, sizeof(*monitor));
     55     if (monitor == NULL) {
     56         return monitor;
     57     }
     58     RETAIN_HERE(monitor, nat64_ipv4_default_route_monitor);
     59     monitor->nat64 = nat64;
     60     RETAIN_HERE(monitor->nat64, nat64);
     61     return monitor;
     62 }
     63 
     64 static void
     65 nat64_ipv4_default_route_monitor_cancel(nat64_ipv4_default_route_monitor_t *monitor)
     66 {
     67     if (monitor != NULL) {
     68         monitor->has_ipv4_default_route = false;
     69         if (monitor->nat64 != NULL) {
     70             RELEASE_HERE(monitor->nat64, nat64);
     71             monitor->nat64 = NULL;
     72         }
     73     }
     74 }
     75 
     76 static void
     77 nat64_ipv4_default_route_monitor_finalize(nat64_ipv4_default_route_monitor_t *monitor)
     78 {
     79     free(monitor);
     80 }
     81 
     82 static void
     83 nat64_infra_prefix_monitor_finalize(nat64_infra_prefix_monitor_t *monitor)
     84 {
     85     free(monitor);
     86 }
     87 
     88 static nat64_infra_prefix_monitor_t *
     89 nat64_infra_prefix_monitor_create(nat64_t *nat64)
     90 {
     91     nat64_infra_prefix_monitor_t *monitor = calloc(1, sizeof(*monitor));
     92     if (monitor == NULL) {
     93         return monitor;
     94     }
     95     RETAIN_HERE(monitor, nat64_infra_prefix_monitor);
     96     monitor->nat64 = nat64;
     97     RETAIN_HERE(monitor->nat64, nat64);
     98     return monitor;
     99 }
    100 
    101 static void
    102 nat64_infra_prefix_monitor_cancel(nat64_infra_prefix_monitor_t *monitor)
    103 {
    104     if (monitor != NULL) {
    105         nat64_prefix_t *next;
    106         for (nat64_prefix_t *prefix = monitor->infra_nat64_prefixes; prefix != NULL; prefix = next) {
    107             next = prefix->next;
    108             prefix->next = NULL;
    109             RELEASE_HERE(prefix, nat64_prefix);
    110         }
    111         monitor->infra_nat64_prefixes = NULL;
    112         if (monitor->sdRef != NULL) {
    113             DNSServiceRefDeallocate(monitor->sdRef);
    114             monitor->sdRef = NULL;
    115             RELEASE_HERE(monitor, nat64_infra_prefix_monitor);
    116         }
    117         if (monitor->nat64 != NULL) {
    118             RELEASE_HERE(monitor->nat64, nat64);
    119             monitor->nat64 = NULL;
    120         }
    121         monitor->canceled = true;
    122     }
    123 }
    124 
    125 static nat64_thread_prefix_monitor_t *
    126 nat64_thread_prefix_monitor_create(nat64_t *nat64)
    127 {
    128     nat64_thread_prefix_monitor_t *monitor = calloc(1, sizeof(*monitor));
    129     if (monitor == NULL) {
    130         return monitor;
    131     }
    132     RETAIN_HERE(monitor, nat64_thread_prefix_monitor);
    133     monitor->nat64 = nat64;
    134     RETAIN_HERE(monitor->nat64, nat64);
    135     return monitor;
    136 }
    137 
    138 static void
    139 nat64_thread_prefix_monitor_cancel(nat64_thread_prefix_monitor_t *monitor)
    140 {
    141     if (monitor != NULL) {
    142         nat64_prefix_t *next;
    143         for (nat64_prefix_t *prefix = monitor->thread_nat64_prefixes; prefix != NULL; prefix = next) {
    144             next = prefix->next;
    145             prefix->next = NULL;
    146             RELEASE_HERE(prefix, nat64_prefix);
    147         }
    148         monitor->thread_nat64_prefixes = NULL;
    149         if (monitor->timer != NULL) {
    150             ioloop_cancel_wake_event(monitor->timer);
    151             ioloop_wakeup_release(monitor->timer);
    152             monitor->timer = NULL;
    153         }
    154         if (monitor->nat64 != NULL) {
    155             RELEASE_HERE(monitor->nat64, nat64);
    156             monitor->nat64 = NULL;
    157         }
    158     }
    159 }
    160 
    161 static void
    162 nat64_thread_prefix_monitor_finalize(nat64_thread_prefix_monitor_t *monitor)
    163 {
    164     free(monitor);
    165 }
    166 
    167 static nat64_infra_prefix_publisher_t *
    168 nat64_infra_prefix_publisher_create(nat64_t *nat64)
    169 {
    170     nat64_infra_prefix_publisher_t *publisher = calloc(1, sizeof(*publisher));
    171     if (publisher == NULL) {
    172         return publisher;
    173     }
    174     RETAIN_HERE(publisher, nat64_infra_prefix_publisher);
    175     publisher->nat64 = nat64;
    176     RETAIN_HERE(publisher->nat64, nat64);
    177     return publisher;
    178 }
    179 
    180 static void
    181 nat64_infra_prefix_publisher_finalize(nat64_infra_prefix_publisher_t *publisher)
    182 {
    183     free(publisher);
    184 }
    185 
    186 static void
    187 nat64_infra_prefix_publisher_cancel(nat64_infra_prefix_publisher_t *publisher)
    188 {
    189     if (publisher != NULL) {
    190         if (publisher->state == nat64_infra_prefix_publisher_state_publishing) {
    191             SEGMENTED_IPv6_ADDR_GEN_SRP(publisher->proposed_prefix->prefix.s6_addr, nat64_prefix_buf);
    192             INFO("thread network shutdown, unpublishing infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
    193                  SEGMENTED_IPv6_ADDR_PARAM_SRP(publisher->proposed_prefix->prefix.s6_addr, nat64_prefix_buf));
    194             nat64_add_prefix_to_update_queue(publisher->nat64, publisher->proposed_prefix, nat64_prefix_action_remove);
    195         }
    196         if (publisher->proposed_prefix != NULL) {
    197             RELEASE_HERE(publisher->proposed_prefix, nat64_prefix);
    198             publisher->proposed_prefix = NULL;
    199         }
    200         if (publisher->nat64 != NULL) {
    201             RELEASE_HERE(publisher->nat64, nat64);
    202             publisher->nat64 = NULL;
    203         }
    204     }
    205 }
    206 
    207 static nat64_br_prefix_publisher_t *
    208 nat64_br_prefix_publisher_create(nat64_t *nat64)
    209 {
    210     nat64_br_prefix_publisher_t *publisher = calloc(1, sizeof(*publisher));
    211     if (publisher == NULL) {
    212         return publisher;
    213     }
    214     RETAIN_HERE(publisher, nat64_br_prefix_publisher);
    215     publisher->nat64 = nat64;
    216     RETAIN_HERE(publisher->nat64, nat64);
    217     return publisher;
    218 }
    219 
    220 static void
    221 nat64_br_prefix_publisher_finalize(nat64_br_prefix_publisher_t *publisher)
    222 {
    223     free(publisher);
    224 }
    225 
    226 static void
    227 nat64_br_prefix_publisher_cancel(nat64_br_prefix_publisher_t *publisher)
    228 {
    229     if (publisher != NULL) {
    230         if (publisher->state == nat64_br_prefix_publisher_state_publishing) {
    231             SEGMENTED_IPv6_ADDR_GEN_SRP(publisher->br_prefix->prefix.s6_addr, nat64_prefix_buf);
    232             INFO("thread network shutdown, unpublishing br prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
    233                  SEGMENTED_IPv6_ADDR_PARAM_SRP(publisher->br_prefix->prefix.s6_addr, nat64_prefix_buf));
    234             nat64_add_prefix_to_update_queue(publisher->nat64, publisher->br_prefix, nat64_prefix_action_remove);
    235         }
    236         if (publisher->br_prefix != NULL) {
    237             RELEASE_HERE(publisher->br_prefix, nat64_prefix);
    238             publisher->br_prefix = NULL;
    239         }
    240         if (publisher->timer != NULL) {
    241             ioloop_cancel_wake_event(publisher->timer);
    242             ioloop_wakeup_release(publisher->timer);
    243             publisher->timer = NULL;
    244         }
    245         if (publisher->nat64 != NULL) {
    246             RELEASE_HERE(publisher->nat64, nat64);
    247             publisher->nat64 = NULL;
    248         }
    249     }
    250 }
    251 
    252 static void
    253 nat64_cancel(nat64_t *nat64)
    254 {
    255     if (nat64->ipv4_monitor) {
    256         INFO("discontinuing nat64 ipv4 default route monitor");
    257         nat64_ipv4_default_route_monitor_cancel(nat64->ipv4_monitor);
    258         RELEASE_HERE(nat64->ipv4_monitor, nat64_ipv4_default_route_monitor);
    259         nat64->ipv4_monitor = NULL;
    260     }
    261     if (nat64->thread_monitor) {
    262         INFO("discontinuing nat64 thread monitor");
    263         nat64_thread_prefix_monitor_cancel(nat64->thread_monitor);
    264         RELEASE_HERE(nat64->thread_monitor, nat64_thread_prefix_monitor);
    265         nat64->thread_monitor = NULL;
    266     }
    267     if (nat64->infra_monitor) {
    268         INFO("discontinuing nat64 infra monitor");
    269         nat64_infra_prefix_monitor_cancel(nat64->infra_monitor);
    270         RELEASE_HERE(nat64->infra_monitor, nat64_infra_prefix_monitor);
    271         nat64->infra_monitor = NULL;
    272     }
    273     if (nat64->nat64_infra_prefix_publisher) {
    274         INFO("discontinuing nat64 infra prefix publisher");
    275         nat64_infra_prefix_publisher_cancel(nat64->nat64_infra_prefix_publisher);
    276         RELEASE_HERE(nat64->nat64_infra_prefix_publisher, nat64_infra_prefix_publisher);
    277         nat64->nat64_infra_prefix_publisher = NULL;
    278     }
    279     if (nat64->nat64_br_prefix_publisher) {
    280         INFO("discontinuing nat64 br prefix publisher");
    281         nat64_br_prefix_publisher_cancel(nat64->nat64_br_prefix_publisher);
    282         RELEASE_HERE(nat64->nat64_br_prefix_publisher, nat64_br_prefix_publisher);
    283         nat64->nat64_br_prefix_publisher = NULL;
    284     }
    285 }
    286 
    287 nat64_t *
    288 nat64_create(route_state_t *route_state)
    289 {
    290     nat64_t *new_nat64 = calloc(1, sizeof(*new_nat64));
    291     if (new_nat64 == NULL) {
    292         ERROR("no memory for nat64_t.");
    293         return NULL;
    294     }
    295     RETAIN_HERE(new_nat64, nat64);
    296     new_nat64->ipv4_monitor = nat64_ipv4_default_route_monitor_create(new_nat64);
    297     new_nat64->infra_monitor = nat64_infra_prefix_monitor_create(new_nat64);
    298     new_nat64->thread_monitor = nat64_thread_prefix_monitor_create(new_nat64);
    299     new_nat64->nat64_infra_prefix_publisher = nat64_infra_prefix_publisher_create(new_nat64);
    300     new_nat64->nat64_br_prefix_publisher = nat64_br_prefix_publisher_create(new_nat64);
    301 
    302     if (new_nat64->ipv4_monitor == NULL || new_nat64->infra_monitor == NULL ||
    303         new_nat64->thread_monitor == NULL || new_nat64->nat64_infra_prefix_publisher == NULL ||
    304         new_nat64->nat64_br_prefix_publisher == NULL) {
    305         ERROR("no memory for nat64 state machines.");
    306         nat64_cancel(new_nat64);
    307         return NULL;
    308     }
    309     new_nat64->route_state = route_state;
    310 
    311     return new_nat64;
    312 }
    313 
    314 nat64_prefix_t *
    315 nat64_prefix_create(struct in6_addr *address, int prefix_length, nat64_preference pref, int rloc)
    316 {
    317     nat64_prefix_t *prefix;
    318 
    319     prefix = calloc(1, (sizeof *prefix));
    320     if (prefix == NULL) {
    321         ERROR("no memory when create nat64 prefix");
    322         return NULL;
    323     }
    324     in6prefix_copy(&prefix->prefix, address, NAT64_PREFIX_SLASH_96_BYTES);
    325     prefix->prefix_len = prefix_length;
    326     prefix->priority = pref;
    327     prefix->rloc = rloc;
    328     RETAIN_HERE(prefix, nat64_prefix);
    329     return prefix;
    330 }
    331 
    332 static nat64_prefix_t *
    333 nat64_prefix_dup(nat64_prefix_t *src)
    334 {
    335     return nat64_prefix_create(&src->prefix, src->prefix_len, src->priority, src->rloc);
    336 }
    337 
    338 static bool
    339 nat64_preference_has_higher_priority(const nat64_preference higher, const nat64_preference lower)
    340 {
    341     // smaller value means higher priority
    342     if (higher < lower) {
    343         return true;
    344     } else {
    345         return false;
    346     }
    347 }
    348 
    349 static bool
    350 nat64_thread_has_routable_prefix(const route_state_t * const route_state)
    351 {
    352     bool have_routable_omr_prefix;
    353     if (route_state->omr_publisher != NULL && omr_publisher_have_routable_prefix(route_state->omr_publisher)) {
    354         have_routable_omr_prefix = true;
    355     } else {
    356         have_routable_omr_prefix = false;
    357     }
    358     return have_routable_omr_prefix;
    359 }
    360 
    361 #define NAT64_EVENT_ANNOUNCE(state_machine, event)                                       \
    362     do {                                                                                 \
    363         INFO("event " PUB_S_SRP " generated in state " PUB_S_SRP,                        \
    364               event.name, state_machine->state_name);                                    \
    365     } while (false)
    366 
    367 #define NAT64_STATE_ANNOUNCE(state_machine, event)                                       \
    368     do {                                                                                 \
    369         if (event != NULL) {                                                             \
    370             INFO("event " PUB_S_SRP " received in state " PUB_S_SRP,                     \
    371                  event->name, state_machine->state_name);                                \
    372         } else {                                                                         \
    373             INFO("entering state " PUB_S_SRP,                                            \
    374             state_machine->state_name);                                                  \
    375         }                                                                                \
    376     } while (false)
    377 
    378 #define NAT64_UNEXPECTED_EVENT(state_machine, event)                                     \
    379     do {                                                                                 \
    380         if (event != NULL) {                                                             \
    381             INFO("unexpected event " PUB_S_SRP " received in state " PUB_S_SRP,          \
    382                  event->name, state_machine->state_name);                                \
    383         } else {                                                                         \
    384             INFO("unexpected NULL event received in state " PUB_S_SRP,                   \
    385             state_machine->state_name);                                                  \
    386         }                                                                                \
    387     } while (false)
    388 
    389 #define DECLARE_NAT64_STATE_GET(type, total)                                              \
    390 static type ## _state_t *                                                                 \
    391 type ## _state_get(type ## _state_type_t state)                                           \
    392 {                                                                                         \
    393     static bool once = false;                                                             \
    394     if (!once) {                                                                          \
    395         for (unsigned i = 0; i < total ## _NUM_STATES; i++) {                             \
    396             if (type ## _states[i].state != (type ## _state_type_t)i) {                   \
    397                 ERROR("type ## states %d doesn't match " PUB_S_SRP, i, type ## _states[i].name);    \
    398                 return NULL;                                                              \
    399             }                                                                             \
    400         }                                                                                 \
    401         once = true;                                                                      \
    402     }                                                                                     \
    403     if (state < 0 || state > total ## _NUM_STATES) {                                      \
    404         return NULL;                                                                      \
    405     }                                                                                     \
    406     return & type ## _states[state];                                                      \
    407 }
    408 
    409 #define DECLARE_NAT64_NEXT_STATE(type)                                                     \
    410 static void                                                                                \
    411 type ## _next_state(type ## _t *state_machine, type ## _state_type_t state)                \
    412 {                                                                                          \
    413     type ## _state_type_t next_state = state;                                              \
    414     do {                                                                                   \
    415         type ## _state_t *new_state = type ## _state_get(next_state);                      \
    416         if (new_state == NULL) {                                                           \
    417             ERROR("next state is invalid: %d", next_state);                                \
    418             return;                                                                        \
    419         }                                                                                  \
    420         state_machine->state = next_state;                                                 \
    421         state_machine->state_name = new_state->name;                                       \
    422         type ## _action_t action = new_state->action;                                      \
    423         if (action != NULL) {                                                              \
    424             next_state = action(state_machine, NULL);                                      \
    425         }                                                                                  \
    426     } while (next_state != type ## _state_invalid);                                        \
    427 }
    428 
    429 #define DECLARE_NAT64_EVENT_CONFIGURATION_GET(type, total)                                  \
    430 static type ## _configuration_t *                                                           \
    431 type ## _configuration_get(type ## _type_t event)                                           \
    432 {                                                                                           \
    433     static bool once = false;                                                               \
    434     if (!once) {                                                                            \
    435         for (unsigned i = 0; i < total ## _NUM_EVENT_TYPES; i++) {                          \
    436             if (type ## _configurations[i].event_type != (type ## _type_t)i) {              \
    437                 ERROR("type ## event %d doesn't match " PUB_S_SRP, i, type ## _configurations[i].name);   \
    438                 return NULL;                                                                \
    439             }                                                                               \
    440         }                                                                                   \
    441         once = true;                                                                        \
    442     }                                                                                       \
    443     if (event < 0 || event > total ## _NUM_EVENT_TYPES) {                                   \
    444         return NULL;                                                                        \
    445     }                                                                                       \
    446     return & type ## _configurations[event];                                                \
    447 }
    448 
    449 #define NAT64_EVENT_NAME_DECL(name) { nat64_event_##name, #name }
    450 
    451 #define DECLARE_NAT64_EVENT_INIT(type)                                                     \
    452 static void                                                                                \
    453 type ## _init(type ## _t *event, type ## _type_t event_type)                               \
    454 {                                                                                          \
    455     memset(event, 0, sizeof(*event));                                                      \
    456     type ## _configuration_t *event_config = type ## _configuration_get(event_type);       \
    457     if (event_config == NULL) {                                                            \
    458         ERROR("invalid event type %d", event_type);                                        \
    459         return;                                                                            \
    460     }                                                                                      \
    461     event->event_type = event_type;                                                        \
    462     event->name = event_config->name;                                                      \
    463 }
    464 
    465 #define DECLARE_NAT64_EVENT_DELIVER(type)                                                                      \
    466 static void                                                                                                    \
    467 type ## _event_deliver(type ## _t *state_machine, type ## _event_t *event)                                     \
    468 {                                                                                                              \
    469     type ## _state_t *state = type ## _state_get(state_machine->state);                                        \
    470     if (state == NULL) {                                                                                       \
    471         ERROR("event " PUB_S_SRP " received in invalid state %d", event->name, state_machine->state);          \
    472         return;                                                                                                \
    473     }                                                                                                          \
    474     if (state->action == NULL) {                                                                               \
    475         FAULT("event " PUB_S_SRP " received in state " PUB_S_SRP " with NULL action", event->name, state->name);  \
    476         return;                                                                                                \
    477     }                                                                                                          \
    478     type ## _state_type_t next_state = state->action(state_machine, event);                                    \
    479     if (next_state != type ## _state_invalid) {                                                                \
    480         type ## _next_state(state_machine, next_state);                                                        \
    481     }                                                                                                          \
    482 }
    483 
    484 // ipv4 default route state machine start
    485 static void nat64_ipv4_default_route_monitor_event_init(nat64_ipv4_default_route_monitor_event_t *event, nat64_ipv4_default_route_monitor_event_type_t event_type);
    486 
    487 typedef nat64_ipv4_default_route_monitor_state_type_t (*nat64_ipv4_default_route_monitor_action_t)(nat64_ipv4_default_route_monitor_t *NONNULL state_machine, nat64_ipv4_default_route_monitor_event_t *NULLABLE event);
    488 
    489 typedef struct {
    490     nat64_ipv4_default_route_monitor_state_type_t state;
    491     char *name;
    492     nat64_ipv4_default_route_monitor_action_t action;
    493 } nat64_ipv4_default_route_monitor_state_t;
    494 
    495 static nat64_ipv4_default_route_monitor_state_type_t
    496 nat64_ipv4_default_route_monitor_init_action(nat64_ipv4_default_route_monitor_t *state_machine, nat64_ipv4_default_route_monitor_event_t *UNUSED event)
    497 {
    498     NAT64_STATE_ANNOUNCE(state_machine, event);
    499     state_machine->has_ipv4_default_route = false;
    500     return nat64_ipv4_default_route_monitor_state_wait_for_event;
    501 }
    502 
    503 static nat64_ipv4_default_route_monitor_state_type_t
    504 nat64_ipv4_default_route_monitor_wait_action(nat64_ipv4_default_route_monitor_t *state_machine, nat64_ipv4_default_route_monitor_event_t *event)
    505 {
    506     NAT64_STATE_ANNOUNCE(state_machine, event);
    507     if (event == NULL) {
    508         return nat64_ipv4_default_route_monitor_state_invalid;
    509     } else if (event->event_type == nat64_event_ipv4_default_route_update) {
    510         nat64_br_prefix_publisher_event_t out_event;
    511         if (event->has_ipv4_connectivity == false) {
    512             state_machine->has_ipv4_default_route = false;
    513             nat64_br_prefix_publisher_event_init(&out_event, nat64_event_nat64_br_prefix_publisher_ipv4_default_route_went_away);
    514         } else {
    515             state_machine->has_ipv4_default_route = true;
    516             nat64_br_prefix_publisher_event_init(&out_event, nat64_event_nat64_br_prefix_publisher_ipv4_default_route_showed_up);
    517         }
    518         NAT64_EVENT_ANNOUNCE(state_machine, out_event);
    519         // Deliver out_event to BR prefix publisher
    520         nat64_br_prefix_publisher_event_deliver(state_machine->nat64->nat64_br_prefix_publisher, &out_event);
    521     } else {
    522         NAT64_UNEXPECTED_EVENT(state_machine, event);
    523     }
    524     return nat64_ipv4_default_route_monitor_state_invalid;
    525 }
    526 
    527 #define IPV4_STATE_NAME_DECL(name) nat64_ipv4_default_route_monitor_state_##name, #name
    528 static nat64_ipv4_default_route_monitor_state_t
    529 nat64_ipv4_default_route_monitor_states[] = {
    530     { IPV4_STATE_NAME_DECL(invalid),                  NULL },
    531     { IPV4_STATE_NAME_DECL(init),                     nat64_ipv4_default_route_monitor_init_action },
    532     { IPV4_STATE_NAME_DECL(wait_for_event),           nat64_ipv4_default_route_monitor_wait_action },
    533 };
    534 #define IPV4_DEFAULT_ROUTE_MONITOR_NUM_STATES (sizeof(nat64_ipv4_default_route_monitor_states) / sizeof(nat64_ipv4_default_route_monitor_state_t))
    535 
    536 DECLARE_NAT64_STATE_GET(nat64_ipv4_default_route_monitor, IPV4_DEFAULT_ROUTE_MONITOR);
    537 DECLARE_NAT64_NEXT_STATE(nat64_ipv4_default_route_monitor);
    538 
    539 // ipv4 default route monitor event functions
    540 typedef struct {
    541     nat64_ipv4_default_route_monitor_event_type_t event_type;
    542     char *name;
    543 } nat64_ipv4_default_route_monitor_event_configuration_t;
    544 
    545 nat64_ipv4_default_route_monitor_event_configuration_t nat64_ipv4_default_route_monitor_event_configurations[] = {
    546     NAT64_EVENT_NAME_DECL(ipv4_default_route_invalid),
    547     NAT64_EVENT_NAME_DECL(ipv4_default_route_update),
    548     NAT64_EVENT_NAME_DECL(ipv4_default_route_showed_up),
    549     NAT64_EVENT_NAME_DECL(ipv4_default_route_went_away),
    550 };
    551 #define IPV4_DEFAULT_ROUTE_MONITOR_NUM_EVENT_TYPES (sizeof(nat64_ipv4_default_route_monitor_event_configurations) / sizeof(nat64_ipv4_default_route_monitor_event_configuration_t))
    552 
    553 DECLARE_NAT64_EVENT_CONFIGURATION_GET(nat64_ipv4_default_route_monitor_event, IPV4_DEFAULT_ROUTE_MONITOR);
    554 DECLARE_NAT64_EVENT_INIT(nat64_ipv4_default_route_monitor_event);
    555 DECLARE_NAT64_EVENT_DELIVER(nat64_ipv4_default_route_monitor);
    556 
    557 void
    558 nat64_default_route_update(nat64_t *NONNULL nat64, bool has_ipv4_connectivity)
    559 {
    560     if (has_ipv4_connectivity != nat64->ipv4_monitor->has_ipv4_default_route){
    561         nat64_ipv4_default_route_monitor_event_t event;
    562         nat64_ipv4_default_route_monitor_event_init(&event, nat64_event_ipv4_default_route_update);
    563         event.has_ipv4_connectivity = has_ipv4_connectivity;
    564         nat64_ipv4_default_route_monitor_event_deliver(nat64->ipv4_monitor, &event);
    565     }
    566 }
    567 // ipv4 default route state machine end
    568 
    569 // Infrastructure nat64 prefix monitor state machine start
    570 static void nat64_infra_prefix_monitor_event_init(nat64_infra_prefix_monitor_event_t *event, nat64_infra_prefix_monitor_event_type_t event_type);
    571 static void nat64_infra_prefix_monitor_event_deliver(nat64_infra_prefix_monitor_t *state_machine, nat64_infra_prefix_monitor_event_t *event);
    572 typedef nat64_infra_prefix_monitor_state_type_t (*nat64_infra_prefix_monitor_action_t)(nat64_infra_prefix_monitor_t *NONNULL sm, nat64_infra_prefix_monitor_event_t *NULLABLE event);
    573 
    574 typedef struct {
    575     nat64_infra_prefix_monitor_state_type_t state;
    576     char *name;
    577     nat64_infra_prefix_monitor_action_t action;
    578 } nat64_infra_prefix_monitor_state_t;
    579 
    580 static void
    581 nat64_query_infra_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
    582                            DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass,
    583                            uint16_t rdlen, const void *rdata, uint32_t ttl, void *context)
    584 {
    585     (void)(sdRef);
    586     (void)(interfaceIndex);
    587 
    588     nat64_infra_prefix_monitor_t *state_machine = context;
    589 
    590     if (errorCode == kDNSServiceErr_NoError) {
    591         SEGMENTED_IPv6_ADDR_GEN_SRP(rdata, ipv6_rdata_buf);
    592         INFO("LLQ " PRI_S_SRP PRI_SEGMENTED_IPv6_ADDR_SRP
    593              "name: " PRI_S_SRP ", rrtype: %u, rrclass: %u, rdlen: %u, ttl: %u.",
    594              (flags & kDNSServiceFlagsAdd) ? "adding " : "removing ",
    595              SEGMENTED_IPv6_ADDR_PARAM_SRP(rdata, ipv6_rdata_buf), fullname, rrtype, rrclass, rdlen, ttl);
    596         nat64_infra_prefix_monitor_event_t event;
    597         nat64_infra_prefix_monitor_event_init(&event, nat64_event_infra_prefix_update);
    598         event.flags = flags;
    599         event.rdata = rdata;
    600         NAT64_EVENT_ANNOUNCE(state_machine, event);
    601         nat64_infra_prefix_monitor_event_deliver(state_machine, &event);
    602     } else {
    603         if (errorCode == kDNSServiceErr_NoSuchRecord) {
    604             // This should never happen.
    605             INFO("No such record for " PRI_S_SRP , NAT64_PREFIX_LLQ_QUERY_DOMAIN);
    606         } else if (errorCode == kDNSServiceErr_ServiceNotRunning) {
    607             INFO("daemon disconnected (probably daemon crash).");
    608         } else {
    609             INFO("Got error code %d when query " PRI_S_SRP , errorCode, NAT64_PREFIX_LLQ_QUERY_DOMAIN);
    610         }
    611         DNSServiceRefDeallocate(state_machine->sdRef);
    612         state_machine->sdRef = NULL;
    613 
    614         // We enter with a reference held on the state machine object. If there is no error, that means we got some kind
    615         // of result, and so we don't release the reference because we can still get more results.  If, on the other hand,
    616         // we get an error, we will restart the query after a delay. This means that the reference we were passed is
    617         // still needed for the duration of the dispatch_after call. When that timer expires, if the state machine hasn't
    618         // been canceled in the meantime, we restart the query.
    619         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC),
    620                        dispatch_get_main_queue(), ^(void) {
    621                            if (!state_machine->canceled) {
    622                                nat64_query_prefix_on_infra(state_machine);
    623                            }
    624                            RELEASE_HERE(state_machine, nat64_infra_prefix_monitor);
    625                        });
    626     }
    627 }
    628 
    629 static bool
    630 nat64_query_prefix_on_infra(nat64_infra_prefix_monitor_t *state_machine)
    631 {
    632     OSStatus err;
    633 
    634     err = DNSServiceQueryRecord(&state_machine->sdRef, kDNSServiceFlagsLongLivedQuery, kDNSServiceInterfaceIndexAny, NAT64_PREFIX_LLQ_QUERY_DOMAIN, kDNSServiceType_AAAA, kDNSServiceClass_IN, nat64_query_infra_callback, state_machine);
    635     if (err != kDNSServiceErr_NoError) {
    636         ERROR("DNSServiceQueryRecord failed for " PRI_S_SRP ": %d", NAT64_PREFIX_LLQ_QUERY_DOMAIN, (int)err);
    637         return false;
    638     }
    639     RETAIN_HERE(state_machine, nat64_infra_prefix_monitor); // For the callback.
    640     err = DNSServiceSetDispatchQueue(state_machine->sdRef, dispatch_get_main_queue());
    641     if (err != kDNSServiceErr_NoError) {
    642         ERROR("DNSServiceSetDispatchQueue failed for " PRI_S_SRP ": %d", NAT64_PREFIX_LLQ_QUERY_DOMAIN, (int)err);
    643         return false;
    644     }
    645     return true;
    646 }
    647 
    648 static nat64_infra_prefix_monitor_state_type_t
    649 nat64_infra_prefix_monitor_init_action(nat64_infra_prefix_monitor_t *state_machine, nat64_infra_prefix_monitor_event_t * event)
    650 {
    651     NAT64_STATE_ANNOUNCE(state_machine, event);
    652     // Init action: start LLQ.
    653     if (!nat64_query_prefix_on_infra(state_machine)) {
    654          return nat64_infra_prefix_monitor_state_invalid;
    655     }
    656     // Switch to next state.
    657     return nat64_infra_prefix_monitor_state_wait_for_change;
    658 }
    659 
    660 static nat64_infra_prefix_monitor_state_type_t
    661 nat64_infra_prefix_monitor_wait_action(nat64_infra_prefix_monitor_t *state_machine, nat64_infra_prefix_monitor_event_t *event)
    662 {
    663     NAT64_STATE_ANNOUNCE(state_machine, event);
    664     if (event == NULL) {
    665         return nat64_infra_prefix_monitor_state_invalid;
    666     } else if (event->event_type == nat64_event_infra_prefix_update){
    667         bool changed = false;
    668         if (event->flags & kDNSServiceFlagsAdd) {
    669             nat64_prefix_t **ppref = &state_machine->infra_nat64_prefixes, *prefix = NULL;
    670             while (*ppref != NULL) {
    671                 prefix = *ppref;
    672                 if (!memcmp(&prefix->prefix, event->rdata, NAT64_PREFIX_SLASH_96_BYTES)) {
    673                     SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, nat64_prefix_buf);
    674                     INFO("ignore dup infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
    675                          SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, nat64_prefix_buf));
    676                     break;
    677                 } else {
    678                     ppref = &prefix->next;
    679                 }
    680             }
    681             if (*ppref == NULL) {
    682                 nat64_prefix_t * new_prefix = nat64_prefix_create((struct in6_addr *)event->rdata, NAT64_PREFIX_SLASH_96_BYTES, nat64_preference_medium, state_machine->nat64->route_state->srp_server->rloc16);
    683                 if (new_prefix == NULL) {
    684                     ERROR("no memory for nat64 prefix.");
    685                     return nat64_infra_prefix_monitor_state_invalid;
    686                 }
    687                 SEGMENTED_IPv6_ADDR_GEN_SRP(new_prefix->prefix.s6_addr, nat64_prefix_buf);
    688                 INFO("adding infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " to list",
    689                      SEGMENTED_IPv6_ADDR_PARAM_SRP(new_prefix->prefix.s6_addr, nat64_prefix_buf));
    690                 new_prefix->next = state_machine->infra_nat64_prefixes;
    691                 state_machine->infra_nat64_prefixes = new_prefix;
    692                 changed = true;
    693             }
    694         } else {
    695             nat64_prefix_t **ppref = &state_machine->infra_nat64_prefixes, *prefix = NULL;
    696             while (*ppref != NULL) {
    697                 prefix = *ppref;
    698                 if (!memcmp(&prefix->prefix, event->rdata, NAT64_PREFIX_SLASH_96_BYTES)) {
    699                     *ppref = prefix->next;
    700                     SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, nat64_prefix_buf);
    701                     INFO("removing infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " from list",
    702                          SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, nat64_prefix_buf));
    703                     RELEASE_HERE(prefix, nat64_prefix);
    704                     changed = true;
    705                 } else {
    706                     ppref = &prefix->next;
    707                 }
    708             }
    709         }
    710         if (changed){
    711             return nat64_infra_prefix_monitor_state_change_occurred;
    712         }
    713     } else {
    714         NAT64_UNEXPECTED_EVENT(state_machine, event);
    715     }
    716     return nat64_infra_prefix_monitor_state_invalid;
    717 }
    718 
    719 static nat64_infra_prefix_monitor_state_type_t
    720 nat64_infra_prefix_monitor_change_occurred_action(nat64_infra_prefix_monitor_t *state_machine, nat64_infra_prefix_monitor_event_t * event)
    721 {
    722     nat64_infra_prefix_publisher_event_t out_event_to_nat64_infra_prefix_publisher;
    723     nat64_br_prefix_publisher_event_t out_event_to_nat64_br_prefix_publisher;
    724 
    725     NAT64_STATE_ANNOUNCE(state_machine, event);
    726     nat64_infra_prefix_publisher_event_init(&out_event_to_nat64_infra_prefix_publisher, nat64_event_nat64_infra_prefix_publisher_infra_prefix_changed);
    727     out_event_to_nat64_infra_prefix_publisher.prefix = state_machine->infra_nat64_prefixes;
    728     NAT64_EVENT_ANNOUNCE(state_machine, out_event_to_nat64_infra_prefix_publisher);
    729     // Deliver this event to infra prefix publisher.
    730     nat64_infra_prefix_publisher_event_deliver(state_machine->nat64->nat64_infra_prefix_publisher, &out_event_to_nat64_infra_prefix_publisher);
    731 
    732     nat64_br_prefix_publisher_event_init(&out_event_to_nat64_br_prefix_publisher, nat64_event_nat64_br_prefix_publisher_infra_prefix_changed);
    733     out_event_to_nat64_br_prefix_publisher.prefix = state_machine->infra_nat64_prefixes;
    734     NAT64_EVENT_ANNOUNCE(state_machine, out_event_to_nat64_br_prefix_publisher);
    735     // Deliver this event to BR prefix publisher.
    736     nat64_br_prefix_publisher_event_deliver(state_machine->nat64->nat64_br_prefix_publisher, &out_event_to_nat64_br_prefix_publisher);
    737 
    738     return nat64_infra_prefix_monitor_state_wait_for_change;
    739 }
    740 
    741 #define INFRA_STATE_NAME_DECL(name) nat64_infra_prefix_monitor_state_##name, #name
    742 static nat64_infra_prefix_monitor_state_t
    743 nat64_infra_prefix_monitor_states[] = {
    744     { INFRA_STATE_NAME_DECL(invalid),                     NULL },
    745     { INFRA_STATE_NAME_DECL(init),                        nat64_infra_prefix_monitor_init_action },
    746     { INFRA_STATE_NAME_DECL(wait_for_change),             nat64_infra_prefix_monitor_wait_action },
    747     { INFRA_STATE_NAME_DECL(change_occurred),             nat64_infra_prefix_monitor_change_occurred_action },
    748 };
    749 #define INFRA_PREFIX_MONITOR_NUM_STATES (sizeof(nat64_infra_prefix_monitor_states) / sizeof(nat64_infra_prefix_monitor_state_t))
    750 
    751 DECLARE_NAT64_STATE_GET(nat64_infra_prefix_monitor, INFRA_PREFIX_MONITOR);
    752 DECLARE_NAT64_NEXT_STATE(nat64_infra_prefix_monitor);
    753 
    754 // Infra prefix monitor event functions
    755 typedef struct {
    756     nat64_infra_prefix_monitor_event_type_t event_type;
    757     char *name;
    758 } nat64_infra_prefix_monitor_event_configuration_t;
    759 
    760 nat64_infra_prefix_monitor_event_configuration_t nat64_infra_prefix_monitor_event_configurations[] = {
    761     NAT64_EVENT_NAME_DECL(infra_prefix_invalid),
    762     NAT64_EVENT_NAME_DECL(infra_prefix_update),
    763 };
    764 #define INFRA_PREFIX_MONITOR_NUM_EVENT_TYPES (sizeof(nat64_infra_prefix_monitor_event_configurations) / sizeof(nat64_infra_prefix_monitor_event_configuration_t))
    765 
    766 DECLARE_NAT64_EVENT_CONFIGURATION_GET(nat64_infra_prefix_monitor_event, INFRA_PREFIX_MONITOR);
    767 DECLARE_NAT64_EVENT_INIT(nat64_infra_prefix_monitor_event);
    768 DECLARE_NAT64_EVENT_DELIVER(nat64_infra_prefix_monitor);
    769 
    770 // Infrastructure nat64 prefix monitor state machine end
    771 
    772 
    773 
    774 // Thread nat64 prefix monitor state machine start
    775 static void nat64_thread_prefix_monitor_event_init(nat64_thread_prefix_monitor_event_t *event, nat64_thread_prefix_monitor_event_type_t event_type);
    776 static void nat64_thread_prefix_monitor_event_deliver(nat64_thread_prefix_monitor_t *state_machine, nat64_thread_prefix_monitor_event_t *event);
    777 typedef nat64_thread_prefix_monitor_state_type_t (*nat64_thread_prefix_monitor_action_t)(nat64_thread_prefix_monitor_t *NONNULL sm, nat64_thread_prefix_monitor_event_t *NULLABLE event);
    778 
    779 typedef struct {
    780     nat64_thread_prefix_monitor_state_type_t state;
    781     char *name;
    782     nat64_thread_prefix_monitor_action_t action;
    783 } nat64_thread_prefix_monitor_state_t;
    784 
    785 static void
    786 nat64_thread_prefix_monitor_context_release(void *context)
    787 {
    788     nat64_thread_prefix_monitor_t *state_machine = context;
    789     RELEASE_HERE(state_machine, nat64_thread_prefix_monitor);
    790 }
    791 
    792 static void
    793 nat64_thread_prefix_monitor_wakeup(void *context)
    794 {
    795     nat64_thread_prefix_monitor_t *state_machine = context;
    796     nat64_thread_prefix_monitor_event_t out_event;
    797     nat64_thread_prefix_monitor_event_init(&out_event, nat64_event_thread_prefix_init_wait_ended);
    798     NAT64_EVENT_ANNOUNCE(state_machine, out_event);
    799     nat64_thread_prefix_monitor_event_deliver(state_machine, &out_event);
    800 }
    801 
    802 static nat64_thread_prefix_monitor_state_type_t
    803 nat64_thread_prefix_monitor_init_action(nat64_thread_prefix_monitor_t *state_machine, nat64_thread_prefix_monitor_event_t * event)
    804 {
    805     NAT64_STATE_ANNOUNCE(state_machine, event);
    806     // Init action: start timer.
    807     if (state_machine->timer == NULL) {
    808         state_machine->timer = ioloop_wakeup_create();
    809         if (state_machine->timer == NULL) {
    810             ERROR("no memory when create timer");
    811             return nat64_thread_prefix_monitor_state_invalid;
    812         }
    813         RETAIN_HERE(state_machine, nat64_thread_prefix_monitor);
    814         // wait rand(0,10) seconds
    815         ioloop_add_wake_event(state_machine->timer, state_machine, nat64_thread_prefix_monitor_wakeup, nat64_thread_prefix_monitor_context_release, srp_random16() % (NAT64_THREAD_PREFIX_SETTLING_TIME * IOLOOP_SECOND));
    816     } else {
    817         INFO("thread prefix monitor timer already started");
    818     }
    819     // Switch to next state.
    820     return nat64_thread_prefix_monitor_state_wait_for_settling;
    821 }
    822 
    823 static nat64_thread_prefix_monitor_state_type_t
    824 nat64_thread_prefix_monitor_wait_for_settling_action(nat64_thread_prefix_monitor_t *state_machine, nat64_thread_prefix_monitor_event_t * event)
    825 {
    826     NAT64_STATE_ANNOUNCE(state_machine, event);
    827     if (event == NULL) {
    828         return nat64_thread_prefix_monitor_state_invalid;
    829     } else if (event->event_type == nat64_event_thread_prefix_init_wait_ended){
    830         // Switch to next state.
    831         return nat64_thread_prefix_monitor_state_wait_for_change;
    832     } else {
    833         NAT64_UNEXPECTED_EVENT(state_machine, event);
    834         return nat64_thread_prefix_monitor_state_invalid;
    835     }
    836 }
    837 
    838 static nat64_preference
    839 route_pref_to_nat64_pref(offmesh_route_preference_t route_pref)
    840 {
    841     if (route_pref == offmesh_route_preference_low) {
    842         return nat64_preference_low;
    843     } else if (route_pref == offmesh_route_preference_high) {
    844         return nat64_preference_high;
    845     } else if (route_pref == offmesh_route_preference_medium) {
    846         return nat64_preference_medium;
    847     } else {
    848         ERROR("Unknown route prefix preference %d", route_pref);
    849         return nat64_preference_reserved;
    850     }
    851 }
    852 
    853 static char *
    854 get_nat64_prefix_pref_name(nat64_preference pref)
    855 {
    856     if (pref == nat64_preference_low) {
    857         return "low";
    858     } else if (pref == nat64_preference_high) {
    859         return "high";
    860     } else if (pref == nat64_preference_medium) {
    861         return "medium";
    862     } else {
    863         ERROR("Unknown nat64 prefix preference %d", pref);
    864         return "unknown";
    865     }
    866 }
    867 
    868 static nat64_thread_prefix_monitor_state_type_t
    869 nat64_thread_prefix_monitor_wait_for_change_action(nat64_thread_prefix_monitor_t *state_machine, nat64_thread_prefix_monitor_event_t * event)
    870 {
    871     NAT64_STATE_ANNOUNCE(state_machine, event);
    872     if (event == NULL) {
    873         return nat64_thread_prefix_monitor_state_invalid;
    874     } else if (event->event_type == nat64_event_thread_prefix_update){
    875         size_t i;
    876         nat64_prefix_t **ppref = &state_machine->thread_nat64_prefixes, *prefix = NULL;
    877         bool changed = false;
    878         // Delete any NAT64 prefixes that are not in the list provided by Thread.
    879         while (*ppref != NULL) {
    880             prefix = *ppref;
    881             for (i = 0; i < event->routes->num; i++) {
    882                 cti_route_t *route = event->routes->routes[i];
    883                 if (route->nat64 && route->origin == offmesh_route_origin_ncp){
    884                     if (!in6prefix_compare(&prefix->prefix, &route->prefix, NAT64_PREFIX_SLASH_96_BYTES)) {
    885                         break;
    886                     }
    887                 }
    888             }
    889             if (i == event->routes->num) {
    890                 *ppref = prefix->next;
    891                 SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, nat64_prefix_buf);
    892                 INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " with pref " PRI_S_SRP " went away",
    893                      SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, nat64_prefix_buf),
    894                      get_nat64_prefix_pref_name(prefix->priority));
    895                 RELEASE_HERE(prefix, nat64_prefix);
    896                 changed = true;
    897             } else {
    898                 ppref = &prefix->next;
    899             }
    900         }
    901         // Add any NAT64 prefixes that are not present.
    902         for (i = 0; i < event->routes->num; i++) {
    903             cti_route_t *route = event->routes->routes[i];
    904             if (route->nat64 && route->origin == offmesh_route_origin_ncp) {
    905                 for(prefix = state_machine->thread_nat64_prefixes; prefix != NULL; prefix = prefix->next){
    906                     if (!in6prefix_compare(&prefix->prefix, &route->prefix, NAT64_PREFIX_SLASH_96_BYTES)) {
    907                         break;
    908                     }
    909                 }
    910                 if (prefix == NULL) {
    911                     prefix = nat64_prefix_create(&route->prefix, NAT64_PREFIX_SLASH_96_BYTES, route_pref_to_nat64_pref(route->preference), route->rloc);
    912                     if (prefix == NULL) {
    913                         ERROR("no memory for nat64 prefix.");
    914                         return nat64_thread_prefix_monitor_state_invalid;
    915                     } else {
    916                         SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, nat64_prefix_buf);
    917                         INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " with pref " PRI_S_SRP " showed up",
    918                              SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, nat64_prefix_buf),
    919                              get_nat64_prefix_pref_name(prefix->priority));
    920                         *ppref = prefix;
    921                         ppref = &prefix->next;
    922                         changed = true;
    923                     }
    924                 }
    925             }
    926         }
    927         if (changed) {
    928         // Switch to next state.
    929             return nat64_thread_prefix_monitor_state_change_occurred;
    930         }
    931     } else {
    932         NAT64_UNEXPECTED_EVENT(state_machine, event);
    933     }
    934     return nat64_thread_prefix_monitor_state_invalid;
    935 }
    936 
    937 static nat64_thread_prefix_monitor_state_type_t
    938 nat64_thread_prefix_monitor_change_occurred_action(nat64_thread_prefix_monitor_t *state_machine, nat64_thread_prefix_monitor_event_t * event)
    939 {
    940     nat64_infra_prefix_publisher_event_t out_event_to_nat64_infra_prefix_publisher;
    941     nat64_br_prefix_publisher_event_t out_event_to_nat64_br_prefix_publisher;
    942 
    943     NAT64_STATE_ANNOUNCE(state_machine, event);
    944     nat64_infra_prefix_publisher_event_init(&out_event_to_nat64_infra_prefix_publisher, nat64_event_nat64_infra_prefix_publisher_thread_prefix_changed);
    945     out_event_to_nat64_infra_prefix_publisher.prefix = state_machine->thread_nat64_prefixes;
    946     NAT64_EVENT_ANNOUNCE(state_machine, out_event_to_nat64_infra_prefix_publisher);
    947     // Deliver this event to infra prefix publisher.
    948     nat64_infra_prefix_publisher_event_deliver(state_machine->nat64->nat64_infra_prefix_publisher, &out_event_to_nat64_infra_prefix_publisher);
    949 
    950     nat64_br_prefix_publisher_event_init(&out_event_to_nat64_br_prefix_publisher, nat64_event_nat64_br_prefix_publisher_thread_prefix_changed);
    951     out_event_to_nat64_br_prefix_publisher.prefix = state_machine->thread_nat64_prefixes;
    952     NAT64_EVENT_ANNOUNCE(state_machine, out_event_to_nat64_br_prefix_publisher);
    953     // Deliver this event to BR prefix publisher.
    954     nat64_br_prefix_publisher_event_deliver(state_machine->nat64->nat64_br_prefix_publisher, &out_event_to_nat64_br_prefix_publisher);
    955 
    956     return nat64_thread_prefix_monitor_state_wait_for_change;
    957 }
    958 
    959 #define THREAD_STATE_NAME_DECL(name) nat64_thread_prefix_monitor_state_##name, #name
    960 static nat64_thread_prefix_monitor_state_t
    961 nat64_thread_prefix_monitor_states[] = {
    962     { THREAD_STATE_NAME_DECL(invalid),                     NULL },
    963     { THREAD_STATE_NAME_DECL(init),                        nat64_thread_prefix_monitor_init_action },
    964     { THREAD_STATE_NAME_DECL(wait_for_settling),           nat64_thread_prefix_monitor_wait_for_settling_action },
    965     { THREAD_STATE_NAME_DECL(wait_for_change),             nat64_thread_prefix_monitor_wait_for_change_action },
    966     { THREAD_STATE_NAME_DECL(change_occurred),             nat64_thread_prefix_monitor_change_occurred_action },
    967 };
    968 #define THREAD_PREFIX_MONITOR_NUM_STATES (sizeof(nat64_thread_prefix_monitor_states) / sizeof(nat64_thread_prefix_monitor_state_t))
    969 
    970 DECLARE_NAT64_STATE_GET(nat64_thread_prefix_monitor, THREAD_PREFIX_MONITOR);
    971 DECLARE_NAT64_NEXT_STATE(nat64_thread_prefix_monitor);
    972 
    973 // Thread prefix monitor event functions
    974 typedef struct {
    975     nat64_thread_prefix_monitor_event_type_t event_type;
    976     char *name;
    977 } nat64_thread_prefix_monitor_event_configuration_t;
    978 
    979 nat64_thread_prefix_monitor_event_configuration_t nat64_thread_prefix_monitor_event_configurations[] = {
    980     NAT64_EVENT_NAME_DECL(thread_prefix_invalid),
    981     NAT64_EVENT_NAME_DECL(thread_prefix_init_wait_ended),
    982     NAT64_EVENT_NAME_DECL(thread_prefix_update),
    983 };
    984 #define THREAD_PREFIX_MONITOR_NUM_EVENT_TYPES (sizeof(nat64_thread_prefix_monitor_event_configurations) / sizeof(nat64_thread_prefix_monitor_event_configuration_t))
    985 
    986 DECLARE_NAT64_EVENT_CONFIGURATION_GET(nat64_thread_prefix_monitor_event, THREAD_PREFIX_MONITOR);
    987 DECLARE_NAT64_EVENT_INIT(nat64_thread_prefix_monitor_event);
    988 DECLARE_NAT64_EVENT_DELIVER(nat64_thread_prefix_monitor);
    989 
    990 // Thread nat64 prefix monitor state machine end
    991 
    992 
    993 // Infrastructure nat64 prefix publisher state machine start
    994 typedef nat64_infra_prefix_publisher_state_type_t (*nat64_infra_prefix_publisher_action_t)(nat64_infra_prefix_publisher_t *NONNULL sm, nat64_infra_prefix_publisher_event_t *NULLABLE event);
    995 
    996 typedef struct {
    997     nat64_infra_prefix_publisher_state_type_t state;
    998     char *name;
    999     nat64_infra_prefix_publisher_action_t action;
   1000 } nat64_infra_prefix_publisher_state_t;
   1001 
   1002 static nat64_infra_prefix_publisher_state_type_t
   1003 nat64_infra_prefix_publisher_init_action(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t * event)
   1004 {
   1005     NAT64_STATE_ANNOUNCE(state_machine, event);
   1006     // Init action
   1007 
   1008     // Switch to next state.
   1009     return nat64_infra_prefix_publisher_state_wait;
   1010 }
   1011 
   1012 static int
   1013 nat64_num_infra_prefix(const nat64_prefix_t *prefix)
   1014 {
   1015     int num_infra_prefix = 0;
   1016 
   1017     for (; prefix != NULL; prefix = prefix->next) {
   1018         if (nat64_preference_has_higher_priority(prefix->priority, nat64_preference_low)) {
   1019             num_infra_prefix++;
   1020         }
   1021     }
   1022     INFO("%d infra nat64 prefixes", num_infra_prefix);
   1023     return num_infra_prefix;
   1024 }
   1025 
   1026 static nat64_infra_prefix_publisher_state_type_t
   1027 nat64_infra_prefix_publisher_wait_action(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t *event)
   1028 {
   1029     NAT64_STATE_ANNOUNCE(state_machine, event);
   1030     if (event == NULL) {
   1031         return nat64_infra_prefix_publisher_state_invalid;
   1032     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_thread_prefix_changed) {
   1033         if (nat64_num_infra_prefix(event->prefix) >= NAT64_INFRA_PREFIX_LIMIT) {
   1034             INFO("more than %d infra nat64 prefix present on thread network, ignore", NAT64_INFRA_PREFIX_LIMIT);
   1035             return nat64_infra_prefix_publisher_state_ignore;
   1036         } else {
   1037             return nat64_infra_prefix_publisher_state_check;
   1038         }
   1039     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_infra_prefix_changed) {
   1040         // Check to see if it's appropriate to publish infra nat64 prefix
   1041         if (event->prefix) {
   1042             return nat64_infra_prefix_publisher_state_check;
   1043         }
   1044     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_routable_omr_prefix_showed_up) {
   1045         // Routable OMR prefix showed up, check to see if we should publish infra nat64 prefix
   1046         return nat64_infra_prefix_publisher_state_check;
   1047     } else {
   1048         NAT64_UNEXPECTED_EVENT(state_machine, event);
   1049     }
   1050     return nat64_infra_prefix_publisher_state_invalid;
   1051 }
   1052 
   1053 static nat64_infra_prefix_publisher_state_type_t
   1054 nat64_infra_prefix_publisher_ignore_action(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t *event)
   1055 {
   1056     NAT64_STATE_ANNOUNCE(state_machine, event);
   1057     if (event == NULL) {
   1058         return nat64_infra_prefix_publisher_state_invalid;
   1059     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_thread_prefix_changed) {
   1060         if (nat64_num_infra_prefix(event->prefix) >= NAT64_INFRA_PREFIX_LIMIT) {
   1061             INFO("more than %d infra nat64 prefixes present, ignore", NAT64_INFRA_PREFIX_LIMIT);
   1062             return nat64_infra_prefix_publisher_state_invalid;
   1063         } else {
   1064             return nat64_infra_prefix_publisher_state_check;
   1065         }
   1066     } else {
   1067         NAT64_UNEXPECTED_EVENT(state_machine, event);
   1068     }
   1069     return nat64_infra_prefix_publisher_state_invalid;
   1070 }
   1071 
   1072 static nat64_infra_prefix_publisher_state_type_t
   1073 nat64_infra_prefix_publisher_check_action(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t *event)
   1074 {
   1075     NAT64_STATE_ANNOUNCE(state_machine, event);
   1076     // Go to publish state when all of the following conditions are met:
   1077     // 1. We have infra prefix
   1078     // 2. We have routable OMR prefix
   1079     // 3. The number of infra prefixes on thread network is less than NAT64_INFRA_PREFIX_LIMIT
   1080     nat64_prefix_t *infra_prefix = state_machine->nat64->infra_monitor->infra_nat64_prefixes;
   1081     if (infra_prefix && nat64_thread_has_routable_prefix(state_machine->nat64->route_state)
   1082         && nat64_num_infra_prefix(state_machine->nat64->thread_monitor->thread_nat64_prefixes) < NAT64_INFRA_PREFIX_LIMIT) {
   1083         state_machine->proposed_prefix = nat64_prefix_dup(infra_prefix);
   1084         if (state_machine->proposed_prefix == NULL) {
   1085             return nat64_infra_prefix_publisher_state_wait;
   1086         }
   1087         return nat64_infra_prefix_publisher_state_publish;
   1088     } else {
   1089         return nat64_infra_prefix_publisher_state_wait;
   1090     }
   1091 }
   1092 
   1093 static nat64_infra_prefix_publisher_state_type_t
   1094 nat64_infra_prefix_publisher_publish_action(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t *event)
   1095 {
   1096     NAT64_STATE_ANNOUNCE(state_machine, event);
   1097     SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf);
   1098     INFO("publishing infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1099           SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf));
   1100     nat64_add_prefix_to_update_queue(state_machine->nat64, state_machine->proposed_prefix,
   1101                                      nat64_prefix_action_add);
   1102     return nat64_infra_prefix_publisher_state_publishing;
   1103 }
   1104 
   1105 static void
   1106 nat64_remove_prefix_from_thread_monitor(nat64_t *nat64, nat64_prefix_t *deprecated_prefix)
   1107 {
   1108     nat64_prefix_t **ppref = &nat64->thread_monitor->thread_nat64_prefixes, *prefix = NULL;
   1109     while (*ppref != NULL) {
   1110         prefix = *ppref;
   1111         if (!in6prefix_compare(&prefix->prefix, &deprecated_prefix->prefix, NAT64_PREFIX_SLASH_96_BYTES)
   1112             && prefix->rloc == deprecated_prefix->rloc)
   1113         {
   1114             *ppref = prefix->next;
   1115             SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, nat64_prefix_buf);
   1116             INFO("prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " with pref " PRI_S_SRP " went away",
   1117                   SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, nat64_prefix_buf),
   1118                   get_nat64_prefix_pref_name(prefix->priority));
   1119             RELEASE_HERE(prefix, nat64_prefix);
   1120         } else {
   1121             ppref = &prefix->next;
   1122         }
   1123     }
   1124 }
   1125 
   1126 static nat64_infra_prefix_publisher_state_type_t
   1127 nat64_infra_prefix_publisher_publishing_action(nat64_infra_prefix_publisher_t *state_machine, nat64_infra_prefix_publisher_event_t *event)
   1128 {
   1129     NAT64_STATE_ANNOUNCE(state_machine, event);
   1130     if (event == NULL) {
   1131         return nat64_infra_prefix_publisher_state_invalid;
   1132     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_infra_prefix_changed ||
   1133                event->event_type == nat64_event_nat64_infra_prefix_publisher_shutdown)
   1134     {
   1135         nat64_prefix_t *infra_prefix;
   1136         for (infra_prefix = event->prefix; infra_prefix; infra_prefix = infra_prefix->next) {
   1137             if (!in6prefix_compare(&infra_prefix->prefix, &state_machine->proposed_prefix->prefix, NAT64_PREFIX_SLASH_96_BYTES)) {
   1138                 // The proposed prefix is still there, do nothing
   1139                 return nat64_infra_prefix_publisher_state_invalid;
   1140             }
   1141         }
   1142         // The proposed infra prefix is gone
   1143         SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf);
   1144         INFO("The proposed infra prefix is gone, unpublishing infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1145              SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf));
   1146         nat64_add_prefix_to_update_queue(state_machine->nat64, state_machine->proposed_prefix, nat64_prefix_action_remove);
   1147         // Remove it from thread_monitor prefix database
   1148         nat64_remove_prefix_from_thread_monitor(state_machine->nat64, state_machine->proposed_prefix);
   1149         RELEASE_HERE(state_machine->proposed_prefix, nat64_prefix);
   1150         state_machine->proposed_prefix = NULL;
   1151         // Is there a different infra NAT64 prefix?
   1152         if (event->prefix) {
   1153             state_machine->proposed_prefix = nat64_prefix_dup(event->prefix);
   1154             if (state_machine->proposed_prefix == NULL) {
   1155                 return nat64_infra_prefix_publisher_state_check;
   1156             }
   1157             return nat64_infra_prefix_publisher_state_publish;
   1158         } else {
   1159             INFO("no longer publishing infra prefix.");
   1160             return nat64_infra_prefix_publisher_state_wait;
   1161         }
   1162     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_routable_omr_prefix_went_away ||
   1163                event->event_type == nat64_event_nat64_infra_prefix_publisher_shutdown)
   1164     {
   1165         // Routable OMR prefix is gone
   1166         SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf);
   1167         INFO("Routable OMR prefix is gone, unpublishing infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1168              SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf));
   1169         nat64_add_prefix_to_update_queue(state_machine->nat64, state_machine->proposed_prefix, nat64_prefix_action_remove);
   1170         // Remove it from thread_monitor prefix database
   1171         nat64_remove_prefix_from_thread_monitor(state_machine->nat64, state_machine->proposed_prefix);
   1172         RELEASE_HERE(state_machine->proposed_prefix, nat64_prefix);
   1173         state_machine->proposed_prefix = NULL;
   1174         INFO("no longer publishing infra prefix.");
   1175         return nat64_infra_prefix_publisher_state_wait;
   1176     } else if (event->event_type == nat64_event_nat64_infra_prefix_publisher_thread_prefix_changed) {
   1177         nat64_prefix_t *thread_prefix;
   1178         int num_infra_prefix = 0;
   1179         for (thread_prefix = event->prefix; thread_prefix; thread_prefix = thread_prefix->next) {
   1180             if (nat64_preference_has_higher_priority(thread_prefix->priority, nat64_preference_low)) {
   1181                 num_infra_prefix++;
   1182             }
   1183         }
   1184         INFO("%d infra nat64 prefixes present on thread network", num_infra_prefix);
   1185         // If more than 3 infra prefixes show on thread network, BR with highest rloc should withdraw
   1186         if (num_infra_prefix > NAT64_INFRA_PREFIX_LIMIT) {
   1187             int max_rloc = event->prefix->rloc;
   1188             for (thread_prefix = event->prefix; thread_prefix; thread_prefix = thread_prefix->next) {
   1189                 if (thread_prefix->rloc > max_rloc) {
   1190                     max_rloc = thread_prefix->rloc;
   1191                 }
   1192             }
   1193             INFO("%d infra nat64 prefixes present on thread network with max_rloc[%d]", num_infra_prefix, max_rloc);
   1194             if (max_rloc == state_machine->nat64->route_state->srp_server->rloc16) {
   1195                 SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf);
   1196                 INFO("BR has highest rloc, unpublishing infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1197                      SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->proposed_prefix->prefix.s6_addr, nat64_prefix_buf));
   1198                 nat64_add_prefix_to_update_queue(state_machine->nat64, state_machine->proposed_prefix, nat64_prefix_action_remove);
   1199                 // Remove it from thread_monitor prefix database
   1200                 nat64_remove_prefix_from_thread_monitor(state_machine->nat64, state_machine->proposed_prefix);
   1201                 RELEASE_HERE(state_machine->proposed_prefix, nat64_prefix);
   1202                 state_machine->proposed_prefix = NULL;
   1203                 INFO("no longer publishing infra prefix.");
   1204                 return nat64_infra_prefix_publisher_state_wait;
   1205             }
   1206         }
   1207     } else {
   1208         NAT64_UNEXPECTED_EVENT(state_machine, event);
   1209     }
   1210     return nat64_infra_prefix_publisher_state_invalid;
   1211 }
   1212 
   1213 #define INFRA_PUBLISHER_STATE_NAME_DECL(name) nat64_infra_prefix_publisher_state_##name, #name
   1214 static nat64_infra_prefix_publisher_state_t
   1215 nat64_infra_prefix_publisher_states[] = {
   1216     { INFRA_PUBLISHER_STATE_NAME_DECL(invalid),            NULL },
   1217     { INFRA_PUBLISHER_STATE_NAME_DECL(init),               nat64_infra_prefix_publisher_init_action },
   1218     { INFRA_PUBLISHER_STATE_NAME_DECL(wait),               nat64_infra_prefix_publisher_wait_action },
   1219     { INFRA_PUBLISHER_STATE_NAME_DECL(ignore),             nat64_infra_prefix_publisher_ignore_action },
   1220     { INFRA_PUBLISHER_STATE_NAME_DECL(check),              nat64_infra_prefix_publisher_check_action },
   1221     { INFRA_PUBLISHER_STATE_NAME_DECL(publish),            nat64_infra_prefix_publisher_publish_action },
   1222     { INFRA_PUBLISHER_STATE_NAME_DECL(publishing),         nat64_infra_prefix_publisher_publishing_action },
   1223 };
   1224 #define INFRA_PREFIX_PUBLISHER_NUM_STATES (sizeof(nat64_infra_prefix_publisher_states) / sizeof(nat64_infra_prefix_publisher_state_t))
   1225 
   1226 DECLARE_NAT64_STATE_GET(nat64_infra_prefix_publisher, INFRA_PREFIX_PUBLISHER);
   1227 DECLARE_NAT64_NEXT_STATE(nat64_infra_prefix_publisher);
   1228 
   1229 // Infra prefix publisher event functions
   1230 typedef struct {
   1231     nat64_infra_prefix_publisher_event_type_t event_type;
   1232     char *name;
   1233 } nat64_infra_prefix_publisher_event_configuration_t;
   1234 
   1235 nat64_infra_prefix_publisher_event_configuration_t nat64_infra_prefix_publisher_event_configurations[] = {
   1236     NAT64_EVENT_NAME_DECL(nat64_infra_prefix_publisher_invalid),
   1237     NAT64_EVENT_NAME_DECL(nat64_infra_prefix_publisher_thread_prefix_changed),
   1238     NAT64_EVENT_NAME_DECL(nat64_infra_prefix_publisher_infra_prefix_changed),
   1239     NAT64_EVENT_NAME_DECL(nat64_infra_prefix_publisher_routable_omr_prefix_went_away),
   1240     NAT64_EVENT_NAME_DECL(nat64_infra_prefix_publisher_routable_omr_prefix_showed_up),
   1241     NAT64_EVENT_NAME_DECL(nat64_infra_prefix_publisher_shutdown),
   1242 };
   1243 #define INFRA_PREFIX_PUBLISHER_NUM_EVENT_TYPES (sizeof(nat64_infra_prefix_publisher_event_configurations) / sizeof(nat64_infra_prefix_publisher_event_configuration_t))
   1244 
   1245 DECLARE_NAT64_EVENT_CONFIGURATION_GET(nat64_infra_prefix_publisher_event, INFRA_PREFIX_PUBLISHER);
   1246 DECLARE_NAT64_EVENT_INIT(nat64_infra_prefix_publisher_event);
   1247 DECLARE_NAT64_EVENT_DELIVER(nat64_infra_prefix_publisher);
   1248 
   1249 void
   1250 nat64_omr_route_update(nat64_t *NONNULL nat64, bool has_routable_omr_prefix)
   1251 {
   1252     if (!has_routable_omr_prefix && nat64->nat64_infra_prefix_publisher->routable_omr_prefix_present){
   1253         nat64_infra_prefix_publisher_event_t event;
   1254 
   1255         nat64->nat64_infra_prefix_publisher->routable_omr_prefix_present = false;
   1256         nat64_infra_prefix_publisher_event_init(&event, nat64_event_nat64_infra_prefix_publisher_routable_omr_prefix_went_away);
   1257         NAT64_EVENT_ANNOUNCE(nat64->nat64_infra_prefix_publisher, event);
   1258         nat64_infra_prefix_publisher_event_deliver(nat64->nat64_infra_prefix_publisher, &event);
   1259     } else if (has_routable_omr_prefix && !nat64->nat64_infra_prefix_publisher->routable_omr_prefix_present){
   1260         nat64_infra_prefix_publisher_event_t event;
   1261 
   1262         nat64->nat64_infra_prefix_publisher->routable_omr_prefix_present = true;
   1263         nat64_infra_prefix_publisher_event_init(&event, nat64_event_nat64_infra_prefix_publisher_routable_omr_prefix_showed_up);
   1264         NAT64_EVENT_ANNOUNCE(nat64->nat64_infra_prefix_publisher, event);
   1265         nat64_infra_prefix_publisher_event_deliver(nat64->nat64_infra_prefix_publisher, &event);
   1266     }
   1267 }
   1268 // Infrastructure nat64 prefix publisher state machine end
   1269 
   1270 
   1271 // BR nat64 prefix publisher state machine start
   1272 typedef nat64_br_prefix_publisher_state_type_t (*nat64_br_prefix_publisher_action_t)(nat64_br_prefix_publisher_t *NONNULL sm, nat64_br_prefix_publisher_event_t *NULLABLE event);
   1273 
   1274 typedef struct {
   1275     nat64_br_prefix_publisher_state_type_t state;
   1276     char *name;
   1277     nat64_br_prefix_publisher_action_t action;
   1278 } nat64_br_prefix_publisher_state_t;
   1279 
   1280 static nat64_br_prefix_publisher_state_type_t
   1281 nat64_br_prefix_publisher_init_action(nat64_br_prefix_publisher_t *state_machine, nat64_br_prefix_publisher_event_t * event)
   1282 {
   1283     NAT64_STATE_ANNOUNCE(state_machine, event);
   1284     // Setup BR nat64 prefix
   1285     state_machine->br_prefix = nat64_prefix_create(&state_machine->nat64->route_state->srp_server->ula_prefix, NAT64_PREFIX_SLASH_96_BYTES, nat64_preference_low, state_machine->nat64->route_state->srp_server->rloc16);
   1286     if (state_machine->br_prefix == NULL) {
   1287         ERROR("no memory when create br prefix");
   1288         return nat64_br_prefix_publisher_state_invalid;
   1289     }
   1290     // Add 0xFFFF to make it different from OMR prefix
   1291     memset(&state_machine->br_prefix->prefix.s6_addr[6], 0xFF, 2);
   1292     SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->br_prefix->prefix.s6_addr, nat64_prefix_buf);
   1293     INFO("set br prefix to " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1294          SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->br_prefix->prefix.s6_addr, nat64_prefix_buf));
   1295     // Switch to next state.
   1296     return nat64_br_prefix_publisher_state_start_timer;
   1297 }
   1298 
   1299 static void
   1300 nat64_br_prefix_publisher_context_release(void *context)
   1301 {
   1302     nat64_br_prefix_publisher_t *state_machine = context;
   1303     RELEASE_HERE(state_machine, nat64_br_prefix_publisher);
   1304 }
   1305 
   1306 static void
   1307 nat64_br_prefix_publisher_wakeup(void *context)
   1308 {
   1309     nat64_br_prefix_publisher_t *state_machine = context;
   1310     nat64_br_prefix_publisher_event_t out_event;
   1311 
   1312     state_machine->wait_finished = true;
   1313     nat64_br_prefix_publisher_event_init(&out_event, nat64_event_nat64_br_prefix_publisher_okay_to_publish);
   1314     NAT64_EVENT_ANNOUNCE(state_machine, out_event);
   1315     nat64_br_prefix_publisher_event_deliver(state_machine, &out_event);
   1316 }
   1317 
   1318 static nat64_br_prefix_publisher_state_type_t
   1319 nat64_br_prefix_publisher_start_timer_action(nat64_br_prefix_publisher_t *state_machine, nat64_br_prefix_publisher_event_t * event)
   1320 {
   1321     NAT64_STATE_ANNOUNCE(state_machine, event);
   1322     if (state_machine->timer == NULL) {
   1323         state_machine->timer = ioloop_wakeup_create();
   1324         if (state_machine->timer == NULL) {
   1325             ERROR("no memory when create timer");
   1326             return nat64_br_prefix_publisher_state_invalid;
   1327         }
   1328         RETAIN_HERE(state_machine, nat64_br_prefix_publisher);
   1329         // wait rand(10,30) seconds, will start after thread monitor is settled
   1330         ioloop_add_wake_event(state_machine->timer, state_machine, nat64_br_prefix_publisher_wakeup, nat64_br_prefix_publisher_context_release,
   1331                               NAT64_THREAD_PREFIX_SETTLING_TIME * IOLOOP_SECOND + srp_random16() % (NAT64_BR_PREFIX_PUBLISHER_WAIT_TIME * IOLOOP_SECOND));
   1332         state_machine->wait_finished = false;
   1333     } else {
   1334         INFO("thread prefix monitor timer already started");
   1335     }
   1336     // Switch to next state.
   1337     return nat64_br_prefix_publisher_state_wait_for_anything;
   1338 }
   1339 
   1340 static nat64_br_prefix_publisher_state_type_t
   1341 nat64_br_prefix_publisher_wait_for_anything_action(nat64_br_prefix_publisher_t *state_machine, nat64_br_prefix_publisher_event_t *event)
   1342 {
   1343     NAT64_STATE_ANNOUNCE(state_machine, event);
   1344     if (event == NULL) {
   1345         return nat64_br_prefix_publisher_state_invalid;
   1346     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_ipv4_default_route_showed_up) {
   1347         if (state_machine->nat64->thread_monitor->thread_nat64_prefixes == NULL
   1348             && state_machine->nat64->nat64_infra_prefix_publisher->proposed_prefix == NULL
   1349             && state_machine->wait_finished) {
   1350             return nat64_br_prefix_publisher_state_publish;
   1351         }
   1352     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_thread_prefix_changed) {
   1353         if (event->prefix == NULL
   1354             && state_machine->nat64->nat64_infra_prefix_publisher->proposed_prefix == NULL
   1355             && state_machine->wait_finished
   1356             && state_machine->nat64->ipv4_monitor->has_ipv4_default_route) {
   1357             return nat64_br_prefix_publisher_state_publish;
   1358         }
   1359     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_okay_to_publish) {
   1360         if (state_machine->nat64->thread_monitor->thread_nat64_prefixes == NULL
   1361             && state_machine->nat64->nat64_infra_prefix_publisher->proposed_prefix == NULL
   1362             && state_machine->nat64->ipv4_monitor->has_ipv4_default_route) {
   1363             return nat64_br_prefix_publisher_state_publish;
   1364         }
   1365     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_infra_prefix_changed) {
   1366         if (event->prefix == NULL
   1367             && state_machine->nat64->thread_monitor->thread_nat64_prefixes == NULL
   1368             && state_machine->wait_finished
   1369             && state_machine->nat64->ipv4_monitor->has_ipv4_default_route) {
   1370             return nat64_br_prefix_publisher_state_publish;
   1371         }
   1372     } else {
   1373         NAT64_UNEXPECTED_EVENT(state_machine, event);
   1374     }
   1375     return nat64_br_prefix_publisher_state_invalid;
   1376 }
   1377 
   1378 static nat64_br_prefix_publisher_state_type_t
   1379 nat64_br_prefix_publisher_publish_action(nat64_br_prefix_publisher_t *state_machine, nat64_br_prefix_publisher_event_t *event)
   1380 {
   1381     NAT64_STATE_ANNOUNCE(state_machine, event);
   1382     // Enable NAT64 translation
   1383     INFO("starting NAT64 translation on BR");
   1384     nat64_start_translation(dispatch_get_main_queue());
   1385     SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->br_prefix->prefix.s6_addr, nat64_prefix_buf);
   1386     INFO("publishing br prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1387           SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->br_prefix->prefix.s6_addr, nat64_prefix_buf));
   1388     nat64_add_prefix_to_update_queue(state_machine->nat64, state_machine->br_prefix,
   1389                                      nat64_prefix_action_add);
   1390     return nat64_br_prefix_publisher_state_publishing;
   1391 }
   1392 
   1393 static void
   1394 nat64_unpublish_br_prefix(nat64_br_prefix_publisher_t *state_machine)
   1395 {
   1396     SEGMENTED_IPv6_ADDR_GEN_SRP(state_machine->br_prefix->prefix.s6_addr, nat64_prefix_buf);
   1397     INFO("unpublishing br prefix " PRI_SEGMENTED_IPv6_ADDR_SRP,
   1398          SEGMENTED_IPv6_ADDR_PARAM_SRP(state_machine->br_prefix->prefix.s6_addr, nat64_prefix_buf));
   1399     nat64_add_prefix_to_update_queue(state_machine->nat64, state_machine->br_prefix,
   1400                                      nat64_prefix_action_remove);
   1401     // Remove it from thread_monitor prefix database
   1402     nat64_remove_prefix_from_thread_monitor(state_machine->nat64, state_machine->br_prefix);
   1403     INFO("stopping NAT64 translation on BR");
   1404     nat64_stop_translation();
   1405 }
   1406 
   1407 static nat64_br_prefix_publisher_state_type_t
   1408 nat64_br_prefix_publisher_publishing_action(nat64_br_prefix_publisher_t *state_machine, nat64_br_prefix_publisher_event_t *event)
   1409 {
   1410     NAT64_STATE_ANNOUNCE(state_machine, event);
   1411     if (event == NULL) {
   1412         return nat64_br_prefix_publisher_state_invalid;
   1413     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_thread_prefix_changed) {
   1414         nat64_prefix_t *thread_prefix;
   1415         for (thread_prefix = event->prefix; thread_prefix; thread_prefix = thread_prefix->next) {
   1416             if (nat64_preference_has_higher_priority(thread_prefix->priority, nat64_preference_low)) {
   1417                 // The thread prefix has higher preference
   1418                 nat64_unpublish_br_prefix(state_machine);
   1419                 return nat64_br_prefix_publisher_state_wait_for_anything;
   1420             } else if (thread_prefix->priority == nat64_preference_low) {
   1421                 if (in6addr_compare(&state_machine->br_prefix->prefix, &thread_prefix->prefix) > 0) {
   1422                     nat64_unpublish_br_prefix(state_machine);
   1423                     return nat64_br_prefix_publisher_state_wait_for_anything;
   1424                 }
   1425             }
   1426         }
   1427     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_ipv4_default_route_went_away ||
   1428                event->event_type == nat64_event_nat64_br_prefix_publisher_shutdown)
   1429     {
   1430         nat64_unpublish_br_prefix(state_machine);
   1431         return nat64_br_prefix_publisher_state_wait_for_anything;
   1432     } else if (event->event_type == nat64_event_nat64_br_prefix_publisher_infra_prefix_changed) {
   1433         // Only unpublish br prefix if there is infra prefix and routable OMR prefix
   1434         if (event->prefix && nat64_thread_has_routable_prefix(state_machine->nat64->route_state)) {
   1435             nat64_unpublish_br_prefix(state_machine);
   1436             return nat64_br_prefix_publisher_state_wait_for_anything;
   1437         }
   1438     } else {
   1439         NAT64_UNEXPECTED_EVENT(state_machine, event);
   1440     }
   1441     return nat64_br_prefix_publisher_state_invalid;
   1442 }
   1443 
   1444 #define BR_PUBLISHER_STATE_NAME_DECL(name) nat64_br_prefix_publisher_state_##name, #name
   1445 static nat64_br_prefix_publisher_state_t
   1446 nat64_br_prefix_publisher_states[] = {
   1447     { BR_PUBLISHER_STATE_NAME_DECL(invalid),                 NULL },
   1448     { BR_PUBLISHER_STATE_NAME_DECL(init),                    nat64_br_prefix_publisher_init_action },
   1449     { BR_PUBLISHER_STATE_NAME_DECL(start_timer),             nat64_br_prefix_publisher_start_timer_action },
   1450     { BR_PUBLISHER_STATE_NAME_DECL(wait_for_anything),       nat64_br_prefix_publisher_wait_for_anything_action },
   1451     { BR_PUBLISHER_STATE_NAME_DECL(publish),                 nat64_br_prefix_publisher_publish_action },
   1452     { BR_PUBLISHER_STATE_NAME_DECL(publishing),              nat64_br_prefix_publisher_publishing_action },
   1453 };
   1454 #define BR_PREFIX_PUBLISHER_NUM_STATES (sizeof(nat64_br_prefix_publisher_states) / sizeof(nat64_br_prefix_publisher_state_t))
   1455 
   1456 DECLARE_NAT64_STATE_GET(nat64_br_prefix_publisher, BR_PREFIX_PUBLISHER);
   1457 DECLARE_NAT64_NEXT_STATE(nat64_br_prefix_publisher);
   1458 
   1459 // BR prefix publisher event functions
   1460 typedef struct {
   1461     nat64_br_prefix_publisher_event_type_t event_type;
   1462     char *name;
   1463 } nat64_br_prefix_publisher_event_configuration_t;
   1464 
   1465 nat64_br_prefix_publisher_event_configuration_t nat64_br_prefix_publisher_event_configurations[] = {
   1466     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_invalid),
   1467     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_okay_to_publish),
   1468     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_ipv4_default_route_showed_up),
   1469     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_ipv4_default_route_went_away),
   1470     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_thread_prefix_changed),
   1471     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_infra_prefix_changed),
   1472     NAT64_EVENT_NAME_DECL(nat64_br_prefix_publisher_shutdown),
   1473 };
   1474 #define BR_PREFIX_PUBLISHER_NUM_EVENT_TYPES (sizeof(nat64_br_prefix_publisher_event_configurations) / sizeof(nat64_br_prefix_publisher_event_configuration_t))
   1475 
   1476 DECLARE_NAT64_EVENT_CONFIGURATION_GET(nat64_br_prefix_publisher_event, BR_PREFIX_PUBLISHER);
   1477 DECLARE_NAT64_EVENT_INIT(nat64_br_prefix_publisher_event);
   1478 DECLARE_NAT64_EVENT_DELIVER(nat64_br_prefix_publisher);
   1479 
   1480 // BR nat64 prefix publisher state machine end
   1481 
   1482 void
   1483 nat64_init(route_state_t *NONNULL route_state)
   1484 {
   1485     INFO("nat64_init");
   1486     // Start state machines
   1487     nat64_ipv4_default_route_monitor_next_state(route_state->nat64->ipv4_monitor, nat64_ipv4_default_route_monitor_state_init);
   1488     nat64_infra_prefix_monitor_next_state(route_state->nat64->infra_monitor, nat64_infra_prefix_monitor_state_init);
   1489     nat64_thread_prefix_monitor_next_state(route_state->nat64->thread_monitor, nat64_thread_prefix_monitor_state_init);
   1490     nat64_infra_prefix_publisher_next_state(route_state->nat64->nat64_infra_prefix_publisher, nat64_infra_prefix_publisher_state_init);
   1491     nat64_br_prefix_publisher_next_state(route_state->nat64->nat64_br_prefix_publisher, nat64_br_prefix_publisher_state_init);
   1492 }
   1493 
   1494 void
   1495 nat64_stop(route_state_t *NONNULL route_state)
   1496 {
   1497     if (route_state->nat64) {
   1498         INFO("stopping nat64.");
   1499         nat64_cancel(route_state->nat64);
   1500         RELEASE_HERE(route_state->nat64, nat64);
   1501         route_state->nat64 = NULL;
   1502     }
   1503 }
   1504 
   1505 void
   1506 nat64_start(route_state_t *NONNULL route_state)
   1507 {
   1508     route_state->nat64 = nat64_create(route_state);
   1509     if (route_state->nat64 == NULL) {
   1510         ERROR("nat64 create failed");
   1511         return;
   1512     }
   1513     nat64_init(route_state);
   1514 }
   1515 
   1516 static void
   1517 nat64_add_route_callback(void *context, cti_status_t status)
   1518 {
   1519     (void)context;
   1520     INFO("%d", status);
   1521 }
   1522 
   1523 void
   1524 nat64_add_prefix(route_state_t *route_state, const uint8_t *const data, offmesh_route_preference_t route_pref)
   1525 {
   1526     SEGMENTED_IPv6_ADDR_GEN_SRP(data, nat64_prefix_buf);
   1527     INFO("nat64_add_prefix(" PRI_SEGMENTED_IPv6_ADDR_SRP ")",
   1528          SEGMENTED_IPv6_ADDR_PARAM_SRP(data, nat64_prefix_buf));
   1529     int status = cti_add_route(route_state->srp_server, route_state, nat64_add_route_callback, NULL,
   1530                                (struct in6_addr *)data, NAT64_PREFIX_SLASH_96_BYTES * 8,
   1531                                route_pref, 0, true, true);
   1532     if (status != kCTIStatus_NoError) {
   1533         ERROR("Unable to add nat64 prefix.");
   1534     }
   1535 }
   1536 
   1537 static void
   1538 nat64_remove_route_callback(void *context, cti_status_t status)
   1539 {
   1540     (void)context;
   1541     INFO("%d", status);
   1542 }
   1543 
   1544 void
   1545 nat64_remove_prefix(route_state_t *route_state, const uint8_t *const data)
   1546 {
   1547     SEGMENTED_IPv6_ADDR_GEN_SRP(data, nat64_prefix_buf);
   1548     INFO("nat64_remove_prefix(" PRI_SEGMENTED_IPv6_ADDR_SRP ")",
   1549          SEGMENTED_IPv6_ADDR_PARAM_SRP(data, nat64_prefix_buf));
   1550     int status = cti_remove_route(route_state->srp_server, route_state, nat64_remove_route_callback, NULL,
   1551                                   (struct in6_addr *)data, NAT64_PREFIX_SLASH_96_BYTES * 8, 0);
   1552     if (status != kCTIStatus_NoError) {
   1553         ERROR("Unable to remove nat64 prefix.");
   1554     }
   1555 }
   1556 
   1557 static offmesh_route_preference_t
   1558 nat64_pref_to_route_pref(nat64_preference nat64_pref)
   1559 {
   1560     if (nat64_pref == nat64_preference_low) {
   1561         return offmesh_route_preference_low;
   1562     } else if (nat64_pref == nat64_preference_high) {
   1563         return offmesh_route_preference_high;
   1564     } else if (nat64_pref == nat64_preference_medium) {
   1565         return offmesh_route_preference_medium;
   1566     } else {
   1567         ERROR("Unknown nat64 prefix preference %d", nat64_pref);
   1568         return offmesh_route_preference_low;
   1569     }
   1570 }
   1571 
   1572 static void
   1573 nat64_prefix_update_callback(void *context, cti_status_t status)
   1574 {
   1575     nat64_t *nat64 = context;
   1576     nat64_prefix_t *prefix = nat64->update_queue;
   1577     INFO("status %d", status);
   1578     if (prefix == NULL) {
   1579         ERROR("update seems to have disappeared");
   1580         return;
   1581     }
   1582     SEGMENTED_IPv6_ADDR_GEN_SRP(&prefix->prefix, prefix_buf);
   1583     INFO(PRI_SEGMENTED_IPv6_ADDR_SRP " was " PUB_S_SRP,
   1584          SEGMENTED_IPv6_ADDR_PARAM_SRP(&prefix->prefix, prefix_buf),
   1585          prefix->action == nat64_prefix_action_add ? "added" : "removed");
   1586     // The pending flag was set to true in nat64_prefix_start_next_update(), meaning that
   1587     // we sent the request to threadradiod, but it's not finished yet, so the status is pending.
   1588     // when this callback function is called, the status is not pending anymore.
   1589     if (prefix->pending) {
   1590         prefix->pending = false;
   1591         nat64->update_queue = prefix->next;
   1592         prefix->next = NULL;
   1593         RELEASE_HERE(prefix, nat64_prefix);
   1594     }
   1595     // Start next update
   1596     if (nat64->update_queue != NULL) {
   1597         nat64_prefix_start_next_update(nat64);
   1598     } else {
   1599         // The update queue holds a reference to nat64 when there is something on the queue.
   1600         // Release here if there is nothing on the queue.
   1601         RELEASE_HERE(nat64, nat64);
   1602     }
   1603 }
   1604 
   1605 static void
   1606 nat64_prefix_start_next_update(nat64_t *nat64)
   1607 {
   1608     cti_status_t status;
   1609     nat64_prefix_t *prefix = nat64->update_queue;
   1610     if (prefix == NULL) {
   1611         ERROR("nat64_prefix_start_next_update called with no update");
   1612         return;
   1613     }
   1614     route_state_t *route_state = nat64->route_state;
   1615     srp_server_t *server_state = route_state->srp_server;
   1616 
   1617     SEGMENTED_IPv6_ADDR_GEN_SRP(&prefix->prefix, prefix_buf);
   1618     if (prefix->action == nat64_prefix_action_remove) {
   1619         INFO("removing: " PRI_SEGMENTED_IPv6_ADDR_SRP ,
   1620              SEGMENTED_IPv6_ADDR_PARAM_SRP(&prefix->prefix, prefix_buf));
   1621         status = cti_remove_route(server_state, nat64, nat64_prefix_update_callback, NULL,
   1622                                   &prefix->prefix, NAT64_PREFIX_SLASH_96_BYTES * 8, 0);
   1623     } else if (prefix->action == nat64_prefix_action_add){
   1624         INFO("adding: " PRI_SEGMENTED_IPv6_ADDR_SRP ,
   1625              SEGMENTED_IPv6_ADDR_PARAM_SRP(&prefix->prefix, prefix_buf));
   1626         status = cti_add_route(server_state, nat64, nat64_prefix_update_callback, NULL,
   1627                                &prefix->prefix, NAT64_PREFIX_SLASH_96_BYTES * 8,
   1628                                nat64_pref_to_route_pref(prefix->priority), 0, true, true);
   1629     } else {
   1630         ERROR("updating: " PRI_SEGMENTED_IPv6_ADDR_SRP " with action %d",
   1631               SEGMENTED_IPv6_ADDR_PARAM_SRP(&prefix->prefix, prefix_buf), prefix->action);
   1632         nat64->update_queue = prefix->next;
   1633         prefix->next = NULL;
   1634         RELEASE_HERE(prefix, nat64_prefix);
   1635         return;
   1636     }
   1637     if (status != kCTIStatus_NoError) {
   1638         ERROR("route update failed: %d", status);
   1639     } else {
   1640         prefix->pending = true;
   1641     }
   1642 }
   1643 
   1644 static void
   1645 nat64_add_prefix_to_update_queue(nat64_t *nat64, nat64_prefix_t *prefix, nat64_prefix_action action)
   1646 {
   1647     nat64_prefix_t **ppref, *old_queue = nat64->update_queue;
   1648     // Find the prefix on the queue, or find the end of the queue.
   1649     for (ppref = &nat64->update_queue; *ppref != NULL && *ppref != prefix; ppref = &(*ppref)->next);
   1650     // Not on the queue
   1651     if (*ppref == NULL) {
   1652         nat64_prefix_t * new_prefix = nat64_prefix_dup(prefix);
   1653         if (new_prefix == NULL) {
   1654             ERROR("no memory for nat64 prefix.");
   1655             return;
   1656         }
   1657         new_prefix->action = action;
   1658         // The pending flag will be set to true in nat64_prefix_start_next_update()
   1659         // when we send the request to threadradiod.
   1660         new_prefix->pending = false;
   1661         *ppref = new_prefix;
   1662         // Turns out we added it to the beginning of the queue.
   1663         if (nat64->update_queue == new_prefix) {
   1664             nat64_prefix_start_next_update(nat64);
   1665         }
   1666         goto out;
   1667     }
   1668     // We have started to update the prefix, but haven't gotten the callback yet. Since we have put the prefix
   1669     // back on the update queue, and it's at the beginning, mark it not pending so that when we get the callback
   1670     // from the update function, we update this route again rather than going on to the next.
   1671     if (prefix == nat64->update_queue) {
   1672         prefix->pending = false;
   1673     }
   1674 out:
   1675     // As long as there is anything in the queue, the queue needs to hold a reference to nat64,
   1676     // so that if it's canceled and released, we finish running the queue before stopping.
   1677     if (old_queue == NULL && nat64->update_queue != NULL) {
   1678         RETAIN_HERE(nat64, nat64);
   1679     }
   1680 }
   1681 
   1682 // Check stale prefix on thread network.
   1683 // For example, prefix that belongs to current BR, but current BR is not in publishing state, this can happen when srp-mdns-proxy daemon restarted.
   1684 // Remove such prefix from thread network.
   1685 static void
   1686 nat64_check_stale_prefix(route_state_t *route_state, const cti_route_vec_t *const routes)
   1687 {
   1688     size_t i;
   1689     for (i = 0; i < routes->num; i++) {
   1690         cti_route_t *route = routes->routes[i];
   1691         // This is nat64 prefix published by us
   1692         if (route->nat64 && route->origin == offmesh_route_origin_ncp
   1693             && route->rloc == route_state->srp_server->rloc16) {
   1694             // br generated nat64 prefix
   1695             if (route->preference == offmesh_route_preference_low) {
   1696                 nat64_prefix_t *prefix = route_state->nat64->nat64_br_prefix_publisher->br_prefix;
   1697                 // If we are not publishing or
   1698                 // we are publishing but the prefix is different, this can happen when ula changed
   1699                 if ((route_state->nat64->nat64_br_prefix_publisher->state != nat64_br_prefix_publisher_state_publishing) ||
   1700                     (prefix && in6prefix_compare(&prefix->prefix, &route->prefix, NAT64_PREFIX_SLASH_96_BYTES))) {
   1701                     nat64_prefix_t *tmp = nat64_prefix_create(&route->prefix, NAT64_PREFIX_SLASH_96_BYTES,
   1702                                                               route_pref_to_nat64_pref(route->preference), route->rloc);
   1703                     SEGMENTED_IPv6_ADDR_GEN_SRP(tmp->prefix.s6_addr, nat64_prefix_buf);
   1704                     INFO("stale br prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " removing",
   1705                          SEGMENTED_IPv6_ADDR_PARAM_SRP(tmp->prefix.s6_addr, nat64_prefix_buf));
   1706                     nat64_add_prefix_to_update_queue(route_state->nat64, tmp, nat64_prefix_action_remove);
   1707                     RELEASE_HERE(tmp, nat64_prefix);
   1708                 }
   1709             // prefix from infrastructure
   1710             } else if (route->preference == offmesh_route_preference_medium) {
   1711                 nat64_prefix_t *prefix = route_state->nat64->nat64_infra_prefix_publisher->proposed_prefix;
   1712                 // If we are not publishing or
   1713                 // we are publishing but the prefix is different, this can happen when infra prefix changed
   1714                 if ((route_state->nat64->nat64_infra_prefix_publisher->state != nat64_infra_prefix_publisher_state_publishing) ||
   1715                     (prefix && in6prefix_compare(&prefix->prefix, &route->prefix, NAT64_PREFIX_SLASH_96_BYTES))) {
   1716                     nat64_prefix_t *tmp = nat64_prefix_create(&route->prefix, NAT64_PREFIX_SLASH_96_BYTES,
   1717                                                               route_pref_to_nat64_pref(route->preference), route->rloc);
   1718                     SEGMENTED_IPv6_ADDR_GEN_SRP(tmp->prefix.s6_addr, nat64_prefix_buf);
   1719                     INFO("stale infra prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " removing",
   1720                          SEGMENTED_IPv6_ADDR_PARAM_SRP(tmp->prefix.s6_addr, nat64_prefix_buf));
   1721                     nat64_add_prefix_to_update_queue(route_state->nat64, tmp, nat64_prefix_action_remove);
   1722                     RELEASE_HERE(tmp, nat64_prefix);
   1723                 }
   1724             }
   1725         }
   1726     }
   1727 }
   1728 
   1729 void
   1730 nat64_offmesh_route_list_callback(route_state_t *route_state, cti_route_vec_t *routes, cti_status_t status)
   1731 {
   1732     if (status != kCTIStatus_NoError) {
   1733         ERROR("status %d", status);
   1734     } else {
   1735         INFO("got %zu offmesh routes", routes->num);
   1736         nat64_check_stale_prefix(route_state, routes);
   1737         nat64_thread_prefix_monitor_t *state_machine = route_state->nat64->thread_monitor;
   1738         nat64_thread_prefix_monitor_event_t out_event;
   1739         nat64_thread_prefix_monitor_event_init(&out_event, nat64_event_thread_prefix_update);
   1740         out_event.routes = routes;
   1741         NAT64_EVENT_ANNOUNCE(state_machine, out_event);
   1742         nat64_thread_prefix_monitor_event_deliver(state_machine, &out_event);
   1743     }
   1744 }
   1745 
   1746 void
   1747 nat64_thread_shutdown(route_state_t *route_state)
   1748 {
   1749     nat64_t *nat64 = route_state->nat64;
   1750     if (nat64->nat64_infra_prefix_publisher != NULL) {
   1751         nat64_infra_prefix_publisher_event_t infra_event;
   1752         nat64_infra_prefix_publisher_event_init(&infra_event, nat64_event_nat64_infra_prefix_publisher_shutdown);
   1753         nat64_infra_prefix_publisher_event_deliver(nat64->nat64_infra_prefix_publisher, &infra_event);
   1754     }
   1755     if (nat64->nat64_br_prefix_publisher != NULL) {
   1756         nat64_br_prefix_publisher_event_t br_event;
   1757         nat64_br_prefix_publisher_event_init(&br_event, nat64_event_nat64_br_prefix_publisher_shutdown);
   1758         nat64_br_prefix_publisher_event_deliver(nat64->nat64_br_prefix_publisher, &br_event);
   1759     }
   1760 }
   1761 #endif
   1762 
   1763 // Local Variables:
   1764 // mode: C
   1765 // tab-width: 4
   1766 // c-file-style: "bsd"
   1767 // c-basic-offset: 4
   1768 // fill-column: 120
   1769 // indent-tabs-mode: nil
   1770 // End:
   1771