1*43a90889SApple OSS Distributions /*
2*43a90889SApple OSS Distributions * Copyright (c) 2018-2025 Apple Inc. All rights reserved.
3*43a90889SApple OSS Distributions *
4*43a90889SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*43a90889SApple OSS Distributions *
6*43a90889SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*43a90889SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*43a90889SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*43a90889SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*43a90889SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*43a90889SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*43a90889SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*43a90889SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*43a90889SApple OSS Distributions *
15*43a90889SApple OSS Distributions * Please obtain a copy of the License at
16*43a90889SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*43a90889SApple OSS Distributions *
18*43a90889SApple OSS Distributions * The Original Code and all software distributed under the License are
19*43a90889SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*43a90889SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*43a90889SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*43a90889SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*43a90889SApple OSS Distributions * Please see the License for the specific language governing rights and
24*43a90889SApple OSS Distributions * limitations under the License.
25*43a90889SApple OSS Distributions *
26*43a90889SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*43a90889SApple OSS Distributions */
28*43a90889SApple OSS Distributions
29*43a90889SApple OSS Distributions /*
30*43a90889SApple OSS Distributions * Copyright (c) 2001 Daniel Hartmeier
31*43a90889SApple OSS Distributions * Copyright (c) 2002 - 2013 Henning Brauer
32*43a90889SApple OSS Distributions * NAT64 - Copyright (c) 2010 Viagenie Inc. (http://www.viagenie.ca)
33*43a90889SApple OSS Distributions * All rights reserved.
34*43a90889SApple OSS Distributions *
35*43a90889SApple OSS Distributions * Redistribution and use in source and binary forms, with or without
36*43a90889SApple OSS Distributions * modification, are permitted provided that the following conditions
37*43a90889SApple OSS Distributions * are met:
38*43a90889SApple OSS Distributions *
39*43a90889SApple OSS Distributions * - Redistributions of source code must retain the above copyright
40*43a90889SApple OSS Distributions * notice, this list of conditions and the following disclaimer.
41*43a90889SApple OSS Distributions * - Redistributions in binary form must reproduce the above
42*43a90889SApple OSS Distributions * copyright notice, this list of conditions and the following
43*43a90889SApple OSS Distributions * disclaimer in the documentation and/or other materials provided
44*43a90889SApple OSS Distributions * with the distribution.
45*43a90889SApple OSS Distributions *
46*43a90889SApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47*43a90889SApple OSS Distributions * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48*43a90889SApple OSS Distributions * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
49*43a90889SApple OSS Distributions * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
50*43a90889SApple OSS Distributions * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
51*43a90889SApple OSS Distributions * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
52*43a90889SApple OSS Distributions * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53*43a90889SApple OSS Distributions * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54*43a90889SApple OSS Distributions * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55*43a90889SApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56*43a90889SApple OSS Distributions * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57*43a90889SApple OSS Distributions * POSSIBILITY OF SUCH DAMAGE.
58*43a90889SApple OSS Distributions *
59*43a90889SApple OSS Distributions * Effort sponsored in part by the Defense Advanced Research Projects
60*43a90889SApple OSS Distributions * Agency (DARPA) and Air Force Research Laboratory, Air Force
61*43a90889SApple OSS Distributions * Materiel Command, USAF, under agreement number F30602-01-2-0537.
62*43a90889SApple OSS Distributions *
63*43a90889SApple OSS Distributions */
64*43a90889SApple OSS Distributions #include <sys/param.h>
65*43a90889SApple OSS Distributions #include <sys/types.h>
66*43a90889SApple OSS Distributions #include <sys/mbuf.h>
67*43a90889SApple OSS Distributions
68*43a90889SApple OSS Distributions #include <net/if.h>
69*43a90889SApple OSS Distributions #include <net/if_types.h>
70*43a90889SApple OSS Distributions #include <net/dlil.h>
71*43a90889SApple OSS Distributions #include <net/nat464_utils.h>
72*43a90889SApple OSS Distributions #include <net/nwk_wq.h>
73*43a90889SApple OSS Distributions
74*43a90889SApple OSS Distributions #include <netinet/in.h>
75*43a90889SApple OSS Distributions #include <netinet/in_var.h>
76*43a90889SApple OSS Distributions #include <netinet/in_systm.h>
77*43a90889SApple OSS Distributions #include <netinet/ip.h>
78*43a90889SApple OSS Distributions #include <netinet/ip6.h>
79*43a90889SApple OSS Distributions #include <netinet/ip_var.h>
80*43a90889SApple OSS Distributions #include <netinet/ip_icmp.h>
81*43a90889SApple OSS Distributions #include <netinet/in_pcb.h>
82*43a90889SApple OSS Distributions #include <netinet/icmp_var.h>
83*43a90889SApple OSS Distributions #include <netinet/icmp6.h>
84*43a90889SApple OSS Distributions #include <netinet/tcp.h>
85*43a90889SApple OSS Distributions #include <netinet/udp.h>
86*43a90889SApple OSS Distributions #include <netinet/udp_var.h>
87*43a90889SApple OSS Distributions #include <os/log.h>
88*43a90889SApple OSS Distributions
89*43a90889SApple OSS Distributions int clat_debug = 0;
90*43a90889SApple OSS Distributions
91*43a90889SApple OSS Distributions os_log_t nat_log_handle;
92*43a90889SApple OSS Distributions
93*43a90889SApple OSS Distributions static void
94*43a90889SApple OSS Distributions nat464_addr_cksum_fixup(uint16_t *, struct nat464_addr *, struct nat464_addr *,
95*43a90889SApple OSS Distributions protocol_family_t, protocol_family_t, uint8_t, boolean_t);
96*43a90889SApple OSS Distributions
97*43a90889SApple OSS Distributions /* Synthesize ipv6 from ipv4 */
98*43a90889SApple OSS Distributions int
nat464_synthesize_ipv6(ifnet_t ifp,const struct in_addr * addrv4,struct in6_addr * addr)99*43a90889SApple OSS Distributions nat464_synthesize_ipv6(ifnet_t ifp, const struct in_addr *addrv4, struct in6_addr *addr)
100*43a90889SApple OSS Distributions {
101*43a90889SApple OSS Distributions static const struct in6_addr well_known_prefix = {
102*43a90889SApple OSS Distributions .__u6_addr.__u6_addr8 = {0x00, 0x64, 0xff, 0x9b, 0x00, 0x00,
103*43a90889SApple OSS Distributions 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104*43a90889SApple OSS Distributions 0x00, 0x00, 0x00, 0x00},
105*43a90889SApple OSS Distributions };
106*43a90889SApple OSS Distributions
107*43a90889SApple OSS Distributions struct ipv6_prefix nat64prefixes[NAT64_MAX_NUM_PREFIXES];
108*43a90889SApple OSS Distributions int error = 0, i = 0;
109*43a90889SApple OSS Distributions /* Below call is not optimized as it creates a copy of prefixes */
110*43a90889SApple OSS Distributions if ((error = ifnet_get_nat64prefix(ifp, nat64prefixes)) != 0) {
111*43a90889SApple OSS Distributions return error;
112*43a90889SApple OSS Distributions }
113*43a90889SApple OSS Distributions
114*43a90889SApple OSS Distributions for (i = 0; i < NAT64_MAX_NUM_PREFIXES; i++) {
115*43a90889SApple OSS Distributions if (nat64prefixes[i].prefix_len != 0) {
116*43a90889SApple OSS Distributions break;
117*43a90889SApple OSS Distributions }
118*43a90889SApple OSS Distributions }
119*43a90889SApple OSS Distributions
120*43a90889SApple OSS Distributions VERIFY(i < NAT64_MAX_NUM_PREFIXES);
121*43a90889SApple OSS Distributions
122*43a90889SApple OSS Distributions struct in6_addr prefix = nat64prefixes[i].ipv6_prefix;
123*43a90889SApple OSS Distributions int prefix_len = nat64prefixes[i].prefix_len;
124*43a90889SApple OSS Distributions
125*43a90889SApple OSS Distributions char *ptrv4 = (char *)__DECONST(struct in_addr *__indexable, addrv4);
126*43a90889SApple OSS Distributions char *ptr = (char *)__DECONST(struct in6_addr *__indexable, addr);
127*43a90889SApple OSS Distributions
128*43a90889SApple OSS Distributions if (IN_ZERONET(ntohl(addrv4->s_addr)) || // 0.0.0.0/8 Source hosts on local network
129*43a90889SApple OSS Distributions IN_LOOPBACK(ntohl(addrv4->s_addr)) || // 127.0.0.0/8 Loopback
130*43a90889SApple OSS Distributions IN_LINKLOCAL(ntohl(addrv4->s_addr)) || // 169.254.0.0/16 Link Local
131*43a90889SApple OSS Distributions IN_DS_LITE(ntohl(addrv4->s_addr)) || // 192.0.0.0/29 DS-Lite
132*43a90889SApple OSS Distributions IN_6TO4_RELAY_ANYCAST(ntohl(addrv4->s_addr)) || // 192.88.99.0/24 6to4 Relay Anycast
133*43a90889SApple OSS Distributions IN_MULTICAST(ntohl(addrv4->s_addr)) || // 224.0.0.0/4 Multicast
134*43a90889SApple OSS Distributions INADDR_BROADCAST == addrv4->s_addr) { // 255.255.255.255/32 Limited Broadcast
135*43a90889SApple OSS Distributions return -1;
136*43a90889SApple OSS Distributions }
137*43a90889SApple OSS Distributions
138*43a90889SApple OSS Distributions /* Check for the well-known prefix */
139*43a90889SApple OSS Distributions if (prefix_len == NAT64_PREFIX_LEN_96 &&
140*43a90889SApple OSS Distributions IN6_ARE_ADDR_EQUAL(&prefix, &well_known_prefix)) { // https://tools.ietf.org/html/rfc6052#section-3.1
141*43a90889SApple OSS Distributions if (IN_PRIVATE(ntohl(addrv4->s_addr)) || // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 Private-Use
142*43a90889SApple OSS Distributions IN_SHARED_ADDRESS_SPACE(ntohl(addrv4->s_addr))) { // 100.64.0.0/10 Shared Address Space
143*43a90889SApple OSS Distributions return -1;
144*43a90889SApple OSS Distributions }
145*43a90889SApple OSS Distributions }
146*43a90889SApple OSS Distributions
147*43a90889SApple OSS Distributions memcpy(ptr, (char *)&prefix, prefix_len);
148*43a90889SApple OSS Distributions
149*43a90889SApple OSS Distributions switch (prefix_len) {
150*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_96:
151*43a90889SApple OSS Distributions memcpy(ptr + 12, ptrv4, 4);
152*43a90889SApple OSS Distributions break;
153*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_64:
154*43a90889SApple OSS Distributions memcpy(ptr + 9, ptrv4, 4);
155*43a90889SApple OSS Distributions break;
156*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_56:
157*43a90889SApple OSS Distributions memcpy(ptr + 7, ptrv4, 1);
158*43a90889SApple OSS Distributions memcpy(ptr + 9, ptrv4 + 1, 3);
159*43a90889SApple OSS Distributions break;
160*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_48:
161*43a90889SApple OSS Distributions memcpy(ptr + 6, ptrv4, 2);
162*43a90889SApple OSS Distributions memcpy(ptr + 9, ptrv4 + 2, 2);
163*43a90889SApple OSS Distributions break;
164*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_40:
165*43a90889SApple OSS Distributions memcpy(ptr + 5, ptrv4, 3);
166*43a90889SApple OSS Distributions memcpy(ptr + 9, ptrv4 + 3, 1);
167*43a90889SApple OSS Distributions break;
168*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_32:
169*43a90889SApple OSS Distributions memcpy(ptr + 4, ptrv4, 4);
170*43a90889SApple OSS Distributions break;
171*43a90889SApple OSS Distributions default:
172*43a90889SApple OSS Distributions panic("NAT64-prefix len is wrong: %u", prefix_len);
173*43a90889SApple OSS Distributions }
174*43a90889SApple OSS Distributions
175*43a90889SApple OSS Distributions if (clat_debug) {
176*43a90889SApple OSS Distributions char buf[MAX_IPv6_STR_LEN];
177*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s synthesized %s\n", __func__,
178*43a90889SApple OSS Distributions inet_ntop(AF_INET6, (void *)addr, buf, sizeof(buf))));
179*43a90889SApple OSS Distributions }
180*43a90889SApple OSS Distributions
181*43a90889SApple OSS Distributions return error;
182*43a90889SApple OSS Distributions }
183*43a90889SApple OSS Distributions
184*43a90889SApple OSS Distributions /* Synthesize ipv4 from ipv6 */
185*43a90889SApple OSS Distributions int
nat464_synthesize_ipv4(ifnet_t ifp,const struct in6_addr * addr,struct in_addr * addrv4,bool * translate_p)186*43a90889SApple OSS Distributions nat464_synthesize_ipv4(ifnet_t ifp, const struct in6_addr *addr,
187*43a90889SApple OSS Distributions struct in_addr *addrv4, bool * translate_p)
188*43a90889SApple OSS Distributions {
189*43a90889SApple OSS Distributions struct ipv6_prefix nat64prefixes[NAT64_MAX_NUM_PREFIXES];
190*43a90889SApple OSS Distributions int error = 0, i = 0;
191*43a90889SApple OSS Distributions bool translate = false;
192*43a90889SApple OSS Distributions
193*43a90889SApple OSS Distributions /* Below call is not optimized as it creates a copy of prefixes */
194*43a90889SApple OSS Distributions if ((error = ifnet_get_nat64prefix(ifp, nat64prefixes)) != 0) {
195*43a90889SApple OSS Distributions goto done;
196*43a90889SApple OSS Distributions }
197*43a90889SApple OSS Distributions
198*43a90889SApple OSS Distributions for (i = 0; i < NAT64_MAX_NUM_PREFIXES; i++) {
199*43a90889SApple OSS Distributions if (nat64prefixes[i].prefix_len != 0) {
200*43a90889SApple OSS Distributions break;
201*43a90889SApple OSS Distributions }
202*43a90889SApple OSS Distributions }
203*43a90889SApple OSS Distributions
204*43a90889SApple OSS Distributions VERIFY(i < NAT64_MAX_NUM_PREFIXES);
205*43a90889SApple OSS Distributions
206*43a90889SApple OSS Distributions struct in6_addr prefix = nat64prefixes[i].ipv6_prefix;
207*43a90889SApple OSS Distributions int prefix_len = nat64prefixes[i].prefix_len;
208*43a90889SApple OSS Distributions
209*43a90889SApple OSS Distributions VERIFY(prefix_len < sizeof(prefix));
210*43a90889SApple OSS Distributions
211*43a90889SApple OSS Distributions char *ptrv4 = (char *)__DECONST(struct in_addr *__indexable, addrv4);
212*43a90889SApple OSS Distributions char *ptr = (char *)__DECONST(struct in6_addr *__indexable, addr);
213*43a90889SApple OSS Distributions
214*43a90889SApple OSS Distributions /* -fbounds-safety:
215*43a90889SApple OSS Distributions * Override a warning about prefix_len being > 16 because
216*43a90889SApple OSS Distributions * we already checked that above.
217*43a90889SApple OSS Distributions */
218*43a90889SApple OSS Distributions if (memcmp((const struct in6_addr *__indexable)addr, &prefix, prefix_len) != 0) {
219*43a90889SApple OSS Distributions /* it's not the NAT64 prefix, so let it pass */
220*43a90889SApple OSS Distributions goto done;
221*43a90889SApple OSS Distributions }
222*43a90889SApple OSS Distributions
223*43a90889SApple OSS Distributions switch (prefix_len) {
224*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_96:
225*43a90889SApple OSS Distributions memcpy(ptrv4, ptr + 12, 4);
226*43a90889SApple OSS Distributions break;
227*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_64:
228*43a90889SApple OSS Distributions memcpy(ptrv4, ptr + 9, 4);
229*43a90889SApple OSS Distributions break;
230*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_56:
231*43a90889SApple OSS Distributions memcpy(ptrv4, ptr + 7, 1);
232*43a90889SApple OSS Distributions memcpy(ptrv4 + 1, ptr + 9, 3);
233*43a90889SApple OSS Distributions break;
234*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_48:
235*43a90889SApple OSS Distributions memcpy(ptrv4, ptr + 6, 2);
236*43a90889SApple OSS Distributions memcpy(ptrv4 + 2, ptr + 9, 2);
237*43a90889SApple OSS Distributions break;
238*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_40:
239*43a90889SApple OSS Distributions memcpy(ptrv4, ptr + 5, 3);
240*43a90889SApple OSS Distributions memcpy(ptrv4 + 3, ptr + 9, 1);
241*43a90889SApple OSS Distributions break;
242*43a90889SApple OSS Distributions case NAT64_PREFIX_LEN_32:
243*43a90889SApple OSS Distributions memcpy(ptrv4, ptr + 4, 4);
244*43a90889SApple OSS Distributions break;
245*43a90889SApple OSS Distributions default:
246*43a90889SApple OSS Distributions panic("NAT64-prefix len is wrong: %u",
247*43a90889SApple OSS Distributions prefix_len);
248*43a90889SApple OSS Distributions }
249*43a90889SApple OSS Distributions
250*43a90889SApple OSS Distributions if (clat_debug) {
251*43a90889SApple OSS Distributions char buf[MAX_IPv4_STR_LEN];
252*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s desynthesized to %s\n", __func__,
253*43a90889SApple OSS Distributions inet_ntop(AF_INET, (void *)addrv4, buf, sizeof(buf))));
254*43a90889SApple OSS Distributions }
255*43a90889SApple OSS Distributions translate = true;
256*43a90889SApple OSS Distributions done:
257*43a90889SApple OSS Distributions *translate_p = translate;
258*43a90889SApple OSS Distributions return error;
259*43a90889SApple OSS Distributions }
260*43a90889SApple OSS Distributions
261*43a90889SApple OSS Distributions #define PTR_IP(field) ((int32_t)offsetof(struct ip, field))
262*43a90889SApple OSS Distributions #define PTR_IP6(field) ((int32_t)offsetof(struct ip6_hdr, field))
263*43a90889SApple OSS Distributions
264*43a90889SApple OSS Distributions /*
265*43a90889SApple OSS Distributions * Translate the ICMP header
266*43a90889SApple OSS Distributions */
267*43a90889SApple OSS Distributions int
nat464_translate_icmp(int naf,void * arg)268*43a90889SApple OSS Distributions nat464_translate_icmp(int naf, void *arg)
269*43a90889SApple OSS Distributions {
270*43a90889SApple OSS Distributions struct icmp *__single icmp4;
271*43a90889SApple OSS Distributions struct icmp6_hdr *__single icmp6;
272*43a90889SApple OSS Distributions uint32_t mtu;
273*43a90889SApple OSS Distributions int32_t ptr = -1;
274*43a90889SApple OSS Distributions uint8_t type;
275*43a90889SApple OSS Distributions uint8_t code;
276*43a90889SApple OSS Distributions
277*43a90889SApple OSS Distributions switch (naf) {
278*43a90889SApple OSS Distributions case AF_INET:
279*43a90889SApple OSS Distributions icmp6 = arg;
280*43a90889SApple OSS Distributions type = icmp6->icmp6_type;
281*43a90889SApple OSS Distributions code = icmp6->icmp6_code;
282*43a90889SApple OSS Distributions mtu = ntohl(icmp6->icmp6_mtu);
283*43a90889SApple OSS Distributions
284*43a90889SApple OSS Distributions switch (type) {
285*43a90889SApple OSS Distributions case ICMP6_ECHO_REQUEST:
286*43a90889SApple OSS Distributions type = ICMP_ECHO;
287*43a90889SApple OSS Distributions break;
288*43a90889SApple OSS Distributions case ICMP6_ECHO_REPLY:
289*43a90889SApple OSS Distributions type = ICMP_ECHOREPLY;
290*43a90889SApple OSS Distributions break;
291*43a90889SApple OSS Distributions case ICMP6_DST_UNREACH:
292*43a90889SApple OSS Distributions type = ICMP_UNREACH;
293*43a90889SApple OSS Distributions switch (code) {
294*43a90889SApple OSS Distributions case ICMP6_DST_UNREACH_NOROUTE:
295*43a90889SApple OSS Distributions case ICMP6_DST_UNREACH_BEYONDSCOPE:
296*43a90889SApple OSS Distributions case ICMP6_DST_UNREACH_ADDR:
297*43a90889SApple OSS Distributions code = ICMP_UNREACH_HOST;
298*43a90889SApple OSS Distributions break;
299*43a90889SApple OSS Distributions case ICMP6_DST_UNREACH_ADMIN:
300*43a90889SApple OSS Distributions code = ICMP_UNREACH_HOST_PROHIB;
301*43a90889SApple OSS Distributions break;
302*43a90889SApple OSS Distributions case ICMP6_DST_UNREACH_NOPORT:
303*43a90889SApple OSS Distributions code = ICMP_UNREACH_PORT;
304*43a90889SApple OSS Distributions break;
305*43a90889SApple OSS Distributions default:
306*43a90889SApple OSS Distributions return -1;
307*43a90889SApple OSS Distributions }
308*43a90889SApple OSS Distributions break;
309*43a90889SApple OSS Distributions case ICMP6_PACKET_TOO_BIG:
310*43a90889SApple OSS Distributions type = ICMP_UNREACH;
311*43a90889SApple OSS Distributions code = ICMP_UNREACH_NEEDFRAG;
312*43a90889SApple OSS Distributions mtu -= 20;
313*43a90889SApple OSS Distributions break;
314*43a90889SApple OSS Distributions case ICMP6_TIME_EXCEEDED:
315*43a90889SApple OSS Distributions type = ICMP_TIMXCEED;
316*43a90889SApple OSS Distributions break;
317*43a90889SApple OSS Distributions case ICMP6_PARAM_PROB:
318*43a90889SApple OSS Distributions switch (code) {
319*43a90889SApple OSS Distributions case ICMP6_PARAMPROB_HEADER:
320*43a90889SApple OSS Distributions type = ICMP_PARAMPROB;
321*43a90889SApple OSS Distributions code = ICMP_PARAMPROB_ERRATPTR;
322*43a90889SApple OSS Distributions ptr = ntohl(icmp6->icmp6_pptr);
323*43a90889SApple OSS Distributions
324*43a90889SApple OSS Distributions if (ptr == PTR_IP6(ip6_vfc)) {
325*43a90889SApple OSS Distributions ; /* preserve */
326*43a90889SApple OSS Distributions } else if (ptr == PTR_IP6(ip6_vfc) + 1) {
327*43a90889SApple OSS Distributions ptr = PTR_IP(ip_tos);
328*43a90889SApple OSS Distributions } else if (ptr == PTR_IP6(ip6_plen) ||
329*43a90889SApple OSS Distributions ptr == PTR_IP6(ip6_plen) + 1) {
330*43a90889SApple OSS Distributions ptr = PTR_IP(ip_len);
331*43a90889SApple OSS Distributions } else if (ptr == PTR_IP6(ip6_nxt)) {
332*43a90889SApple OSS Distributions ptr = PTR_IP(ip_p);
333*43a90889SApple OSS Distributions } else if (ptr == PTR_IP6(ip6_hlim)) {
334*43a90889SApple OSS Distributions ptr = PTR_IP(ip_ttl);
335*43a90889SApple OSS Distributions } else if (ptr >= PTR_IP6(ip6_src) &&
336*43a90889SApple OSS Distributions ptr < PTR_IP6(ip6_dst)) {
337*43a90889SApple OSS Distributions ptr = PTR_IP(ip_src);
338*43a90889SApple OSS Distributions } else if (ptr >= PTR_IP6(ip6_dst) &&
339*43a90889SApple OSS Distributions ptr < (int32_t)sizeof(struct ip6_hdr)) {
340*43a90889SApple OSS Distributions ptr = PTR_IP(ip_dst);
341*43a90889SApple OSS Distributions } else {
342*43a90889SApple OSS Distributions return -1;
343*43a90889SApple OSS Distributions }
344*43a90889SApple OSS Distributions break;
345*43a90889SApple OSS Distributions case ICMP6_PARAMPROB_NEXTHEADER:
346*43a90889SApple OSS Distributions type = ICMP_UNREACH;
347*43a90889SApple OSS Distributions code = ICMP_UNREACH_PROTOCOL;
348*43a90889SApple OSS Distributions break;
349*43a90889SApple OSS Distributions default:
350*43a90889SApple OSS Distributions return -1;
351*43a90889SApple OSS Distributions }
352*43a90889SApple OSS Distributions break;
353*43a90889SApple OSS Distributions default:
354*43a90889SApple OSS Distributions return -1;
355*43a90889SApple OSS Distributions }
356*43a90889SApple OSS Distributions icmp6->icmp6_type = type;
357*43a90889SApple OSS Distributions icmp6->icmp6_code = code;
358*43a90889SApple OSS Distributions /* aligns well with a icmpv4 nextmtu */
359*43a90889SApple OSS Distributions icmp6->icmp6_mtu = htonl(mtu);
360*43a90889SApple OSS Distributions /* icmpv4 pptr is a one most significant byte */
361*43a90889SApple OSS Distributions if (ptr >= 0) {
362*43a90889SApple OSS Distributions icmp6->icmp6_pptr = htonl(ptr << 24);
363*43a90889SApple OSS Distributions }
364*43a90889SApple OSS Distributions break;
365*43a90889SApple OSS Distributions
366*43a90889SApple OSS Distributions case AF_INET6:
367*43a90889SApple OSS Distributions icmp4 = arg;
368*43a90889SApple OSS Distributions type = icmp4->icmp_type;
369*43a90889SApple OSS Distributions code = icmp4->icmp_code;
370*43a90889SApple OSS Distributions mtu = ntohs(icmp4->icmp_nextmtu);
371*43a90889SApple OSS Distributions
372*43a90889SApple OSS Distributions switch (type) {
373*43a90889SApple OSS Distributions case ICMP_ECHO:
374*43a90889SApple OSS Distributions type = ICMP6_ECHO_REQUEST;
375*43a90889SApple OSS Distributions break;
376*43a90889SApple OSS Distributions case ICMP_ECHOREPLY:
377*43a90889SApple OSS Distributions type = ICMP6_ECHO_REPLY;
378*43a90889SApple OSS Distributions break;
379*43a90889SApple OSS Distributions case ICMP_UNREACH:
380*43a90889SApple OSS Distributions type = ICMP6_DST_UNREACH;
381*43a90889SApple OSS Distributions switch (code) {
382*43a90889SApple OSS Distributions case ICMP_UNREACH_NET:
383*43a90889SApple OSS Distributions case ICMP_UNREACH_HOST:
384*43a90889SApple OSS Distributions case ICMP_UNREACH_NET_UNKNOWN:
385*43a90889SApple OSS Distributions case ICMP_UNREACH_HOST_UNKNOWN:
386*43a90889SApple OSS Distributions case ICMP_UNREACH_ISOLATED:
387*43a90889SApple OSS Distributions case ICMP_UNREACH_TOSNET:
388*43a90889SApple OSS Distributions case ICMP_UNREACH_TOSHOST:
389*43a90889SApple OSS Distributions code = ICMP6_DST_UNREACH_NOROUTE;
390*43a90889SApple OSS Distributions break;
391*43a90889SApple OSS Distributions case ICMP_UNREACH_PORT:
392*43a90889SApple OSS Distributions code = ICMP6_DST_UNREACH_NOPORT;
393*43a90889SApple OSS Distributions break;
394*43a90889SApple OSS Distributions case ICMP_UNREACH_NET_PROHIB:
395*43a90889SApple OSS Distributions case ICMP_UNREACH_HOST_PROHIB:
396*43a90889SApple OSS Distributions case ICMP_UNREACH_FILTER_PROHIB:
397*43a90889SApple OSS Distributions case ICMP_UNREACH_PRECEDENCE_CUTOFF:
398*43a90889SApple OSS Distributions code = ICMP6_DST_UNREACH_ADMIN;
399*43a90889SApple OSS Distributions break;
400*43a90889SApple OSS Distributions case ICMP_UNREACH_PROTOCOL:
401*43a90889SApple OSS Distributions type = ICMP6_PARAM_PROB;
402*43a90889SApple OSS Distributions code = ICMP6_PARAMPROB_NEXTHEADER;
403*43a90889SApple OSS Distributions ptr = offsetof(struct ip6_hdr, ip6_nxt);
404*43a90889SApple OSS Distributions break;
405*43a90889SApple OSS Distributions case ICMP_UNREACH_NEEDFRAG:
406*43a90889SApple OSS Distributions type = ICMP6_PACKET_TOO_BIG;
407*43a90889SApple OSS Distributions code = 0;
408*43a90889SApple OSS Distributions /*
409*43a90889SApple OSS Distributions * Make sure we don't overflow adjusting for
410*43a90889SApple OSS Distributions * translation overhead.
411*43a90889SApple OSS Distributions * If we do, just work with a lower mtu as is.
412*43a90889SApple OSS Distributions */
413*43a90889SApple OSS Distributions if (mtu <= (UINT16_MAX - CLAT46_HDR_EXPANSION_OVERHD)) {
414*43a90889SApple OSS Distributions mtu += CLAT46_HDR_EXPANSION_OVERHD;
415*43a90889SApple OSS Distributions }
416*43a90889SApple OSS Distributions break;
417*43a90889SApple OSS Distributions default:
418*43a90889SApple OSS Distributions return -1;
419*43a90889SApple OSS Distributions }
420*43a90889SApple OSS Distributions break;
421*43a90889SApple OSS Distributions case ICMP_TIMXCEED:
422*43a90889SApple OSS Distributions type = ICMP6_TIME_EXCEEDED;
423*43a90889SApple OSS Distributions break;
424*43a90889SApple OSS Distributions case ICMP_PARAMPROB:
425*43a90889SApple OSS Distributions type = ICMP6_PARAM_PROB;
426*43a90889SApple OSS Distributions switch (code) {
427*43a90889SApple OSS Distributions case ICMP_PARAMPROB_ERRATPTR:
428*43a90889SApple OSS Distributions code = ICMP6_PARAMPROB_HEADER;
429*43a90889SApple OSS Distributions break;
430*43a90889SApple OSS Distributions case ICMP_PARAMPROB_LENGTH:
431*43a90889SApple OSS Distributions code = ICMP6_PARAMPROB_HEADER;
432*43a90889SApple OSS Distributions break;
433*43a90889SApple OSS Distributions default:
434*43a90889SApple OSS Distributions return -1;
435*43a90889SApple OSS Distributions }
436*43a90889SApple OSS Distributions
437*43a90889SApple OSS Distributions ptr = icmp4->icmp_pptr;
438*43a90889SApple OSS Distributions if (ptr == 0 || ptr == PTR_IP(ip_tos)) {
439*43a90889SApple OSS Distributions ; /* preserve */
440*43a90889SApple OSS Distributions } else if (ptr == PTR_IP(ip_len) ||
441*43a90889SApple OSS Distributions ptr == PTR_IP(ip_len) + 1) {
442*43a90889SApple OSS Distributions ptr = PTR_IP6(ip6_plen);
443*43a90889SApple OSS Distributions } else if (ptr == PTR_IP(ip_ttl)) {
444*43a90889SApple OSS Distributions ptr = PTR_IP6(ip6_hlim);
445*43a90889SApple OSS Distributions } else if (ptr == PTR_IP(ip_p)) {
446*43a90889SApple OSS Distributions ptr = PTR_IP6(ip6_nxt);
447*43a90889SApple OSS Distributions } else if (ptr >= PTR_IP(ip_src) &&
448*43a90889SApple OSS Distributions ptr < PTR_IP(ip_dst)) {
449*43a90889SApple OSS Distributions ptr = PTR_IP6(ip6_src);
450*43a90889SApple OSS Distributions } else if (ptr >= PTR_IP(ip_dst) &&
451*43a90889SApple OSS Distributions ptr < (int32_t)sizeof(struct ip)) {
452*43a90889SApple OSS Distributions ptr = PTR_IP6(ip6_dst);
453*43a90889SApple OSS Distributions } else {
454*43a90889SApple OSS Distributions return -1;
455*43a90889SApple OSS Distributions }
456*43a90889SApple OSS Distributions break;
457*43a90889SApple OSS Distributions default:
458*43a90889SApple OSS Distributions return -1;
459*43a90889SApple OSS Distributions }
460*43a90889SApple OSS Distributions icmp4->icmp_type = type;
461*43a90889SApple OSS Distributions icmp4->icmp_code = code;
462*43a90889SApple OSS Distributions icmp4->icmp_nextmtu = htons((uint16_t)mtu);
463*43a90889SApple OSS Distributions
464*43a90889SApple OSS Distributions if (ptr >= 0) {
465*43a90889SApple OSS Distributions icmp4->icmp_void = htonl(ptr);
466*43a90889SApple OSS Distributions }
467*43a90889SApple OSS Distributions break;
468*43a90889SApple OSS Distributions }
469*43a90889SApple OSS Distributions
470*43a90889SApple OSS Distributions return 0;
471*43a90889SApple OSS Distributions }
472*43a90889SApple OSS Distributions
473*43a90889SApple OSS Distributions /*
474*43a90889SApple OSS Distributions * @brief This routine is called to perform address family translation on the
475*43a90889SApple OSS Distributions * inner IP header (that may come as payload) of an ICMP(v4/v6) error
476*43a90889SApple OSS Distributions * response.
477*43a90889SApple OSS Distributions *
478*43a90889SApple OSS Distributions * @param pbuf Pointer to packet buffer
479*43a90889SApple OSS Distributions * @param off Points to end of ICMP header
480*43a90889SApple OSS Distributions * @param tot_len Pointer to total length of the outer IP header
481*43a90889SApple OSS Distributions * @param off2 Points to end of inner IP header
482*43a90889SApple OSS Distributions * @param proto2 Inner IP proto field
483*43a90889SApple OSS Distributions * @param ttl2 Inner IP ttl field
484*43a90889SApple OSS Distributions * @param tot_len2 Inner IP total length
485*43a90889SApple OSS Distributions * @param src Pointer to the generic v4/v6 src address
486*43a90889SApple OSS Distributions * @param dst Pointer to the generic v4/v6 dst address
487*43a90889SApple OSS Distributions * @param af Old protocol family
488*43a90889SApple OSS Distributions * @param naf New protocol family
489*43a90889SApple OSS Distributions *
490*43a90889SApple OSS Distributions * @return -1 on error and 0 on success
491*43a90889SApple OSS Distributions */
492*43a90889SApple OSS Distributions int
nat464_translate_icmp_ip(pbuf_t * pbuf,uint16_t off,uint16_t * tot_len,uint16_t * off2,uint8_t proto2,uint8_t ttl2,uint16_t tot_len2,struct nat464_addr * src,struct nat464_addr * dst,protocol_family_t af,protocol_family_t naf)493*43a90889SApple OSS Distributions nat464_translate_icmp_ip(pbuf_t *pbuf, uint16_t off, uint16_t *tot_len, uint16_t *off2,
494*43a90889SApple OSS Distributions uint8_t proto2, uint8_t ttl2, uint16_t tot_len2, struct nat464_addr *src,
495*43a90889SApple OSS Distributions struct nat464_addr *dst, protocol_family_t af, protocol_family_t naf)
496*43a90889SApple OSS Distributions {
497*43a90889SApple OSS Distributions struct ip *__single ip4 = NULL;
498*43a90889SApple OSS Distributions struct ip6_hdr *__single ip6 = NULL;
499*43a90889SApple OSS Distributions void *__single hdr = NULL;
500*43a90889SApple OSS Distributions int hlen = 0, olen = 0;
501*43a90889SApple OSS Distributions uint64_t ipid_salt = (uint64_t)pbuf_get_packet_buffer_address(pbuf);
502*43a90889SApple OSS Distributions
503*43a90889SApple OSS Distributions if (af == naf || (af != AF_INET && af != AF_INET6) ||
504*43a90889SApple OSS Distributions (naf != AF_INET && naf != AF_INET6)) {
505*43a90889SApple OSS Distributions return -1;
506*43a90889SApple OSS Distributions }
507*43a90889SApple OSS Distributions
508*43a90889SApple OSS Distributions /* old header */
509*43a90889SApple OSS Distributions olen = *off2 - off;
510*43a90889SApple OSS Distributions /* new header */
511*43a90889SApple OSS Distributions hlen = naf == PF_INET ? sizeof(*ip4) : sizeof(*ip6);
512*43a90889SApple OSS Distributions
513*43a90889SApple OSS Distributions /* Modify the pbuf to accommodate the new header */
514*43a90889SApple OSS Distributions hdr = pbuf_resize_segment(pbuf, off, olen, hlen);
515*43a90889SApple OSS Distributions if (hdr == NULL) {
516*43a90889SApple OSS Distributions return -1;
517*43a90889SApple OSS Distributions }
518*43a90889SApple OSS Distributions
519*43a90889SApple OSS Distributions /* translate inner ip/ip6 header */
520*43a90889SApple OSS Distributions switch (naf) {
521*43a90889SApple OSS Distributions case AF_INET:
522*43a90889SApple OSS Distributions ip4 = hdr;
523*43a90889SApple OSS Distributions bzero(ip4, sizeof(*ip4));
524*43a90889SApple OSS Distributions ip4->ip_v = IPVERSION;
525*43a90889SApple OSS Distributions ip4->ip_hl = sizeof(*ip4) >> 2;
526*43a90889SApple OSS Distributions ip4->ip_len = htons((uint16_t)(sizeof(*ip4) + tot_len2 - olen));
527*43a90889SApple OSS Distributions ip4->ip_id = rfc6864 ? 0 : htons(ip_randomid(ipid_salt));
528*43a90889SApple OSS Distributions ip4->ip_off = htons(IP_DF);
529*43a90889SApple OSS Distributions ip4->ip_ttl = ttl2;
530*43a90889SApple OSS Distributions if (proto2 == IPPROTO_ICMPV6) {
531*43a90889SApple OSS Distributions ip4->ip_p = IPPROTO_ICMP;
532*43a90889SApple OSS Distributions } else {
533*43a90889SApple OSS Distributions ip4->ip_p = proto2;
534*43a90889SApple OSS Distributions }
535*43a90889SApple OSS Distributions ip4->ip_src = src->natv4addr;
536*43a90889SApple OSS Distributions ip4->ip_dst = dst->natv4addr;
537*43a90889SApple OSS Distributions ip4->ip_sum = pbuf_inet_cksum(pbuf, 0, 0, ip4->ip_hl << 2);
538*43a90889SApple OSS Distributions
539*43a90889SApple OSS Distributions if (clat_debug) {
540*43a90889SApple OSS Distributions char buf[MAX_IPv4_STR_LEN];
541*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s translated to IPv4 (inner) "
542*43a90889SApple OSS Distributions "ip_len: %#x ip_p: %d ip_sum: %#x ip_src: %s ip_dst: %s \n",
543*43a90889SApple OSS Distributions __func__, ntohs(ip4->ip_len), ip4->ip_p, ntohs(ip4->ip_sum),
544*43a90889SApple OSS Distributions inet_ntop(AF_INET, (void *)&ip4->ip_src, buf, sizeof(buf)),
545*43a90889SApple OSS Distributions inet_ntop(AF_INET, (void *)&ip4->ip_dst, buf, sizeof(buf))));
546*43a90889SApple OSS Distributions }
547*43a90889SApple OSS Distributions break;
548*43a90889SApple OSS Distributions case AF_INET6:
549*43a90889SApple OSS Distributions ip6 = hdr;
550*43a90889SApple OSS Distributions bzero(ip6, sizeof(*ip6));
551*43a90889SApple OSS Distributions ip6->ip6_vfc = IPV6_VERSION;
552*43a90889SApple OSS Distributions ip6->ip6_plen = htons((uint16_t)(tot_len2 - olen));
553*43a90889SApple OSS Distributions if (proto2 == IPPROTO_ICMP) {
554*43a90889SApple OSS Distributions ip6->ip6_nxt = IPPROTO_ICMPV6;
555*43a90889SApple OSS Distributions } else {
556*43a90889SApple OSS Distributions ip6->ip6_nxt = proto2;
557*43a90889SApple OSS Distributions }
558*43a90889SApple OSS Distributions if (!ttl2 || ttl2 > IPV6_DEFHLIM) {
559*43a90889SApple OSS Distributions ip6->ip6_hlim = IPV6_DEFHLIM;
560*43a90889SApple OSS Distributions } else {
561*43a90889SApple OSS Distributions ip6->ip6_hlim = ttl2;
562*43a90889SApple OSS Distributions }
563*43a90889SApple OSS Distributions ip6->ip6_src = src->natv6addr;
564*43a90889SApple OSS Distributions ip6->ip6_dst = dst->natv6addr;
565*43a90889SApple OSS Distributions
566*43a90889SApple OSS Distributions if (clat_debug) {
567*43a90889SApple OSS Distributions char buf2[MAX_IPv6_STR_LEN];
568*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s translated to IPv6 (inner) "
569*43a90889SApple OSS Distributions "ip6_plen: %#x ip6_nxt: %d ip6_src: %s ip6_dst: %s \n",
570*43a90889SApple OSS Distributions __func__, ntohs(ip6->ip6_plen), ip6->ip6_nxt,
571*43a90889SApple OSS Distributions inet_ntop(AF_INET6, (void *)&ip6->ip6_src, buf2, sizeof(buf2)),
572*43a90889SApple OSS Distributions inet_ntop(AF_INET6, (void *)&ip6->ip6_dst, buf2, sizeof(buf2))));
573*43a90889SApple OSS Distributions }
574*43a90889SApple OSS Distributions break;
575*43a90889SApple OSS Distributions }
576*43a90889SApple OSS Distributions
577*43a90889SApple OSS Distributions /* adjust payload offset and total packet length */
578*43a90889SApple OSS Distributions *off2 += hlen - olen;
579*43a90889SApple OSS Distributions *tot_len += hlen - olen;
580*43a90889SApple OSS Distributions
581*43a90889SApple OSS Distributions return 0;
582*43a90889SApple OSS Distributions }
583*43a90889SApple OSS Distributions /*
584*43a90889SApple OSS Distributions * @brief The function inserts IPv6 fragmentation header
585*43a90889SApple OSS Distributions * and populates it with the passed parameters.
586*43a90889SApple OSS Distributions *
587*43a90889SApple OSS Distributions * @param pbuf Pointer to the packet buffer
588*43a90889SApple OSS Distributions * @param ip_id IP identifier (in network byte order)
589*43a90889SApple OSS Distributions * @param frag_offset Fragment offset (in network byte order)
590*43a90889SApple OSS Distributions * @param is_last_frag Boolean indicating if the fragment header is for
591*43a90889SApple OSS Distributions * last fragment or not.
592*43a90889SApple OSS Distributions *
593*43a90889SApple OSS Distributions * @return -1 on error and 0 on success.
594*43a90889SApple OSS Distributions */
595*43a90889SApple OSS Distributions int
nat464_insert_frag46(pbuf_t * pbuf,uint16_t ip_id_val,uint16_t frag_offset,boolean_t is_last_frag)596*43a90889SApple OSS Distributions nat464_insert_frag46(pbuf_t *pbuf, uint16_t ip_id_val, uint16_t frag_offset,
597*43a90889SApple OSS Distributions boolean_t is_last_frag)
598*43a90889SApple OSS Distributions {
599*43a90889SApple OSS Distributions struct ip6_frag *p_ip6_frag = NULL;
600*43a90889SApple OSS Distributions struct ip6_hdr *p_ip6h = NULL;
601*43a90889SApple OSS Distributions
602*43a90889SApple OSS Distributions /* Insert IPv6 fragmentation header */
603*43a90889SApple OSS Distributions if (pbuf_resize_segment(pbuf, sizeof(struct ip6_hdr), 0,
604*43a90889SApple OSS Distributions sizeof(struct ip6_frag)) == NULL) {
605*43a90889SApple OSS Distributions return -1;
606*43a90889SApple OSS Distributions }
607*43a90889SApple OSS Distributions
608*43a90889SApple OSS Distributions p_ip6h = mtod(pbuf->pb_mbuf, struct ip6_hdr *);
609*43a90889SApple OSS Distributions p_ip6_frag = (struct ip6_frag *)pbuf_contig_segment(pbuf,
610*43a90889SApple OSS Distributions sizeof(struct ip6_hdr), sizeof(struct ip6_frag));
611*43a90889SApple OSS Distributions
612*43a90889SApple OSS Distributions if (p_ip6_frag == NULL) {
613*43a90889SApple OSS Distributions return -1;
614*43a90889SApple OSS Distributions }
615*43a90889SApple OSS Distributions
616*43a90889SApple OSS Distributions /* Populate IPv6 fragmentation header */
617*43a90889SApple OSS Distributions p_ip6_frag->ip6f_nxt = p_ip6h->ip6_nxt;
618*43a90889SApple OSS Distributions p_ip6_frag->ip6f_reserved = 0;
619*43a90889SApple OSS Distributions p_ip6_frag->ip6f_offlg = (uint16_t)(frag_offset << 3);
620*43a90889SApple OSS Distributions if (!is_last_frag) {
621*43a90889SApple OSS Distributions p_ip6_frag->ip6f_offlg |= 0x1;
622*43a90889SApple OSS Distributions }
623*43a90889SApple OSS Distributions p_ip6_frag->ip6f_offlg = htons(p_ip6_frag->ip6f_offlg);
624*43a90889SApple OSS Distributions p_ip6_frag->ip6f_ident = ip_id_val;
625*43a90889SApple OSS Distributions
626*43a90889SApple OSS Distributions /* Update IPv6 header */
627*43a90889SApple OSS Distributions p_ip6h->ip6_nxt = IPPROTO_FRAGMENT;
628*43a90889SApple OSS Distributions p_ip6h->ip6_plen = htons(ntohs(p_ip6h->ip6_plen) +
629*43a90889SApple OSS Distributions sizeof(struct ip6_frag));
630*43a90889SApple OSS Distributions
631*43a90889SApple OSS Distributions return 0;
632*43a90889SApple OSS Distributions }
633*43a90889SApple OSS Distributions
634*43a90889SApple OSS Distributions int
nat464_translate_64(pbuf_t * pbuf,int off,uint8_t tos,uint8_t * proto,uint8_t ttl,struct in_addr src_v4,struct in_addr dst_v4,uint64_t tot_len,boolean_t * p_is_first_frag)635*43a90889SApple OSS Distributions nat464_translate_64(pbuf_t *pbuf, int off, uint8_t tos,
636*43a90889SApple OSS Distributions uint8_t *proto, uint8_t ttl, struct in_addr src_v4,
637*43a90889SApple OSS Distributions struct in_addr dst_v4, uint64_t tot_len, boolean_t *p_is_first_frag)
638*43a90889SApple OSS Distributions {
639*43a90889SApple OSS Distributions struct ip *ip4;
640*43a90889SApple OSS Distributions struct ip6_frag *p_frag6 = NULL;
641*43a90889SApple OSS Distributions struct ip6_frag frag6 = {};
642*43a90889SApple OSS Distributions boolean_t is_frag = FALSE;
643*43a90889SApple OSS Distributions uint16_t ip_frag_off = 0;
644*43a90889SApple OSS Distributions
645*43a90889SApple OSS Distributions /*
646*43a90889SApple OSS Distributions * ip_input asserts for rcvif to be not NULL
647*43a90889SApple OSS Distributions * That may not be true for two corner cases
648*43a90889SApple OSS Distributions * 1. If for some reason a local app sends DNS
649*43a90889SApple OSS Distributions * AAAA query to local host
650*43a90889SApple OSS Distributions * 2. If IPv6 stack in kernel internally generates a
651*43a90889SApple OSS Distributions * message destined for a synthesized IPv6 end-point.
652*43a90889SApple OSS Distributions */
653*43a90889SApple OSS Distributions if (pbuf->pb_ifp == NULL) {
654*43a90889SApple OSS Distributions return NT_DROP;
655*43a90889SApple OSS Distributions }
656*43a90889SApple OSS Distributions
657*43a90889SApple OSS Distributions if (*proto == IPPROTO_FRAGMENT) {
658*43a90889SApple OSS Distributions p_frag6 = (struct ip6_frag *)pbuf_contig_segment(pbuf,
659*43a90889SApple OSS Distributions sizeof(struct ip6_hdr), sizeof(struct ip6_frag));
660*43a90889SApple OSS Distributions if (p_frag6 == NULL) {
661*43a90889SApple OSS Distributions ip6stat.ip6s_clat464_in_64frag_transfail_drop++;
662*43a90889SApple OSS Distributions return NT_DROP;
663*43a90889SApple OSS Distributions }
664*43a90889SApple OSS Distributions
665*43a90889SApple OSS Distributions frag6 = *p_frag6;
666*43a90889SApple OSS Distributions p_frag6 = NULL;
667*43a90889SApple OSS Distributions *proto = frag6.ip6f_nxt;
668*43a90889SApple OSS Distributions off += sizeof(struct ip6_frag);
669*43a90889SApple OSS Distributions is_frag = TRUE;
670*43a90889SApple OSS Distributions ip_frag_off = (ntohs(frag6.ip6f_offlg & IP6F_OFF_MASK)) >> 3;
671*43a90889SApple OSS Distributions if (ip_frag_off != 0) {
672*43a90889SApple OSS Distributions *p_is_first_frag = FALSE;
673*43a90889SApple OSS Distributions }
674*43a90889SApple OSS Distributions }
675*43a90889SApple OSS Distributions
676*43a90889SApple OSS Distributions ip4 = (struct ip *)pbuf_resize_segment(pbuf, 0, off, sizeof(*ip4));
677*43a90889SApple OSS Distributions if (ip4 == NULL) {
678*43a90889SApple OSS Distributions return NT_DROP;
679*43a90889SApple OSS Distributions }
680*43a90889SApple OSS Distributions ip4->ip_v = 4;
681*43a90889SApple OSS Distributions ip4->ip_hl = 5;
682*43a90889SApple OSS Distributions ip4->ip_tos = tos;
683*43a90889SApple OSS Distributions ip4->ip_len = htons((uint16_t)(sizeof(*ip4) + (tot_len - off)));
684*43a90889SApple OSS Distributions ip4->ip_id = 0;
685*43a90889SApple OSS Distributions ip4->ip_off = 0;
686*43a90889SApple OSS Distributions ip4->ip_ttl = ttl;
687*43a90889SApple OSS Distributions ip4->ip_p = *proto;
688*43a90889SApple OSS Distributions ip4->ip_sum = 0;
689*43a90889SApple OSS Distributions ip4->ip_src = src_v4;
690*43a90889SApple OSS Distributions ip4->ip_dst = dst_v4;
691*43a90889SApple OSS Distributions if (is_frag) {
692*43a90889SApple OSS Distributions /*
693*43a90889SApple OSS Distributions * https://tools.ietf.org/html/rfc7915#section-5.1.1
694*43a90889SApple OSS Distributions * Identification: Copied from the low-order 16 bits in the
695*43a90889SApple OSS Distributions * Identification field in the Fragment Header.
696*43a90889SApple OSS Distributions */
697*43a90889SApple OSS Distributions ip4->ip_id = ntohl(frag6.ip6f_ident) & 0xffff;
698*43a90889SApple OSS Distributions ip4->ip_id = htons(ip4->ip_id);
699*43a90889SApple OSS Distributions if (frag6.ip6f_offlg & IP6F_MORE_FRAG) {
700*43a90889SApple OSS Distributions ip_frag_off |= IP_MF;
701*43a90889SApple OSS Distributions }
702*43a90889SApple OSS Distributions ip4->ip_off = htons(ip_frag_off);
703*43a90889SApple OSS Distributions } else {
704*43a90889SApple OSS Distributions ip4->ip_off |= htons(IP_DF);
705*43a90889SApple OSS Distributions }
706*43a90889SApple OSS Distributions
707*43a90889SApple OSS Distributions /*
708*43a90889SApple OSS Distributions * Defer calculating ip_sum for ICMPv6 as we do it
709*43a90889SApple OSS Distributions * later in Protocol translation
710*43a90889SApple OSS Distributions */
711*43a90889SApple OSS Distributions if (*proto != IPPROTO_ICMPV6) {
712*43a90889SApple OSS Distributions ip4->ip_sum = pbuf_inet_cksum(pbuf, 0, 0, ip4->ip_hl << 2);
713*43a90889SApple OSS Distributions }
714*43a90889SApple OSS Distributions
715*43a90889SApple OSS Distributions if (clat_debug) {
716*43a90889SApple OSS Distributions char buf1[MAX_IPv4_STR_LEN], buf2[MAX_IPv4_STR_LEN];
717*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s translated to IPv4 ip_len: %#x "
718*43a90889SApple OSS Distributions "ip_p: %d ip_sum: %#x ip_src: %s ip_dst: %s \n", __func__,
719*43a90889SApple OSS Distributions ntohs(ip4->ip_len), ip4->ip_p, ntohs(ip4->ip_sum),
720*43a90889SApple OSS Distributions inet_ntop(AF_INET, (void *)&ip4->ip_src, buf1, sizeof(buf1)),
721*43a90889SApple OSS Distributions inet_ntop(AF_INET, (void *)&ip4->ip_dst, buf2, sizeof(buf2))));
722*43a90889SApple OSS Distributions }
723*43a90889SApple OSS Distributions return NT_NAT64;
724*43a90889SApple OSS Distributions }
725*43a90889SApple OSS Distributions /*
726*43a90889SApple OSS Distributions * @brief The routine translates the IPv4 header to IPv6 header.
727*43a90889SApple OSS Distributions *
728*43a90889SApple OSS Distributions * @param pbuf Pointer to the generic packet buffer
729*43a90889SApple OSS Distributions * @param off Offset to the end of IP header
730*43a90889SApple OSS Distributions * @param tos Type of service
731*43a90889SApple OSS Distributions * @param proto Protocol running over IP
732*43a90889SApple OSS Distributions * @param ttl Time to live
733*43a90889SApple OSS Distributions * @param src_v6 Source IPv6 address
734*43a90889SApple OSS Distributions * @param dst_v6 Destination IPv6 address
735*43a90889SApple OSS Distributions * @param tot_len Total payload length
736*43a90889SApple OSS Distributions *
737*43a90889SApple OSS Distributions * @return NT_NAT64 if IP header translation is successful, else error
738*43a90889SApple OSS Distributions */
739*43a90889SApple OSS Distributions int
nat464_translate_46(pbuf_t * pbuf,uint16_t off,uint8_t tos,uint8_t proto,uint8_t ttl,struct in6_addr src_v6,struct in6_addr dst_v6,uint16_t tot_len)740*43a90889SApple OSS Distributions nat464_translate_46(pbuf_t *pbuf, uint16_t off, uint8_t tos,
741*43a90889SApple OSS Distributions uint8_t proto, uint8_t ttl, struct in6_addr src_v6,
742*43a90889SApple OSS Distributions struct in6_addr dst_v6, uint16_t tot_len)
743*43a90889SApple OSS Distributions {
744*43a90889SApple OSS Distributions struct ip6_hdr *ip6;
745*43a90889SApple OSS Distributions
746*43a90889SApple OSS Distributions if (pbuf->pb_ifp == NULL) {
747*43a90889SApple OSS Distributions return NT_DROP;
748*43a90889SApple OSS Distributions }
749*43a90889SApple OSS Distributions
750*43a90889SApple OSS Distributions /*
751*43a90889SApple OSS Distributions * Trim the buffer from head of size equal to to off (which is equal to
752*43a90889SApple OSS Distributions * the size of IP header and prepend IPv6 header length to the buffer
753*43a90889SApple OSS Distributions */
754*43a90889SApple OSS Distributions ip6 = (struct ip6_hdr *)pbuf_resize_segment(pbuf, 0, off, sizeof(*ip6));
755*43a90889SApple OSS Distributions if (ip6 == NULL) {
756*43a90889SApple OSS Distributions return NT_DROP;
757*43a90889SApple OSS Distributions }
758*43a90889SApple OSS Distributions ip6->ip6_flow = htonl((6 << 28) | (tos << 20));
759*43a90889SApple OSS Distributions ip6->ip6_plen = htons(tot_len - off);
760*43a90889SApple OSS Distributions ip6->ip6_nxt = proto;
761*43a90889SApple OSS Distributions ip6->ip6_hlim = ttl;
762*43a90889SApple OSS Distributions ip6->ip6_src = src_v6;
763*43a90889SApple OSS Distributions ip6->ip6_dst = dst_v6;
764*43a90889SApple OSS Distributions
765*43a90889SApple OSS Distributions if (clat_debug) {
766*43a90889SApple OSS Distributions char buf1[MAX_IPv6_STR_LEN], buf2[MAX_IPv6_STR_LEN];
767*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s translated to IPv6 ip6_plen: %#x "
768*43a90889SApple OSS Distributions " ip6_nxt: %d ip6_src: %s ip6_dst: %s \n", __func__,
769*43a90889SApple OSS Distributions ntohs(ip6->ip6_plen), ip6->ip6_nxt,
770*43a90889SApple OSS Distributions inet_ntop(AF_INET6, (void *)&ip6->ip6_src, buf1, sizeof(buf1)),
771*43a90889SApple OSS Distributions inet_ntop(AF_INET6, (void *)&ip6->ip6_dst, buf2, sizeof(buf2))));
772*43a90889SApple OSS Distributions }
773*43a90889SApple OSS Distributions return NT_NAT64;
774*43a90889SApple OSS Distributions }
775*43a90889SApple OSS Distributions
776*43a90889SApple OSS Distributions /* Handle the next protocol checksum */
777*43a90889SApple OSS Distributions /*
778*43a90889SApple OSS Distributions * @brief This routine translates the Proto running over IP and updates the checksum
779*43a90889SApple OSS Distributions * for IP header translation. It also updates pbuf checksum flags and related fields.
780*43a90889SApple OSS Distributions *
781*43a90889SApple OSS Distributions * @param pbuf Pointer to protocol buffer
782*43a90889SApple OSS Distributions * @param nsrc New source address
783*43a90889SApple OSS Distributions * @param ndst New destination address
784*43a90889SApple OSS Distributions * @param af Old family
785*43a90889SApple OSS Distributions * @param naf New family
786*43a90889SApple OSS Distributions *
787*43a90889SApple OSS Distributions * @return void
788*43a90889SApple OSS Distributions */
789*43a90889SApple OSS Distributions int
nat464_translate_proto(pbuf_t * pbuf,struct nat464_addr * osrc,struct nat464_addr * odst,uint8_t oproto,protocol_family_t af,protocol_family_t naf,int direction,boolean_t only_csum)790*43a90889SApple OSS Distributions nat464_translate_proto(pbuf_t *pbuf, struct nat464_addr *osrc,
791*43a90889SApple OSS Distributions struct nat464_addr *odst, uint8_t oproto, protocol_family_t af,
792*43a90889SApple OSS Distributions protocol_family_t naf, int direction, boolean_t only_csum)
793*43a90889SApple OSS Distributions {
794*43a90889SApple OSS Distributions struct ip *iph = NULL;
795*43a90889SApple OSS Distributions struct ip6_hdr *ip6h = NULL;
796*43a90889SApple OSS Distributions uint16_t hlen = 0, plen = 0;
797*43a90889SApple OSS Distributions uint16_t tot_len = 0;
798*43a90889SApple OSS Distributions void *nsrc = NULL, *ndst = NULL;
799*43a90889SApple OSS Distributions uint8_t *proto = 0;
800*43a90889SApple OSS Distributions uint16_t *psum = NULL;
801*43a90889SApple OSS Distributions boolean_t do_ones_complement = FALSE;
802*43a90889SApple OSS Distributions
803*43a90889SApple OSS Distributions /* For now these routines only support 464 translations */
804*43a90889SApple OSS Distributions VERIFY(af != naf);
805*43a90889SApple OSS Distributions VERIFY(af == PF_INET || af == PF_INET6);
806*43a90889SApple OSS Distributions
807*43a90889SApple OSS Distributions /*
808*43a90889SApple OSS Distributions * For now out must be for v4 to v6 translation
809*43a90889SApple OSS Distributions * and in must be for v6 to v4 translation.
810*43a90889SApple OSS Distributions */
811*43a90889SApple OSS Distributions switch (naf) {
812*43a90889SApple OSS Distributions case PF_INET: {
813*43a90889SApple OSS Distributions iph = pbuf->pb_data;
814*43a90889SApple OSS Distributions hlen = (uint16_t)(iph->ip_hl << 2);
815*43a90889SApple OSS Distributions plen = ntohs(iph->ip_len) - hlen;
816*43a90889SApple OSS Distributions tot_len = ntohs(iph->ip_len);
817*43a90889SApple OSS Distributions nsrc = &iph->ip_src;
818*43a90889SApple OSS Distributions ndst = &iph->ip_dst;
819*43a90889SApple OSS Distributions proto = &iph->ip_p;
820*43a90889SApple OSS Distributions break;
821*43a90889SApple OSS Distributions }
822*43a90889SApple OSS Distributions case PF_INET6: {
823*43a90889SApple OSS Distributions ip6h = pbuf->pb_data;
824*43a90889SApple OSS Distributions hlen = (uint16_t)sizeof(*ip6h);
825*43a90889SApple OSS Distributions plen = ntohs(ip6h->ip6_plen);
826*43a90889SApple OSS Distributions tot_len = hlen + plen;
827*43a90889SApple OSS Distributions nsrc = &ip6h->ip6_src;
828*43a90889SApple OSS Distributions ndst = &ip6h->ip6_dst;
829*43a90889SApple OSS Distributions proto = &ip6h->ip6_nxt;
830*43a90889SApple OSS Distributions break;
831*43a90889SApple OSS Distributions }
832*43a90889SApple OSS Distributions default:
833*43a90889SApple OSS Distributions return NT_DROP; /* We should never come here */
834*43a90889SApple OSS Distributions }
835*43a90889SApple OSS Distributions
836*43a90889SApple OSS Distributions if (*proto != oproto) {
837*43a90889SApple OSS Distributions return NT_DROP;
838*43a90889SApple OSS Distributions }
839*43a90889SApple OSS Distributions
840*43a90889SApple OSS Distributions /*
841*43a90889SApple OSS Distributions * We may want to manipulate csum flags in some cases
842*43a90889SApple OSS Distributions * and not act on the protocol header as it may not
843*43a90889SApple OSS Distributions * carry protocol checksums.
844*43a90889SApple OSS Distributions * For example, fragments other than the first one would
845*43a90889SApple OSS Distributions * not carry protocol headers.
846*43a90889SApple OSS Distributions */
847*43a90889SApple OSS Distributions if (only_csum) {
848*43a90889SApple OSS Distributions /*
849*43a90889SApple OSS Distributions * Only translate ICMP proto in the header
850*43a90889SApple OSS Distributions * and adjust checksums
851*43a90889SApple OSS Distributions */
852*43a90889SApple OSS Distributions if (*proto == IPPROTO_ICMP) {
853*43a90889SApple OSS Distributions if (naf != PF_INET6) {
854*43a90889SApple OSS Distributions return NT_DROP;
855*43a90889SApple OSS Distributions }
856*43a90889SApple OSS Distributions
857*43a90889SApple OSS Distributions *proto = IPPROTO_ICMPV6;
858*43a90889SApple OSS Distributions } else if (*proto == IPPROTO_ICMPV6) {
859*43a90889SApple OSS Distributions if (naf != PF_INET) {
860*43a90889SApple OSS Distributions return NT_DROP;
861*43a90889SApple OSS Distributions }
862*43a90889SApple OSS Distributions
863*43a90889SApple OSS Distributions *proto = IPPROTO_ICMP;
864*43a90889SApple OSS Distributions /* Recalculate IP checksum as proto field has changed */
865*43a90889SApple OSS Distributions iph->ip_sum = 0;
866*43a90889SApple OSS Distributions iph->ip_sum = pbuf_inet_cksum(pbuf, 0, 0, hlen);
867*43a90889SApple OSS Distributions }
868*43a90889SApple OSS Distributions goto done;
869*43a90889SApple OSS Distributions }
870*43a90889SApple OSS Distributions
871*43a90889SApple OSS Distributions switch (*proto) {
872*43a90889SApple OSS Distributions case IPPROTO_UDP: {
873*43a90889SApple OSS Distributions struct udphdr *uh = (struct udphdr *)pbuf_contig_segment(pbuf, hlen,
874*43a90889SApple OSS Distributions sizeof(*uh));
875*43a90889SApple OSS Distributions
876*43a90889SApple OSS Distributions if (uh == NULL) {
877*43a90889SApple OSS Distributions return NT_DROP;
878*43a90889SApple OSS Distributions }
879*43a90889SApple OSS Distributions
880*43a90889SApple OSS Distributions if (!(*pbuf->pb_csum_flags & (CSUM_UDP | CSUM_PARTIAL)) &&
881*43a90889SApple OSS Distributions uh->uh_sum == 0 && af == PF_INET && naf == PF_INET6) {
882*43a90889SApple OSS Distributions uh->uh_sum = pbuf_inet6_cksum(pbuf, IPPROTO_UDP,
883*43a90889SApple OSS Distributions hlen, ntohs(ip6h->ip6_plen));
884*43a90889SApple OSS Distributions if (uh->uh_sum == 0) {
885*43a90889SApple OSS Distributions uh->uh_sum = 0xffff;
886*43a90889SApple OSS Distributions }
887*43a90889SApple OSS Distributions goto done;
888*43a90889SApple OSS Distributions }
889*43a90889SApple OSS Distributions
890*43a90889SApple OSS Distributions psum = &uh->uh_sum;
891*43a90889SApple OSS Distributions break;
892*43a90889SApple OSS Distributions }
893*43a90889SApple OSS Distributions case IPPROTO_TCP: {
894*43a90889SApple OSS Distributions struct tcphdr *th = (struct tcphdr *)pbuf_contig_segment(pbuf, hlen,
895*43a90889SApple OSS Distributions sizeof(*th));
896*43a90889SApple OSS Distributions
897*43a90889SApple OSS Distributions if (th == NULL) {
898*43a90889SApple OSS Distributions return NT_DROP;
899*43a90889SApple OSS Distributions }
900*43a90889SApple OSS Distributions
901*43a90889SApple OSS Distributions psum = &th->th_sum;
902*43a90889SApple OSS Distributions break;
903*43a90889SApple OSS Distributions }
904*43a90889SApple OSS Distributions }
905*43a90889SApple OSS Distributions
906*43a90889SApple OSS Distributions /*
907*43a90889SApple OSS Distributions * Translate the protocol header, update IP header if needed,
908*43a90889SApple OSS Distributions * calculate checksums and update the checksum flags.
909*43a90889SApple OSS Distributions */
910*43a90889SApple OSS Distributions switch (*proto) {
911*43a90889SApple OSS Distributions case IPPROTO_UDP:
912*43a90889SApple OSS Distributions /* Fall through */
913*43a90889SApple OSS Distributions case IPPROTO_TCP:
914*43a90889SApple OSS Distributions {
915*43a90889SApple OSS Distributions /*
916*43a90889SApple OSS Distributions * If it is a locally generated and has CSUM flags set
917*43a90889SApple OSS Distributions * for TCP and UDP it means we have pseudo header checksum
918*43a90889SApple OSS Distributions * that has not yet been one's complemented.
919*43a90889SApple OSS Distributions */
920*43a90889SApple OSS Distributions if (direction == NT_OUT &&
921*43a90889SApple OSS Distributions (*pbuf->pb_csum_flags & CSUM_PARTIAL)) {
922*43a90889SApple OSS Distributions do_ones_complement = TRUE;
923*43a90889SApple OSS Distributions }
924*43a90889SApple OSS Distributions
925*43a90889SApple OSS Distributions nat464_addr_cksum_fixup(psum, osrc, (struct nat464_addr *)nsrc,
926*43a90889SApple OSS Distributions af, naf, (*proto == IPPROTO_UDP) ? 1 : 0, do_ones_complement);
927*43a90889SApple OSS Distributions nat464_addr_cksum_fixup(psum, odst, (struct nat464_addr *)ndst,
928*43a90889SApple OSS Distributions af, naf, (*proto == IPPROTO_UDP) ? 1 : 0, do_ones_complement);
929*43a90889SApple OSS Distributions
930*43a90889SApple OSS Distributions break;
931*43a90889SApple OSS Distributions }
932*43a90889SApple OSS Distributions case IPPROTO_ICMP: {
933*43a90889SApple OSS Distributions if (naf != PF_INET6) { /* allow only v6 as naf for ICMP */
934*43a90889SApple OSS Distributions return NT_DROP;
935*43a90889SApple OSS Distributions }
936*43a90889SApple OSS Distributions
937*43a90889SApple OSS Distributions struct icmp *__single icmph = NULL;
938*43a90889SApple OSS Distributions struct icmp6_hdr *__single icmp6h = NULL;
939*43a90889SApple OSS Distributions uint16_t ip2off = 0, hlen2 = 0, tot_len2 = 0;
940*43a90889SApple OSS Distributions
941*43a90889SApple OSS Distributions icmph = (struct icmp*) pbuf_contig_segment(pbuf, hlen,
942*43a90889SApple OSS Distributions ICMP_MINLEN);
943*43a90889SApple OSS Distributions if (icmph == NULL) {
944*43a90889SApple OSS Distributions return NT_DROP;
945*43a90889SApple OSS Distributions }
946*43a90889SApple OSS Distributions
947*43a90889SApple OSS Distributions /* Translate the ICMP header */
948*43a90889SApple OSS Distributions if (nat464_translate_icmp(PF_INET6, icmph) != 0) {
949*43a90889SApple OSS Distributions return NT_DROP;
950*43a90889SApple OSS Distributions }
951*43a90889SApple OSS Distributions
952*43a90889SApple OSS Distributions *proto = IPPROTO_ICMPV6;
953*43a90889SApple OSS Distributions icmp6h = (struct icmp6_hdr *__single)(void *)icmph;
954*43a90889SApple OSS Distributions pbuf_copy_back(pbuf, hlen, sizeof(struct icmp6_hdr),
955*43a90889SApple OSS Distributions icmp6h, sizeof(*icmp6h));
956*43a90889SApple OSS Distributions
957*43a90889SApple OSS Distributions /*Translate the inner IP header only for error messages */
958*43a90889SApple OSS Distributions if (ICMP6_ERRORTYPE(icmp6h->icmp6_type)) {
959*43a90889SApple OSS Distributions ip2off = (uint16_t)(hlen + sizeof(*icmp6h));
960*43a90889SApple OSS Distributions struct ip *iph2 = NULL;
961*43a90889SApple OSS Distributions iph2 = (struct ip*) pbuf_contig_segment(pbuf, ip2off,
962*43a90889SApple OSS Distributions sizeof(*iph2));
963*43a90889SApple OSS Distributions if (iph2 == NULL) {
964*43a90889SApple OSS Distributions return NT_DROP;
965*43a90889SApple OSS Distributions }
966*43a90889SApple OSS Distributions
967*43a90889SApple OSS Distributions hlen2 = (uint16_t)(ip2off + (iph2->ip_hl << 2));
968*43a90889SApple OSS Distributions tot_len2 = ntohs(iph2->ip_len);
969*43a90889SApple OSS Distributions
970*43a90889SApple OSS Distributions /*
971*43a90889SApple OSS Distributions * Destination in outer IP should be Source in inner IP,
972*43a90889SApple OSS Distributions * otherwise the ICMP is likely errnoneous.
973*43a90889SApple OSS Distributions */
974*43a90889SApple OSS Distributions if (!IN_ARE_ADDR_EQUAL(&odst->natv4addr, &iph2->ip_src)) {
975*43a90889SApple OSS Distributions return NT_DROP;
976*43a90889SApple OSS Distributions }
977*43a90889SApple OSS Distributions
978*43a90889SApple OSS Distributions if (nat464_translate_icmp_ip(pbuf, ip2off, &tot_len,
979*43a90889SApple OSS Distributions &hlen2, iph2->ip_p, iph2->ip_ttl, tot_len2,
980*43a90889SApple OSS Distributions (struct nat464_addr *)ndst, (struct nat464_addr *)nsrc,
981*43a90889SApple OSS Distributions PF_INET, PF_INET6) != 0) {
982*43a90889SApple OSS Distributions return NT_DROP;
983*43a90889SApple OSS Distributions }
984*43a90889SApple OSS Distributions /* Update total length/payload length for outer header */
985*43a90889SApple OSS Distributions switch (naf) {
986*43a90889SApple OSS Distributions case PF_INET:
987*43a90889SApple OSS Distributions iph->ip_len = htons(tot_len);
988*43a90889SApple OSS Distributions break;
989*43a90889SApple OSS Distributions case PF_INET6:
990*43a90889SApple OSS Distributions ip6h->ip6_plen = htons(tot_len - hlen);
991*43a90889SApple OSS Distributions break;
992*43a90889SApple OSS Distributions }
993*43a90889SApple OSS Distributions iph2 = NULL;
994*43a90889SApple OSS Distributions }
995*43a90889SApple OSS Distributions
996*43a90889SApple OSS Distributions icmp6h->icmp6_cksum = 0;
997*43a90889SApple OSS Distributions icmp6h->icmp6_cksum = pbuf_inet6_cksum(pbuf, IPPROTO_ICMPV6, hlen,
998*43a90889SApple OSS Distributions ntohs(ip6h->ip6_plen));
999*43a90889SApple OSS Distributions
1000*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s translated to ICMPV6 type: %d "
1001*43a90889SApple OSS Distributions "code: %d checksum: %#x \n", __func__, icmp6h->icmp6_type,
1002*43a90889SApple OSS Distributions icmp6h->icmp6_code, icmp6h->icmp6_cksum));
1003*43a90889SApple OSS Distributions
1004*43a90889SApple OSS Distributions icmph = NULL;
1005*43a90889SApple OSS Distributions icmp6h = NULL;
1006*43a90889SApple OSS Distributions break;
1007*43a90889SApple OSS Distributions }
1008*43a90889SApple OSS Distributions case IPPROTO_ICMPV6:
1009*43a90889SApple OSS Distributions { if (naf != PF_INET) { /* allow only v4 as naf for ICMPV6 */
1010*43a90889SApple OSS Distributions return NT_DROP;
1011*43a90889SApple OSS Distributions }
1012*43a90889SApple OSS Distributions
1013*43a90889SApple OSS Distributions struct icmp6_hdr *__single icmp6h = NULL;
1014*43a90889SApple OSS Distributions struct icmp *__single icmph = NULL;
1015*43a90889SApple OSS Distributions uint16_t ip2off = 0, hlen2 = 0, tot_len2 = 0;
1016*43a90889SApple OSS Distributions
1017*43a90889SApple OSS Distributions icmp6h = (struct icmp6_hdr*) pbuf_contig_segment(pbuf, hlen,
1018*43a90889SApple OSS Distributions sizeof(*icmp6h));
1019*43a90889SApple OSS Distributions if (icmp6h == NULL) {
1020*43a90889SApple OSS Distributions return NT_DROP;
1021*43a90889SApple OSS Distributions }
1022*43a90889SApple OSS Distributions
1023*43a90889SApple OSS Distributions /* Translate the ICMP header */
1024*43a90889SApple OSS Distributions if (nat464_translate_icmp(PF_INET, icmp6h) != 0) {
1025*43a90889SApple OSS Distributions return NT_DROP;
1026*43a90889SApple OSS Distributions }
1027*43a90889SApple OSS Distributions
1028*43a90889SApple OSS Distributions *proto = IPPROTO_ICMP;
1029*43a90889SApple OSS Distributions icmph = (struct icmp *__single)(void *)icmp6h;
1030*43a90889SApple OSS Distributions pbuf_copy_back(pbuf, hlen, ICMP_MINLEN,
1031*43a90889SApple OSS Distributions icmph, sizeof(*icmph));
1032*43a90889SApple OSS Distributions
1033*43a90889SApple OSS Distributions /*Translate the inner IP header only for error messages */
1034*43a90889SApple OSS Distributions if (ICMP_ERRORTYPE(icmph->icmp_type)) {
1035*43a90889SApple OSS Distributions ip2off = hlen + ICMP_MINLEN;
1036*43a90889SApple OSS Distributions struct ip6_hdr *iph2 = NULL;
1037*43a90889SApple OSS Distributions iph2 = (struct ip6_hdr*) pbuf_contig_segment(pbuf, ip2off,
1038*43a90889SApple OSS Distributions sizeof(*iph2));
1039*43a90889SApple OSS Distributions if (iph2 == NULL) {
1040*43a90889SApple OSS Distributions return NT_DROP;
1041*43a90889SApple OSS Distributions }
1042*43a90889SApple OSS Distributions
1043*43a90889SApple OSS Distributions /* hlen2 points to end of inner IP header from the beginning */
1044*43a90889SApple OSS Distributions hlen2 = ip2off + sizeof(struct ip6_hdr);
1045*43a90889SApple OSS Distributions tot_len2 = ntohs(iph2->ip6_plen) + sizeof(struct ip6_hdr);
1046*43a90889SApple OSS Distributions
1047*43a90889SApple OSS Distributions if (nat464_translate_icmp_ip(pbuf, ip2off, &tot_len,
1048*43a90889SApple OSS Distributions &hlen2, iph2->ip6_nxt, iph2->ip6_hlim, tot_len2,
1049*43a90889SApple OSS Distributions (struct nat464_addr *)ndst, (struct nat464_addr *)nsrc,
1050*43a90889SApple OSS Distributions PF_INET6, PF_INET) != 0) {
1051*43a90889SApple OSS Distributions return NT_DROP;
1052*43a90889SApple OSS Distributions }
1053*43a90889SApple OSS Distributions
1054*43a90889SApple OSS Distributions /* Update total length for outer header */
1055*43a90889SApple OSS Distributions switch (naf) {
1056*43a90889SApple OSS Distributions case PF_INET:
1057*43a90889SApple OSS Distributions iph->ip_len = htons(tot_len);
1058*43a90889SApple OSS Distributions break;
1059*43a90889SApple OSS Distributions case PF_INET6:
1060*43a90889SApple OSS Distributions ip6h->ip6_plen = htons(tot_len - hlen);
1061*43a90889SApple OSS Distributions break;
1062*43a90889SApple OSS Distributions }
1063*43a90889SApple OSS Distributions iph2 = NULL;
1064*43a90889SApple OSS Distributions }
1065*43a90889SApple OSS Distributions /* Recalculate IP checksum as some IP fields might have changed */
1066*43a90889SApple OSS Distributions iph->ip_sum = 0;
1067*43a90889SApple OSS Distributions iph->ip_sum = pbuf_inet_cksum(pbuf, 0, 0, iph->ip_hl << 2);
1068*43a90889SApple OSS Distributions icmph->icmp_cksum = 0;
1069*43a90889SApple OSS Distributions icmph->icmp_cksum = pbuf_inet_cksum(pbuf, 0, hlen,
1070*43a90889SApple OSS Distributions ntohs(iph->ip_len) - hlen);
1071*43a90889SApple OSS Distributions
1072*43a90889SApple OSS Distributions clat_log2((LOG_DEBUG, "%s translated to ICMP type: %d "
1073*43a90889SApple OSS Distributions "code: %d checksum: %#x \n", __func__, icmph->icmp_type,
1074*43a90889SApple OSS Distributions icmph->icmp_code, icmph->icmp_cksum));
1075*43a90889SApple OSS Distributions
1076*43a90889SApple OSS Distributions icmp6h = NULL;
1077*43a90889SApple OSS Distributions icmph = NULL;
1078*43a90889SApple OSS Distributions break;}
1079*43a90889SApple OSS Distributions
1080*43a90889SApple OSS Distributions /*
1081*43a90889SApple OSS Distributions * https://tools.ietf.org/html/rfc7915#section-5.1.1
1082*43a90889SApple OSS Distributions * If the Next Header field of the Fragment Header is an
1083*43a90889SApple OSS Distributions * extension header (except ESP, but including the Authentication
1084*43a90889SApple OSS Distributions * Header (AH)), then the packet SHOULD be dropped and logged.
1085*43a90889SApple OSS Distributions */
1086*43a90889SApple OSS Distributions case IPPROTO_HOPOPTS:
1087*43a90889SApple OSS Distributions case IPPROTO_ROUTING:
1088*43a90889SApple OSS Distributions case IPPROTO_DSTOPTS:
1089*43a90889SApple OSS Distributions case IPPROTO_AH:
1090*43a90889SApple OSS Distributions return NT_DROP;
1091*43a90889SApple OSS Distributions
1092*43a90889SApple OSS Distributions case IPPROTO_FRAGMENT:
1093*43a90889SApple OSS Distributions /*
1094*43a90889SApple OSS Distributions * The fragment header is appended after or removed before
1095*43a90889SApple OSS Distributions * calling into this routine.
1096*43a90889SApple OSS Distributions */
1097*43a90889SApple OSS Distributions VERIFY(FALSE);
1098*43a90889SApple OSS Distributions case IPPROTO_ESP:
1099*43a90889SApple OSS Distributions break;
1100*43a90889SApple OSS Distributions
1101*43a90889SApple OSS Distributions default:
1102*43a90889SApple OSS Distributions return NT_DROP;
1103*43a90889SApple OSS Distributions }
1104*43a90889SApple OSS Distributions
1105*43a90889SApple OSS Distributions done:
1106*43a90889SApple OSS Distributions /* Update checksum flags and offsets based on direction */
1107*43a90889SApple OSS Distributions if (direction == NT_OUT) {
1108*43a90889SApple OSS Distributions if ((*pbuf->pb_csum_flags & (CSUM_DATA_VALID | CSUM_PARTIAL)) ==
1109*43a90889SApple OSS Distributions (CSUM_DATA_VALID | CSUM_PARTIAL)) {
1110*43a90889SApple OSS Distributions (pbuf->pb_mbuf)->m_pkthdr.csum_tx_start += CLAT46_HDR_EXPANSION_OVERHD;
1111*43a90889SApple OSS Distributions (pbuf->pb_mbuf)->m_pkthdr.csum_tx_stuff += CLAT46_HDR_EXPANSION_OVERHD;
1112*43a90889SApple OSS Distributions }
1113*43a90889SApple OSS Distributions
1114*43a90889SApple OSS Distributions if (*pbuf->pb_csum_flags & CSUM_TCP) {
1115*43a90889SApple OSS Distributions *pbuf->pb_csum_flags |= CSUM_TCPIPV6;
1116*43a90889SApple OSS Distributions }
1117*43a90889SApple OSS Distributions if (*pbuf->pb_csum_flags & CSUM_UDP) {
1118*43a90889SApple OSS Distributions *pbuf->pb_csum_flags |= CSUM_UDPIPV6;
1119*43a90889SApple OSS Distributions }
1120*43a90889SApple OSS Distributions if (*pbuf->pb_csum_flags & CSUM_FRAGMENT) {
1121*43a90889SApple OSS Distributions *pbuf->pb_csum_flags |= CSUM_FRAGMENT_IPV6;
1122*43a90889SApple OSS Distributions }
1123*43a90889SApple OSS Distributions
1124*43a90889SApple OSS Distributions /* Clear IPv4 checksum flags */
1125*43a90889SApple OSS Distributions *pbuf->pb_csum_flags &= ~(CSUM_IP | CSUM_IP_FRAGS | CSUM_DELAY_DATA | CSUM_FRAGMENT);
1126*43a90889SApple OSS Distributions /*
1127*43a90889SApple OSS Distributions * If the packet requires TCP segmentation due to TSO offload,
1128*43a90889SApple OSS Distributions * then change the checksum flag to indicate that an IPv6
1129*43a90889SApple OSS Distributions * TCP segmentation is needed now.
1130*43a90889SApple OSS Distributions */
1131*43a90889SApple OSS Distributions if (*pbuf->pb_csum_flags & CSUM_TSO_IPV4) {
1132*43a90889SApple OSS Distributions *pbuf->pb_csum_flags &= ~CSUM_TSO_IPV4;
1133*43a90889SApple OSS Distributions *pbuf->pb_csum_flags |= CSUM_TSO_IPV6;
1134*43a90889SApple OSS Distributions }
1135*43a90889SApple OSS Distributions } else if (direction == NT_IN) {
1136*43a90889SApple OSS Distributions /* XXX On input just reset csum flags */
1137*43a90889SApple OSS Distributions *pbuf->pb_csum_flags = 0; /* Reset all flags for now */
1138*43a90889SApple OSS Distributions #if 0
1139*43a90889SApple OSS Distributions /* Update csum flags and offsets for rx */
1140*43a90889SApple OSS Distributions if (*pbuf->pb_csum_flags & CSUM_PARTIAL) {
1141*43a90889SApple OSS Distributions (pbuf->pb_mbuf)->m_pkthdr.csum_rx_start -= CLAT46_HDR_EXPANSION_OVERHD;
1142*43a90889SApple OSS Distributions }
1143*43a90889SApple OSS Distributions #endif
1144*43a90889SApple OSS Distributions }
1145*43a90889SApple OSS Distributions return NT_NAT64;
1146*43a90889SApple OSS Distributions }
1147*43a90889SApple OSS Distributions
1148*43a90889SApple OSS Distributions /* Fix the proto checksum for address change */
1149*43a90889SApple OSS Distributions static void
nat464_addr_cksum_fixup(uint16_t * pc,struct nat464_addr * ao,struct nat464_addr * an,protocol_family_t af,protocol_family_t naf,uint8_t u,boolean_t do_ones_complement)1150*43a90889SApple OSS Distributions nat464_addr_cksum_fixup(uint16_t *pc, struct nat464_addr *ao, struct nat464_addr *an,
1151*43a90889SApple OSS Distributions protocol_family_t af, protocol_family_t naf, uint8_t u, boolean_t do_ones_complement)
1152*43a90889SApple OSS Distributions {
1153*43a90889SApple OSS Distributions /* Currently we only support v4 to v6 and vice versa */
1154*43a90889SApple OSS Distributions VERIFY(af != naf);
1155*43a90889SApple OSS Distributions
1156*43a90889SApple OSS Distributions switch (af) {
1157*43a90889SApple OSS Distributions case PF_INET:
1158*43a90889SApple OSS Distributions switch (naf) {
1159*43a90889SApple OSS Distributions case PF_INET6:
1160*43a90889SApple OSS Distributions if (do_ones_complement) {
1161*43a90889SApple OSS Distributions *pc = ~nat464_cksum_fixup(nat464_cksum_fixup(
1162*43a90889SApple OSS Distributions nat464_cksum_fixup(nat464_cksum_fixup(nat464_cksum_fixup(
1163*43a90889SApple OSS Distributions nat464_cksum_fixup(nat464_cksum_fixup(nat464_cksum_fixup(~*pc,
1164*43a90889SApple OSS Distributions ao->nataddr16[0], an->nataddr16[0], u),
1165*43a90889SApple OSS Distributions ao->nataddr16[1], an->nataddr16[1], u),
1166*43a90889SApple OSS Distributions 0, an->nataddr16[2], u),
1167*43a90889SApple OSS Distributions 0, an->nataddr16[3], u),
1168*43a90889SApple OSS Distributions 0, an->nataddr16[4], u),
1169*43a90889SApple OSS Distributions 0, an->nataddr16[5], u),
1170*43a90889SApple OSS Distributions 0, an->nataddr16[6], u),
1171*43a90889SApple OSS Distributions 0, an->nataddr16[7], u);
1172*43a90889SApple OSS Distributions } else {
1173*43a90889SApple OSS Distributions *pc = nat464_cksum_fixup(nat464_cksum_fixup(
1174*43a90889SApple OSS Distributions nat464_cksum_fixup(nat464_cksum_fixup(nat464_cksum_fixup(
1175*43a90889SApple OSS Distributions nat464_cksum_fixup(nat464_cksum_fixup(nat464_cksum_fixup(*pc,
1176*43a90889SApple OSS Distributions ao->nataddr16[0], an->nataddr16[0], u),
1177*43a90889SApple OSS Distributions ao->nataddr16[1], an->nataddr16[1], u),
1178*43a90889SApple OSS Distributions 0, an->nataddr16[2], u),
1179*43a90889SApple OSS Distributions 0, an->nataddr16[3], u),
1180*43a90889SApple OSS Distributions 0, an->nataddr16[4], u),
1181*43a90889SApple OSS Distributions 0, an->nataddr16[5], u),
1182*43a90889SApple OSS Distributions 0, an->nataddr16[6], u),
1183*43a90889SApple OSS Distributions 0, an->nataddr16[7], u);
1184*43a90889SApple OSS Distributions }
1185*43a90889SApple OSS Distributions break;
1186*43a90889SApple OSS Distributions }
1187*43a90889SApple OSS Distributions break;
1188*43a90889SApple OSS Distributions case PF_INET6:
1189*43a90889SApple OSS Distributions /*
1190*43a90889SApple OSS Distributions * XXX For NAT464 this only applies to the incoming path.
1191*43a90889SApple OSS Distributions * The checksum therefore is already ones complemented.
1192*43a90889SApple OSS Distributions * Therefore we just perform normal fixup.
1193*43a90889SApple OSS Distributions */
1194*43a90889SApple OSS Distributions switch (naf) {
1195*43a90889SApple OSS Distributions case PF_INET:
1196*43a90889SApple OSS Distributions *pc = nat464_cksum_fixup(nat464_cksum_fixup(
1197*43a90889SApple OSS Distributions nat464_cksum_fixup(nat464_cksum_fixup(nat464_cksum_fixup(
1198*43a90889SApple OSS Distributions nat464_cksum_fixup(nat464_cksum_fixup(nat464_cksum_fixup(*pc,
1199*43a90889SApple OSS Distributions ao->nataddr16[0], an->nataddr16[0], u),
1200*43a90889SApple OSS Distributions ao->nataddr16[1], an->nataddr16[1], u),
1201*43a90889SApple OSS Distributions ao->nataddr16[2], 0, u),
1202*43a90889SApple OSS Distributions ao->nataddr16[3], 0, u),
1203*43a90889SApple OSS Distributions ao->nataddr16[4], 0, u),
1204*43a90889SApple OSS Distributions ao->nataddr16[5], 0, u),
1205*43a90889SApple OSS Distributions ao->nataddr16[6], 0, u),
1206*43a90889SApple OSS Distributions ao->nataddr16[7], 0, u);
1207*43a90889SApple OSS Distributions break;
1208*43a90889SApple OSS Distributions }
1209*43a90889SApple OSS Distributions break;
1210*43a90889SApple OSS Distributions }
1211*43a90889SApple OSS Distributions }
1212*43a90889SApple OSS Distributions
1213*43a90889SApple OSS Distributions uint16_t
nat464_cksum_fixup(uint16_t cksum,uint16_t old,uint16_t new,uint8_t udp)1214*43a90889SApple OSS Distributions nat464_cksum_fixup(uint16_t cksum, uint16_t old, uint16_t new, uint8_t udp)
1215*43a90889SApple OSS Distributions {
1216*43a90889SApple OSS Distributions uint32_t l;
1217*43a90889SApple OSS Distributions
1218*43a90889SApple OSS Distributions if (udp && !cksum) {
1219*43a90889SApple OSS Distributions return 0;
1220*43a90889SApple OSS Distributions }
1221*43a90889SApple OSS Distributions l = cksum + old - new;
1222*43a90889SApple OSS Distributions l = (l >> 16) + (l & 0xffff);
1223*43a90889SApple OSS Distributions l = l & 0xffff;
1224*43a90889SApple OSS Distributions if (udp && !l) {
1225*43a90889SApple OSS Distributions return 0xffff;
1226*43a90889SApple OSS Distributions }
1227*43a90889SApple OSS Distributions return (uint16_t)l;
1228*43a90889SApple OSS Distributions }
1229*43a90889SApple OSS Distributions
1230*43a90889SApple OSS Distributions /* CLAT46 event handlers */
1231*43a90889SApple OSS Distributions void
in6_clat46_eventhdlr_callback(struct eventhandler_entry_arg arg0 __unused,in6_clat46_evhdlr_code_t in6_clat46_ev_code,pid_t epid,uuid_t euuid)1232*43a90889SApple OSS Distributions in6_clat46_eventhdlr_callback(struct eventhandler_entry_arg arg0 __unused,
1233*43a90889SApple OSS Distributions in6_clat46_evhdlr_code_t in6_clat46_ev_code, pid_t epid, uuid_t euuid)
1234*43a90889SApple OSS Distributions {
1235*43a90889SApple OSS Distributions struct kev_msg ev_msg;
1236*43a90889SApple OSS Distributions struct kev_netevent_clat46_data clat46_event_data;
1237*43a90889SApple OSS Distributions
1238*43a90889SApple OSS Distributions bzero(&ev_msg, sizeof(ev_msg));
1239*43a90889SApple OSS Distributions bzero(&clat46_event_data, sizeof(clat46_event_data));
1240*43a90889SApple OSS Distributions
1241*43a90889SApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
1242*43a90889SApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
1243*43a90889SApple OSS Distributions ev_msg.kev_subclass = KEV_NETEVENT_SUBCLASS;
1244*43a90889SApple OSS Distributions ev_msg.event_code = KEV_NETEVENT_CLAT46_EVENT;
1245*43a90889SApple OSS Distributions
1246*43a90889SApple OSS Distributions bzero(&clat46_event_data, sizeof(clat46_event_data));
1247*43a90889SApple OSS Distributions clat46_event_data.clat46_event_code = in6_clat46_ev_code;
1248*43a90889SApple OSS Distributions clat46_event_data.epid = epid;
1249*43a90889SApple OSS Distributions uuid_copy(clat46_event_data.euuid, euuid);
1250*43a90889SApple OSS Distributions
1251*43a90889SApple OSS Distributions ev_msg.dv[0].data_ptr = &clat46_event_data;
1252*43a90889SApple OSS Distributions ev_msg.dv[0].data_length = sizeof(clat46_event_data);
1253*43a90889SApple OSS Distributions
1254*43a90889SApple OSS Distributions kev_post_msg(&ev_msg);
1255*43a90889SApple OSS Distributions }
1256*43a90889SApple OSS Distributions
1257*43a90889SApple OSS Distributions struct in6_clat46_event_nwk_wq_entry {
1258*43a90889SApple OSS Distributions struct nwk_wq_entry nwk_wqe;
1259*43a90889SApple OSS Distributions struct kev_netevent_clat46_data in6_clat46_ev_arg;
1260*43a90889SApple OSS Distributions };
1261*43a90889SApple OSS Distributions
1262*43a90889SApple OSS Distributions static void
in6_clat46_event_callback(struct nwk_wq_entry * nwk_item)1263*43a90889SApple OSS Distributions in6_clat46_event_callback(struct nwk_wq_entry *nwk_item)
1264*43a90889SApple OSS Distributions {
1265*43a90889SApple OSS Distributions struct in6_clat46_event_nwk_wq_entry *p_ev;
1266*43a90889SApple OSS Distributions
1267*43a90889SApple OSS Distributions p_ev = __container_of(nwk_item,
1268*43a90889SApple OSS Distributions struct in6_clat46_event_nwk_wq_entry, nwk_wqe);
1269*43a90889SApple OSS Distributions
1270*43a90889SApple OSS Distributions EVENTHANDLER_INVOKE(&in6_clat46_evhdlr_ctxt, in6_clat46_event,
1271*43a90889SApple OSS Distributions p_ev->in6_clat46_ev_arg.clat46_event_code, p_ev->in6_clat46_ev_arg.epid,
1272*43a90889SApple OSS Distributions p_ev->in6_clat46_ev_arg.euuid);
1273*43a90889SApple OSS Distributions
1274*43a90889SApple OSS Distributions kfree_type(struct in6_clat46_event_nwk_wq_entry, p_ev);
1275*43a90889SApple OSS Distributions }
1276*43a90889SApple OSS Distributions
1277*43a90889SApple OSS Distributions void
in6_clat46_event_enqueue_nwk_wq_entry(in6_clat46_evhdlr_code_t in6_clat46_event_code,pid_t epid,uuid_t euuid)1278*43a90889SApple OSS Distributions in6_clat46_event_enqueue_nwk_wq_entry(in6_clat46_evhdlr_code_t in6_clat46_event_code,
1279*43a90889SApple OSS Distributions pid_t epid, uuid_t euuid)
1280*43a90889SApple OSS Distributions {
1281*43a90889SApple OSS Distributions struct in6_clat46_event_nwk_wq_entry *p_ev = NULL;
1282*43a90889SApple OSS Distributions
1283*43a90889SApple OSS Distributions p_ev = kalloc_type(struct in6_clat46_event_nwk_wq_entry,
1284*43a90889SApple OSS Distributions Z_WAITOK | Z_ZERO | Z_NOFAIL);
1285*43a90889SApple OSS Distributions
1286*43a90889SApple OSS Distributions p_ev->nwk_wqe.func = in6_clat46_event_callback;
1287*43a90889SApple OSS Distributions p_ev->in6_clat46_ev_arg.clat46_event_code = in6_clat46_event_code;
1288*43a90889SApple OSS Distributions p_ev->in6_clat46_ev_arg.epid = epid;
1289*43a90889SApple OSS Distributions uuid_copy(p_ev->in6_clat46_ev_arg.euuid, euuid);
1290*43a90889SApple OSS Distributions
1291*43a90889SApple OSS Distributions evhlog(debug, "%s: eventhandler enqueuing event of type=in6_clat46_event event_code=%s",
1292*43a90889SApple OSS Distributions __func__, in6_clat46_evhdlr_code2str(in6_clat46_event_code));
1293*43a90889SApple OSS Distributions
1294*43a90889SApple OSS Distributions nwk_wq_enqueue(&p_ev->nwk_wqe);
1295*43a90889SApple OSS Distributions }
1296*43a90889SApple OSS Distributions
1297*43a90889SApple OSS Distributions extern const char*
in6_clat46_evhdlr_code2str(enum in6_clat46_evhdlr_code_t code)1298*43a90889SApple OSS Distributions in6_clat46_evhdlr_code2str(enum in6_clat46_evhdlr_code_t code)
1299*43a90889SApple OSS Distributions {
1300*43a90889SApple OSS Distributions switch (code) {
1301*43a90889SApple OSS Distributions #define CLAT46_CODE_TO_STRING(type) case type: return #type;
1302*43a90889SApple OSS Distributions CLAT46_CODE_TO_STRING(IN6_CLAT46_EVENT_V4_FLOW)
1303*43a90889SApple OSS Distributions CLAT46_CODE_TO_STRING(IN6_CLAT46_EVENT_V6_ADDR_CONFFAIL)
1304*43a90889SApple OSS Distributions #undef CLAT46_CODE_TO_STRING
1305*43a90889SApple OSS Distributions }
1306*43a90889SApple OSS Distributions return "UNKNOWN_IN6_CLAT46_EVHDLR_CODE";
1307*43a90889SApple OSS Distributions }
1308