Home | History | Annotate | Line # | Download | only in ServiceRegistration
      1 /* nat64-macos.c
      2  *
      3  * Copyright (c) 2021-2023 Apple Inc. All rights reserved.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *     https://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include "dns-msg.h"
     19 #include "ioloop.h"
     20 #include "srp-mdns-proxy.h"
     21 #include "nat64-macos.h"
     22 #include "nat64.h"
     23 #include "interface-monitor-macos.h"
     24 #include "srp-log.h"
     25 #include "srp.h"
     26 #include <CoreUtils/CoreUtils.h>
     27 #include <mdns/pf.h>
     28 #include <mdns/system.h>
     29 
     30 static bool pass_all_rule_is_set = false;
     31 
     32 #if SRP_FEATURE_NAT64
     33 static struct sockaddr_in nat64_primary_ipv4;
     34 static struct in6_addr nat64_prefix;
     35 static ifmon_t nat64_ifmon = NULL;
     36 static bool nat64_prefix_is_set = false;
     37 static bool nat64_active = false;
     38 
     39 static void
     40 nat64_reset(void)
     41 {
     42     OSStatus err;
     43     if (nat64_primary_ipv4.sin_family == AF_INET) {
     44         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         if (!err) {
     46             mdns_system_set_ipv4_forwarding(true);
     47             nat64_active = true;
     48         } else {
     49             ERROR("nat64_reset: failed to set NAT64 rules: %ld.", (long)err);
     50         }
     51     } else {
     52         err = mdns_pf_delete_thread_rules();
     53         if (err) {
     54             ERROR("nat64_reset: failed to delete NAT64 rules: %ld.", (long)err);
     55         }
     56         mdns_system_set_ipv4_forwarding(false);
     57     }
     58 }
     59 
     60 void
     61 nat64_pass_all_pf_rule_delete(void)
     62 {
     63     if (pass_all_rule_is_set) {
     64         OSStatus err = mdns_pf_delete_thread_pass_all_rule_for_conn_tracking();
     65         if (err != 0) {
     66             ERROR("failed to delete pass all rule: %ld.", (long)err);
     67         } else {
     68             pass_all_rule_is_set = false;
     69         }
     70     }
     71 }
     72 #endif // SRP_FEATURE_NAT64
     73 
     74 void
     75 nat64_pass_all_pf_rule_set(const char *interface)
     76 {
     77     nat64_pass_all_pf_rule_delete();
     78     if (!pass_all_rule_is_set) {
     79         OSStatus err = mdns_pf_set_thread_pass_all_rule_for_conn_tracking(interface);
     80         if (err != 0) {
     81             ERROR("failed to set pass all rule: %ld.", (long)err);
     82         } else {
     83             pass_all_rule_is_set = true;
     84         }
     85     }
     86 }
     87 
     88 #if SRP_FEATURE_NAT64
     89 void
     90 nat64_stop_translation(void)
     91 {
     92     OSStatus err;
     93     err = mdns_pf_delete_thread_rules();
     94     if (err) {
     95         ERROR("nat64_reset: failed to delete NAT64 rules: %ld.", (long)err);
     96     }
     97     mdns_system_set_ipv4_forwarding(false);
     98 }
     99 
    100 void
    101 nat64_start_translation(const dispatch_queue_t queue)
    102 {
    103     nat64_primary_ipv4.sin_family = AF_UNSPEC;
    104     nat64_ifmon = ifmon_create(queue);
    105     dispatch_block_t handler = ^{
    106         const sockaddr_ip new_primary = ifmon_get_primary_ipv4_address(nat64_ifmon);
    107         if (SockAddrCompareAddr(&nat64_primary_ipv4, &new_primary.v4) != 0) {
    108             nat64_primary_ipv4 = new_primary.v4;
    109             if (nat64_prefix_is_set) {
    110                 nat64_reset();
    111             }
    112         }
    113     };
    114     ifmon_set_primary_ip_changed_handler(nat64_ifmon, handler);
    115     ifmon_activate(nat64_ifmon, handler);
    116 }
    117 
    118 void
    119 nat64_set_ula_prefix(const struct in6_addr *const ula_prefix)
    120 {
    121     bool changed;
    122     if (!nat64_prefix_is_set || (in6prefix_compare(&nat64_prefix, ula_prefix, 5) != 0)) {
    123         changed = true;
    124     } else {
    125         changed = false;
    126     }
    127     if (changed) {
    128         // Set the 48-bit ULA prefix (0xfd + global identifier), then set the next 16 bits to all-ones to make the
    129         // 64-bit IPv6 prefix.
    130         in6addr_zero(&nat64_prefix);
    131         in6prefix_copy(&nat64_prefix, ula_prefix, 6);
    132         memset(&nat64_prefix.s6_addr[6], 0xFF, 2);
    133         nat64_prefix_is_set = true;
    134         if (nat64_primary_ipv4.sin_family == AF_INET) {
    135             nat64_reset();
    136         }
    137     }
    138 }
    139 
    140 const struct in6_addr *
    141 nat64_get_ipv6_prefix(void)
    142 {
    143     return &nat64_prefix;
    144 }
    145 
    146 bool
    147 nat64_is_active(void)
    148 {
    149     return nat64_active;
    150 }
    151 
    152 #endif // SRP_FEATURE_NAT64
    153