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