]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/natpt_tslot.c
xnu-201.42.3.tar.gz
[apple/xnu.git] / bsd / netinet6 / natpt_tslot.c
CommitLineData
1c79356b
A
1/* $KAME: natpt_tslot.c,v 1.8 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/kernel.h>
34#include <sys/malloc.h>
35#include <sys/socket.h>
36#include <sys/syslog.h>
37#include <sys/systm.h>
38
39#include <net/if.h>
40
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>
48
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>
53#endif
54
55#include <netinet6/natpt_defs.h>
56#include <netinet6/natpt_list.h>
57#include <netinet6/natpt_soctl.h>
58#include <netinet6/natpt_var.h>
59
60
61/*
62 *
63 */
64
65static Cell *_insideHash [NATPT_MAXHASH];
66static Cell *_outsideHash[NATPT_MAXHASH];
67
68static Cell *tSlotEntry;
69static int tSlotEntryMax;
70static int tSlotEntryUsed;
71
72static time_t tSlotTimer;
73static time_t maxTTLany;
74static time_t maxTTLicmp;
75static time_t maxTTLudp;
76static time_t maxTTLtcp;
77
78static time_t _natpt_TCPT_2MSL;
79static time_t _natpt_tcp_maxidle;
80
81extern struct in6_addr natpt_prefix;
82extern struct in6_addr natpt_prefixmask;
83extern struct in6_addr faith_prefix;
84extern struct in6_addr faith_prefixmask;
85
86static struct pAddr *fillupOutgoingV6local __P((struct _cSlot *, struct _cv *, struct pAddr *));
87static struct pAddr *fillupOutgoingV6Remote __P((struct _cSlot *, struct _cv *, struct pAddr *));
88
89static struct _tSlot *registTSlotEntry __P((struct _tSlot *));
90static void _expireTSlot __P((void *));
91static void _expireTSlotEntry __P((struct timeval *));
92static void _removeTSlotEntry __P((struct _cell *, struct _cell *));
93static int _removeHash __P((struct _cell *(*table)[], int, caddr_t));
94
95static int _hash_ip4 __P((struct _cv *));
96static int _hash_ip6 __P((struct _cv *));
97static int _hash_pat4 __P((struct pAddr *));
98static int _hash_pat6 __P((struct pAddr *));
99static int _hash_sockaddr4 __P((struct sockaddr_in *));
100static int _hash_sockaddr6 __P((struct sockaddr_in6 *));
101static int _hash_pjw __P((u_char *, int));
102
103
104#if defined(__FreeBSD__) && __FreeBSD__ >= 3
105static MALLOC_DEFINE(M_NATPT, "NATPT", "Network Address Translation - Protocol Translation");
106#endif
107
108
109/*
110 *
111 */
112
113struct _tSlot *
114lookingForIncomingV4Hash(struct _cv *cv)
115{
116 register Cell *p;
117 register struct _tSlot *ats;
118 register struct ip *ip4;
119
120 int hv = _hash_ip4(cv);
121
122 for (p = _outsideHash[hv]; p; p = CDR(p))
123 {
124 ats = (struct _tSlot *)CAR(p);
125
126 if ((ats->remote.ip_p != IPPROTO_IPV4)
127 || (cv->ip_payload != ats->ip_payload)) continue;
128
129 if ((cv->ip_payload == IPPROTO_TCP)
130 || (cv->ip_payload == IPPROTO_UDP))
131 {
132 if (cv->_payload._tcp4->th_sport!= ats->remote._dport) continue;
133 if (cv->_payload._tcp4->th_dport!= ats->remote._sport) continue;
134 }
135
136 ip4 = cv->_ip._ip4;
137 if ((ip4->ip_src.s_addr == ats->remote.in4dst.s_addr)
138 && (ip4->ip_dst.s_addr == ats->remote.in4src.s_addr))
139 return (ats);
140 }
141
142 return (NULL);
143}
144
145
146struct _tSlot *
147lookingForOutgoingV4Hash(struct _cv *cv)
148{
149 register Cell *p;
150 register struct _tSlot *ats;
151 register struct ip *ip4;
152
153 int hv = _hash_ip4(cv);
154
155 for (p = _insideHash[hv]; p; p = CDR(p))
156 {
157 ats = (struct _tSlot *)CAR(p);
158
159 if ((ats->local.ip_p != IPPROTO_IPV4)
160 || (cv->ip_payload != ats->ip_payload)) continue;
161
162 if ((cv->ip_payload == IPPROTO_TCP)
163 || (cv->ip_payload == IPPROTO_UDP))
164 {
165 if (cv->_payload._tcp4->th_sport != ats->local._dport) continue;
166 if (cv->_payload._tcp4->th_dport != ats->local._sport) continue;
167 }
168
169 ip4 = cv->_ip._ip4;
170 if ((ip4->ip_src.s_addr == ats->local.in4dst.s_addr)
171 && (ip4->ip_dst.s_addr == ats->local.in4src.s_addr))
172 return (ats);
173 }
174
175 return (NULL);
176}
177
178
179struct _tSlot *
180lookingForIncomingV6Hash(struct _cv *cv)
181{
182 register Cell *p;
183 register struct _tSlot *ats;
184 register struct ip6_hdr *ip6;
185
186 int hv = _hash_ip6(cv);
187
188 for (p = _outsideHash[hv]; p; p = CDR(p))
189 {
190 ats = (struct _tSlot *)CAR(p);
191
192 if ((ats->remote.ip_p != IPPROTO_IPV6)
193 || (cv->ip_payload != ats->ip_payload)) continue;
194
195 if ((cv->ip_payload == IPPROTO_TCP)
196 || (cv->ip_payload == IPPROTO_UDP))
197 {
198 if (cv->_payload._tcp6->th_sport != ats->remote._dport) continue;
199 if (cv->_payload._tcp6->th_dport != ats->remote._sport) continue;
200 }
201
202 ip6 = cv->_ip._ip6;
203 if ((IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ats->remote.in6dst))
204 && (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ats->remote.in6src)))
205 return (ats);
206 }
207
208 return (NULL);
209}
210
211
212struct _tSlot *
213lookingForOutgoingV6Hash(struct _cv *cv)
214{
215 register Cell *p;
216 register struct _tSlot *ats;
217 register struct ip6_hdr *ip6;
218
219 int hv = _hash_ip6(cv);
220
221 for (p = _insideHash[hv]; p; p = CDR(p))
222 {
223 ats = (struct _tSlot *)CAR(p);
224
225 if ((ats->local.ip_p != IPPROTO_IPV6)
226 || (cv->ip_payload != ats->ip_payload)) continue;
227
228 if ((cv->ip_payload == IPPROTO_TCP)
229 || (cv->ip_payload == IPPROTO_UDP))
230 {
231 if (cv->_payload._tcp6->th_sport != ats->local._dport) continue;
232 if (cv->_payload._tcp6->th_dport != ats->local._sport) continue;
233 }
234
235 ip6 = cv->_ip._ip6;
236 if ((IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ats->local.in6dst))
237 && (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ats->local.in6src)))
238 return (ats);
239 }
240
241 return (NULL);
242}
243
244
245struct _tSlot *
246internIncomingV4Hash(int sess, struct _cSlot *acs, struct _cv *cv4)
247{
248 int s, hv4, hv6;
249 struct pAddr *local, *remote;
250 struct _tSlot *ats;
251
252 MALLOC(ats, struct _tSlot *, sizeof(struct _tSlot), M_TEMP, M_NOWAIT);
253 if (ats == NULL)
254 {
255 printf("ENOBUFS in internIncomingV4Hash %d\n", __LINE__);
256 return (NULL);
257 }
258
259 bzero(ats, sizeof(struct _tSlot));
260
261 local = &ats->local;
262 remote = &ats->remote;
263
264#ifdef NATPT_NAT
265 if (acs->local.sa_family == AF_INET)
266 {
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))
273 {
274 local->_sport = cv4->_payload._tcp4->th_sport;
275 local->_dport = cv4->_payload._tcp4->th_dport;
276 if (acs->map & NATPT_PORT_MAP)
277 {
278 local->_dport = acs->local._port0;
279 }
280 }
281 }
282 else
283#else
284 {
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))
292 {
293 local->_sport = cv4->_payload._tcp4->th_sport;
294 local->_dport = cv4->_payload._tcp4->th_dport;
295
296 if (acs->map & NATPT_PORT_MAP)
297 {
298 local->_dport = acs->local._port0;
299 }
300 }
301 }
302#endif
303
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)
310 {
311 remote->in4src = cv4->_ip._ip4->ip_dst;
312 }
313
314 if ((cv4->ip_payload == IPPROTO_TCP)
315 || (cv4->ip_payload == IPPROTO_UDP))
316 {
317 remote->_sport = cv4->_payload._tcp4->th_dport;
318 remote->_dport = cv4->_payload._tcp4->th_sport;
319 }
320
321 ats->ip_payload = cv4->ip_payload;
322 ats->session = sess;
323 registTSlotEntry(ats); /* XXX */
324
325 hv4 = _hash_pat4(remote);
326#ifdef NATPT_NAT
327 if (acs->local.sa_family == AF_INET)
328 hv6 = _hash_pat4(local);
329 else
330#else
331 hv6 = _hash_pat6(local);
332#endif
333
334 s = splnet();
335 LST_hookup_list(&_insideHash [hv6], ats);
336 LST_hookup_list(&_outsideHash[hv4], ats);
337 splx(s);
338
339 return (ats);
340}
341
342
343struct _tSlot *
344internOutgoingV4Hash(int sess, struct _cSlot *acs, struct _cv *cv4)
345{
346 int s, hv4, hv6;
347 struct pAddr *local, *remote;
348 struct _tSlot *ats;
349
350 MALLOC(ats, struct _tSlot *, sizeof(struct _tSlot), M_TEMP, M_NOWAIT);
351 if (ats == NULL)
352 {
353 printf("ENOBUFS in internOutgoingV4Hash %d\n", __LINE__);
354 return (NULL);
355 }
356
357 bzero(ats, sizeof(struct _tSlot));
358
359 local = &ats->local;
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))
364 {
365 local->_sport = cv4->_payload._tcp4->th_dport;
366 local->_dport = cv4->_payload._tcp4->th_sport;
367 }
368
369 local->in4src = cv4->_ip._ip4->ip_dst;
370 local->in4dst = cv4->_ip._ip4->ip_src;
371
372 remote = &ats->remote;
373#ifdef NATPT_NAT
374 if (acs->remote.sa_family == AF_INET)
375 {
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))
380 {
381 remote->_sport = cv4->_payload._tcp4->th_sport;
382 remote->_dport = cv4->_payload._tcp4->th_dport;
383 }
384 remote->in4src = acs->remote.in4src;
385 remote->in4dst = cv4->_ip._ip4->ip_dst;
386 }
387 else
388#else /* need check */
389 {
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))
394 {
395 remote->_sport = cv4->_payload._tcp4->th_sport;
396 remote->_dport = cv4->_payload._tcp4->th_dport;
397 }
398
399 if (acs->flags == NATPT_FAITH)
400 {
401 struct in6_ifaddr *ia6;
402
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;
406
407 ia6 = in6_ifawithscope(natpt_ip6src, &remote->in6dst);
408 remote->in6src = ia6->ia_addr.sin6_addr;
409 }
410 else
411 {
412 remote->in6src.s6_addr32[3] = cv4->_ip._ip4->ip_src.s_addr;
413 remote->in6dst = acs->remote.in6src;
414 }
415 }
416#endif
417
418 ats->ip_payload = cv4->ip_payload;
419 ats->session = sess;
420 registTSlotEntry(ats); /* XXX */
421
422 hv4 = _hash_pat4(local);
423#ifdef NATPT_NAT
424 if (acs->remote.sa_family == AF_INET)
425 hv6 = _hash_pat4(remote);
426 else
427#else
428 hv6 = _hash_pat6(remote);
429#endif
430
431 s = splnet();
432 LST_hookup_list(&_insideHash [hv4], ats);
433 LST_hookup_list(&_outsideHash[hv6], ats);
434 splx(s);
435
436 return (ats);
437}
438
439
440struct _tSlot *
441internIncomingV6Hash(int sess, struct _cSlot *acs, struct _cv *cv6)
442{
443 int s, hv4, hv6;
444 struct pAddr *local, *remote;
445 struct _tSlot *ats;
446
447 MALLOC(ats, struct _tSlot *, sizeof(struct _tSlot), M_TEMP, M_NOWAIT);
448 if (ats == NULL)
449 {
450 printf("ENOBUFS in internIncomingV6Hash %d\n", __LINE__);
451 return (NULL);
452 }
453
454 bzero(ats, sizeof(struct _tSlot));
455
456 local = &ats->local;
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))
461 {
462 local->_sport = cv6->_payload._tcp6->th_sport;
463 local->_dport = cv6->_payload._tcp6->th_dport;
464 }
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;
469
470 remote = &ats->remote;
471 remote->ip_p = IPPROTO_IPV6;
472 if ((cv6->ip_payload == IPPROTO_TCP)
473 || (cv6->ip_payload == IPPROTO_UDP))
474 {
475 remote->_sport = cv6->_payload._tcp6->th_dport;
476 remote->_dport = cv6->_payload._tcp6->th_sport;
477 }
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;
482
483 ats->ip_payload = cv6->ip_payload;
484 ats->session = sess;
485 registTSlotEntry(ats); /* XXX */
486
487 hv6 = _hash_pat6(remote);
488 hv4 = _hash_pat4(local);
489
490 s = splnet();
491 LST_hookup_list(&_outsideHash[hv6], ats);
492 LST_hookup_list(&_insideHash [hv4], ats);
493 splx(s);
494
495 return (ats);
496}
497
498
499struct _tSlot *
500internOutgoingV6Hash(int sess, struct _cSlot *acs, struct _cv *cv6)
501{
502 int s, hv4, hv6;
503 struct pAddr *local, *remote;
504 struct _tSlot *ats;
505
506 natpt_logIp6(LOG_DEBUG, cv6->_ip._ip6);
507
508 MALLOC(ats, struct _tSlot *, sizeof(struct _tSlot), M_TEMP, M_NOWAIT);
509 if (ats == NULL)
510 {
511 printf("ENOBUFS in internOutgoingV6Hash %d\n", __LINE__);
512 return (NULL);
513 }
514
515 bzero(ats, sizeof(struct _tSlot));
516
517 local = fillupOutgoingV6local(acs, cv6, &ats->local);
518 if ((remote = fillupOutgoingV6Remote(acs, cv6, &ats->remote)) == 0)
519 {
520 FREE(ats, M_TEMP);
521 return (NULL);
522 }
523
524 ats->ip_payload = cv6->ip_payload;
525 ats->session = sess;
526 registTSlotEntry(ats); /* XXX */
527
528 hv6 = _hash_pat6(local);
529 hv4 = _hash_pat4(remote);
530
531 s = splnet();
532 LST_hookup_list(&_insideHash [hv6], ats);
533 LST_hookup_list(&_outsideHash[hv4], ats);
534 splx(s);
535
536 return (ats);
537}
538
539
540struct _tSlot *
541checkTraceroute6Return(struct _cv *cv4)
542{
543 int hv;
544 Cell *p;
545 struct ip *icmpip4;
546 struct udphdr *icmpudp4;
547 struct sockaddr_in src, dst;
548 struct _tSlot *ats;
549
550 if ((cv4->ip_payload != IPPROTO_ICMP)
551 || ((cv4->_payload._icmp4->icmp_type != ICMP_UNREACH)
552 && (cv4->_payload._icmp4->icmp_type != ICMP_TIMXCEED)))
553 return (NULL);
554
555 icmpip4 = &cv4->_payload._icmp4->icmp_ip;
556 if (icmpip4->ip_p != IPPROTO_UDP)
557 return (NULL);
558
559#ifdef fixSuMiReICMPBug
560 icmpip4->ip_src.s_addr = ICMPSRC; /* XXX */
561#endif
562
563 icmpudp4 = (struct udphdr *)((caddr_t)icmpip4 + (icmpip4->ip_hl << 2));
564
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))
573 {
574 ats = (struct _tSlot *)CAR(p);
575
576 if (ats->remote.ip_p != IPPROTO_IPV4) continue;
577 if (ats->ip_payload != IPPROTO_UDP) continue;
578
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;
581
582 if (icmpudp4->uh_sport != ats->remote._sport) continue;
583 if (icmpudp4->uh_dport != ats->remote._dport) continue;
584
585 cv4->flags |= NATPT_TRACEROUTE;
586 return (ats);
587 }
588
589 return (NULL);
590}
591
592
593static struct pAddr *
594fillupOutgoingV6local(struct _cSlot *acs, struct _cv *cv6, struct pAddr *local)
595{
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;
600
601 if ((cv6->ip_payload == IPPROTO_TCP)
602 || (cv6->ip_payload == IPPROTO_UDP))
603 {
604 local->_sport = cv6->_payload._tcp6->th_dport;
605 local->_dport = cv6->_payload._tcp6->th_sport;
606 }
607
608 return (local);
609}
610
611
612static struct pAddr *
613fillupOutgoingV6Remote(struct _cSlot *acs, struct _cv *cv6, struct pAddr *remote)
614{
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];
619
620 if ((cv6->ip_payload == IPPROTO_TCP)
621 || (cv6->ip_payload == IPPROTO_UDP))
622 {
623 remote->_sport = cv6->_payload._tcp6->th_sport;
624 remote->_dport = cv6->_payload._tcp6->th_dport;
625
626 /*
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.
630 */
631 if (acs->map & NATPT_PORT_MAP_DYNAMIC)
632 {
633 int firsttime = 0;
634 u_short cport, sport, eport;
635 struct pAddr pata; /* pata.{s,d}port hold network byte order */
636
637 cport = ntohs(acs->cport);
638 sport = ntohs(acs->remote._sport);
639 eport = ntohs(acs->remote._eport);
640
641 if (cport == 0)
642 cport = sport - 1;
643
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;
650
651 for (;;)
652 {
653 while (++cport <= eport)
654 {
655 pata._sport = htons(cport);
656 if (_outsideHash[_hash_pat4(&pata)] == NULL)
657 goto found;
658 }
659
660 if (firsttime == 0)
661 firsttime++,
662 cport = sport - 1;
663 else
664 return (NULL);
665 }
666
667 found:;
668 remote->_sport = acs->cport = htons(cport);
669 }
670 }
671
672 return (remote);
673}
674
675
676static struct _tSlot *
677registTSlotEntry(struct _tSlot *ats)
678{
679 int s;
680 Cell *p;
681 struct timeval atv;
682
683 if (tSlotEntryUsed >= tSlotEntryMax)
684 return (NULL);
685
686 tSlotEntryUsed++;
687
688 microtime(&atv);
689 ats->tstamp = atv.tv_sec;
690
691 p = LST_cons(ats, NULL);
692
693 s = splnet();
694
695 if (tSlotEntry == NULL)
696 tSlotEntry = p;
697 else
698 CDR(p) = tSlotEntry, tSlotEntry = p;
699
700 splx(s);
701
702 return (ats);
703}
704
705
706/*
707 *
708 */
709
710static void
711_expireTSlot(void *ignored_arg)
712{
713 struct timeval atv;
714#ifdef __APPLE__
715 boolean_t funnel_state;
0b4e3aa0 716 funnel_state = thread_funnel_set(network_flock, TRUE);
1c79356b
A
717#endif
718
719 timeout(_expireTSlot, (caddr_t)0, tSlotTimer);
720 microtime(&atv);
721
722 _expireTSlotEntry(&atv);
723#ifdef __APPLE__
0b4e3aa0 724 (void) thread_funnel_set(network_flock, FALSE);
1c79356b
A
725#endif
726}
727
728
729static void
730_expireTSlotEntry(struct timeval *atv)
731{
732 struct _cell *p0, *p1, *q;
733 struct _tSlot *tsl;
734
735 p0 = tSlotEntry;
736 q = NULL;
737 while (p0)
738 {
739 tsl = (struct _tSlot *)CAR(p0);
740 p1 = CDR(p0);
741
742 switch (tsl->ip_payload)
743 {
744 case IPPROTO_ICMP:
745 if ((atv->tv_sec - tsl->tstamp) >= maxTTLicmp)
746 _removeTSlotEntry(p0, q);
747 break;
748
749 case IPPROTO_UDP:
750 if ((atv->tv_sec - tsl->tstamp) >= maxTTLudp)
751 _removeTSlotEntry(p0, q);
752 break;
753
754 case IPPROTO_TCP:
755 switch (tsl->suit.tcp->_state)
756 {
757 case TCPS_CLOSED:
758 if ((atv->tv_sec - tsl->tstamp) >= _natpt_TCPT_2MSL)
759 _removeTSlotEntry(p0, q);
760 break;
761
762 case TCPS_SYN_SENT:
763 case TCPS_SYN_RECEIVED:
764 if ((atv->tv_sec - tsl->tstamp) >= _natpt_tcp_maxidle)
765 _removeTSlotEntry(p0, q);
766 break;
767
768 case TCPS_ESTABLISHED:
769 if ((atv->tv_sec - tsl->tstamp) >= maxTTLtcp)
770 _removeTSlotEntry(p0, q);
771 break;
772
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);
777 break;
778
779 case TCPS_TIME_WAIT:
780 if ((atv->tv_sec - tsl->tstamp) >= _natpt_TCPT_2MSL)
781 _removeTSlotEntry(p0, q);
782 break;
783
784 default:
785 if ((atv->tv_sec - tsl->tstamp) >= maxTTLtcp)
786 _removeTSlotEntry(p0, q);
787 break;
788 }
789 break;
790
791 default:
792 if ((atv->tv_sec - tsl->tstamp) >= maxTTLany)
793 _removeTSlotEntry(p0, q);
794 break;
795 }
796
797 if (CAR(p0) != CELL_FREE_MARKER) /* p0 may not removed */
798 q = p0;
799
800 p0 = p1;
801 }
802}
803
804
805static void
806_removeTSlotEntry(struct _cell *p, struct _cell *q)
807{
808 int s;
809 int hvin, hvout;
810 struct _tSlot *tsl = (struct _tSlot *)CAR(p);
811
812 if ((tsl->ip_payload == IPPROTO_TCP)
813 && (tsl->suit.tcp != NULL))
814 {
815 FREE(tsl->suit.tcp, M_NATPT);
816 }
817
818 if (tsl->local.ip_p == IPPROTO_IPV4)
819 hvin = _hash_pat4(&tsl->local);
820 else
821 hvin = _hash_pat6(&tsl->local);
822
823 if (tsl->remote.ip_p == IPPROTO_IPV4)
824 hvout = _hash_pat4(&tsl->remote);
825 else
826 hvout = _hash_pat6(&tsl->remote);
827
828 s = splnet();
829
830 _removeHash(&_insideHash, hvin, (caddr_t)tsl);
831 _removeHash(&_outsideHash, hvout, (caddr_t)tsl);
832
833 if (q != NULL)
834 CDR(q) = CDR(p);
835 else
836 tSlotEntry = CDR(p);
837
838 splx(s);
839
840 LST_free(p);
841 FREE(tsl, M_NATPT);
842
843 tSlotEntryUsed--;
844}
845
846
847static int
848_removeHash(Cell *(*table)[], int hv, caddr_t node)
849{
850 register Cell *p, *q;
851
852 if ((p = (*table)[hv]) == NULL)
853 return (0);
854
855 if (CDR(p) == NULL)
856 {
857 if (CAR(p) == (Cell *)node)
858 {
859 LST_free(p);
860 (*table)[hv] = NULL;
861 }
862 return (0);
863 }
864
865 for (p = (*table)[hv], q = NULL; p; q = p, p = CDR(p))
866 {
867 if (CAR(p) != (Cell *)node)
868 continue;
869
870 if (q == NULL)
871 (*table)[hv] = CDR(p);
872 else
873 CDR(q) = CDR(p);
874
875 LST_free(p);
876 return (0);
877 }
878
879 return (0);
880}
881
882
883/*
884 *
885 */
886
887static int
888_hash_ip4(struct _cv *cv)
889{
890 struct ip *ip;
891 struct sockaddr_in src, dst;
892
893 bzero(&src, sizeof(struct sockaddr_in));
894 bzero(&dst, sizeof(struct sockaddr_in));
895
896 ip = cv->_ip._ip4;
897 src.sin_addr = ip->ip_src;
898 dst.sin_addr = ip->ip_dst;
899
900 if ((ip->ip_p == IPPROTO_TCP) || (ip->ip_p == IPPROTO_UDP))
901 {
902 struct tcphdr *tcp = cv->_payload._tcp4;
903
904 src.sin_port = tcp->th_sport;
905 dst.sin_port = tcp->th_dport;
906 }
907
908 return ((_hash_sockaddr4(&src) + _hash_sockaddr4(&dst)) % NATPT_MAXHASH);
909}
910
911
912static int
913_hash_ip6(struct _cv *cv)
914{
915 struct ip6_hdr *ip6;
916 struct sockaddr_in6 src, dst;
917
918 bzero(&src, sizeof(struct sockaddr_in6));
919 bzero(&dst, sizeof(struct sockaddr_in6));
920
921 ip6 = cv->_ip._ip6;
922 src.sin6_addr = ip6->ip6_src;
923 dst.sin6_addr = ip6->ip6_dst;
924
925 if ((cv->ip_payload == IPPROTO_TCP) || (cv->ip_payload == IPPROTO_UDP))
926 {
927 struct tcp6hdr *tcp6 = cv->_payload._tcp6;
928
929 src.sin6_port = tcp6->th_sport;
930 dst.sin6_port = tcp6->th_dport;
931 }
932
933 return ((_hash_sockaddr6(&src) + _hash_sockaddr6(&dst)) % NATPT_MAXHASH);
934}
935
936
937static int
938_hash_pat4(struct pAddr *pat4)
939{
940 struct sockaddr_in src, dst;
941
942 bzero(&src, sizeof(struct sockaddr_in));
943 bzero(&dst, sizeof(struct sockaddr_in));
944
945 src.sin_port = pat4->_sport;
946 src.sin_addr = pat4->in4src;
947 dst.sin_port = pat4->_dport;
948 dst.sin_addr = pat4->in4dst;
949
950 return ((_hash_sockaddr4(&src) + _hash_sockaddr4(&dst)) % NATPT_MAXHASH);
951}
952
953
954static int
955_hash_pat6(struct pAddr *pat6)
956{
957 struct sockaddr_in6 src, dst;
958
959 bzero(&src, sizeof(struct sockaddr_in6));
960 bzero(&dst, sizeof(struct sockaddr_in6));
961
962 src.sin6_port = pat6->_sport;
963 src.sin6_addr = pat6->in6src;
964 dst.sin6_port = pat6->_dport;
965 dst.sin6_addr = pat6->in6dst;
966
967 return ((_hash_sockaddr6(&src) + _hash_sockaddr6(&dst)) % NATPT_MAXHASH);
968}
969
970
971static int
972_hash_sockaddr4(struct sockaddr_in *sin4)
973{
974 int byte;
975
976 byte = sizeof(sin4->sin_port) + sizeof(sin4->sin_addr);
977 return (_hash_pjw((char *)&sin4->sin_port, byte));
978}
979
980
981static int
982_hash_sockaddr6(struct sockaddr_in6 *sin6)
983{
984 int byte;
985
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));
991}
992
993
994/* CAUTION */
995/* This hash routine is byte order sensitive. Be Careful. */
996
997static int
998_hash_pjw(register u_char *s, int len)
999{
1000 register u_int c;
1001 register u_int h, g;
1002
1003 for (c = h = g = 0; c < len; c++, s++)
1004 {
1005 h = (h << 4) + (*s);
1006 if ((g = h & 0xf0000000))
1007 {
1008 h ^= (g >> 24);
1009 h ^= g;
1010 }
1011 }
1012 return (h % NATPT_MAXHASH);
1013}
1014
1015
1016/*
1017 *
1018 */
1019
1020void
1021init_hash()
1022{
1023 bzero((caddr_t)_insideHash, sizeof(_insideHash));
1024 bzero((caddr_t)_outsideHash, sizeof(_outsideHash));
1025}
1026
1027
1028void
1029init_tslot()
1030{
1031 tSlotEntry = NULL;
1032 tSlotEntryMax = MAXTSLOTENTRY;
1033 tSlotEntryUsed = 0;
1034
1035 tSlotTimer = 60 * hz;
1036 timeout(_expireTSlot, (caddr_t)0, tSlotTimer);
1037
1038 _natpt_TCPT_2MSL = 120; /* [sec] */
1039 _natpt_tcp_maxidle = 600; /* [sec] */
1040
1041 maxTTLicmp = maxTTLudp = _natpt_TCPT_2MSL;
1042 maxTTLtcp = maxTTLany = 86400; /* [sec] */
1043}