]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/natpt_trans.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netinet6 / natpt_trans.c
CommitLineData
1c79356b
A
1/* $KAME: natpt_trans.c,v 1.12 2000/03/25 07:23:56 sumikawa Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/malloc.h>
34#include <sys/mbuf.h>
35#include <sys/socket.h>
36#include <sys/syslog.h>
37#include <sys/systm.h>
38
39#ifdef __FreeBSD__
40# include <sys/kernel.h>
41#endif
42
43#include <net/if.h>
44#ifdef __bsdi__
45#include <net/route.h>
46#endif
47
48#include <netinet/in_systm.h>
49#include <netinet/in.h>
50#include <netinet/ip.h>
51
52#if defined(__bsdi__) || defined(__NetBSD__)
53#include <net/route.h> /* netinet/in_pcb.h line 71 make happy. */
54#include <netinet/in_pcb.h>
55#endif
56
57#include <netinet/ip_icmp.h>
58#include <netinet/ip_var.h>
59#include <netinet/ip6.h>
60#include <netinet/tcp.h>
61#include <netinet/tcpip.h>
62#include <netinet/tcp_fsm.h>
63#include <netinet/udp.h>
64#include <netinet/udp_var.h>
65
66#include <netinet/ip6.h>
67#include <netinet/icmp6.h>
68#if !defined(__NetBSD__) && (!defined(__FreeBSD__) || (__FreeBSD__ < 3)) && !defined(__APPLE__)
69#include <netinet6/tcp6.h>
70#endif
71
72#include <netinet6/natpt_defs.h>
73#include <netinet6/natpt_list.h>
74#include <netinet6/natpt_var.h>
75
76
77#define recalculateTCP4Checksum 1
78#define recalculateTCP6Checksum 1
79
80
81/*
82 *
83 */
84
85int errno;
86int natpt_initialized;
87int ip6_protocol_tr;
88
89extern struct in6_addr natpt_prefix;
90extern struct in6_addr natpt_prefixmask;
91
92struct mbuf *translatingTCPUDPv4To4 __P((struct _cv *, struct pAddr *, struct _cv *));
93
94void tr_icmp4EchoReply __P((struct _cv *, struct _cv *));
95void tr_icmp4Unreach __P((struct _cv *, struct _cv *, struct pAddr *));
96void tr_icmp4Echo __P((struct _cv *, struct _cv *));
97void tr_icmp4Timxceed __P((struct _cv *, struct _cv *, struct pAddr *));
98void tr_icmp4Paramprob __P((struct _cv *, struct _cv *));
99void tr_icmp4MimicPayload __P((struct _cv *, struct _cv *, struct pAddr *));
100
101void tr_icmp6DstUnreach __P((struct _cv *, struct _cv *));
102void tr_icmp6PacketTooBig __P((struct _cv *, struct _cv *));
103void tr_icmp6TimeExceed __P((struct _cv *, struct _cv *));
104void tr_icmp6ParamProb __P((struct _cv *, struct _cv *));
105void tr_icmp6EchoRequest __P((struct _cv *, struct _cv *));
106void tr_icmp6EchoReply __P((struct _cv *, struct _cv *));
107
108static void _recalculateTCP4Checksum __P((struct _cv *));
109
110static int updateTcpStatus __P((struct _cv *));
111static int _natpt_tcpfsm __P((int, int, u_short, u_char));
112static int _natpt_tcpfsmSessOut __P((int, short, u_char));
113static int _natpt_tcpfsmSessIn __P((int, short, u_char));
114
115static void adjustUpperLayerChecksum __P((int, int, struct _cv *, struct _cv *));
116static int adjustChecksum __P((int, u_char *, int, u_char *, int));
117
118
119#if defined(__FreeBSD__) && __FreeBSD__ >= 3
120static MALLOC_DEFINE(M_NATPT, "NATPT", "Network Address Translation - Protocol Translation");
121#endif
122
123
124#ifdef NATPT_NAT
125/*
126 * Translating From IPv4 to IPv4
127 */
128
129struct mbuf *
130translatingIPv4To4(struct _cv *cv4, struct pAddr *pad)
131{
132 struct timeval atv;
133 struct mbuf *m4 = NULL;
134
135 if (isDump(D_TRANSLATINGIPV4))
136 natpt_logIp4(LOG_DEBUG, cv4->_ip._ip4);
137
138 microtime(&atv);
139 cv4->ats->tstamp = atv.tv_sec;
140
141 switch (cv4->ip_payload)
142 {
143 case IPPROTO_ICMP:
144 m4 = translatingICMPv4To4(cv4, pad);
145 break;
146
147 case IPPROTO_TCP:
148 m4 = translatingTCPv4To4(cv4, pad);
149 break;
150
151 case IPPROTO_UDP:
152 m4 = translatingUDPv4To4(cv4, pad);
153 break;
154 }
155
156 if (m4)
157 {
158 struct ip *ip4;
159
160 ip4 = mtod(m4, struct ip *);
161 ip4->ip_sum = 0; /* Header checksum */
162 ip4->ip_sum = in_cksum(m4, sizeof(struct ip));
163 m4->m_pkthdr.rcvif = cv4->m->m_pkthdr.rcvif;
164
165 m4->m_pkthdr.len = cv4->m->m_pkthdr.len;
166 }
167
168 return (m4);
169}
170
171
172struct mbuf *
173translatingICMPv4To4(struct _cv *cv4from, struct pAddr *pad)
174{
175 struct _cv cv4to;
176 struct mbuf *m4;
177 struct ip *ip4from, *ip4to;
178 struct icmp *icmp4from;
179
180 ip4from = mtod(cv4from->m, struct ip *);
181 icmp4from = cv4from->_payload._icmp4;
182
183 m4 = m_copym(cv4from->m,0, M_COPYALL, M_NOWAIT);
184 ReturnEnobufs(m4);
185
186 bzero(&cv4to, sizeof(struct _cv));
187 cv4to.m = m4;
188 cv4to._ip._ip4 = ip4to = mtod(m4, struct ip *);
189 cv4to._payload._caddr = (caddr_t)cv4to._ip._ip4 + (ip4from->ip_hl << 2);
190
191 ip4to->ip_src = pad->in4src; /* source address */
192 ip4to->ip_dst = pad->in4dst; /* destination address */
193
194 switch (icmp4from->icmp_type)
195 {
196 case ICMP_ECHOREPLY:
197 case ICMP_ECHO:
198 break;
199
200 default:
201 m_freem(m4);
202 return (NULL);
203 }
204
205 m4->m_len = cv4from->m->m_len;
206 return (m4);
207}
208
209
210struct mbuf *
211translatingTCPv4To4(struct _cv *cv4from, struct pAddr *pad)
212{
213 struct _cv cv4to;
214 struct mbuf *m4;
215
216 bzero(&cv4to, sizeof(struct _cv));
217 m4 = translatingTCPUDPv4To4(cv4from, pad, &cv4to);
218 cv4to.ip_p = cv4to.ip_payload = IPPROTO_TCP;
219
220 updateTcpStatus(&cv4to);
221 adjustUpperLayerChecksum(IPPROTO_IPV4, IPPROTO_TCP, cv4from, &cv4to);
222
223#ifdef recalculateTCP4Checksum
224 _recalculateTCP4Checksum(&cv4to);
225#endif
226
227 return (m4);
228}
229
230
231struct mbuf *
232translatingUDPv4To4(struct _cv *cv4from, struct pAddr *pad)
233{
234 struct _cv cv4to;
235 struct mbuf *m4;
236
237 bzero(&cv4to, sizeof(struct _cv));
238 m4 = translatingTCPUDPv4To4(cv4from, pad, &cv4to);
239 cv4to.ip_p = cv4to.ip_payload = IPPROTO_UDP;
240
241 adjustUpperLayerChecksum(IPPROTO_IPV4, IPPROTO_UDP, cv4from, &cv4to);
242
243 return (m4);
244}
245
246
247struct mbuf *
248translatingTCPUDPv4To4(struct _cv *cv4from, struct pAddr *pad, struct _cv *cv4to)
249{
250 struct mbuf *m4;
251 struct ip *ip4to;
252 struct tcphdr *tcp4to;
253
254 m4 = m_copym(cv4from->m,0, M_COPYALL, M_NOWAIT);
255 ReturnEnobufs(m4);
256
257 ip4to = mtod(m4, struct ip *);
258
259 ip4to->ip_src = pad->in4src;
260 ip4to->ip_dst = pad->in4dst;
261
262 tcp4to = (struct tcphdr *)((caddr_t)ip4to + (ip4to->ip_hl << 2));
263 tcp4to->th_sport = pad->_sport;
264 tcp4to->th_dport = pad->_dport;
265
266 cv4to->m = m4;
267 cv4to->_ip._ip4 = ip4to;
268 cv4to->_payload._tcp4 = tcp4to;
269 cv4to->ats = cv4from->ats;
270
271 return (m4);
272}
273
274#endif /* ifdef NATPT_NAT */
275
276
277/*
278 * Translating From IPv4 To IPv6
279 */
280
281struct mbuf *
282translatingIPv4To6(struct _cv *cv4, struct pAddr *pad)
283{
284 struct timeval atv;
285 struct mbuf *m6 = NULL;
286
287 if (isDump(D_TRANSLATINGIPV4))
288 natpt_logIp4(LOG_DEBUG, cv4->_ip._ip4);
289
290 microtime(&atv);
291 cv4->ats->tstamp = atv.tv_sec;
292
293 switch (cv4->ip_payload)
294 {
295 case IPPROTO_ICMP:
296 m6 = translatingICMPv4To6(cv4, pad);
297 break;
298
299 case IPPROTO_TCP:
300 m6 = translatingTCPv4To6(cv4, pad);
301 break;
302
303 case IPPROTO_UDP:
304 m6 = translatingUDPv4To6(cv4, pad);
305 break;
306 }
307
308 if (m6)
309 m6->m_pkthdr.rcvif = cv4->m->m_pkthdr.rcvif;
310
311 return (m6);
312}
313
314
315struct mbuf *
316translatingICMPv4To6(struct _cv *cv4, struct pAddr *pad)
317{
318 struct _cv cv6;
319 struct mbuf *m6;
320 struct ip *ip4;
321 struct ip6_hdr *ip6;
322 struct icmp *icmp4;
323 struct icmp6_hdr *icmp6;
324
325 ip4 = mtod(cv4->m, struct ip *);
326 icmp4 = cv4->_payload._icmp4;
327
328 {
329 caddr_t icmp4end;
330 int icmp4len;
331
332 icmp4end = (caddr_t)ip4 + cv4->m->m_pkthdr.len;
333 icmp4len = icmp4end - (caddr_t)cv4->_payload._icmp4;
334
335 MGETHDR(m6, M_NOWAIT, MT_HEADER);
336 if (m6 == NULL)
337 {
338 errno = ENOBUFS;
339 return (NULL);
340 }
341 if (MHLEN < (sizeof(struct ip6_hdr) + icmp4len))
342 MCLGET(m6, M_NOWAIT);
343 }
344
345 cv6.m = m6;
346 cv6._ip._ip6 = mtod(m6, struct ip6_hdr *);
347 cv6._payload._caddr = (caddr_t)cv6._ip._ip6 + sizeof(struct ip6_hdr);
348
349 ip6 = mtod(cv6.m, struct ip6_hdr *);
350 icmp6 = cv6._payload._icmp6;;
351
352 ip6->ip6_flow = 0;
353 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
354 ip6->ip6_vfc |= IPV6_VERSION;
355 ip6->ip6_plen = 0; /* XXX */
356 ip6->ip6_nxt = IPPROTO_ICMPV6;
357 ip6->ip6_hlim = ip4->ip_ttl -1;
358 ip6->ip6_dst = pad->in6dst;
359 ip6->ip6_src = pad->in6src;
360 if (natpt_prefix.s6_addr32[0] != 0)
361 {
362 ip6->ip6_src.s6_addr32[0] = natpt_prefix.s6_addr32[0];
363 ip6->ip6_src.s6_addr32[1] = natpt_prefix.s6_addr32[1];
364 ip6->ip6_src.s6_addr32[2] = natpt_prefix.s6_addr32[2];
365 }
366 else
367 {
368 ip6->ip6_src.s6_addr32[0] = 0;
369 ip6->ip6_src.s6_addr32[1] = 0;
370 ip6->ip6_src.s6_addr32[2] = 0;
371 }
372 ip6->ip6_src.s6_addr32[3] = ip4->ip_src.s_addr;
373
374 switch (icmp4->icmp_type)
375 {
376 case ICMP_ECHOREPLY:
377 tr_icmp4EchoReply(cv4, &cv6);
378 break;
379
380 case ICMP_UNREACH:
381 tr_icmp4Unreach(cv4, &cv6, pad);
382 break;
383
384 case ICMP_ECHO:
385 tr_icmp4Echo(cv4, &cv6);
386 break;
387
388 case ICMP_TIMXCEED:
389 tr_icmp4Timxceed(cv4, &cv6, pad);
390 break;
391
392 case ICMP_PARAMPROB:
393 tr_icmp4Paramprob(cv4, &cv6);
394 break;
395
396 case ICMP_REDIRECT:
397 case ICMP_ROUTERADVERT:
398 case ICMP_ROUTERSOLICIT:
399 m_freem(m6); /* Single hop message. Silently drop. */
400 return (NULL);
401
402 case ICMP_SOURCEQUENCH:
403 case ICMP_TSTAMP:
404 case ICMP_TSTAMPREPLY:
405 case ICMP_IREQ:
406 case ICMP_IREQREPLY:
407 case ICMP_MASKREQ:
408 case ICMP_MASKREPLY:
409 m_freem(m6); /* Obsoleted in ICMPv6. Silently drop. */
410 return (NULL);
411
412 default:
413 m_freem(m6); /* Silently drop. */
414 return (NULL);
415 }
416
417 icmp6->icmp6_cksum = 0;
418 icmp6->icmp6_cksum = in6_cksum(cv6.m, IPPROTO_ICMPV6,
419 sizeof(struct ip6_hdr), ntohs(ip6->ip6_plen));
420
421 return (m6);
422}
423
424
425void
426tr_icmp4EchoReply(struct _cv *cv4, struct _cv *cv6)
427{
428 struct icmp *icmp4 = cv4->_payload._icmp4;
429 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
430
431 icmp6->icmp6_type = ICMP6_ECHO_REPLY;
432 icmp6->icmp6_code = 0;
433 icmp6->icmp6_id = icmp4->icmp_id;
434 icmp6->icmp6_seq = icmp4->icmp_seq;
435
436 {
437 int dlen;
438 struct ip *ip4 = cv4->_ip._ip4;
439 struct ip6_hdr *ip6 = cv6->_ip._ip6;
440 caddr_t icmp4off, icmp6off;
441 caddr_t icmp4end = (caddr_t)ip4 + cv4->m->m_pkthdr.len;
442 int icmp4len = icmp4end - (caddr_t)cv4->_payload._icmp4;
443
444 dlen = icmp4len - ICMP_MINLEN;
445 icmp4off = (caddr_t)(cv4->_payload._icmp4) + ICMP_MINLEN;
446 icmp6off = (caddr_t)(cv6->_payload._icmp6) + sizeof(struct icmp6_hdr);
447 bcopy(icmp4off, icmp6off, dlen);
448
449 ip6->ip6_plen = ntohs(sizeof(struct icmp6_hdr) + dlen);
450 cv6->m->m_pkthdr.len
451 = cv6->m->m_len
452 = sizeof(struct ip6_hdr) + htons(ip6->ip6_plen);
453 }
454}
455
456
457void
458tr_icmp4Unreach(struct _cv *cv4, struct _cv *cv6, struct pAddr *pad)
459{
460 struct icmp *icmp4 = cv4->_payload._icmp4;
461 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
462
463 icmp6->icmp6_type = ICMP6_DST_UNREACH;
464 icmp6->icmp6_code = 0;
465 icmp6->icmp6_id = icmp4->icmp_id;
466 icmp6->icmp6_seq = icmp4->icmp_seq;
467
468 switch (icmp4->icmp_code)
469 {
470 case ICMP_UNREACH_NET:
471 case ICMP_UNREACH_HOST:
472 icmp6->icmp6_code = ICMP6_DST_UNREACH_NOROUTE;
473 break;
474
475 case ICMP_UNREACH_PROTOCOL: /* do more */
476 icmp6->icmp6_type = ICMP6_PARAM_PROB;
477 icmp6->icmp6_code = ICMP6_PARAMPROB_NEXTHEADER; /* xxx */
478 break;
479
480 case ICMP_UNREACH_PORT:
481 icmp6->icmp6_code = ICMP6_DST_UNREACH_NOPORT;
482 break;
483
484 case ICMP_UNREACH_NEEDFRAG: /* do more */
485 icmp6->icmp6_type = ICMP6_PACKET_TOO_BIG;
486 icmp6->icmp6_code = ICMP6_PARAMPROB_HEADER;
487 break;
488
489 case ICMP_UNREACH_SRCFAIL:
490 icmp6->icmp6_code = ICMP6_DST_UNREACH_NOTNEIGHBOR;
491 break;
492
493 case ICMP_UNREACH_NET_UNKNOWN:
494 case ICMP_UNREACH_HOST_UNKNOWN:
495 icmp6->icmp6_code = ICMP6_DST_UNREACH_NOROUTE;
496 break;
497
498 case ICMP_UNREACH_ISOLATED:
499 icmp6->icmp6_code = ICMP6_DST_UNREACH_NOROUTE;
500 break;
501
502 case ICMP_UNREACH_NET_PROHIB:
503 case ICMP_UNREACH_HOST_PROHIB:
504 icmp6->icmp6_code = ICMP6_DST_UNREACH_ADMIN;
505 break;
506
507 case ICMP_UNREACH_TOSNET:
508 case ICMP_UNREACH_TOSHOST:
509 icmp6->icmp6_code = ICMP6_DST_UNREACH_NOROUTE;
510 break;
511
512 default:
513 break;
514 }
515
516 tr_icmp4MimicPayload(cv4, cv6, pad);
517}
518
519
520void
521tr_icmp4Echo(struct _cv *cv4, struct _cv *cv6)
522{
523 struct icmp *icmp4 = cv4->_payload._icmp4;
524 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
525
526 icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
527 icmp6->icmp6_code = 0;
528 icmp6->icmp6_id = icmp4->icmp_id;
529 icmp6->icmp6_seq = icmp4->icmp_seq;
530
531 {
532 int dlen;
533 struct ip *ip4 = cv4->_ip._ip4;
534 struct ip6_hdr *ip6 = cv6->_ip._ip6;
535 caddr_t icmp4off, icmp6off;
536 caddr_t icmp4end = (caddr_t)ip4 + cv4->m->m_pkthdr.len;
537 int icmp4len = icmp4end - (caddr_t)cv4->_payload._icmp4;
538
539 dlen = icmp4len - ICMP_MINLEN;
540 icmp4off = (caddr_t)(cv4->_payload._icmp4) + ICMP_MINLEN;
541 icmp6off = (caddr_t)(cv6->_payload._icmp6) + sizeof(struct icmp6_hdr);
542 bcopy(icmp4off, icmp6off, dlen);
543
544 ip6->ip6_plen = ntohs(sizeof(struct icmp6_hdr) + dlen);
545 cv6->m->m_pkthdr.len
546 = cv6->m->m_len
547 = sizeof(struct ip6_hdr) + htons(ip6->ip6_plen);
548 }
549}
550
551
552void
553tr_icmp4Timxceed(struct _cv *cv4, struct _cv *cv6, struct pAddr *pad)
554{
555 struct icmp *icmp4 = cv4->_payload._icmp4;
556 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
557
558 icmp6->icmp6_type = ICMP6_TIME_EXCEEDED;
559 icmp6->icmp6_code = 0;
560 icmp6->icmp6_id = icmp4->icmp_id;
561 icmp6->icmp6_seq = icmp4->icmp_seq;
562
563 tr_icmp4MimicPayload(cv4, cv6, pad);
564}
565
566
567void
568tr_icmp4Paramprob(struct _cv *cv4, struct _cv *cv6)
569{
570 struct icmp *icmp4 = cv4->_payload._icmp4;
571 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
572
573 icmp6->icmp6_type = ICMP6_PARAM_PROB;
574 icmp6->icmp6_code = 0;
575 icmp6->icmp6_id = icmp4->icmp_id;
576 icmp6->icmp6_seq = icmp4->icmp_seq;
577}
578
579
580void
581tr_icmp4MimicPayload(struct _cv *cv4, struct _cv *cv6, struct pAddr *pad)
582{
583 int dgramlen;
584 int icmp6dlen, icmp6rest;
585 struct ip *ip4 = cv6->_ip._ip4;
586 struct ip6_hdr *ip6 = cv6->_ip._ip6;
587 struct ip6_hdr *icmpip6;
588 caddr_t icmp4off, icmp4dgramoff;
589 caddr_t icmp6off, icmp6dgramoff;
590 caddr_t icmp4end = (caddr_t)ip4 + cv4->m->m_pkthdr.len;
591 int icmp4len = icmp4end - (caddr_t)cv4->_payload._icmp4;
592
593 icmp6rest = MHLEN - sizeof(struct ip6_hdr) * 2 - sizeof(struct icmp6_hdr);
594 dgramlen = icmp4len - ICMP_MINLEN - sizeof(struct ip);
595 dgramlen = min(icmp6rest, dgramlen);
596
597 icmp4off = (caddr_t)(cv4->_payload._icmp4) + ICMP_MINLEN;
598 icmp6off = (caddr_t)(cv6->_payload._icmp6) + sizeof(struct icmp6_hdr);
599 icmp4dgramoff = icmp4off + sizeof(struct ip);
600 icmp6dgramoff = icmp6off + sizeof(struct ip6_hdr);
601
602 icmpip6 = (struct ip6_hdr *)icmp6off;
603 bzero(icmpip6, sizeof(struct ip6_hdr));
604 bcopy(icmp4dgramoff, icmp6dgramoff, dgramlen);
605
606 icmpip6->ip6_flow = 0;
607 icmpip6->ip6_vfc &= ~IPV6_VERSION_MASK;
608 icmpip6->ip6_vfc |= IPV6_VERSION;
609 icmpip6->ip6_plen = 0;
610 icmpip6->ip6_nxt = IPPROTO_UDP;
611 icmpip6->ip6_hlim = 0;
612 icmpip6->ip6_src = pad->in6dst;
613 icmpip6->ip6_dst = pad->in6src;
614
615 icmp6dlen = sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr) + dgramlen;
616 ip6->ip6_plen = ntohs(icmp6dlen);
617 cv6->m->m_pkthdr.len
618 = cv6->m->m_len
619 = sizeof(struct ip6_hdr) + htons(ip6->ip6_plen);
620
621 if (cv4->flags & NATPT_TRACEROUTE)
622 {
623 struct udphdr *icmpudp6;
624
625 icmpudp6 = (struct udphdr *)((caddr_t)icmpip6 + sizeof(struct ip6_hdr));
626 icmpudp6->uh_sport = cv4->ats->local._dport;
627 icmpudp6->uh_dport = cv4->ats->local._sport;
628 }
629}
630
631
632struct mbuf *
633translatingTCPv4To6(struct _cv *cv4, struct pAddr *pad)
634{
635 int cksumOrg;
636 struct _cv cv6;
637 struct mbuf *m6;
638
639 bzero(&cv6, sizeof(struct _cv));
640 m6 = translatingTCPUDPv4To6(cv4, pad, &cv6);
641 cv6.ip_p = cv6.ip_payload = IPPROTO_TCP;
642 cksumOrg = ntohs(cv4->_payload._tcp4->th_sum);
643
644 updateTcpStatus(cv4);
645 adjustUpperLayerChecksum(IPPROTO_IPV4, IPPROTO_TCP, &cv6, cv4);
646
647#ifdef recalculateTCP6Checksum
648 {
649 int cksumAdj, cksumCks;
650 struct tcp6hdr *th;
651
652 cksumAdj = cv6._payload._tcp6->th_sum;
653
654 th = cv6._payload._tcp6;
655 th->th_sum = 0;
656 th->th_sum = in6_cksum(cv6.m, IPPROTO_TCP, sizeof(struct ip6_hdr),
657 cv6.m->m_pkthdr.len - sizeof(struct ip6_hdr));
658
659 cksumCks = th->th_sum;
660#if 0
661 printf("translatingTCPv4To6: TCP4->TCP6: %04x, %04x, %04x %d\n",
662 cksumOrg, cksumAdj, cksumCks, cv6.m->m_pkthdr.len);
663#endif
664 }
665#endif
666
667 return (m6);
668}
669
670
671struct mbuf *
672translatingUDPv4To6(struct _cv *cv4, struct pAddr *pad)
673{
674 struct _cv cv6;
675 struct mbuf *m6;
676
677 bzero(&cv6, sizeof(struct _cv));
678 m6 = translatingTCPUDPv4To6(cv4, pad, &cv6);
679 cv6.ip_p = cv6.ip_payload = IPPROTO_UDP;
680
681 return (m6);
682}
683
684
685struct mbuf *
686translatingTCPUDPv4To6(struct _cv *cv4, struct pAddr *pad, struct _cv *cv6)
687{
688 struct mbuf *m6;
689 struct ip *ip4;
690 struct ip6_hdr *ip6;
691 struct tcp6hdr *tcp6;
692
693 if (cv4->m->m_flags & M_EXT)
694 {
695 if (cv4->plen + sizeof(struct ip6_hdr) > MHLEN)
696 {
697 struct mbuf *m6next;
698
699 m6next = m_copym(cv4->m, 0, M_COPYALL, M_NOWAIT);
700 ReturnEnobufs(m6next);
701
702 m6next->m_data += cv4->poff;
703 m6next->m_len -= cv4->poff;
704
705 MGETHDR(m6, M_NOWAIT, MT_HEADER);
706 ReturnEnobufs(m6);
707
708 m6->m_next = m6next;
709 m6->m_data += (MHLEN - sizeof(struct ip6_hdr));
710 m6->m_len = sizeof(struct ip6_hdr);
711 m6->m_pkthdr.len = sizeof(struct ip6_hdr) + cv4->plen;
712 ip6 = mtod(m6, struct ip6_hdr *);
713
714 cv6->m = m6;
715 cv6->_ip._ip6 = mtod(m6, struct ip6_hdr *);
716 cv6->_payload._caddr = m6next->m_data;
717 cv6->plen = cv4->plen;
718 cv6->poff = 0;
719 }
720 else /* (sizeof(struct ip6_hdr) + cv4->plen <= MHLEN) */
721 {
722 caddr_t tcp4;
723 caddr_t tcp6;
724
725 MGETHDR(m6, M_NOWAIT, MT_HEADER);
726 if (m6 == NULL)
727 {
728 errno = ENOBUFS;
729 return (NULL);
730 }
731
732 ip6 = mtod(m6, struct ip6_hdr *);
733 tcp4 = (caddr_t)cv4->_payload._tcp4;
734 tcp6 = (caddr_t)ip6 + sizeof(struct ip6_hdr);
735 bcopy(tcp4, tcp6, cv4->plen);
736
737 m6->m_pkthdr.len
738 = m6->m_len
739 = sizeof(struct ip6_hdr) + cv4->plen;
740
741 cv6->m = m6;
742 cv6->_ip._ip6 = mtod(m6, struct ip6_hdr *);
743 cv6->_payload._caddr = (caddr_t)cv6->_ip._ip6 + sizeof(struct ip6_hdr);
744 cv6->plen = cv4->plen;
745 cv6->poff = cv6->_payload._caddr - (caddr_t)cv6->_ip._ip6;
746 }
747 }
748 else if (cv4->plen + sizeof(struct ip6_hdr) > MHLEN)
749 {
750 caddr_t tcp4;
751 caddr_t tcp6;
752
753 MGETHDR(m6, M_NOWAIT, MT_HEADER);
754 ReturnEnobufs(m6);
755 MCLGET(m6, M_NOWAIT);
756
757 m6->m_data += 128; /* make struct ether_header{} space. -- too many? */
758 m6->m_pkthdr.len = m6->m_len = sizeof(struct ip6_hdr) + cv4->plen;
759 ip6 = mtod(m6, struct ip6_hdr *);
760
761 tcp4 = (caddr_t)cv4->_payload._tcp4;
762 tcp6 = (caddr_t)ip6 + sizeof(struct ip6_hdr);
763 bcopy(tcp4, tcp6, cv4->plen);
764
765 cv6->m = m6;
766 cv6->_ip._ip6 = mtod(m6, struct ip6_hdr *);
767 cv6->_payload._caddr = tcp6;
768 cv6->plen = cv4->plen;
769 cv6->poff = cv6->_payload._caddr - (caddr_t)cv6->_ip._ip6;
770 }
771 else
772 {
773 caddr_t tcp4;
774 caddr_t tcp6;
775
776 MGETHDR(m6, M_NOWAIT, MT_HEADER);
777 if (m6 == NULL)
778 {
779 errno = ENOBUFS;
780 return (NULL);
781 }
782
783 cv6->m = m6;
784 ip6 = mtod(m6, struct ip6_hdr *);
785 tcp4 = (caddr_t)cv4->_payload._tcp4;
786 tcp6 = (caddr_t)ip6 + sizeof(struct ip6_hdr);
787 bcopy(tcp4, tcp6, cv4->plen);
788
789 m6->m_pkthdr.len
790 = m6->m_len
791 = sizeof(struct ip6_hdr) + cv4->plen;
792
793 cv6->_ip._ip6 = mtod(m6, struct ip6_hdr *);
794 cv6->_payload._caddr = (caddr_t)cv6->_ip._ip6 + sizeof(struct ip6_hdr);
795 cv6->plen = cv4->plen;
796 cv6->poff = cv6->_payload._caddr - (caddr_t)cv6->_ip._ip6;
797 }
798
799 cv6->ats = cv4->ats;
800
801 ip4 = mtod(cv4->m, struct ip *);
802 ip6->ip6_flow = 0;
803 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
804 ip6->ip6_vfc |= IPV6_VERSION;
805 ip6->ip6_plen = htons(cv4->plen);
806 ip6->ip6_nxt = IPPROTO_TCP;
807 ip6->ip6_hlim = ip4->ip_ttl -1;
808 ip6->ip6_src = pad->in6src;
809 ip6->ip6_dst = pad->in6dst;
810
811 tcp6 = cv6->_payload._tcp6;
812 tcp6->th_sport = pad->_sport;
813 tcp6->th_dport = pad->_dport;
814
815 return (m6);
816}
817
818
819/*
820 * Translating Form IPv6 To IPv4
821 */
822
823struct mbuf *
824translatingIPv6To4(struct _cv *cv6, struct pAddr *pad)
825{
826 struct timeval atv;
827 struct mbuf *m4 = NULL;
828
829 if (isDump(D_TRANSLATINGIPV6))
830 natpt_logIp6(LOG_DEBUG, cv6->_ip._ip6);
831
832 microtime(&atv);
833 cv6->ats->tstamp = atv.tv_sec;
834
835 switch (cv6->ip_payload)
836 {
837 case IPPROTO_ICMP:
838 m4 = translatingICMPv6To4(cv6, pad);
839 break;
840
841 case IPPROTO_TCP:
842 m4 = translatingTCPv6To4(cv6, pad);
843 break;
844
845 case IPPROTO_UDP:
846 m4 = translatingUDPv6To4(cv6, pad);
847 break;
848 }
849
850 if (m4)
851 {
852 int mlen;
853 struct mbuf *mm;
854 struct ip *ip4;
855
856 ip4 = mtod(m4, struct ip *);
857 ip4->ip_sum = 0; /* Header checksum */
858 ip4->ip_sum = in_cksum(m4, sizeof(struct ip));
859 m4->m_pkthdr.rcvif = cv6->m->m_pkthdr.rcvif;
860
861 for (mlen = 0, mm = m4; mm; mm = mm->m_next)
862 {
863 mlen += mm->m_len;
864 }
865
866 m4->m_pkthdr.len = mlen;
867
868 if (isDump(D_TRANSLATEDIPV4))
869 natpt_logIp4(LOG_DEBUG, ip4);
870 }
871
872 return (m4);
873}
874
875
876struct mbuf *
877translatingICMPv6To4(struct _cv *cv6, struct pAddr *pad)
878{
879 struct _cv cv4;
880 struct mbuf *m4;
881 struct ip *ip4;
882 struct ip6_hdr *ip6;
883 struct icmp *icmp4;
884 struct icmp6_hdr *icmp6;
885
886 ip6 = mtod(cv6->m, struct ip6_hdr *);
887 icmp6 = cv6->_payload._icmp6;
888
889 {
890 caddr_t icmp6end = (caddr_t)ip6 + cv6->m->m_pkthdr.len;
891 int icmp6len = icmp6end - (caddr_t)cv6->_payload._icmp6;
892
893 MGETHDR(m4, M_NOWAIT, MT_HEADER);
894 if (m4 == NULL)
895 {
896 errno = ENOBUFS;
897 return (NULL);
898 }
899 if (MHLEN < (sizeof(struct ip) + icmp6len))
900 MCLGET(m4, M_NOWAIT);
901 }
902
903 cv4.m = m4;
904 cv4._ip._ip4 = mtod(m4, struct ip *);
905 cv4._payload._caddr = (caddr_t)cv4._ip._ip4 + sizeof(struct ip);
906
907 ip4 = mtod(cv4.m, struct ip *);
908 icmp4 = cv4._payload._icmp4;
909
910 ip4->ip_v = IPVERSION; /* IP version */
911 ip4->ip_hl = 5; /* header length (no IPv4 option) */
912 ip4->ip_tos = 0; /* Type Of Service */
913 ip4->ip_len = htons(ip6->ip6_plen); /* Payload length */
914 ip4->ip_id = 0; /* Identification */
915 ip4->ip_off = 0; /* flag and fragment offset */
916 ip4->ip_ttl = ip6->ip6_hlim - 1; /* Time To Live */
917 ip4->ip_p = cv6->ip_payload; /* Final Payload */
918 ip4->ip_src = pad->in4src; /* source addresss */
919 ip4->ip_dst = pad->in4dst; /* destination address */
920
921 switch (icmp6->icmp6_type)
922 {
923 case ICMP6_DST_UNREACH:
924 tr_icmp6DstUnreach(cv6, &cv4);
925 break;
926
927 case ICMP6_PACKET_TOO_BIG:
928 tr_icmp6PacketTooBig(cv6, &cv4);
929 break;
930
931 case ICMP6_TIME_EXCEEDED:
932 tr_icmp6TimeExceed(cv6, &cv4);
933 break;
934
935 case ICMP6_PARAM_PROB:
936 tr_icmp6ParamProb(cv6, &cv4);
937 break;
938
939 case ICMP6_ECHO_REQUEST:
940 tr_icmp6EchoRequest(cv6, &cv4);
941 break;
942
943 case ICMP6_ECHO_REPLY:
944 tr_icmp6EchoReply(cv6, &cv4);
945 break;
946
947 case MLD6_LISTENER_QUERY:
948 case MLD6_LISTENER_REPORT:
949 case MLD6_LISTENER_DONE:
950 m_freem(m4); /* Single hop message. Silently drop. */
951 return (NULL);
952
953 default:
954 m_freem(m4); /* Silently drop. */
955 return (NULL);
956 }
957
958 {
959 int hlen;
960 struct mbuf *m4 = cv4.m;
961 struct ip *ip4 = cv4._ip._ip4;
962
963 hlen = ip4->ip_hl << 2;
964 m4->m_data += hlen;
965 m4->m_len -= hlen;
966 icmp4->icmp_cksum = 0;
967 icmp4->icmp_cksum = in_cksum(cv4.m, ip4->ip_len - hlen);
968 m4->m_data -= hlen;
969 m4->m_len += hlen;
970 }
971
972 return (m4);
973}
974
975
976void
977tr_icmp6DstUnreach(struct _cv *cv6, struct _cv *cv4)
978{
979 struct icmp *icmp4 = cv4->_payload._icmp4;
980 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
981
982 icmp4->icmp_type = ICMP_UNREACH;
983 icmp4->icmp_code = 0;
984 icmp4->icmp_id = icmp6->icmp6_id;
985 icmp4->icmp_seq = icmp6->icmp6_seq;
986
987 switch (icmp6->icmp6_code)
988 {
989 case ICMP6_DST_UNREACH_NOROUTE:
990 icmp4->icmp_code = ICMP_UNREACH_HOST;
991 break;
992
993 case ICMP6_DST_UNREACH_ADMIN:
994 icmp4->icmp_code = ICMP_UNREACH_HOST_PROHIB;
995 break;
996
997 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
998 icmp4->icmp_code = ICMP_UNREACH_SRCFAIL;
999 break;
1000
1001 case ICMP6_DST_UNREACH_ADDR:
1002 icmp4->icmp_code = ICMP_UNREACH_HOST;
1003 break;
1004
1005 case ICMP6_DST_UNREACH_NOPORT:
1006 icmp4->icmp_code = ICMP_UNREACH_PORT;
1007 break;
1008 }
1009}
1010
1011
1012void
1013tr_icmp6PacketTooBig(struct _cv *cv6, struct _cv *cv4)
1014{
1015 struct icmp *icmp4 = cv4->_payload._icmp4;
1016 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
1017
1018 icmp4->icmp_type = ICMP_UNREACH;
1019 icmp4->icmp_code = ICMP_UNREACH_NEEDFRAG; /* do more */
1020 icmp4->icmp_id = icmp6->icmp6_id;
1021 icmp4->icmp_seq = icmp6->icmp6_seq;
1022}
1023
1024
1025void
1026tr_icmp6TimeExceed(struct _cv *cv6, struct _cv *cv4)
1027{
1028 struct icmp *icmp4 = cv4->_payload._icmp4;
1029 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
1030
1031 icmp4->icmp_type = ICMP_TIMXCEED;
1032 icmp4->icmp_code = icmp6->icmp6_code; /* code unchanged. */
1033 icmp4->icmp_id = icmp6->icmp6_id;
1034 icmp4->icmp_seq = icmp6->icmp6_seq;
1035}
1036
1037
1038void
1039tr_icmp6ParamProb(struct _cv *cv6, struct _cv *cv4)
1040{
1041 struct icmp *icmp4 = cv4->_payload._icmp4;
1042 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
1043
1044 icmp4->icmp_type = ICMP_PARAMPROB; /* do more */
1045 icmp4->icmp_code = 0;
1046 icmp4->icmp_id = icmp6->icmp6_id;
1047 icmp4->icmp_seq = icmp6->icmp6_seq;
1048
1049 if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER)
1050 {
1051 icmp4->icmp_type = ICMP_UNREACH;
1052 icmp4->icmp_code = ICMP_UNREACH_PROTOCOL;
1053 }
1054}
1055
1056
1057void
1058tr_icmp6EchoRequest(struct _cv *cv6, struct _cv *cv4)
1059{
1060 struct icmp *icmp4 = cv4->_payload._icmp4;
1061 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
1062
1063 icmp4->icmp_type = ICMP_ECHO;
1064 icmp4->icmp_code = 0;
1065 icmp4->icmp_id = icmp6->icmp6_id;
1066 icmp4->icmp_seq = icmp6->icmp6_seq;
1067
1068 {
1069 int dlen;
1070 struct ip *ip4 = cv4->_ip._ip4;
1071 struct ip6_hdr *ip6 = cv6->_ip._ip6;
1072 caddr_t icmp6off, icmp4off;
1073 caddr_t icmp6end = (caddr_t)ip6 + cv6->m->m_pkthdr.len;
1074 int icmp6len = icmp6end - (caddr_t)cv6->_payload._icmp6;
1075
1076 dlen = icmp6len - sizeof(struct icmp6_hdr);
1077 icmp6off = (caddr_t)(cv6->_payload._icmp6) + sizeof(struct icmp6_hdr);
1078 icmp4off = (caddr_t)(cv4->_payload._icmp4) + ICMP_MINLEN;
1079 bcopy(icmp6off, icmp4off, dlen);
1080
1081 ip4->ip_len = cv4->m->m_len = sizeof(struct ip) + ICMP_MINLEN + dlen;
1082 }
1083}
1084
1085
1086void
1087tr_icmp6EchoReply(struct _cv *cv6, struct _cv *cv4)
1088{
1089 struct icmp *icmp4 = cv4->_payload._icmp4;
1090 struct icmp6_hdr *icmp6 = cv6->_payload._icmp6;
1091
1092 icmp4->icmp_type = ICMP_ECHOREPLY;
1093 icmp4->icmp_code = 0;
1094 icmp4->icmp_id = icmp6->icmp6_id;
1095 icmp4->icmp_seq = icmp6->icmp6_seq;
1096
1097 {
1098 int dlen;
1099 struct ip *ip4 = cv4->_ip._ip4;
1100 struct ip6_hdr *ip6 = cv6->_ip._ip6;
1101 caddr_t icmp6off, icmp4off;
1102 caddr_t icmp6end = (caddr_t)ip6 + cv6->m->m_pkthdr.len;
1103 int icmp6len = icmp6end - (caddr_t)cv6->_payload._icmp6;
1104
1105 dlen = icmp6len - sizeof(struct icmp6_hdr);
1106 icmp6off = (caddr_t)(cv6->_payload._icmp6) + sizeof(struct icmp6_hdr);
1107 icmp4off = (caddr_t)(cv4->_payload._icmp4) + ICMP_MINLEN;
1108 bcopy(icmp6off, icmp4off, dlen);
1109
1110 ip4->ip_len = cv4->m->m_len = sizeof(struct ip) + ICMP_MINLEN + dlen;
1111 }
1112}
1113
1114
1115struct mbuf *
1116translatingTCPv6To4(struct _cv *cv6, struct pAddr *pad)
1117{
1118 int cksumOrg;
1119 struct _cv cv4;
1120 struct mbuf *m4;
1121
1122 bzero(&cv4, sizeof(struct _cv));
1123 m4 = translatingTCPUDPv6To4(cv6, pad, &cv4);
1124 cv4.ip_p = cv4.ip_payload = IPPROTO_TCP;
1125 cksumOrg = ntohs(cv6->_payload._tcp6->th_sum);
1126
1127 updateTcpStatus(cv6);
1128 adjustUpperLayerChecksum(IPPROTO_IPV6, IPPROTO_TCP, cv6, &cv4);
1129
1130#ifdef recalculateTCP4Checksum
1131 _recalculateTCP4Checksum(&cv4);
1132#endif
1133
1134 return (m4);
1135}
1136
1137
1138struct mbuf *
1139translatingUDPv6To4(struct _cv *cv6, struct pAddr *pad)
1140{
1141 struct _cv cv4;
1142 struct mbuf *m4;
1143
1144 bzero(&cv4, sizeof(struct _cv));
1145 m4 = translatingTCPUDPv6To4(cv6, pad, &cv4);
1146 cv4.ip_p = cv4.ip_payload = IPPROTO_UDP;
1147
1148 adjustUpperLayerChecksum(IPPROTO_IPV6, IPPROTO_UDP, cv6, &cv4);
1149
1150#if 1
1151 {
1152 int cksumAdj, cksumCks;
1153 int iphlen;
1154 struct ip *ip4 = cv4._ip._ip4;
1155 struct ip save_ip;
1156 struct udpiphdr *ui;
1157
1158 cksumAdj = cv4._payload._tcp4->th_sum;
1159
1160 ui = mtod(cv4.m, struct udpiphdr *);
1161 iphlen = ip4->ip_hl << 2;
1162
1163 save_ip = *cv4._ip._ip4;
1164 bzero(ui, sizeof(struct udpiphdr));
1165 ui->ui_pr = IPPROTO_UDP;
1166 ui->ui_len = htons(cv4.m->m_pkthdr.len - iphlen);
1167 ui->ui_src = save_ip.ip_src;
1168 ui->ui_dst = save_ip.ip_dst;
1169
1170 ui->ui_sum = 0;
1171 ui->ui_sum = in_cksum(cv4.m, cv4.m->m_pkthdr.len);
1172 *cv4._ip._ip4 = save_ip;
1173
1174 cksumCks = ui->ui_sum;
1175#if 0
1176 printf("translatingUDPv6To4: UDP6->UDP4: %04x, %04x %d\n",
1177 cksumAdj, cksumCks, cv4.m->m_pkthdr.len);
1178#endif
1179 }
1180#endif
1181
1182 return (m4);
1183}
1184
1185
1186struct mbuf *
1187translatingTCPUDPv6To4(struct _cv *cv6, struct pAddr *pad, struct _cv *cv4)
1188{
1189 struct mbuf *m4;
1190 struct ip *ip4;
1191 struct ip6_hdr *ip6;
1192 struct tcphdr *th;
1193
1194 m4 = m_copym(cv6->m, 0, M_COPYALL, M_NOWAIT);
1195 ReturnEnobufs(m4);
1196
1197 m4->m_data += sizeof(struct ip6_hdr) - sizeof(struct ip);
1198 m4->m_pkthdr.len = m4->m_len = sizeof(struct ip) + cv6->plen;
1199
1200 cv4->m = m4;
1201 cv4->plen = cv6->plen;
1202 cv4->poff = sizeof(struct ip);
1203 cv4->_ip._ip4 = mtod(m4, struct ip *);
1204 cv4->_payload._caddr = (caddr_t)cv4->_ip._ip4 + sizeof(struct ip);
1205
1206 cv4->ats = cv6->ats;
1207
1208 ip4 = mtod(m4, struct ip *);
1209 ip6 = mtod(cv6->m, struct ip6_hdr *);
1210 ip4->ip_v = IPVERSION; /* IP version */
1211 ip4->ip_hl = 5; /* header length (no IPv4 option) */
1212 ip4->ip_tos = 0; /* Type Of Service */
1213 ip4->ip_len = sizeof(struct ip) + ntohs(ip6->ip6_plen);
1214 /* Payload length */
1215 ip4->ip_id = 0; /* Identification */
1216 ip4->ip_off = 0; /* flag and fragment offset */
1217 ip4->ip_ttl = ip6->ip6_hlim; /* Time To Live */
1218 ip4->ip_p = cv6->ip_payload; /* Final Payload */
1219 ip4->ip_src = pad->in4src; /* source addresss */
1220 ip4->ip_dst = pad->in4dst; /* destination address */
1221
1222 th = (struct tcphdr *)(ip4 + 1);
1223 th->th_sport = pad->_sport;
1224 th->th_dport = pad->_dport;
1225
1226 return (m4);
1227}
1228
1229
1230/*
1231 * Itojun said 'code fragment in "#ifdef recalculateTCP4Checksum"
1232 * does not make sense to me'. I agree, but
1233 * adjustUpperLayerChecksum() cause checksum error sometime but
1234 * not always, so I left its code. After I fixed it, this code
1235 * will become vanish.
1236 */
1237
1238static void
1239_recalculateTCP4Checksum(struct _cv *cv4)
1240{
1241 int cksumAdj, cksumCks;
1242 int iphlen;
1243 struct ip *ip4 = cv4->_ip._ip4;
1244 struct ip save_ip;
1245 struct tcpiphdr *ti;
1246
1247 cksumAdj = cv4->_payload._tcp4->th_sum;
1248
1249 ti = mtod(cv4->m, struct tcpiphdr *);
1250 iphlen = ip4->ip_hl << 2;
1251
1252 save_ip = *cv4->_ip._ip4;
1253#ifdef ti_next
1254 ti->ti_next = ti->ti_prev = 0;
1255 ti->ti_x1 = 0;
1256#else
1257 bzero(ti->ti_x1, 9);
1258#endif
1259 ti->ti_pr = IPPROTO_TCP;
1260 ti->ti_len = htons(cv4->m->m_pkthdr.len - iphlen);
1261 ti->ti_src = save_ip.ip_src;
1262 ti->ti_dst = save_ip.ip_dst;
1263
1264 ti->ti_sum = 0;
1265 ti->ti_sum = in_cksum(cv4->m, cv4->m->m_pkthdr.len);
1266 *cv4->_ip._ip4 = save_ip;
1267
1268 cksumCks = ti->ti_sum;
1269#if 0
1270 printf("translatingTCPv6To4: TCP6->TCP4: %04x, %04x, %04x %d\n",
1271 cksumOrg, cksumAdj, cksumCks, cv4->m->m_pkthdr.len);
1272#endif
1273}
1274
1275
1276/*
1277 *
1278 */
1279
1280static int
1281updateTcpStatus(struct _cv *cv)
1282{
1283 struct _tSlot *ats = cv->ats;
1284 struct _tcpstate *ts;
1285
1286 if (ats->ip_payload != IPPROTO_TCP)
1287 return (0); /* XXX */
1288
1289 if ((ts = ats->suit.tcp) == NULL)
1290 {
1291 MALLOC(ts, struct _tcpstate *, sizeof(struct _tcpstate), M_NATPT, M_NOWAIT);
1292 if (ts == NULL)
1293 {
1294 return (0); /* XXX */
1295 }
1296
1297 bzero(ts, sizeof(struct _tcpstate));
1298
1299 ts->_state = TCPS_CLOSED;
1300 ats->suit.tcp = ts;
1301 }
1302
1303 ts->_state
1304 = _natpt_tcpfsm(ats->session, cv->inout, ts->_state, cv->_payload._tcp4->th_flags);
1305
1306 return (0);
1307}
1308
1309
1310static int
1311_natpt_tcpfsm(int session, int inout, u_short state, u_char flags)
1312{
1313 int rv;
1314
1315 if (flags & TH_RST)
1316 return (TCPS_CLOSED);
1317
1318 if (session == NATPT_OUTBOUND)
1319 rv = _natpt_tcpfsmSessOut(inout, state, flags);
1320 else
1321 rv = _natpt_tcpfsmSessIn (inout, state, flags);
1322
1323 return (rv);
1324}
1325
1326
1327/*
1328//##
1329//#------------------------------------------------------------------------
1330//# _natpt_tcpfsmSessOut
1331
1332 delta(start, eps) -> CLOSED
1333 delta(CLOSED, TH_SYN & !TH_ACK) -> SYN_SENT
1334 delta(SYN_SENT, in TH_SYN & TH_ACK) -> SYN_RCVD
1335 delta(SYN_RCVD, TH_ACK) -> ESTABLISHED
1336 delta(ESTABLISHED, TH_FIN) -> FIN_WAIT_1
1337 delta(FIN_WAIT_1, in TH_FIN | TH_ACK) -> TIME_WAIT
1338 delta(FIN_WAIT_1, in TH_ACK) -> FIN_WAIT_2
1339 delta(FIN_WAIT_1, in TH_FIN) -> CLOSING
1340 delta(FIN_WAIT_2, in TH_FIN) -> TIME_WAIT
1341 delta(CLOSING, TH_ACK) -> TIME_WAIT
1342 delta(TIME_WAIT, eps) -> CLOSED
1343
1344//#------------------------------------------------------------------------
1345*/
1346
1347static int
1348_natpt_tcpfsmSessOut(int inout, short state, u_char flags)
1349{
1350 int rv = state;
1351
1352 switch (state)
1353 {
1354 case TCPS_CLOSED:
1355 if ((inout == NATPT_OUTBOUND)
1356 && (((flags & TH_SYN) != 0)
1357 && (flags & TH_ACK) == 0))
1358 rv = TCPS_SYN_SENT;
1359 break;
1360
1361 case TCPS_SYN_SENT:
1362 if ((inout == NATPT_INBOUND)
1363 && (flags & (TH_SYN | TH_ACK)))
1364 rv = TCPS_SYN_RECEIVED;
1365 break;
1366
1367 case TCPS_SYN_RECEIVED:
1368 if ((inout == NATPT_OUTBOUND)
1369 && (flags & TH_ACK))
1370 rv = TCPS_ESTABLISHED;
1371 break;
1372
1373 case TCPS_ESTABLISHED:
1374 if ((inout == NATPT_OUTBOUND)
1375 && (flags & TH_FIN))
1376 rv = TCPS_FIN_WAIT_1;
1377 break;
1378
1379 case TCPS_FIN_WAIT_1:
1380 if (inout == NATPT_INBOUND)
1381 {
1382 if (flags & (TH_FIN | TH_ACK)) rv = TCPS_TIME_WAIT;
1383 else if (flags & TH_ACK) rv = TCPS_FIN_WAIT_2;
1384 else if (flags & TH_FIN) rv = TCPS_CLOSING;
1385 }
1386 break;
1387
1388 case TCPS_CLOSING:
1389 if ((inout == NATPT_OUTBOUND)
1390 && (flags & TH_ACK))
1391 rv = TCPS_TIME_WAIT;
1392 break;
1393
1394 case TCPS_FIN_WAIT_2:
1395 if ((inout == NATPT_INBOUND)
1396 && (flags & TH_FIN))
1397 rv = TCPS_TIME_WAIT;
1398 break;
1399 }
1400
1401 return (rv);
1402}
1403
1404
1405/*
1406//##
1407//#------------------------------------------------------------------------
1408//# _natpt_tcpfsmSessIn
1409
1410 delta(start, eps) -> CLOSED
1411 delta(CLOSED, TH_SYN & !TH_ACK) -> SYN_RCVD
1412 delta(SYN_RCVD, TH_ACK) -> ESTABLISHED
1413 delta(ESTABLISHED, in TH_FIN) -> CLOSE_WAIT
1414 delta(ESTABLISHED, out TH_FIN) -> FIN_WAIT_1
1415 delta(CLOSE_WAIT, out TH_FIN) -> LAST_ACK
1416 delta(FIN_WAIT_1, TH_FIN & TH_ACK) -> TIME_WAIT
1417 delta(FIN_WAIT_1, TH_FIN) -> CLOSING
1418 delta(FIN_WAIT_1, TH_ACK) -> FIN_WAIT_2
1419 delta(CLOSING, TH_ACK) -> TIME_WAIT
1420 delta(LAST_ACK), TH_ACK) -> CLOSED
1421 delta(FIN_WAIT_2, TH_FIN) -> TIME_WAIT
1422 delta(TIME_WAIT, eps) -> CLOSED
1423
1424//#------------------------------------------------------------------------
1425*/
1426
1427static int
1428_natpt_tcpfsmSessIn(int inout, short state, u_char flags)
1429{
1430 int rv = state;
1431
1432 switch (state)
1433 {
1434 case TCPS_CLOSED:
1435 if ((inout == NATPT_INBOUND)
1436 && (((flags & TH_SYN) != 0)
1437 && (flags & TH_ACK) == 0))
1438 rv = TCPS_SYN_RECEIVED;
1439 break;
1440
1441 case TCPS_SYN_RECEIVED:
1442 if ((inout == NATPT_INBOUND)
1443 && (flags & TH_ACK))
1444 rv = TCPS_ESTABLISHED;
1445 break;
1446
1447 case TCPS_ESTABLISHED:
1448 if ((inout == NATPT_INBOUND)
1449 && (flags & TH_FIN))
1450 rv = TCPS_CLOSE_WAIT;
1451 if ((inout == NATPT_OUTBOUND)
1452 && (flags & TH_FIN))
1453 rv = TCPS_FIN_WAIT_1;
1454 break;
1455
1456 case TCPS_CLOSE_WAIT:
1457 if ((inout == NATPT_OUTBOUND)
1458 && (flags & TH_FIN))
1459 rv = TCPS_LAST_ACK;
1460 break;
1461
1462 case TCPS_FIN_WAIT_1:
1463 if (inout == NATPT_INBOUND)
1464 {
1465 if (flags & (TH_FIN | TH_ACK)) rv = TCPS_TIME_WAIT;
1466 else if (flags & TH_FIN) rv = TCPS_CLOSING;
1467 else if (flags & TH_ACK) rv = TCPS_FIN_WAIT_2;
1468 }
1469 break;
1470
1471 case TCPS_CLOSING:
1472 if ((inout == NATPT_INBOUND)
1473 && (flags & TH_ACK))
1474 rv = TCPS_TIME_WAIT;
1475 break;
1476
1477 case TCPS_LAST_ACK:
1478 if ((inout == NATPT_INBOUND)
1479 && (flags & TH_ACK))
1480 rv = TCPS_CLOSED;
1481 break;
1482
1483 case TCPS_FIN_WAIT_2:
1484 if ((inout == NATPT_INBOUND)
1485 && (flags & TH_FIN))
1486 rv = TCPS_TIME_WAIT;
1487 break;
1488 }
1489
1490 return (rv);
1491}
1492
1493
1494/*
1495 *
1496 */
1497
1498static void
1499adjustUpperLayerChecksum(int header, int proto, struct _cv *cv6, struct _cv *cv4)
1500{
1501 u_short cksum;
1502 struct ipovly ip4;
1503 struct ulc
1504 {
1505 struct in6_addr ulc_src;
1506 struct in6_addr ulc_dst;
1507 u_long ulc_len;
1508 u_char ulc_zero[3];
1509 u_char ulc_nxt;
1510 } ulc;
1511
1512 bzero(&ulc, sizeof(struct ulc));
1513 bzero(&ip4, sizeof(struct ipovly));
1514
1515 ulc.ulc_src = cv6->_ip._ip6->ip6_src;
1516 ulc.ulc_dst = cv6->_ip._ip6->ip6_dst;
1517 ulc.ulc_len = htonl(cv6->plen);
1518 ulc.ulc_nxt = cv6->ip_p;
1519
1520 ip4.ih_src = cv4->_ip._ip4->ip_src;
1521 ip4.ih_dst = cv4->_ip._ip4->ip_dst;
1522 ip4.ih_len = htons(cv4->plen);
1523 ip4.ih_pr = cv4->ip_p;
1524
1525 switch (proto)
1526 {
1527 case IPPROTO_TCP:
1528 if (header == IPPROTO_IPV6)
1529 {
1530 cksum = adjustChecksum(ntohs(cv6->_payload._tcp6->th_sum),
1531 (u_char *)&ulc, sizeof(struct ulc),
1532 (u_char *)&ip4, sizeof(struct ipovly));
1533 cv4->_payload._tcp4->th_sum = htons(cksum);
1534 }
1535 else
1536 {
1537 cksum = adjustChecksum(ntohs(cv4->_payload._tcp4->th_sum),
1538 (u_char *)&ip4, sizeof(struct ipovly),
1539 (u_char *)&ulc, sizeof(struct ulc));
1540 cv6->_payload._tcp6->th_sum = htons(cksum);
1541 }
1542 break;
1543
1544 case IPPROTO_UDP:
1545 if (header == IPPROTO_IPV6)
1546 {
1547 cksum = adjustChecksum(ntohs(cv6->_payload._udp->uh_sum),
1548 (u_char *)&ulc, sizeof(struct ulc),
1549 (u_char *)&ip4, sizeof(struct ipovly));
1550 cv4->_payload._udp->uh_sum = htons(cksum);
1551 }
1552 else
1553 {
1554 cksum = adjustChecksum(ntohs(cv4->_payload._udp->uh_sum),
1555 (u_char *)&ip4, sizeof(struct ipovly),
1556 (u_char *)&ulc, sizeof(struct ulc));
1557 cv6->_payload._udp->uh_sum = htons(cksum);
1558 }
1559 break;
1560
1561 default:
1562 }
1563}
1564
1565
1566static int
1567adjustChecksum(int cksum, u_char *optr, int olen, u_char *nptr, int nlen)
1568{
1569 long x, old, new;
1570
1571 x = ~cksum & 0xffff;
1572
1573 while (olen)
1574 {
1575 if (olen == 1)
1576 {
1577 old = optr[0] * 256 + optr[1];
1578 x -= old & 0xff00;
1579 if ( x <= 0 ) { x--; x &= 0xffff; }
1580 break;
1581 }
1582 else
1583 {
1584 old = optr[0] * 256 + optr[1];
1585 x -= old & 0xffff;
1586 if ( x <= 0 ) { x--; x &= 0xffff; }
1587 optr += 2;
1588 olen -= 2;
1589 }
1590 }
1591
1592 while (nlen)
1593 {
1594 if (nlen == 1)
1595 {
1596 new = nptr[0] * 256 + nptr[1];
1597 x += new & 0xff00;
1598 if (x & 0x10000) { x++; x &= 0xffff; }
1599 break;
1600 }
1601 else
1602 {
1603 new = nptr[0] * 256 + nptr[1];
1604 x += new & 0xffff;
1605 if (x & 0x10000) { x++; x &= 0xffff; }
1606 nptr += 2;
1607 nlen -= 2;
1608 }
1609 }
1610
1611 return (~x & 0xffff);
1612}