1 /* $KAME: natpt_tslot.c,v 1.8 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/kernel.h>
34 #include <sys/malloc.h>
35 #include <sys/socket.h>
36 #include <sys/syslog.h>
37 #include <sys/systm.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/in.h>
43 #include <netinet/ip.h>
44 #include <netinet/ip_icmp.h>
45 #include <netinet/tcp.h>
46 #include <netinet/tcp_fsm.h>
47 #include <netinet/udp.h>
49 #include <netinet6/in6_var.h>
50 #include <netinet/ip6.h>
51 #if !defined(__NetBSD__) && (!defined(__FreeBSD__) || (__FreeBSD__ < 3)) && !defined(__APPLE__)
52 #include <netinet6/tcp6.h>
55 #include <netinet6/natpt_defs.h>
56 #include <netinet6/natpt_list.h>
57 #include <netinet6/natpt_soctl.h>
58 #include <netinet6/natpt_var.h>
65 static Cell
*_insideHash
[NATPT_MAXHASH
];
66 static Cell
*_outsideHash
[NATPT_MAXHASH
];
68 static Cell
*tSlotEntry
;
69 static int tSlotEntryMax
;
70 static int tSlotEntryUsed
;
72 static time_t tSlotTimer
;
73 static time_t maxTTLany
;
74 static time_t maxTTLicmp
;
75 static time_t maxTTLudp
;
76 static time_t maxTTLtcp
;
78 static time_t _natpt_TCPT_2MSL
;
79 static time_t _natpt_tcp_maxidle
;
81 extern struct in6_addr natpt_prefix
;
82 extern struct in6_addr natpt_prefixmask
;
83 extern struct in6_addr faith_prefix
;
84 extern struct in6_addr faith_prefixmask
;
86 static struct pAddr
*fillupOutgoingV6local
__P((struct _cSlot
*, struct _cv
*, struct pAddr
*));
87 static struct pAddr
*fillupOutgoingV6Remote
__P((struct _cSlot
*, struct _cv
*, struct pAddr
*));
89 static struct _tSlot
*registTSlotEntry
__P((struct _tSlot
*));
90 static void _expireTSlot
__P((void *));
91 static void _expireTSlotEntry
__P((struct timeval
*));
92 static void _removeTSlotEntry
__P((struct _cell
*, struct _cell
*));
93 static int _removeHash
__P((struct _cell
*(*table
)[], int, caddr_t
));
95 static int _hash_ip4
__P((struct _cv
*));
96 static int _hash_ip6
__P((struct _cv
*));
97 static int _hash_pat4
__P((struct pAddr
*));
98 static int _hash_pat6
__P((struct pAddr
*));
99 static int _hash_sockaddr4
__P((struct sockaddr_in
*));
100 static int _hash_sockaddr6
__P((struct sockaddr_in6
*));
101 static int _hash_pjw
__P((u_char
*, int));
104 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
105 static MALLOC_DEFINE(M_NATPT
, "NATPT", "Network Address Translation - Protocol Translation");
114 lookingForIncomingV4Hash(struct _cv
*cv
)
117 register struct _tSlot
*ats
;
118 register struct ip
*ip4
;
120 int hv
= _hash_ip4(cv
);
122 for (p
= _outsideHash
[hv
]; p
; p
= CDR(p
))
124 ats
= (struct _tSlot
*)CAR(p
);
126 if ((ats
->remote
.ip_p
!= IPPROTO_IPV4
)
127 || (cv
->ip_payload
!= ats
->ip_payload
)) continue;
129 if ((cv
->ip_payload
== IPPROTO_TCP
)
130 || (cv
->ip_payload
== IPPROTO_UDP
))
132 if (cv
->_payload
._tcp4
->th_sport
!= ats
->remote
._dport
) continue;
133 if (cv
->_payload
._tcp4
->th_dport
!= ats
->remote
._sport
) continue;
137 if ((ip4
->ip_src
.s_addr
== ats
->remote
.in4dst
.s_addr
)
138 && (ip4
->ip_dst
.s_addr
== ats
->remote
.in4src
.s_addr
))
147 lookingForOutgoingV4Hash(struct _cv
*cv
)
150 register struct _tSlot
*ats
;
151 register struct ip
*ip4
;
153 int hv
= _hash_ip4(cv
);
155 for (p
= _insideHash
[hv
]; p
; p
= CDR(p
))
157 ats
= (struct _tSlot
*)CAR(p
);
159 if ((ats
->local
.ip_p
!= IPPROTO_IPV4
)
160 || (cv
->ip_payload
!= ats
->ip_payload
)) continue;
162 if ((cv
->ip_payload
== IPPROTO_TCP
)
163 || (cv
->ip_payload
== IPPROTO_UDP
))
165 if (cv
->_payload
._tcp4
->th_sport
!= ats
->local
._dport
) continue;
166 if (cv
->_payload
._tcp4
->th_dport
!= ats
->local
._sport
) continue;
170 if ((ip4
->ip_src
.s_addr
== ats
->local
.in4dst
.s_addr
)
171 && (ip4
->ip_dst
.s_addr
== ats
->local
.in4src
.s_addr
))
180 lookingForIncomingV6Hash(struct _cv
*cv
)
183 register struct _tSlot
*ats
;
184 register struct ip6_hdr
*ip6
;
186 int hv
= _hash_ip6(cv
);
188 for (p
= _outsideHash
[hv
]; p
; p
= CDR(p
))
190 ats
= (struct _tSlot
*)CAR(p
);
192 if ((ats
->remote
.ip_p
!= IPPROTO_IPV6
)
193 || (cv
->ip_payload
!= ats
->ip_payload
)) continue;
195 if ((cv
->ip_payload
== IPPROTO_TCP
)
196 || (cv
->ip_payload
== IPPROTO_UDP
))
198 if (cv
->_payload
._tcp6
->th_sport
!= ats
->remote
._dport
) continue;
199 if (cv
->_payload
._tcp6
->th_dport
!= ats
->remote
._sport
) continue;
203 if ((IN6_ARE_ADDR_EQUAL(&ip6
->ip6_src
, &ats
->remote
.in6dst
))
204 && (IN6_ARE_ADDR_EQUAL(&ip6
->ip6_dst
, &ats
->remote
.in6src
)))
213 lookingForOutgoingV6Hash(struct _cv
*cv
)
216 register struct _tSlot
*ats
;
217 register struct ip6_hdr
*ip6
;
219 int hv
= _hash_ip6(cv
);
221 for (p
= _insideHash
[hv
]; p
; p
= CDR(p
))
223 ats
= (struct _tSlot
*)CAR(p
);
225 if ((ats
->local
.ip_p
!= IPPROTO_IPV6
)
226 || (cv
->ip_payload
!= ats
->ip_payload
)) continue;
228 if ((cv
->ip_payload
== IPPROTO_TCP
)
229 || (cv
->ip_payload
== IPPROTO_UDP
))
231 if (cv
->_payload
._tcp6
->th_sport
!= ats
->local
._dport
) continue;
232 if (cv
->_payload
._tcp6
->th_dport
!= ats
->local
._sport
) continue;
236 if ((IN6_ARE_ADDR_EQUAL(&ip6
->ip6_src
, &ats
->local
.in6dst
))
237 && (IN6_ARE_ADDR_EQUAL(&ip6
->ip6_dst
, &ats
->local
.in6src
)))
246 internIncomingV4Hash(int sess
, struct _cSlot
*acs
, struct _cv
*cv4
)
249 struct pAddr
*local
, *remote
;
252 MALLOC(ats
, struct _tSlot
*, sizeof(struct _tSlot
), M_TEMP
, M_NOWAIT
);
255 printf("ENOBUFS in internIncomingV4Hash %d\n", __LINE__
);
259 bzero(ats
, sizeof(struct _tSlot
));
262 remote
= &ats
->remote
;
265 if (acs
->local
.sa_family
== AF_INET
)
267 local
->ip_p
= IPPROTO_IPV4
;
268 local
->sa_family
= AF_INET
;
269 local
->in4src
= cv4
->_ip
._ip4
->ip_src
;
270 local
->in4dst
= acs
->local
.in4Addr
;
271 if ((cv4
->ip_payload
== IPPROTO_TCP
)
272 || (cv4
->ip_payload
== IPPROTO_UDP
))
274 local
->_sport
= cv4
->_payload
._tcp4
->th_sport
;
275 local
->_dport
= cv4
->_payload
._tcp4
->th_dport
;
276 if (acs
->map
& NATPT_PORT_MAP
)
278 local
->_dport
= acs
->local
._port0
;
285 local
->ip_p
= IPPROTO_IPV6
;
286 local
->sa_family
= AF_INET6
;
287 local
->in6src
= natpt_prefix
;
288 local
->in6src
.s6_addr32
[3] = cv4
->_ip
._ip4
->ip_src
.s_addr
;
289 local
->in6dst
= acs
->local
.in6src
;
290 if ((cv4
->ip_payload
== IPPROTO_TCP
)
291 || (cv4
->ip_payload
== IPPROTO_UDP
))
293 local
->_sport
= cv4
->_payload
._tcp4
->th_sport
;
294 local
->_dport
= cv4
->_payload
._tcp4
->th_dport
;
296 if (acs
->map
& NATPT_PORT_MAP
)
298 local
->_dport
= acs
->local
._port0
;
304 remote
= &ats
->remote
;
305 remote
->ip_p
= IPPROTO_IPV4
;
306 remote
->sa_family
= AF_INET
;
307 remote
->in4src
= acs
->remote
.in4src
;
308 remote
->in4dst
= cv4
->_ip
._ip4
->ip_src
;
309 if (acs
->remote
.ad
.type
== ADDR_ANY
)
311 remote
->in4src
= cv4
->_ip
._ip4
->ip_dst
;
314 if ((cv4
->ip_payload
== IPPROTO_TCP
)
315 || (cv4
->ip_payload
== IPPROTO_UDP
))
317 remote
->_sport
= cv4
->_payload
._tcp4
->th_dport
;
318 remote
->_dport
= cv4
->_payload
._tcp4
->th_sport
;
321 ats
->ip_payload
= cv4
->ip_payload
;
323 registTSlotEntry(ats
); /* XXX */
325 hv4
= _hash_pat4(remote
);
327 if (acs
->local
.sa_family
== AF_INET
)
328 hv6
= _hash_pat4(local
);
331 hv6
= _hash_pat6(local
);
335 LST_hookup_list(&_insideHash
[hv6
], ats
);
336 LST_hookup_list(&_outsideHash
[hv4
], ats
);
344 internOutgoingV4Hash(int sess
, struct _cSlot
*acs
, struct _cv
*cv4
)
347 struct pAddr
*local
, *remote
;
350 MALLOC(ats
, struct _tSlot
*, sizeof(struct _tSlot
), M_TEMP
, M_NOWAIT
);
353 printf("ENOBUFS in internOutgoingV4Hash %d\n", __LINE__
);
357 bzero(ats
, sizeof(struct _tSlot
));
360 local
->ip_p
= IPPROTO_IPV4
;
361 local
->sa_family
= AF_INET
;
362 if ((cv4
->ip_payload
== IPPROTO_TCP
)
363 || (cv4
->ip_payload
== IPPROTO_UDP
))
365 local
->_sport
= cv4
->_payload
._tcp4
->th_dport
;
366 local
->_dport
= cv4
->_payload
._tcp4
->th_sport
;
369 local
->in4src
= cv4
->_ip
._ip4
->ip_dst
;
370 local
->in4dst
= cv4
->_ip
._ip4
->ip_src
;
372 remote
= &ats
->remote
;
374 if (acs
->remote
.sa_family
== AF_INET
)
376 remote
->ip_p
= IPPROTO_IPV4
;
377 remote
->sa_family
= AF_INET
;
378 if ((cv4
->ip_payload
== IPPROTO_TCP
)
379 || (cv4
->ip_payload
== IPPROTO_UDP
))
381 remote
->_sport
= cv4
->_payload
._tcp4
->th_sport
;
382 remote
->_dport
= cv4
->_payload
._tcp4
->th_dport
;
384 remote
->in4src
= acs
->remote
.in4src
;
385 remote
->in4dst
= cv4
->_ip
._ip4
->ip_dst
;
388 #else /* need check */
390 remote
->ip_p
= IPPROTO_IPV6
;
391 remote
->sa_family
= AF_INET6
;
392 if ((cv4
->ip_payload
== IPPROTO_TCP
)
393 || (cv4
->ip_payload
== IPPROTO_UDP
))
395 remote
->_sport
= cv4
->_payload
._tcp4
->th_sport
;
396 remote
->_dport
= cv4
->_payload
._tcp4
->th_dport
;
399 if (acs
->flags
== NATPT_FAITH
)
401 struct in6_ifaddr
*ia6
;
403 remote
->in6dst
.s6_addr32
[0] = faith_prefix
.s6_addr32
[0];
404 remote
->in6dst
.s6_addr32
[1] = faith_prefix
.s6_addr32
[1];
405 remote
->in6dst
.s6_addr32
[3] = cv4
->_ip
._ip4
->ip_dst
.s_addr
;
407 ia6
= in6_ifawithscope(natpt_ip6src
, &remote
->in6dst
);
408 remote
->in6src
= ia6
->ia_addr
.sin6_addr
;
412 remote
->in6src
.s6_addr32
[3] = cv4
->_ip
._ip4
->ip_src
.s_addr
;
413 remote
->in6dst
= acs
->remote
.in6src
;
418 ats
->ip_payload
= cv4
->ip_payload
;
420 registTSlotEntry(ats
); /* XXX */
422 hv4
= _hash_pat4(local
);
424 if (acs
->remote
.sa_family
== AF_INET
)
425 hv6
= _hash_pat4(remote
);
428 hv6
= _hash_pat6(remote
);
432 LST_hookup_list(&_insideHash
[hv4
], ats
);
433 LST_hookup_list(&_outsideHash
[hv6
], ats
);
441 internIncomingV6Hash(int sess
, struct _cSlot
*acs
, struct _cv
*cv6
)
444 struct pAddr
*local
, *remote
;
447 MALLOC(ats
, struct _tSlot
*, sizeof(struct _tSlot
), M_TEMP
, M_NOWAIT
);
450 printf("ENOBUFS in internIncomingV6Hash %d\n", __LINE__
);
454 bzero(ats
, sizeof(struct _tSlot
));
457 local
->ip_p
= IPPROTO_IPV4
;
458 local
->sa_family
= AF_INET
;
459 if ((cv6
->ip_payload
== IPPROTO_TCP
)
460 || (cv6
->ip_payload
== IPPROTO_UDP
))
462 local
->_sport
= cv6
->_payload
._tcp6
->th_sport
;
463 local
->_dport
= cv6
->_payload
._tcp6
->th_dport
;
465 local
->in4src
= acs
->local
.in4src
;
466 local
->in4dst
.s_addr
= cv6
->_ip
._ip6
->ip6_dst
.s6_addr32
[3];
467 local
->sa_family
= AF_INET
;
468 local
->ip_p
= IPPROTO_IPV4
;
470 remote
= &ats
->remote
;
471 remote
->ip_p
= IPPROTO_IPV6
;
472 if ((cv6
->ip_payload
== IPPROTO_TCP
)
473 || (cv6
->ip_payload
== IPPROTO_UDP
))
475 remote
->_sport
= cv6
->_payload
._tcp6
->th_dport
;
476 remote
->_dport
= cv6
->_payload
._tcp6
->th_sport
;
478 remote
->in6src
= cv6
->_ip
._ip6
->ip6_dst
;
479 remote
->in6dst
= acs
->remote
.in6dst
;
480 remote
->sa_family
= AF_INET6
;
481 remote
->ip_p
= IPPROTO_IPV6
;
483 ats
->ip_payload
= cv6
->ip_payload
;
485 registTSlotEntry(ats
); /* XXX */
487 hv6
= _hash_pat6(remote
);
488 hv4
= _hash_pat4(local
);
491 LST_hookup_list(&_outsideHash
[hv6
], ats
);
492 LST_hookup_list(&_insideHash
[hv4
], ats
);
500 internOutgoingV6Hash(int sess
, struct _cSlot
*acs
, struct _cv
*cv6
)
503 struct pAddr
*local
, *remote
;
506 natpt_logIp6(LOG_DEBUG
, cv6
->_ip
._ip6
);
508 MALLOC(ats
, struct _tSlot
*, sizeof(struct _tSlot
), M_TEMP
, M_NOWAIT
);
511 printf("ENOBUFS in internOutgoingV6Hash %d\n", __LINE__
);
515 bzero(ats
, sizeof(struct _tSlot
));
517 local
= fillupOutgoingV6local(acs
, cv6
, &ats
->local
);
518 if ((remote
= fillupOutgoingV6Remote(acs
, cv6
, &ats
->remote
)) == 0)
524 ats
->ip_payload
= cv6
->ip_payload
;
526 registTSlotEntry(ats
); /* XXX */
528 hv6
= _hash_pat6(local
);
529 hv4
= _hash_pat4(remote
);
532 LST_hookup_list(&_insideHash
[hv6
], ats
);
533 LST_hookup_list(&_outsideHash
[hv4
], ats
);
541 checkTraceroute6Return(struct _cv
*cv4
)
546 struct udphdr
*icmpudp4
;
547 struct sockaddr_in src
, dst
;
550 if ((cv4
->ip_payload
!= IPPROTO_ICMP
)
551 || ((cv4
->_payload
._icmp4
->icmp_type
!= ICMP_UNREACH
)
552 && (cv4
->_payload
._icmp4
->icmp_type
!= ICMP_TIMXCEED
)))
555 icmpip4
= &cv4
->_payload
._icmp4
->icmp_ip
;
556 if (icmpip4
->ip_p
!= IPPROTO_UDP
)
559 #ifdef fixSuMiReICMPBug
560 icmpip4
->ip_src
.s_addr
= ICMPSRC
; /* XXX */
563 icmpudp4
= (struct udphdr
*)((caddr_t
)icmpip4
+ (icmpip4
->ip_hl
<< 2));
565 bzero(&src
, sizeof(struct sockaddr_in
));
566 bzero(&dst
, sizeof(struct sockaddr_in
));
567 src
.sin_addr
= icmpip4
->ip_src
;
568 src
.sin_port
= icmpudp4
->uh_sport
;
569 dst
.sin_addr
= icmpip4
->ip_dst
;
570 dst
.sin_port
= icmpudp4
->uh_dport
;
571 hv
= ((_hash_sockaddr4(&src
) + _hash_sockaddr4(&dst
)) % NATPT_MAXHASH
);
572 for (p
= _outsideHash
[hv
]; p
; p
= CDR(p
))
574 ats
= (struct _tSlot
*)CAR(p
);
576 if (ats
->remote
.ip_p
!= IPPROTO_IPV4
) continue;
577 if (ats
->ip_payload
!= IPPROTO_UDP
) continue;
579 if (icmpip4
->ip_src
.s_addr
!= ats
->remote
.in4src
.s_addr
) continue;
580 if (icmpip4
->ip_dst
.s_addr
!= ats
->remote
.in4dst
.s_addr
) continue;
582 if (icmpudp4
->uh_sport
!= ats
->remote
._sport
) continue;
583 if (icmpudp4
->uh_dport
!= ats
->remote
._dport
) continue;
585 cv4
->flags
|= NATPT_TRACEROUTE
;
593 static struct pAddr
*
594 fillupOutgoingV6local(struct _cSlot
*acs
, struct _cv
*cv6
, struct pAddr
*local
)
596 local
->ip_p
= IPPROTO_IPV6
;
597 local
->sa_family
= AF_INET6
;
598 local
->in6src
= cv6
->_ip
._ip6
->ip6_dst
;
599 local
->in6dst
= cv6
->_ip
._ip6
->ip6_src
;
601 if ((cv6
->ip_payload
== IPPROTO_TCP
)
602 || (cv6
->ip_payload
== IPPROTO_UDP
))
604 local
->_sport
= cv6
->_payload
._tcp6
->th_dport
;
605 local
->_dport
= cv6
->_payload
._tcp6
->th_sport
;
612 static struct pAddr
*
613 fillupOutgoingV6Remote(struct _cSlot
*acs
, struct _cv
*cv6
, struct pAddr
*remote
)
615 remote
->ip_p
= IPPROTO_IPV4
;
616 remote
->sa_family
= AF_INET
;
617 remote
->in4src
= acs
->remote
.in4src
;
618 remote
->in4dst
.s_addr
= cv6
->_ip
._ip6
->ip6_dst
.s6_addr32
[3];
620 if ((cv6
->ip_payload
== IPPROTO_TCP
)
621 || (cv6
->ip_payload
== IPPROTO_UDP
))
623 remote
->_sport
= cv6
->_payload
._tcp6
->th_sport
;
624 remote
->_dport
= cv6
->_payload
._tcp6
->th_dport
;
627 * In case mappoing port number,
628 * acs->remote.port[0..1] has source port mapping range (from command line).
629 * remote->port[0..1] has actual translation slot info.
631 if (acs
->map
& NATPT_PORT_MAP_DYNAMIC
)
634 u_short cport
, sport
, eport
;
635 struct pAddr pata
; /* pata.{s,d}port hold network byte order */
637 cport
= ntohs(acs
->cport
);
638 sport
= ntohs(acs
->remote
._sport
);
639 eport
= ntohs(acs
->remote
._eport
);
644 bzero(&pata
, sizeof(pata
));
645 pata
.ip_p
= IPPROTO_IPV4
;
646 pata
.sa_family
= AF_INET
;
647 pata
.in4src
= acs
->remote
.in4src
;
648 pata
.in4dst
.s_addr
= cv6
->_ip
._ip6
->ip6_dst
.s6_addr32
[3];
649 pata
._dport
= remote
->_dport
;
653 while (++cport
<= eport
)
655 pata
._sport
= htons(cport
);
656 if (_outsideHash
[_hash_pat4(&pata
)] == NULL
)
668 remote
->_sport
= acs
->cport
= htons(cport
);
676 static struct _tSlot
*
677 registTSlotEntry(struct _tSlot
*ats
)
683 if (tSlotEntryUsed
>= tSlotEntryMax
)
689 ats
->tstamp
= atv
.tv_sec
;
691 p
= LST_cons(ats
, NULL
);
695 if (tSlotEntry
== NULL
)
698 CDR(p
) = tSlotEntry
, tSlotEntry
= p
;
711 _expireTSlot(void *ignored_arg
)
715 boolean_t funnel_state
;
716 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
719 timeout(_expireTSlot
, (caddr_t
)0, tSlotTimer
);
722 _expireTSlotEntry(&atv
);
724 (void) thread_funnel_set(network_flock
, FALSE
);
730 _expireTSlotEntry(struct timeval
*atv
)
732 struct _cell
*p0
, *p1
, *q
;
739 tsl
= (struct _tSlot
*)CAR(p0
);
742 switch (tsl
->ip_payload
)
745 if ((atv
->tv_sec
- tsl
->tstamp
) >= maxTTLicmp
)
746 _removeTSlotEntry(p0
, q
);
750 if ((atv
->tv_sec
- tsl
->tstamp
) >= maxTTLudp
)
751 _removeTSlotEntry(p0
, q
);
755 switch (tsl
->suit
.tcp
->_state
)
758 if ((atv
->tv_sec
- tsl
->tstamp
) >= _natpt_TCPT_2MSL
)
759 _removeTSlotEntry(p0
, q
);
763 case TCPS_SYN_RECEIVED
:
764 if ((atv
->tv_sec
- tsl
->tstamp
) >= _natpt_tcp_maxidle
)
765 _removeTSlotEntry(p0
, q
);
768 case TCPS_ESTABLISHED
:
769 if ((atv
->tv_sec
- tsl
->tstamp
) >= maxTTLtcp
)
770 _removeTSlotEntry(p0
, q
);
773 case TCPS_FIN_WAIT_1
:
774 case TCPS_FIN_WAIT_2
:
775 if ((atv
->tv_sec
- tsl
->tstamp
) >= _natpt_tcp_maxidle
)
776 _removeTSlotEntry(p0
, q
);
780 if ((atv
->tv_sec
- tsl
->tstamp
) >= _natpt_TCPT_2MSL
)
781 _removeTSlotEntry(p0
, q
);
785 if ((atv
->tv_sec
- tsl
->tstamp
) >= maxTTLtcp
)
786 _removeTSlotEntry(p0
, q
);
792 if ((atv
->tv_sec
- tsl
->tstamp
) >= maxTTLany
)
793 _removeTSlotEntry(p0
, q
);
797 if (CAR(p0
) != CELL_FREE_MARKER
) /* p0 may not removed */
806 _removeTSlotEntry(struct _cell
*p
, struct _cell
*q
)
810 struct _tSlot
*tsl
= (struct _tSlot
*)CAR(p
);
812 if ((tsl
->ip_payload
== IPPROTO_TCP
)
813 && (tsl
->suit
.tcp
!= NULL
))
815 FREE(tsl
->suit
.tcp
, M_NATPT
);
818 if (tsl
->local
.ip_p
== IPPROTO_IPV4
)
819 hvin
= _hash_pat4(&tsl
->local
);
821 hvin
= _hash_pat6(&tsl
->local
);
823 if (tsl
->remote
.ip_p
== IPPROTO_IPV4
)
824 hvout
= _hash_pat4(&tsl
->remote
);
826 hvout
= _hash_pat6(&tsl
->remote
);
830 _removeHash(&_insideHash
, hvin
, (caddr_t
)tsl
);
831 _removeHash(&_outsideHash
, hvout
, (caddr_t
)tsl
);
848 _removeHash(Cell
*(*table
)[], int hv
, caddr_t node
)
850 register Cell
*p
, *q
;
852 if ((p
= (*table
)[hv
]) == NULL
)
857 if (CAR(p
) == (Cell
*)node
)
865 for (p
= (*table
)[hv
], q
= NULL
; p
; q
= p
, p
= CDR(p
))
867 if (CAR(p
) != (Cell
*)node
)
871 (*table
)[hv
] = CDR(p
);
888 _hash_ip4(struct _cv
*cv
)
891 struct sockaddr_in src
, dst
;
893 bzero(&src
, sizeof(struct sockaddr_in
));
894 bzero(&dst
, sizeof(struct sockaddr_in
));
897 src
.sin_addr
= ip
->ip_src
;
898 dst
.sin_addr
= ip
->ip_dst
;
900 if ((ip
->ip_p
== IPPROTO_TCP
) || (ip
->ip_p
== IPPROTO_UDP
))
902 struct tcphdr
*tcp
= cv
->_payload
._tcp4
;
904 src
.sin_port
= tcp
->th_sport
;
905 dst
.sin_port
= tcp
->th_dport
;
908 return ((_hash_sockaddr4(&src
) + _hash_sockaddr4(&dst
)) % NATPT_MAXHASH
);
913 _hash_ip6(struct _cv
*cv
)
916 struct sockaddr_in6 src
, dst
;
918 bzero(&src
, sizeof(struct sockaddr_in6
));
919 bzero(&dst
, sizeof(struct sockaddr_in6
));
922 src
.sin6_addr
= ip6
->ip6_src
;
923 dst
.sin6_addr
= ip6
->ip6_dst
;
925 if ((cv
->ip_payload
== IPPROTO_TCP
) || (cv
->ip_payload
== IPPROTO_UDP
))
927 struct tcp6hdr
*tcp6
= cv
->_payload
._tcp6
;
929 src
.sin6_port
= tcp6
->th_sport
;
930 dst
.sin6_port
= tcp6
->th_dport
;
933 return ((_hash_sockaddr6(&src
) + _hash_sockaddr6(&dst
)) % NATPT_MAXHASH
);
938 _hash_pat4(struct pAddr
*pat4
)
940 struct sockaddr_in src
, dst
;
942 bzero(&src
, sizeof(struct sockaddr_in
));
943 bzero(&dst
, sizeof(struct sockaddr_in
));
945 src
.sin_port
= pat4
->_sport
;
946 src
.sin_addr
= pat4
->in4src
;
947 dst
.sin_port
= pat4
->_dport
;
948 dst
.sin_addr
= pat4
->in4dst
;
950 return ((_hash_sockaddr4(&src
) + _hash_sockaddr4(&dst
)) % NATPT_MAXHASH
);
955 _hash_pat6(struct pAddr
*pat6
)
957 struct sockaddr_in6 src
, dst
;
959 bzero(&src
, sizeof(struct sockaddr_in6
));
960 bzero(&dst
, sizeof(struct sockaddr_in6
));
962 src
.sin6_port
= pat6
->_sport
;
963 src
.sin6_addr
= pat6
->in6src
;
964 dst
.sin6_port
= pat6
->_dport
;
965 dst
.sin6_addr
= pat6
->in6dst
;
967 return ((_hash_sockaddr6(&src
) + _hash_sockaddr6(&dst
)) % NATPT_MAXHASH
);
972 _hash_sockaddr4(struct sockaddr_in
*sin4
)
976 byte
= sizeof(sin4
->sin_port
) + sizeof(sin4
->sin_addr
);
977 return (_hash_pjw((char *)&sin4
->sin_port
, byte
));
982 _hash_sockaddr6(struct sockaddr_in6
*sin6
)
986 sin6
->sin6_flowinfo
= 0;
987 byte
= sizeof(sin6
->sin6_port
)
988 + sizeof(sin6
->sin6_flowinfo
)
989 + sizeof(sin6
->sin6_addr
);
990 return (_hash_pjw((char *)&sin6
->sin6_port
, byte
));
995 /* This hash routine is byte order sensitive. Be Careful. */
998 _hash_pjw(register u_char
*s
, int len
)
1001 register u_int h
, g
;
1003 for (c
= h
= g
= 0; c
< len
; c
++, s
++)
1005 h
= (h
<< 4) + (*s
);
1006 if ((g
= h
& 0xf0000000))
1012 return (h
% NATPT_MAXHASH
);
1023 bzero((caddr_t
)_insideHash
, sizeof(_insideHash
));
1024 bzero((caddr_t
)_outsideHash
, sizeof(_outsideHash
));
1032 tSlotEntryMax
= MAXTSLOTENTRY
;
1035 tSlotTimer
= 60 * hz
;
1036 timeout(_expireTSlot
, (caddr_t
)0, tSlotTimer
);
1038 _natpt_TCPT_2MSL
= 120; /* [sec] */
1039 _natpt_tcp_maxidle
= 600; /* [sec] */
1041 maxTTLicmp
= maxTTLudp
= _natpt_TCPT_2MSL
;
1042 maxTTLtcp
= maxTTLany
= 86400; /* [sec] */