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