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