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