Home | History | Annotate | Line # | Download | only in ServiceRegistration
      1  1.1  christos /* nat64-macos.c
      2  1.1  christos  *
      3  1.1  christos  * Copyright (c) 2021-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 "dns-msg.h"
     19  1.1  christos #include "ioloop.h"
     20  1.1  christos #include "srp-mdns-proxy.h"
     21  1.1  christos #include "nat64-macos.h"
     22  1.1  christos #include "nat64.h"
     23  1.1  christos #include "interface-monitor-macos.h"
     24  1.1  christos #include "srp-log.h"
     25  1.1  christos #include "srp.h"
     26  1.1  christos #include <CoreUtils/CoreUtils.h>
     27  1.1  christos #include <mdns/pf.h>
     28  1.1  christos #include <mdns/system.h>
     29  1.1  christos 
     30  1.1  christos static bool pass_all_rule_is_set = false;
     31  1.1  christos 
     32  1.1  christos #if SRP_FEATURE_NAT64
     33  1.1  christos static struct sockaddr_in nat64_primary_ipv4;
     34  1.1  christos static struct in6_addr nat64_prefix;
     35  1.1  christos static ifmon_t nat64_ifmon = NULL;
     36  1.1  christos static bool nat64_prefix_is_set = false;
     37  1.1  christos static bool nat64_active = false;
     38  1.1  christos 
     39  1.1  christos static void
     40  1.1  christos nat64_reset(void)
     41  1.1  christos {
     42  1.1  christos     OSStatus err;
     43  1.1  christos     if (nat64_primary_ipv4.sin_family == AF_INET) {
     44  1.1  christos         err = mdns_pf_set_thread_nat64_rules(nat64_prefix.s6_addr, NAT64_PREFIX_SLASH_96_BYTES * 8, nat64_primary_ipv4.sin_addr.s_addr);
     45  1.1  christos         if (!err) {
     46  1.1  christos             mdns_system_set_ipv4_forwarding(true);
     47  1.1  christos             nat64_active = true;
     48  1.1  christos         } else {
     49  1.1  christos             ERROR("nat64_reset: failed to set NAT64 rules: %ld.", (long)err);
     50  1.1  christos         }
     51  1.1  christos     } else {
     52  1.1  christos         err = mdns_pf_delete_thread_rules();
     53  1.1  christos         if (err) {
     54  1.1  christos             ERROR("nat64_reset: failed to delete NAT64 rules: %ld.", (long)err);
     55  1.1  christos         }
     56  1.1  christos         mdns_system_set_ipv4_forwarding(false);
     57  1.1  christos     }
     58  1.1  christos }
     59  1.1  christos 
     60  1.1  christos void
     61  1.1  christos nat64_pass_all_pf_rule_delete(void)
     62  1.1  christos {
     63  1.1  christos     if (pass_all_rule_is_set) {
     64  1.1  christos         OSStatus err = mdns_pf_delete_thread_pass_all_rule_for_conn_tracking();
     65  1.1  christos         if (err != 0) {
     66  1.1  christos             ERROR("failed to delete pass all rule: %ld.", (long)err);
     67  1.1  christos         } else {
     68  1.1  christos             pass_all_rule_is_set = false;
     69  1.1  christos         }
     70  1.1  christos     }
     71  1.1  christos }
     72  1.1  christos #endif // SRP_FEATURE_NAT64
     73  1.1  christos 
     74  1.1  christos void
     75  1.1  christos nat64_pass_all_pf_rule_set(const char *interface)
     76  1.1  christos {
     77  1.1  christos     nat64_pass_all_pf_rule_delete();
     78  1.1  christos     if (!pass_all_rule_is_set) {
     79  1.1  christos         OSStatus err = mdns_pf_set_thread_pass_all_rule_for_conn_tracking(interface);
     80  1.1  christos         if (err != 0) {
     81  1.1  christos             ERROR("failed to set pass all rule: %ld.", (long)err);
     82  1.1  christos         } else {
     83  1.1  christos             pass_all_rule_is_set = true;
     84  1.1  christos         }
     85  1.1  christos     }
     86  1.1  christos }
     87  1.1  christos 
     88  1.1  christos #if SRP_FEATURE_NAT64
     89  1.1  christos void
     90  1.1  christos nat64_stop_translation(void)
     91  1.1  christos {
     92  1.1  christos     OSStatus err;
     93  1.1  christos     err = mdns_pf_delete_thread_rules();
     94  1.1  christos     if (err) {
     95  1.1  christos         ERROR("nat64_reset: failed to delete NAT64 rules: %ld.", (long)err);
     96  1.1  christos     }
     97  1.1  christos     mdns_system_set_ipv4_forwarding(false);
     98  1.1  christos }
     99  1.1  christos 
    100  1.1  christos void
    101  1.1  christos nat64_start_translation(const dispatch_queue_t queue)
    102  1.1  christos {
    103  1.1  christos     nat64_primary_ipv4.sin_family = AF_UNSPEC;
    104  1.1  christos     nat64_ifmon = ifmon_create(queue);
    105  1.1  christos     dispatch_block_t handler = ^{
    106  1.1  christos         const sockaddr_ip new_primary = ifmon_get_primary_ipv4_address(nat64_ifmon);
    107  1.1  christos         if (SockAddrCompareAddr(&nat64_primary_ipv4, &new_primary.v4) != 0) {
    108  1.1  christos             nat64_primary_ipv4 = new_primary.v4;
    109  1.1  christos             if (nat64_prefix_is_set) {
    110  1.1  christos                 nat64_reset();
    111  1.1  christos             }
    112  1.1  christos         }
    113  1.1  christos     };
    114  1.1  christos     ifmon_set_primary_ip_changed_handler(nat64_ifmon, handler);
    115  1.1  christos     ifmon_activate(nat64_ifmon, handler);
    116  1.1  christos }
    117  1.1  christos 
    118  1.1  christos void
    119  1.1  christos nat64_set_ula_prefix(const struct in6_addr *const ula_prefix)
    120  1.1  christos {
    121  1.1  christos     bool changed;
    122  1.1  christos     if (!nat64_prefix_is_set || (in6prefix_compare(&nat64_prefix, ula_prefix, 5) != 0)) {
    123  1.1  christos         changed = true;
    124  1.1  christos     } else {
    125  1.1  christos         changed = false;
    126  1.1  christos     }
    127  1.1  christos     if (changed) {
    128  1.1  christos         // Set the 48-bit ULA prefix (0xfd + global identifier), then set the next 16 bits to all-ones to make the
    129  1.1  christos         // 64-bit IPv6 prefix.
    130  1.1  christos         in6addr_zero(&nat64_prefix);
    131  1.1  christos         in6prefix_copy(&nat64_prefix, ula_prefix, 6);
    132  1.1  christos         memset(&nat64_prefix.s6_addr[6], 0xFF, 2);
    133  1.1  christos         nat64_prefix_is_set = true;
    134  1.1  christos         if (nat64_primary_ipv4.sin_family == AF_INET) {
    135  1.1  christos             nat64_reset();
    136  1.1  christos         }
    137  1.1  christos     }
    138  1.1  christos }
    139  1.1  christos 
    140  1.1  christos const struct in6_addr *
    141  1.1  christos nat64_get_ipv6_prefix(void)
    142  1.1  christos {
    143  1.1  christos     return &nat64_prefix;
    144  1.1  christos }
    145  1.1  christos 
    146  1.1  christos bool
    147  1.1  christos nat64_is_active(void)
    148  1.1  christos {
    149  1.1  christos     return nat64_active;
    150  1.1  christos }
    151  1.1  christos 
    152  1.1  christos #endif // SRP_FEATURE_NAT64
    153