1 /* $KAME: natpt_trans.c,v 1.12 2000/03/25 07:23:56 sumikawa Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/param.h>
33 #include <sys/malloc.h>
35 #include <sys/socket.h>
36 #include <sys/syslog.h>
37 #include <sys/systm.h>
40 # include <sys/kernel.h>
45 #include <net/route.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/in.h>
50 #include <netinet/ip.h>
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>
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>
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>
72 #include <netinet6/natpt_defs.h>
73 #include <netinet6/natpt_list.h>
74 #include <netinet6/natpt_var.h>
77 #define recalculateTCP4Checksum 1
78 #define recalculateTCP6Checksum 1
86 int natpt_initialized
;
89 extern struct in6_addr natpt_prefix
;
90 extern struct in6_addr natpt_prefixmask
;
92 struct mbuf
*translatingTCPUDPv4To4
__P((struct _cv
*, struct pAddr
*, struct _cv
*));
94 void tr_icmp4EchoReply
__P((struct _cv
*, struct _cv
*));
95 void tr_icmp4Unreach
__P((struct _cv
*, struct _cv
*, struct pAddr
*));
96 void tr_icmp4Echo
__P((struct _cv
*, struct _cv
*));
97 void tr_icmp4Timxceed
__P((struct _cv
*, struct _cv
*, struct pAddr
*));
98 void tr_icmp4Paramprob
__P((struct _cv
*, struct _cv
*));
99 void tr_icmp4MimicPayload
__P((struct _cv
*, struct _cv
*, struct pAddr
*));
101 void tr_icmp6DstUnreach
__P((struct _cv
*, struct _cv
*));
102 void tr_icmp6PacketTooBig
__P((struct _cv
*, struct _cv
*));
103 void tr_icmp6TimeExceed
__P((struct _cv
*, struct _cv
*));
104 void tr_icmp6ParamProb
__P((struct _cv
*, struct _cv
*));
105 void tr_icmp6EchoRequest
__P((struct _cv
*, struct _cv
*));
106 void tr_icmp6EchoReply
__P((struct _cv
*, struct _cv
*));
108 static void _recalculateTCP4Checksum
__P((struct _cv
*));
110 static int updateTcpStatus
__P((struct _cv
*));
111 static int _natpt_tcpfsm
__P((int, int, u_short
, u_char
));
112 static int _natpt_tcpfsmSessOut
__P((int, short, u_char
));
113 static int _natpt_tcpfsmSessIn
__P((int, short, u_char
));
115 static void adjustUpperLayerChecksum
__P((int, int, struct _cv
*, struct _cv
*));
116 static int adjustChecksum
__P((int, u_char
*, int, u_char
*, int));
119 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
120 static MALLOC_DEFINE(M_NATPT
, "NATPT", "Network Address Translation - Protocol Translation");
126 * Translating From IPv4 to IPv4
130 translatingIPv4To4(struct _cv
*cv4
, struct pAddr
*pad
)
133 struct mbuf
*m4
= NULL
;
135 if (isDump(D_TRANSLATINGIPV4
))
136 natpt_logIp4(LOG_DEBUG
, cv4
->_ip
._ip4
);
139 cv4
->ats
->tstamp
= atv
.tv_sec
;
141 switch (cv4
->ip_payload
)
144 m4
= translatingICMPv4To4(cv4
, pad
);
148 m4
= translatingTCPv4To4(cv4
, pad
);
152 m4
= translatingUDPv4To4(cv4
, pad
);
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
;
165 m4
->m_pkthdr
.len
= cv4
->m
->m_pkthdr
.len
;
173 translatingICMPv4To4(struct _cv
*cv4from
, struct pAddr
*pad
)
177 struct ip
*ip4from
, *ip4to
;
178 struct icmp
*icmp4from
;
180 ip4from
= mtod(cv4from
->m
, struct ip
*);
181 icmp4from
= cv4from
->_payload
._icmp4
;
183 m4
= m_copym(cv4from
->m
,0, M_COPYALL
, M_NOWAIT
);
186 bzero(&cv4to
, sizeof(struct _cv
));
188 cv4to
._ip
._ip4
= ip4to
= mtod(m4
, struct ip
*);
189 cv4to
._payload
._caddr
= (caddr_t
)cv4to
._ip
._ip4
+ (ip4from
->ip_hl
<< 2);
191 ip4to
->ip_src
= pad
->in4src
; /* source address */
192 ip4to
->ip_dst
= pad
->in4dst
; /* destination address */
194 switch (icmp4from
->icmp_type
)
205 m4
->m_len
= cv4from
->m
->m_len
;
211 translatingTCPv4To4(struct _cv
*cv4from
, struct pAddr
*pad
)
216 bzero(&cv4to
, sizeof(struct _cv
));
217 m4
= translatingTCPUDPv4To4(cv4from
, pad
, &cv4to
);
218 cv4to
.ip_p
= cv4to
.ip_payload
= IPPROTO_TCP
;
220 updateTcpStatus(&cv4to
);
221 adjustUpperLayerChecksum(IPPROTO_IPV4
, IPPROTO_TCP
, cv4from
, &cv4to
);
223 #ifdef recalculateTCP4Checksum
224 _recalculateTCP4Checksum(&cv4to
);
232 translatingUDPv4To4(struct _cv
*cv4from
, struct pAddr
*pad
)
237 bzero(&cv4to
, sizeof(struct _cv
));
238 m4
= translatingTCPUDPv4To4(cv4from
, pad
, &cv4to
);
239 cv4to
.ip_p
= cv4to
.ip_payload
= IPPROTO_UDP
;
241 adjustUpperLayerChecksum(IPPROTO_IPV4
, IPPROTO_UDP
, cv4from
, &cv4to
);
248 translatingTCPUDPv4To4(struct _cv
*cv4from
, struct pAddr
*pad
, struct _cv
*cv4to
)
252 struct tcphdr
*tcp4to
;
254 m4
= m_copym(cv4from
->m
,0, M_COPYALL
, M_NOWAIT
);
257 ip4to
= mtod(m4
, struct ip
*);
259 ip4to
->ip_src
= pad
->in4src
;
260 ip4to
->ip_dst
= pad
->in4dst
;
262 tcp4to
= (struct tcphdr
*)((caddr_t
)ip4to
+ (ip4to
->ip_hl
<< 2));
263 tcp4to
->th_sport
= pad
->_sport
;
264 tcp4to
->th_dport
= pad
->_dport
;
267 cv4to
->_ip
._ip4
= ip4to
;
268 cv4to
->_payload
._tcp4
= tcp4to
;
269 cv4to
->ats
= cv4from
->ats
;
274 #endif /* ifdef NATPT_NAT */
278 * Translating From IPv4 To IPv6
282 translatingIPv4To6(struct _cv
*cv4
, struct pAddr
*pad
)
285 struct mbuf
*m6
= NULL
;
287 if (isDump(D_TRANSLATINGIPV4
))
288 natpt_logIp4(LOG_DEBUG
, cv4
->_ip
._ip4
);
291 cv4
->ats
->tstamp
= atv
.tv_sec
;
293 switch (cv4
->ip_payload
)
296 m6
= translatingICMPv4To6(cv4
, pad
);
300 m6
= translatingTCPv4To6(cv4
, pad
);
304 m6
= translatingUDPv4To6(cv4
, pad
);
309 m6
->m_pkthdr
.rcvif
= cv4
->m
->m_pkthdr
.rcvif
;
316 translatingICMPv4To6(struct _cv
*cv4
, struct pAddr
*pad
)
323 struct icmp6_hdr
*icmp6
;
325 ip4
= mtod(cv4
->m
, struct ip
*);
326 icmp4
= cv4
->_payload
._icmp4
;
332 icmp4end
= (caddr_t
)ip4
+ cv4
->m
->m_pkthdr
.len
;
333 icmp4len
= icmp4end
- (caddr_t
)cv4
->_payload
._icmp4
;
335 MGETHDR(m6
, M_NOWAIT
, MT_HEADER
);
341 if (MHLEN
< (sizeof(struct ip6_hdr
) + icmp4len
))
342 MCLGET(m6
, M_NOWAIT
);
346 cv6
._ip
._ip6
= mtod(m6
, struct ip6_hdr
*);
347 cv6
._payload
._caddr
= (caddr_t
)cv6
._ip
._ip6
+ sizeof(struct ip6_hdr
);
349 ip6
= mtod(cv6
.m
, struct ip6_hdr
*);
350 icmp6
= cv6
._payload
._icmp6
;;
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)
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];
368 ip6
->ip6_src
.s6_addr32
[0] = 0;
369 ip6
->ip6_src
.s6_addr32
[1] = 0;
370 ip6
->ip6_src
.s6_addr32
[2] = 0;
372 ip6
->ip6_src
.s6_addr32
[3] = ip4
->ip_src
.s_addr
;
374 switch (icmp4
->icmp_type
)
377 tr_icmp4EchoReply(cv4
, &cv6
);
381 tr_icmp4Unreach(cv4
, &cv6
, pad
);
385 tr_icmp4Echo(cv4
, &cv6
);
389 tr_icmp4Timxceed(cv4
, &cv6
, pad
);
393 tr_icmp4Paramprob(cv4
, &cv6
);
397 case ICMP_ROUTERADVERT
:
398 case ICMP_ROUTERSOLICIT
:
399 m_freem(m6
); /* Single hop message. Silently drop. */
402 case ICMP_SOURCEQUENCH
:
404 case ICMP_TSTAMPREPLY
:
409 m_freem(m6
); /* Obsoleted in ICMPv6. Silently drop. */
413 m_freem(m6
); /* Silently drop. */
417 icmp6
->icmp6_cksum
= 0;
418 icmp6
->icmp6_cksum
= in6_cksum(cv6
.m
, IPPROTO_ICMPV6
,
419 sizeof(struct ip6_hdr
), ntohs(ip6
->ip6_plen
));
426 tr_icmp4EchoReply(struct _cv
*cv4
, struct _cv
*cv6
)
428 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
429 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
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
;
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
);
449 ip6
->ip6_plen
= ntohs(sizeof(struct icmp6_hdr
) + dlen
);
452 = sizeof(struct ip6_hdr
) + htons(ip6
->ip6_plen
);
458 tr_icmp4Unreach(struct _cv
*cv4
, struct _cv
*cv6
, struct pAddr
*pad
)
460 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
461 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
468 switch (icmp4
->icmp_code
)
470 case ICMP_UNREACH_NET
:
471 case ICMP_UNREACH_HOST
:
472 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_NOROUTE
;
475 case ICMP_UNREACH_PROTOCOL
: /* do more */
476 icmp6
->icmp6_type
= ICMP6_PARAM_PROB
;
477 icmp6
->icmp6_code
= ICMP6_PARAMPROB_NEXTHEADER
; /* xxx */
480 case ICMP_UNREACH_PORT
:
481 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_NOPORT
;
484 case ICMP_UNREACH_NEEDFRAG
: /* do more */
485 icmp6
->icmp6_type
= ICMP6_PACKET_TOO_BIG
;
486 icmp6
->icmp6_code
= ICMP6_PARAMPROB_HEADER
;
489 case ICMP_UNREACH_SRCFAIL
:
490 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_NOTNEIGHBOR
;
493 case ICMP_UNREACH_NET_UNKNOWN
:
494 case ICMP_UNREACH_HOST_UNKNOWN
:
495 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_NOROUTE
;
498 case ICMP_UNREACH_ISOLATED
:
499 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_NOROUTE
;
502 case ICMP_UNREACH_NET_PROHIB
:
503 case ICMP_UNREACH_HOST_PROHIB
:
504 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_ADMIN
;
507 case ICMP_UNREACH_TOSNET
:
508 case ICMP_UNREACH_TOSHOST
:
509 icmp6
->icmp6_code
= ICMP6_DST_UNREACH_NOROUTE
;
516 tr_icmp4MimicPayload(cv4
, cv6
, pad
);
521 tr_icmp4Echo(struct _cv
*cv4
, struct _cv
*cv6
)
523 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
524 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
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
;
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
);
544 ip6
->ip6_plen
= ntohs(sizeof(struct icmp6_hdr
) + dlen
);
547 = sizeof(struct ip6_hdr
) + htons(ip6
->ip6_plen
);
553 tr_icmp4Timxceed(struct _cv
*cv4
, struct _cv
*cv6
, struct pAddr
*pad
)
555 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
556 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
563 tr_icmp4MimicPayload(cv4
, cv6
, pad
);
568 tr_icmp4Paramprob(struct _cv
*cv4
, struct _cv
*cv6
)
570 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
571 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
581 tr_icmp4MimicPayload(struct _cv
*cv4
, struct _cv
*cv6
, struct pAddr
*pad
)
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
;
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
);
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
);
602 icmpip6
= (struct ip6_hdr
*)icmp6off
;
603 bzero(icmpip6
, sizeof(struct ip6_hdr
));
604 bcopy(icmp4dgramoff
, icmp6dgramoff
, dgramlen
);
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
;
615 icmp6dlen
= sizeof(struct icmp6_hdr
) + sizeof(struct ip6_hdr
) + dgramlen
;
616 ip6
->ip6_plen
= ntohs(icmp6dlen
);
619 = sizeof(struct ip6_hdr
) + htons(ip6
->ip6_plen
);
621 if (cv4
->flags
& NATPT_TRACEROUTE
)
623 struct udphdr
*icmpudp6
;
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
;
633 translatingTCPv4To6(struct _cv
*cv4
, struct pAddr
*pad
)
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
);
644 updateTcpStatus(cv4
);
645 adjustUpperLayerChecksum(IPPROTO_IPV4
, IPPROTO_TCP
, &cv6
, cv4
);
647 #ifdef recalculateTCP6Checksum
649 int cksumAdj
, cksumCks
;
652 cksumAdj
= cv6
._payload
._tcp6
->th_sum
;
654 th
= cv6
._payload
._tcp6
;
656 th
->th_sum
= in6_cksum(cv6
.m
, IPPROTO_TCP
, sizeof(struct ip6_hdr
),
657 cv6
.m
->m_pkthdr
.len
- sizeof(struct ip6_hdr
));
659 cksumCks
= th
->th_sum
;
661 printf("translatingTCPv4To6: TCP4->TCP6: %04x, %04x, %04x %d\n",
662 cksumOrg
, cksumAdj
, cksumCks
, cv6
.m
->m_pkthdr
.len
);
672 translatingUDPv4To6(struct _cv
*cv4
, struct pAddr
*pad
)
677 bzero(&cv6
, sizeof(struct _cv
));
678 m6
= translatingTCPUDPv4To6(cv4
, pad
, &cv6
);
679 cv6
.ip_p
= cv6
.ip_payload
= IPPROTO_UDP
;
686 translatingTCPUDPv4To6(struct _cv
*cv4
, struct pAddr
*pad
, struct _cv
*cv6
)
691 struct tcp6hdr
*tcp6
;
693 if (cv4
->m
->m_flags
& M_EXT
)
695 if (cv4
->plen
+ sizeof(struct ip6_hdr
) > MHLEN
)
699 m6next
= m_copym(cv4
->m
, 0, M_COPYALL
, M_NOWAIT
);
700 ReturnEnobufs(m6next
);
702 m6next
->m_data
+= cv4
->poff
;
703 m6next
->m_len
-= cv4
->poff
;
705 MGETHDR(m6
, M_NOWAIT
, MT_HEADER
);
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
*);
715 cv6
->_ip
._ip6
= mtod(m6
, struct ip6_hdr
*);
716 cv6
->_payload
._caddr
= m6next
->m_data
;
717 cv6
->plen
= cv4
->plen
;
720 else /* (sizeof(struct ip6_hdr) + cv4->plen <= MHLEN) */
725 MGETHDR(m6
, M_NOWAIT
, MT_HEADER
);
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
);
739 = sizeof(struct ip6_hdr
) + cv4
->plen
;
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
;
748 else if (cv4
->plen
+ sizeof(struct ip6_hdr
) > MHLEN
)
753 MGETHDR(m6
, M_NOWAIT
, MT_HEADER
);
755 MCLGET(m6
, M_NOWAIT
);
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
*);
761 tcp4
= (caddr_t
)cv4
->_payload
._tcp4
;
762 tcp6
= (caddr_t
)ip6
+ sizeof(struct ip6_hdr
);
763 bcopy(tcp4
, tcp6
, cv4
->plen
);
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
;
776 MGETHDR(m6
, M_NOWAIT
, MT_HEADER
);
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
);
791 = sizeof(struct ip6_hdr
) + cv4
->plen
;
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
;
801 ip4
= mtod(cv4
->m
, struct ip
*);
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
;
811 tcp6
= cv6
->_payload
._tcp6
;
812 tcp6
->th_sport
= pad
->_sport
;
813 tcp6
->th_dport
= pad
->_dport
;
820 * Translating Form IPv6 To IPv4
824 translatingIPv6To4(struct _cv
*cv6
, struct pAddr
*pad
)
827 struct mbuf
*m4
= NULL
;
829 if (isDump(D_TRANSLATINGIPV6
))
830 natpt_logIp6(LOG_DEBUG
, cv6
->_ip
._ip6
);
833 cv6
->ats
->tstamp
= atv
.tv_sec
;
835 switch (cv6
->ip_payload
)
838 m4
= translatingICMPv6To4(cv6
, pad
);
842 m4
= translatingTCPv6To4(cv6
, pad
);
846 m4
= translatingUDPv6To4(cv6
, pad
);
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
;
861 for (mlen
= 0, mm
= m4
; mm
; mm
= mm
->m_next
)
866 m4
->m_pkthdr
.len
= mlen
;
868 if (isDump(D_TRANSLATEDIPV4
))
869 natpt_logIp4(LOG_DEBUG
, ip4
);
877 translatingICMPv6To4(struct _cv
*cv6
, struct pAddr
*pad
)
884 struct icmp6_hdr
*icmp6
;
886 ip6
= mtod(cv6
->m
, struct ip6_hdr
*);
887 icmp6
= cv6
->_payload
._icmp6
;
890 caddr_t icmp6end
= (caddr_t
)ip6
+ cv6
->m
->m_pkthdr
.len
;
891 int icmp6len
= icmp6end
- (caddr_t
)cv6
->_payload
._icmp6
;
893 MGETHDR(m4
, M_NOWAIT
, MT_HEADER
);
899 if (MHLEN
< (sizeof(struct ip
) + icmp6len
))
900 MCLGET(m4
, M_NOWAIT
);
904 cv4
._ip
._ip4
= mtod(m4
, struct ip
*);
905 cv4
._payload
._caddr
= (caddr_t
)cv4
._ip
._ip4
+ sizeof(struct ip
);
907 ip4
= mtod(cv4
.m
, struct ip
*);
908 icmp4
= cv4
._payload
._icmp4
;
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 */
921 switch (icmp6
->icmp6_type
)
923 case ICMP6_DST_UNREACH
:
924 tr_icmp6DstUnreach(cv6
, &cv4
);
927 case ICMP6_PACKET_TOO_BIG
:
928 tr_icmp6PacketTooBig(cv6
, &cv4
);
931 case ICMP6_TIME_EXCEEDED
:
932 tr_icmp6TimeExceed(cv6
, &cv4
);
935 case ICMP6_PARAM_PROB
:
936 tr_icmp6ParamProb(cv6
, &cv4
);
939 case ICMP6_ECHO_REQUEST
:
940 tr_icmp6EchoRequest(cv6
, &cv4
);
943 case ICMP6_ECHO_REPLY
:
944 tr_icmp6EchoReply(cv6
, &cv4
);
947 case MLD6_LISTENER_QUERY
:
948 case MLD6_LISTENER_REPORT
:
949 case MLD6_LISTENER_DONE
:
950 m_freem(m4
); /* Single hop message. Silently drop. */
954 m_freem(m4
); /* Silently drop. */
960 struct mbuf
*m4
= cv4
.m
;
961 struct ip
*ip4
= cv4
._ip
._ip4
;
963 hlen
= ip4
->ip_hl
<< 2;
966 icmp4
->icmp_cksum
= 0;
967 icmp4
->icmp_cksum
= in_cksum(cv4
.m
, ip4
->ip_len
- hlen
);
977 tr_icmp6DstUnreach(struct _cv
*cv6
, struct _cv
*cv4
)
979 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
980 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
987 switch (icmp6
->icmp6_code
)
989 case ICMP6_DST_UNREACH_NOROUTE
:
990 icmp4
->icmp_code
= ICMP_UNREACH_HOST
;
993 case ICMP6_DST_UNREACH_ADMIN
:
994 icmp4
->icmp_code
= ICMP_UNREACH_HOST_PROHIB
;
997 case ICMP6_DST_UNREACH_NOTNEIGHBOR
:
998 icmp4
->icmp_code
= ICMP_UNREACH_SRCFAIL
;
1001 case ICMP6_DST_UNREACH_ADDR
:
1002 icmp4
->icmp_code
= ICMP_UNREACH_HOST
;
1005 case ICMP6_DST_UNREACH_NOPORT
:
1006 icmp4
->icmp_code
= ICMP_UNREACH_PORT
;
1013 tr_icmp6PacketTooBig(struct _cv
*cv6
, struct _cv
*cv4
)
1015 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
1016 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
1026 tr_icmp6TimeExceed(struct _cv
*cv6
, struct _cv
*cv4
)
1028 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
1029 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
1039 tr_icmp6ParamProb(struct _cv
*cv6
, struct _cv
*cv4
)
1041 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
1042 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
1049 if (icmp6
->icmp6_code
== ICMP6_PARAMPROB_NEXTHEADER
)
1051 icmp4
->icmp_type
= ICMP_UNREACH
;
1052 icmp4
->icmp_code
= ICMP_UNREACH_PROTOCOL
;
1058 tr_icmp6EchoRequest(struct _cv
*cv6
, struct _cv
*cv4
)
1060 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
1061 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
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
;
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
);
1081 ip4
->ip_len
= cv4
->m
->m_len
= sizeof(struct ip
) + ICMP_MINLEN
+ dlen
;
1087 tr_icmp6EchoReply(struct _cv
*cv6
, struct _cv
*cv4
)
1089 struct icmp
*icmp4
= cv4
->_payload
._icmp4
;
1090 struct icmp6_hdr
*icmp6
= cv6
->_payload
._icmp6
;
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
;
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
;
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
);
1110 ip4
->ip_len
= cv4
->m
->m_len
= sizeof(struct ip
) + ICMP_MINLEN
+ dlen
;
1116 translatingTCPv6To4(struct _cv
*cv6
, struct pAddr
*pad
)
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
);
1127 updateTcpStatus(cv6
);
1128 adjustUpperLayerChecksum(IPPROTO_IPV6
, IPPROTO_TCP
, cv6
, &cv4
);
1130 #ifdef recalculateTCP4Checksum
1131 _recalculateTCP4Checksum(&cv4
);
1139 translatingUDPv6To4(struct _cv
*cv6
, struct pAddr
*pad
)
1144 bzero(&cv4
, sizeof(struct _cv
));
1145 m4
= translatingTCPUDPv6To4(cv6
, pad
, &cv4
);
1146 cv4
.ip_p
= cv4
.ip_payload
= IPPROTO_UDP
;
1148 adjustUpperLayerChecksum(IPPROTO_IPV6
, IPPROTO_UDP
, cv6
, &cv4
);
1152 int cksumAdj
, cksumCks
;
1154 struct ip
*ip4
= cv4
._ip
._ip4
;
1156 struct udpiphdr
*ui
;
1158 cksumAdj
= cv4
._payload
._tcp4
->th_sum
;
1160 ui
= mtod(cv4
.m
, struct udpiphdr
*);
1161 iphlen
= ip4
->ip_hl
<< 2;
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
;
1171 ui
->ui_sum
= in_cksum(cv4
.m
, cv4
.m
->m_pkthdr
.len
);
1172 *cv4
._ip
._ip4
= save_ip
;
1174 cksumCks
= ui
->ui_sum
;
1176 printf("translatingUDPv6To4: UDP6->UDP4: %04x, %04x %d\n",
1177 cksumAdj
, cksumCks
, cv4
.m
->m_pkthdr
.len
);
1187 translatingTCPUDPv6To4(struct _cv
*cv6
, struct pAddr
*pad
, struct _cv
*cv4
)
1191 struct ip6_hdr
*ip6
;
1194 m4
= m_copym(cv6
->m
, 0, M_COPYALL
, M_NOWAIT
);
1197 m4
->m_data
+= sizeof(struct ip6_hdr
) - sizeof(struct ip
);
1198 m4
->m_pkthdr
.len
= m4
->m_len
= sizeof(struct ip
) + cv6
->plen
;
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
);
1206 cv4
->ats
= cv6
->ats
;
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 */
1222 th
= (struct tcphdr
*)(ip4
+ 1);
1223 th
->th_sport
= pad
->_sport
;
1224 th
->th_dport
= pad
->_dport
;
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.
1239 _recalculateTCP4Checksum(struct _cv
*cv4
)
1241 int cksumAdj
, cksumCks
;
1243 struct ip
*ip4
= cv4
->_ip
._ip4
;
1245 struct tcpiphdr
*ti
;
1247 cksumAdj
= cv4
->_payload
._tcp4
->th_sum
;
1249 ti
= mtod(cv4
->m
, struct tcpiphdr
*);
1250 iphlen
= ip4
->ip_hl
<< 2;
1252 save_ip
= *cv4
->_ip
._ip4
;
1254 ti
->ti_next
= ti
->ti_prev
= 0;
1257 bzero(ti
->ti_x1
, 9);
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
;
1265 ti
->ti_sum
= in_cksum(cv4
->m
, cv4
->m
->m_pkthdr
.len
);
1266 *cv4
->_ip
._ip4
= save_ip
;
1268 cksumCks
= ti
->ti_sum
;
1270 printf("translatingTCPv6To4: TCP6->TCP4: %04x, %04x, %04x %d\n",
1271 cksumOrg
, cksumAdj
, cksumCks
, cv4
->m
->m_pkthdr
.len
);
1281 updateTcpStatus(struct _cv
*cv
)
1283 struct _tSlot
*ats
= cv
->ats
;
1284 struct _tcpstate
*ts
;
1286 if (ats
->ip_payload
!= IPPROTO_TCP
)
1287 return (0); /* XXX */
1289 if ((ts
= ats
->suit
.tcp
) == NULL
)
1291 MALLOC(ts
, struct _tcpstate
*, sizeof(struct _tcpstate
), M_NATPT
, M_NOWAIT
);
1294 return (0); /* XXX */
1297 bzero(ts
, sizeof(struct _tcpstate
));
1299 ts
->_state
= TCPS_CLOSED
;
1304 = _natpt_tcpfsm(ats
->session
, cv
->inout
, ts
->_state
, cv
->_payload
._tcp4
->th_flags
);
1311 _natpt_tcpfsm(int session
, int inout
, u_short state
, u_char flags
)
1316 return (TCPS_CLOSED
);
1318 if (session
== NATPT_OUTBOUND
)
1319 rv
= _natpt_tcpfsmSessOut(inout
, state
, flags
);
1321 rv
= _natpt_tcpfsmSessIn (inout
, state
, flags
);
1329 //#------------------------------------------------------------------------
1330 //# _natpt_tcpfsmSessOut
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
1344 //#------------------------------------------------------------------------
1348 _natpt_tcpfsmSessOut(int inout
, short state
, u_char flags
)
1355 if ((inout
== NATPT_OUTBOUND
)
1356 && (((flags
& TH_SYN
) != 0)
1357 && (flags
& TH_ACK
) == 0))
1362 if ((inout
== NATPT_INBOUND
)
1363 && (flags
& (TH_SYN
| TH_ACK
)))
1364 rv
= TCPS_SYN_RECEIVED
;
1367 case TCPS_SYN_RECEIVED
:
1368 if ((inout
== NATPT_OUTBOUND
)
1369 && (flags
& TH_ACK
))
1370 rv
= TCPS_ESTABLISHED
;
1373 case TCPS_ESTABLISHED
:
1374 if ((inout
== NATPT_OUTBOUND
)
1375 && (flags
& TH_FIN
))
1376 rv
= TCPS_FIN_WAIT_1
;
1379 case TCPS_FIN_WAIT_1
:
1380 if (inout
== NATPT_INBOUND
)
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
;
1389 if ((inout
== NATPT_OUTBOUND
)
1390 && (flags
& TH_ACK
))
1391 rv
= TCPS_TIME_WAIT
;
1394 case TCPS_FIN_WAIT_2
:
1395 if ((inout
== NATPT_INBOUND
)
1396 && (flags
& TH_FIN
))
1397 rv
= TCPS_TIME_WAIT
;
1407 //#------------------------------------------------------------------------
1408 //# _natpt_tcpfsmSessIn
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
1424 //#------------------------------------------------------------------------
1428 _natpt_tcpfsmSessIn(int inout
, short state
, u_char flags
)
1435 if ((inout
== NATPT_INBOUND
)
1436 && (((flags
& TH_SYN
) != 0)
1437 && (flags
& TH_ACK
) == 0))
1438 rv
= TCPS_SYN_RECEIVED
;
1441 case TCPS_SYN_RECEIVED
:
1442 if ((inout
== NATPT_INBOUND
)
1443 && (flags
& TH_ACK
))
1444 rv
= TCPS_ESTABLISHED
;
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
;
1456 case TCPS_CLOSE_WAIT
:
1457 if ((inout
== NATPT_OUTBOUND
)
1458 && (flags
& TH_FIN
))
1462 case TCPS_FIN_WAIT_1
:
1463 if (inout
== NATPT_INBOUND
)
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
;
1472 if ((inout
== NATPT_INBOUND
)
1473 && (flags
& TH_ACK
))
1474 rv
= TCPS_TIME_WAIT
;
1478 if ((inout
== NATPT_INBOUND
)
1479 && (flags
& TH_ACK
))
1483 case TCPS_FIN_WAIT_2
:
1484 if ((inout
== NATPT_INBOUND
)
1485 && (flags
& TH_FIN
))
1486 rv
= TCPS_TIME_WAIT
;
1499 adjustUpperLayerChecksum(int header
, int proto
, struct _cv
*cv6
, struct _cv
*cv4
)
1505 struct in6_addr ulc_src
;
1506 struct in6_addr ulc_dst
;
1512 bzero(&ulc
, sizeof(struct ulc
));
1513 bzero(&ip4
, sizeof(struct ipovly
));
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
;
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
;
1528 if (header
== IPPROTO_IPV6
)
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
);
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
);
1545 if (header
== IPPROTO_IPV6
)
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
);
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
);
1567 adjustChecksum(int cksum
, u_char
*optr
, int olen
, u_char
*nptr
, int nlen
)
1571 x
= ~cksum
& 0xffff;
1577 old
= optr
[0] * 256 + optr
[1];
1579 if ( x
<= 0 ) { x
--; x
&= 0xffff; }
1584 old
= optr
[0] * 256 + optr
[1];
1586 if ( x
<= 0 ) { x
--; x
&= 0xffff; }
1596 new = nptr
[0] * 256 + nptr
[1];
1598 if (x
& 0x10000) { x
++; x
&= 0xffff; }
1603 new = nptr
[0] * 256 + nptr
[1];
1605 if (x
& 0x10000) { x
++; x
&= 0xffff; }
1611 return (~x
& 0xffff);