Wed May 26 14:48:02 2021 UTC ()
Fix ip_nat memory leak and use-after-free, wrong element freed (Cy Schubert)
https://cgit.freebsd.org/src/commit/?id=323a4e2c4e285e6f8eee8db3fe2cb74


(christos)
diff -r1.23 -r1.24 src/sys/external/bsd/ipf/netinet/ip_nat.c

cvs diff -r1.23 -r1.24 src/sys/external/bsd/ipf/netinet/ip_nat.c (switch to unified diff)

--- src/sys/external/bsd/ipf/netinet/ip_nat.c 2020/08/01 06:50:42 1.23
+++ src/sys/external/bsd/ipf/netinet/ip_nat.c 2021/05/26 14:48:02 1.24
@@ -1,1114 +1,1114 @@ @@ -1,1114 +1,1114 @@
1/* $NetBSD: ip_nat.c,v 1.23 2020/08/01 06:50:42 maxv Exp $ */ 1/* $NetBSD: ip_nat.c,v 1.24 2021/05/26 14:48:02 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (C) 2012 by Darren Reed. 4 * Copyright (C) 2012 by Darren Reed.
5 * 5 *
6 * See the IPFILTER.LICENCE file for details on licencing. 6 * See the IPFILTER.LICENCE file for details on licencing.
7 */ 7 */
8#if defined(KERNEL) || defined(_KERNEL) 8#if defined(KERNEL) || defined(_KERNEL)
9# undef KERNEL 9# undef KERNEL
10# undef KERNEL 10# undef KERNEL
11# define KERNEL 1 11# define KERNEL 1
12# define KERNEL 1 12# define KERNEL 1
13#endif 13#endif
14#include <sys/errno.h> 14#include <sys/errno.h>
15#include <sys/types.h> 15#include <sys/types.h>
16#include <sys/param.h> 16#include <sys/param.h>
17#include <sys/time.h> 17#include <sys/time.h>
18#include <sys/file.h> 18#include <sys/file.h>
19#if defined(_KERNEL) && \ 19#if defined(_KERNEL) && \
20 (defined(__NetBSD_Version) && (__NetBSD_Version >= 399002000)) 20 (defined(__NetBSD_Version) && (__NetBSD_Version >= 399002000))
21# include <sys/kauth.h> 21# include <sys/kauth.h>
22#endif 22#endif
23#if !defined(_KERNEL) 23#if !defined(_KERNEL)
24# include <stdio.h> 24# include <stdio.h>
25# include <string.h> 25# include <string.h>
26# include <stdlib.h> 26# include <stdlib.h>
27# define KERNEL 27# define KERNEL
28# ifdef _OpenBSD__ 28# ifdef _OpenBSD__
29struct file; 29struct file;
30# endif 30# endif
31# include <sys/uio.h> 31# include <sys/uio.h>
32# undef KERNEL 32# undef KERNEL
33#endif 33#endif
34#if defined(_KERNEL) && \ 34#if defined(_KERNEL) && \
35 defined(__FreeBSD_version) && (__FreeBSD_version >= 220000) 35 defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
36# include <sys/filio.h> 36# include <sys/filio.h>
37# include <sys/fcntl.h> 37# include <sys/fcntl.h>
38#else 38#else
39# include <sys/ioctl.h> 39# include <sys/ioctl.h>
40#endif 40#endif
41#if !defined(AIX) 41#if !defined(AIX)
42# include <sys/fcntl.h> 42# include <sys/fcntl.h>
43#endif 43#endif
44#if !defined(linux) 44#if !defined(linux)
45# include <sys/protosw.h> 45# include <sys/protosw.h>
46#endif 46#endif
47#include <sys/socket.h> 47#include <sys/socket.h>
48#if defined(_KERNEL) 48#if defined(_KERNEL)
49# include <sys/systm.h> 49# include <sys/systm.h>
50# if !defined(__SVR4) && !defined(__svr4__) 50# if !defined(__SVR4) && !defined(__svr4__)
51# include <sys/mbuf.h> 51# include <sys/mbuf.h>
52# endif 52# endif
53#endif 53#endif
54#if defined(__SVR4) || defined(__svr4__) 54#if defined(__SVR4) || defined(__svr4__)
55# include <sys/filio.h> 55# include <sys/filio.h>
56# include <sys/byteorder.h> 56# include <sys/byteorder.h>
57# ifdef KERNEL 57# ifdef KERNEL
58# include <sys/dditypes.h> 58# include <sys/dditypes.h>
59# endif 59# endif
60# include <sys/stream.h> 60# include <sys/stream.h>
61# include <sys/kmem.h> 61# include <sys/kmem.h>
62#endif 62#endif
63#if _FreeBSD_version >= 300000 63#if _FreeBSD_version >= 300000
64# include <sys/queue.h> 64# include <sys/queue.h>
65#endif 65#endif
66#include <net/if.h> 66#include <net/if.h>
67#if _FreeBSD_version >= 300000 67#if _FreeBSD_version >= 300000
68# include <net/if_var.h> 68# include <net/if_var.h>
69#endif 69#endif
70#ifdef sun 70#ifdef sun
71# include <net/af.h> 71# include <net/af.h>
72#endif 72#endif
73#include <netinet/in.h> 73#include <netinet/in.h>
74#include <netinet/in_systm.h> 74#include <netinet/in_systm.h>
75#include <netinet/ip.h> 75#include <netinet/ip.h>
76 76
77#ifdef RFC1825 77#ifdef RFC1825
78# include <vpn/md5.h> 78# include <vpn/md5.h>
79# include <vpn/ipsec.h> 79# include <vpn/ipsec.h>
80extern struct ifnet vpnif; 80extern struct ifnet vpnif;
81#endif 81#endif
82 82
83#if !defined(linux) 83#if !defined(linux)
84# include <netinet/ip_var.h> 84# include <netinet/ip_var.h>
85#endif 85#endif
86#include <netinet/tcp.h> 86#include <netinet/tcp.h>
87#include <netinet/udp.h> 87#include <netinet/udp.h>
88#include <netinet/ip_icmp.h> 88#include <netinet/ip_icmp.h>
89#include "netinet/ip_compat.h" 89#include "netinet/ip_compat.h"
90#include "netinet/ipl.h" 90#include "netinet/ipl.h"
91#include "netinet/ip_fil.h" 91#include "netinet/ip_fil.h"
92#include "netinet/ip_nat.h" 92#include "netinet/ip_nat.h"
93#include "netinet/ip_frag.h" 93#include "netinet/ip_frag.h"
94#include "netinet/ip_state.h" 94#include "netinet/ip_state.h"
95#include "netinet/ip_proxy.h" 95#include "netinet/ip_proxy.h"
96#include "netinet/ip_lookup.h" 96#include "netinet/ip_lookup.h"
97#include "netinet/ip_dstlist.h" 97#include "netinet/ip_dstlist.h"
98#include "netinet/ip_sync.h" 98#include "netinet/ip_sync.h"
99#if FREEBSD_GE_REV(300000) 99#if FREEBSD_GE_REV(300000)
100# include <sys/malloc.h> 100# include <sys/malloc.h>
101#endif 101#endif
102#ifdef HAS_SYS_MD5_H 102#ifdef HAS_SYS_MD5_H
103# include <sys/md5.h> 103# include <sys/md5.h>
104#else 104#else
105# include "md5.h" 105# include "md5.h"
106#endif 106#endif
107/* END OF INCLUDES */ 107/* END OF INCLUDES */
108 108
109#undef SOCKADDR_IN 109#undef SOCKADDR_IN
110#define SOCKADDR_IN struct sockaddr_in 110#define SOCKADDR_IN struct sockaddr_in
111 111
112#if !defined(lint) 112#if !defined(lint)
113#if defined(__NetBSD__) 113#if defined(__NetBSD__)
114#include <sys/cdefs.h> 114#include <sys/cdefs.h>
115__KERNEL_RCSID(0, "$NetBSD: ip_nat.c,v 1.23 2020/08/01 06:50:42 maxv Exp $"); 115__KERNEL_RCSID(0, "$NetBSD: ip_nat.c,v 1.24 2021/05/26 14:48:02 christos Exp $");
116#else 116#else
117static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; 117static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
118static const char rcsid[] = "@(#)Id: ip_nat.c,v 1.1.1.2 2012/07/22 13:45:27 darrenr Exp"; 118static const char rcsid[] = "@(#)Id: ip_nat.c,v 1.1.1.2 2012/07/22 13:45:27 darrenr Exp";
119#endif 119#endif
120#endif 120#endif
121 121
122 122
123#define NATFSUM(n,v,f) ((v) == 4 ? (n)->f.in4.s_addr : (n)->f.i6[0] + \ 123#define NATFSUM(n,v,f) ((v) == 4 ? (n)->f.in4.s_addr : (n)->f.i6[0] + \
124 (n)->f.i6[1] + (n)->f.i6[2] + (n)->f.i6[3]) 124 (n)->f.i6[1] + (n)->f.i6[2] + (n)->f.i6[3])
125#define NBUMP(x) softn->(x)++ 125#define NBUMP(x) softn->(x)++
126#define NBUMPD(x, y) do { \ 126#define NBUMPD(x, y) do { \
127 softn->x.y++; \ 127 softn->x.y++; \
128 DT(y); \ 128 DT(y); \
129 } while (0) 129 } while (0)
130#define NBUMPSIDE(y,x) softn->ipf_nat_stats.ns_side[y].x++ 130#define NBUMPSIDE(y,x) softn->ipf_nat_stats.ns_side[y].x++
131#define NBUMPSIDED(y,x) do { softn->ipf_nat_stats.ns_side[y].x++; \ 131#define NBUMPSIDED(y,x) do { softn->ipf_nat_stats.ns_side[y].x++; \
132 DT(x); } while (0) 132 DT(x); } while (0)
133#define NBUMPSIDEX(y,x,z) \ 133#define NBUMPSIDEX(y,x,z) \
134 do { softn->ipf_nat_stats.ns_side[y].x++; \ 134 do { softn->ipf_nat_stats.ns_side[y].x++; \
135 DT(z); } while (0) 135 DT(z); } while (0)
136#define NBUMPSIDEDF(y,x)do { softn->ipf_nat_stats.ns_side[y].x++; \ 136#define NBUMPSIDEDF(y,x)do { softn->ipf_nat_stats.ns_side[y].x++; \
137 DT1(x, fr_info_t *, fin); } while (0) 137 DT1(x, fr_info_t *, fin); } while (0)
138 138
139frentry_t ipfnatblock; 139frentry_t ipfnatblock;
140 140
141static const ipftuneable_t ipf_nat_tuneables[] = { 141static const ipftuneable_t ipf_nat_tuneables[] = {
142 /* nat */ 142 /* nat */
143 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_lock) }, 143 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_lock) },
144 "nat_lock", 0, 1, 144 "nat_lock", 0, 1,
145 stsizeof(ipf_nat_softc_t, ipf_nat_lock), 145 stsizeof(ipf_nat_softc_t, ipf_nat_lock),
146 IPFT_RDONLY, NULL, NULL }, 146 IPFT_RDONLY, NULL, NULL },
147 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_sz) }, 147 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_sz) },
148 "nat_table_size", 1, 0x7fffffff, 148 "nat_table_size", 1, 0x7fffffff,
149 stsizeof(ipf_nat_softc_t, ipf_nat_table_sz), 149 stsizeof(ipf_nat_softc_t, ipf_nat_table_sz),
150 0, NULL, ipf_nat_rehash }, 150 0, NULL, ipf_nat_rehash },
151 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_max) }, 151 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_max) },
152 "nat_table_max", 1, 0x7fffffff, 152 "nat_table_max", 1, 0x7fffffff,
153 stsizeof(ipf_nat_softc_t, ipf_nat_table_max), 153 stsizeof(ipf_nat_softc_t, ipf_nat_table_max),
154 0, NULL, NULL }, 154 0, NULL, NULL },
155 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz) }, 155 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_maprules_sz) },
156 "nat_rules_size", 1, 0x7fffffff, 156 "nat_rules_size", 1, 0x7fffffff,
157 stsizeof(ipf_nat_softc_t, ipf_nat_maprules_sz), 157 stsizeof(ipf_nat_softc_t, ipf_nat_maprules_sz),
158 0, NULL, ipf_nat_rehash_rules }, 158 0, NULL, ipf_nat_rehash_rules },
159 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz) }, 159 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_rdrrules_sz) },
160 "rdr_rules_size", 1, 0x7fffffff, 160 "rdr_rules_size", 1, 0x7fffffff,
161 stsizeof(ipf_nat_softc_t, ipf_nat_rdrrules_sz), 161 stsizeof(ipf_nat_softc_t, ipf_nat_rdrrules_sz),
162 0, NULL, ipf_nat_rehash_rules }, 162 0, NULL, ipf_nat_rehash_rules },
163 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz) }, 163 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_hostmap_sz) },
164 "hostmap_size", 1, 0x7fffffff, 164 "hostmap_size", 1, 0x7fffffff,
165 stsizeof(ipf_nat_softc_t, ipf_nat_hostmap_sz), 165 stsizeof(ipf_nat_softc_t, ipf_nat_hostmap_sz),
166 0, NULL, ipf_nat_hostmap_rehash }, 166 0, NULL, ipf_nat_hostmap_rehash },
167 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_maxbucket) }, 167 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_maxbucket) },
168 "nat_maxbucket",1, 0x7fffffff, 168 "nat_maxbucket",1, 0x7fffffff,
169 stsizeof(ipf_nat_softc_t, ipf_nat_maxbucket), 169 stsizeof(ipf_nat_softc_t, ipf_nat_maxbucket),
170 0, NULL, NULL }, 170 0, NULL, NULL },
171 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_logging) }, 171 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_logging) },
172 "nat_logging", 0, 1, 172 "nat_logging", 0, 1,
173 stsizeof(ipf_nat_softc_t, ipf_nat_logging), 173 stsizeof(ipf_nat_softc_t, ipf_nat_logging),
174 0, NULL, NULL }, 174 0, NULL, NULL },
175 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_doflush) }, 175 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_doflush) },
176 "nat_doflush", 0, 1, 176 "nat_doflush", 0, 1,
177 stsizeof(ipf_nat_softc_t, ipf_nat_doflush), 177 stsizeof(ipf_nat_softc_t, ipf_nat_doflush),
178 0, NULL, NULL }, 178 0, NULL, NULL },
179 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_wm_low) }, 179 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_wm_low) },
180 "nat_table_wm_low", 1, 99, 180 "nat_table_wm_low", 1, 99,
181 stsizeof(ipf_nat_softc_t, ipf_nat_table_wm_low), 181 stsizeof(ipf_nat_softc_t, ipf_nat_table_wm_low),
182 0, NULL, NULL }, 182 0, NULL, NULL },
183 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_wm_high) }, 183 { { (void *)offsetof(ipf_nat_softc_t, ipf_nat_table_wm_high) },
184 "nat_table_wm_high", 2, 100, 184 "nat_table_wm_high", 2, 100,
185 stsizeof(ipf_nat_softc_t, ipf_nat_table_wm_high), 185 stsizeof(ipf_nat_softc_t, ipf_nat_table_wm_high),
186 0, NULL, NULL }, 186 0, NULL, NULL },
187 { { 0 }, 187 { { 0 },
188 NULL, 0, 0, 188 NULL, 0, 0,
189 0, 189 0,
190 0, NULL, NULL } 190 0, NULL, NULL }
191}; 191};
192 192
193/* ======================================================================== */ 193/* ======================================================================== */
194/* How the NAT is organised and works. */ 194/* How the NAT is organised and works. */
195/* */ 195/* */
196/* Inside (interface y) NAT Outside (interface x) */ 196/* Inside (interface y) NAT Outside (interface x) */
197/* -------------------- -+- ------------------------------------- */ 197/* -------------------- -+- ------------------------------------- */
198/* Packet going | out, processsed by ipf_nat_checkout() for x */ 198/* Packet going | out, processsed by ipf_nat_checkout() for x */
199/* ------------> | ------------> */ 199/* ------------> | ------------> */
200/* src=10.1.1.1 | src=192.1.1.1 */ 200/* src=10.1.1.1 | src=192.1.1.1 */
201/* | */ 201/* | */
202/* | in, processed by ipf_nat_checkin() for x */ 202/* | in, processed by ipf_nat_checkin() for x */
203/* <------------ | <------------ */ 203/* <------------ | <------------ */
204/* dst=10.1.1.1 | dst=192.1.1.1 */ 204/* dst=10.1.1.1 | dst=192.1.1.1 */
205/* -------------------- -+- ------------------------------------- */ 205/* -------------------- -+- ------------------------------------- */
206/* ipf_nat_checkout() - changes ip_src and if required, sport */ 206/* ipf_nat_checkout() - changes ip_src and if required, sport */
207/* - creates a new mapping, if required. */ 207/* - creates a new mapping, if required. */
208/* ipf_nat_checkin() - changes ip_dst and if required, dport */ 208/* ipf_nat_checkin() - changes ip_dst and if required, dport */
209/* */ 209/* */
210/* In the NAT table, internal source is recorded as "in" and externally */ 210/* In the NAT table, internal source is recorded as "in" and externally */
211/* seen as "out". */ 211/* seen as "out". */
212/* ======================================================================== */ 212/* ======================================================================== */
213 213
214 214
215#if SOLARIS && !defined(INSTANCES) 215#if SOLARIS && !defined(INSTANCES)
216extern int pfil_delayed_copy; 216extern int pfil_delayed_copy;
217#endif 217#endif
218 218
219static int ipf_nat_flush_entry(ipf_main_softc_t *, void *); 219static int ipf_nat_flush_entry(ipf_main_softc_t *, void *);
220static int ipf_nat_getent(ipf_main_softc_t *, void *, int); 220static int ipf_nat_getent(ipf_main_softc_t *, void *, int);
221static int ipf_nat_getsz(ipf_main_softc_t *, void *, int); 221static int ipf_nat_getsz(ipf_main_softc_t *, void *, int);
222static int ipf_nat_putent(ipf_main_softc_t *, void *, int); 222static int ipf_nat_putent(ipf_main_softc_t *, void *, int);
223static void ipf_nat_addmap(ipf_nat_softc_t *, ipnat_t *); 223static void ipf_nat_addmap(ipf_nat_softc_t *, ipnat_t *);
224static void ipf_nat_addrdr(ipf_nat_softc_t *, ipnat_t *); 224static void ipf_nat_addrdr(ipf_nat_softc_t *, ipnat_t *);
225static int ipf_nat_builddivertmp(ipf_nat_softc_t *, ipnat_t *); 225static int ipf_nat_builddivertmp(ipf_nat_softc_t *, ipnat_t *);
226static int ipf_nat_clearlist(ipf_main_softc_t *, ipf_nat_softc_t *); 226static int ipf_nat_clearlist(ipf_main_softc_t *, ipf_nat_softc_t *);
227static int ipf_nat_cmp_rules(ipnat_t *, ipnat_t *); 227static int ipf_nat_cmp_rules(ipnat_t *, ipnat_t *);
228static int ipf_nat_decap(fr_info_t *, nat_t *); 228static int ipf_nat_decap(fr_info_t *, nat_t *);
229static void ipf_nat_delrule(ipf_main_softc_t *, ipf_nat_softc_t *, 229static void ipf_nat_delrule(ipf_main_softc_t *, ipf_nat_softc_t *,
230 ipnat_t *, int); 230 ipnat_t *, int);
231static int ipf_nat_extraflush(ipf_main_softc_t *, ipf_nat_softc_t *, int); 231static int ipf_nat_extraflush(ipf_main_softc_t *, ipf_nat_softc_t *, int);
232static int ipf_nat_finalise(fr_info_t *, nat_t *); 232static int ipf_nat_finalise(fr_info_t *, nat_t *);
233static int ipf_nat_flushtable(ipf_main_softc_t *, ipf_nat_softc_t *); 233static int ipf_nat_flushtable(ipf_main_softc_t *, ipf_nat_softc_t *);
234static int ipf_nat_getnext(ipf_main_softc_t *, ipftoken_t *, 234static int ipf_nat_getnext(ipf_main_softc_t *, ipftoken_t *,
235 ipfgeniter_t *, ipfobj_t *); 235 ipfgeniter_t *, ipfobj_t *);
236static int ipf_nat_gettable(ipf_main_softc_t *, ipf_nat_softc_t *, char *); 236static int ipf_nat_gettable(ipf_main_softc_t *, ipf_nat_softc_t *, char *);
237static hostmap_t *ipf_nat_hostmap(ipf_nat_softc_t *, ipnat_t *, 237static hostmap_t *ipf_nat_hostmap(ipf_nat_softc_t *, ipnat_t *,
238 struct in_addr, struct in_addr, 238 struct in_addr, struct in_addr,
239 struct in_addr, u_32_t); 239 struct in_addr, u_32_t);
240static int ipf_nat_icmpquerytype(int); 240static int ipf_nat_icmpquerytype(int);
241static int ipf_nat_iterator(ipf_main_softc_t *, ipftoken_t *, 241static int ipf_nat_iterator(ipf_main_softc_t *, ipftoken_t *,
242 ipfgeniter_t *, ipfobj_t *); 242 ipfgeniter_t *, ipfobj_t *);
243static int ipf_nat_match(fr_info_t *, ipnat_t *); 243static int ipf_nat_match(fr_info_t *, ipnat_t *);
244static int ipf_nat_matcharray(nat_t *, int *, u_long); 244static int ipf_nat_matcharray(nat_t *, int *, u_long);
245static int ipf_nat_matchflush(ipf_main_softc_t *, ipf_nat_softc_t *, 245static int ipf_nat_matchflush(ipf_main_softc_t *, ipf_nat_softc_t *,
246 void *); 246 void *);
247static void ipf_nat_mssclamp(tcphdr_t *, u_32_t, fr_info_t *, u_short *); 247static void ipf_nat_mssclamp(tcphdr_t *, u_32_t, fr_info_t *, u_short *);
248static int ipf_nat_newmap(fr_info_t *, nat_t *, natinfo_t *); 248static int ipf_nat_newmap(fr_info_t *, nat_t *, natinfo_t *);
249static int ipf_nat_newdivert(fr_info_t *, nat_t *, natinfo_t *); 249static int ipf_nat_newdivert(fr_info_t *, nat_t *, natinfo_t *);
250static int ipf_nat_newrdr(fr_info_t *, nat_t *, natinfo_t *); 250static int ipf_nat_newrdr(fr_info_t *, nat_t *, natinfo_t *);
251static int ipf_nat_newrewrite(fr_info_t *, nat_t *, natinfo_t *); 251static int ipf_nat_newrewrite(fr_info_t *, nat_t *, natinfo_t *);
252static int ipf_nat_nextaddr(fr_info_t *, nat_addr_t *, u_32_t *, u_32_t *); 252static int ipf_nat_nextaddr(fr_info_t *, nat_addr_t *, u_32_t *, u_32_t *);
253static int ipf_nat_nextaddrinit(ipf_main_softc_t *, char *, 253static int ipf_nat_nextaddrinit(ipf_main_softc_t *, char *,
254 nat_addr_t *, int, void *); 254 nat_addr_t *, int, void *);
255static int ipf_nat_resolverule(ipf_main_softc_t *, ipnat_t *); 255static int ipf_nat_resolverule(ipf_main_softc_t *, ipnat_t *);
256static int ipf_nat_ruleaddrinit(ipf_main_softc_t *, 256static int ipf_nat_ruleaddrinit(ipf_main_softc_t *,
257 ipf_nat_softc_t *, ipnat_t *); 257 ipf_nat_softc_t *, ipnat_t *);
258static void ipf_nat_rule_fini(ipf_main_softc_t *, ipnat_t *); 258static void ipf_nat_rule_fini(ipf_main_softc_t *, ipnat_t *);
259static int ipf_nat_rule_init(ipf_main_softc_t *, ipf_nat_softc_t *, 259static int ipf_nat_rule_init(ipf_main_softc_t *, ipf_nat_softc_t *,
260 ipnat_t *); 260 ipnat_t *);
261static int ipf_nat_siocaddnat(ipf_main_softc_t *, ipf_nat_softc_t *, 261static int ipf_nat_siocaddnat(ipf_main_softc_t *, ipf_nat_softc_t *,
262 ipnat_t *, int); 262 ipnat_t *, int);
263static void ipf_nat_siocdelnat(ipf_main_softc_t *, ipf_nat_softc_t *, 263static void ipf_nat_siocdelnat(ipf_main_softc_t *, ipf_nat_softc_t *,
264 ipnat_t *, int); 264 ipnat_t *, int);
265static void ipf_nat_tabmove(ipf_nat_softc_t *, nat_t *); 265static void ipf_nat_tabmove(ipf_nat_softc_t *, nat_t *);
266 266
267/* ------------------------------------------------------------------------ */ 267/* ------------------------------------------------------------------------ */
268/* Function: ipf_nat_main_load */ 268/* Function: ipf_nat_main_load */
269/* Returns: int - 0 == success, -1 == failure */ 269/* Returns: int - 0 == success, -1 == failure */
270/* Parameters: Nil */ 270/* Parameters: Nil */
271/* */ 271/* */
272/* The only global NAT structure that needs to be initialised is the filter */ 272/* The only global NAT structure that needs to be initialised is the filter */
273/* rule that is used with blocking packets. */ 273/* rule that is used with blocking packets. */
274/* ------------------------------------------------------------------------ */ 274/* ------------------------------------------------------------------------ */
275int 275int
276ipf_nat_main_load(void) 276ipf_nat_main_load(void)
277{ 277{
278 bzero((char *)&ipfnatblock, sizeof(ipfnatblock)); 278 bzero((char *)&ipfnatblock, sizeof(ipfnatblock));
279 ipfnatblock.fr_flags = FR_BLOCK|FR_QUICK; 279 ipfnatblock.fr_flags = FR_BLOCK|FR_QUICK;
280 ipfnatblock.fr_ref = 1; 280 ipfnatblock.fr_ref = 1;
281 281
282 return 0; 282 return 0;
283} 283}
284 284
285 285
286/* ------------------------------------------------------------------------ */ 286/* ------------------------------------------------------------------------ */
287/* Function: ipf_nat_main_unload */ 287/* Function: ipf_nat_main_unload */
288/* Returns: int - 0 == success, -1 == failure */ 288/* Returns: int - 0 == success, -1 == failure */
289/* Parameters: Nil */ 289/* Parameters: Nil */
290/* */ 290/* */
291/* A null-op function that exists as a placeholder so that the flow in */ 291/* A null-op function that exists as a placeholder so that the flow in */
292/* other functions is obvious. */ 292/* other functions is obvious. */
293/* ------------------------------------------------------------------------ */ 293/* ------------------------------------------------------------------------ */
294int 294int
295ipf_nat_main_unload(void) 295ipf_nat_main_unload(void)
296{ 296{
297 return 0; 297 return 0;
298} 298}
299 299
300 300
301/* ------------------------------------------------------------------------ */ 301/* ------------------------------------------------------------------------ */
302/* Function: ipf_nat_soft_create */ 302/* Function: ipf_nat_soft_create */
303/* Returns: void * - NULL = failure, else pointer to NAT context */ 303/* Returns: void * - NULL = failure, else pointer to NAT context */
304/* Parameters: softc(I) - pointer to soft context main structure */ 304/* Parameters: softc(I) - pointer to soft context main structure */
305/* */ 305/* */
306/* Allocate the initial soft context structure for NAT and populate it with */ 306/* Allocate the initial soft context structure for NAT and populate it with */
307/* some default values. Creating the tables is left until we call _init so */ 307/* some default values. Creating the tables is left until we call _init so */
308/* that sizes can be changed before we get under way. */ 308/* that sizes can be changed before we get under way. */
309/* ------------------------------------------------------------------------ */ 309/* ------------------------------------------------------------------------ */
310void * 310void *
311ipf_nat_soft_create(ipf_main_softc_t *softc) 311ipf_nat_soft_create(ipf_main_softc_t *softc)
312{ 312{
313 ipf_nat_softc_t *softn; 313 ipf_nat_softc_t *softn;
314 314
315 KMALLOC(softn, ipf_nat_softc_t *); 315 KMALLOC(softn, ipf_nat_softc_t *);
316 if (softn == NULL) 316 if (softn == NULL)
317 return NULL; 317 return NULL;
318 318
319 bzero((char *)softn, sizeof(*softn)); 319 bzero((char *)softn, sizeof(*softn));
320 320
321 softn->ipf_nat_tune = ipf_tune_array_copy(softn, 321 softn->ipf_nat_tune = ipf_tune_array_copy(softn,
322 sizeof(ipf_nat_tuneables), 322 sizeof(ipf_nat_tuneables),
323 ipf_nat_tuneables); 323 ipf_nat_tuneables);
324 if (softn->ipf_nat_tune == NULL) { 324 if (softn->ipf_nat_tune == NULL) {
325 ipf_nat_soft_destroy(softc, softn); 325 ipf_nat_soft_destroy(softc, softn);
326 return NULL; 326 return NULL;
327 } 327 }
328 if (ipf_tune_array_link(softc, softn->ipf_nat_tune) == -1) { 328 if (ipf_tune_array_link(softc, softn->ipf_nat_tune) == -1) {
329 ipf_nat_soft_destroy(softc, softn); 329 ipf_nat_soft_destroy(softc, softn);
330 return NULL; 330 return NULL;
331 } 331 }
332 332
333 softn->ipf_nat_list_tail = &softn->ipf_nat_list; 333 softn->ipf_nat_list_tail = &softn->ipf_nat_list;
334 334
335 softn->ipf_nat_table_max = NAT_TABLE_MAX; 335 softn->ipf_nat_table_max = NAT_TABLE_MAX;
336 softn->ipf_nat_table_sz = NAT_TABLE_SZ; 336 softn->ipf_nat_table_sz = NAT_TABLE_SZ;
337 softn->ipf_nat_maprules_sz = NAT_SIZE; 337 softn->ipf_nat_maprules_sz = NAT_SIZE;
338 softn->ipf_nat_rdrrules_sz = RDR_SIZE; 338 softn->ipf_nat_rdrrules_sz = RDR_SIZE;
339 softn->ipf_nat_hostmap_sz = HOSTMAP_SIZE; 339 softn->ipf_nat_hostmap_sz = HOSTMAP_SIZE;
340 softn->ipf_nat_doflush = 0; 340 softn->ipf_nat_doflush = 0;
341#ifdef IPFILTER_LOG 341#ifdef IPFILTER_LOG
342 softn->ipf_nat_logging = 1; 342 softn->ipf_nat_logging = 1;
343#else 343#else
344 softn->ipf_nat_logging = 0; 344 softn->ipf_nat_logging = 0;
345#endif 345#endif
346 346
347 softn->ipf_nat_defage = DEF_NAT_AGE; 347 softn->ipf_nat_defage = DEF_NAT_AGE;
348 softn->ipf_nat_defipage = IPF_TTLVAL(60); 348 softn->ipf_nat_defipage = IPF_TTLVAL(60);
349 softn->ipf_nat_deficmpage = IPF_TTLVAL(3); 349 softn->ipf_nat_deficmpage = IPF_TTLVAL(3);
350 softn->ipf_nat_table_wm_high = 99; 350 softn->ipf_nat_table_wm_high = 99;
351 softn->ipf_nat_table_wm_low = 90; 351 softn->ipf_nat_table_wm_low = 90;
352 352
353 return softn; 353 return softn;
354} 354}
355 355
356/* ------------------------------------------------------------------------ */ 356/* ------------------------------------------------------------------------ */
357/* Function: ipf_nat_soft_destroy */ 357/* Function: ipf_nat_soft_destroy */
358/* Returns: Nil */ 358/* Returns: Nil */
359/* Parameters: softc(I) - pointer to soft context main structure */ 359/* Parameters: softc(I) - pointer to soft context main structure */
360/* */ 360/* */
361/* ------------------------------------------------------------------------ */ 361/* ------------------------------------------------------------------------ */
362void 362void
363ipf_nat_soft_destroy(ipf_main_softc_t *softc, void *arg) 363ipf_nat_soft_destroy(ipf_main_softc_t *softc, void *arg)
364{ 364{
365 ipf_nat_softc_t *softn = arg; 365 ipf_nat_softc_t *softn = arg;
366 366
367 if (softn->ipf_nat_tune != NULL) { 367 if (softn->ipf_nat_tune != NULL) {
368 ipf_tune_array_unlink(softc, softn->ipf_nat_tune); 368 ipf_tune_array_unlink(softc, softn->ipf_nat_tune);
369 KFREES(softn->ipf_nat_tune, sizeof(ipf_nat_tuneables)); 369 KFREES(softn->ipf_nat_tune, sizeof(ipf_nat_tuneables));
370 softn->ipf_nat_tune = NULL; 370 softn->ipf_nat_tune = NULL;
371 } 371 }
372 372
373 KFREE(softn); 373 KFREE(softn);
374} 374}
375 375
376 376
377/* ------------------------------------------------------------------------ */ 377/* ------------------------------------------------------------------------ */
378/* Function: ipf_nat_init */ 378/* Function: ipf_nat_init */
379/* Returns: int - 0 == success, -1 == failure */ 379/* Returns: int - 0 == success, -1 == failure */
380/* Parameters: softc(I) - pointer to soft context main structure */ 380/* Parameters: softc(I) - pointer to soft context main structure */
381/* */ 381/* */
382/* Initialise all of the NAT locks, tables and other structures. */ 382/* Initialise all of the NAT locks, tables and other structures. */
383/* ------------------------------------------------------------------------ */ 383/* ------------------------------------------------------------------------ */
384int 384int
385ipf_nat_soft_init(ipf_main_softc_t *softc, void *arg) 385ipf_nat_soft_init(ipf_main_softc_t *softc, void *arg)
386{ 386{
387 ipf_nat_softc_t *softn = arg; 387 ipf_nat_softc_t *softn = arg;
388 ipftq_t *tq; 388 ipftq_t *tq;
389 int i; 389 int i;
390 390
391 KMALLOCS(softn->ipf_nat_table[0], nat_t **, \ 391 KMALLOCS(softn->ipf_nat_table[0], nat_t **, \
392 sizeof(nat_t *) * softn->ipf_nat_table_sz); 392 sizeof(nat_t *) * softn->ipf_nat_table_sz);
393 393
394 if (softn->ipf_nat_table[0] != NULL) { 394 if (softn->ipf_nat_table[0] != NULL) {
395 bzero((char *)softn->ipf_nat_table[0], 395 bzero((char *)softn->ipf_nat_table[0],
396 softn->ipf_nat_table_sz * sizeof(nat_t *)); 396 softn->ipf_nat_table_sz * sizeof(nat_t *));
397 } else { 397 } else {
398 return -1; 398 return -1;
399 } 399 }
400 400
401 KMALLOCS(softn->ipf_nat_table[1], nat_t **, \ 401 KMALLOCS(softn->ipf_nat_table[1], nat_t **, \
402 sizeof(nat_t *) * softn->ipf_nat_table_sz); 402 sizeof(nat_t *) * softn->ipf_nat_table_sz);
403 403
404 if (softn->ipf_nat_table[1] != NULL) { 404 if (softn->ipf_nat_table[1] != NULL) {
405 bzero((char *)softn->ipf_nat_table[1], 405 bzero((char *)softn->ipf_nat_table[1],
406 softn->ipf_nat_table_sz * sizeof(nat_t *)); 406 softn->ipf_nat_table_sz * sizeof(nat_t *));
407 } else { 407 } else {
408 return -2; 408 return -2;
409 } 409 }
410 410
411 KMALLOCS(softn->ipf_nat_map_rules, ipnat_t **, \ 411 KMALLOCS(softn->ipf_nat_map_rules, ipnat_t **, \
412 sizeof(ipnat_t *) * softn->ipf_nat_maprules_sz); 412 sizeof(ipnat_t *) * softn->ipf_nat_maprules_sz);
413 413
414 if (softn->ipf_nat_map_rules != NULL) { 414 if (softn->ipf_nat_map_rules != NULL) {
415 bzero((char *)softn->ipf_nat_map_rules, 415 bzero((char *)softn->ipf_nat_map_rules,
416 softn->ipf_nat_maprules_sz * sizeof(ipnat_t *)); 416 softn->ipf_nat_maprules_sz * sizeof(ipnat_t *));
417 } else { 417 } else {
418 return -3; 418 return -3;
419 } 419 }
420 420
421 KMALLOCS(softn->ipf_nat_rdr_rules, ipnat_t **, \ 421 KMALLOCS(softn->ipf_nat_rdr_rules, ipnat_t **, \
422 sizeof(ipnat_t *) * softn->ipf_nat_rdrrules_sz); 422 sizeof(ipnat_t *) * softn->ipf_nat_rdrrules_sz);
423 423
424 if (softn->ipf_nat_rdr_rules != NULL) { 424 if (softn->ipf_nat_rdr_rules != NULL) {
425 bzero((char *)softn->ipf_nat_rdr_rules, 425 bzero((char *)softn->ipf_nat_rdr_rules,
426 softn->ipf_nat_rdrrules_sz * sizeof(ipnat_t *)); 426 softn->ipf_nat_rdrrules_sz * sizeof(ipnat_t *));
427 } else { 427 } else {
428 return -4; 428 return -4;
429 } 429 }
430 430
431 KMALLOCS(softn->ipf_hm_maptable, hostmap_t **, \ 431 KMALLOCS(softn->ipf_hm_maptable, hostmap_t **, \
432 sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz); 432 sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz);
433 433
434 if (softn->ipf_hm_maptable != NULL) { 434 if (softn->ipf_hm_maptable != NULL) {
435 bzero((char *)softn->ipf_hm_maptable, 435 bzero((char *)softn->ipf_hm_maptable,
436 sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz); 436 sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz);
437 } else { 437 } else {
438 return -5; 438 return -5;
439 } 439 }
440 softn->ipf_hm_maplist = NULL; 440 softn->ipf_hm_maplist = NULL;
441 441
442 KMALLOCS(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, u_int *, 442 KMALLOCS(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, u_int *,
443 softn->ipf_nat_table_sz * sizeof(u_int)); 443 softn->ipf_nat_table_sz * sizeof(u_int));
444 444
445 if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen == NULL) { 445 if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen == NULL) {
446 return -6; 446 return -6;
447 } 447 }
448 bzero((char *)softn->ipf_nat_stats.ns_side[0].ns_bucketlen, 448 bzero((char *)softn->ipf_nat_stats.ns_side[0].ns_bucketlen,
449 softn->ipf_nat_table_sz * sizeof(u_int)); 449 softn->ipf_nat_table_sz * sizeof(u_int));
450 450
451 KMALLOCS(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, u_int *, 451 KMALLOCS(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, u_int *,
452 softn->ipf_nat_table_sz * sizeof(u_int)); 452 softn->ipf_nat_table_sz * sizeof(u_int));
453 453
454 if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen == NULL) { 454 if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen == NULL) {
455 return -7; 455 return -7;
456 } 456 }
457 457
458 bzero((char *)softn->ipf_nat_stats.ns_side[1].ns_bucketlen, 458 bzero((char *)softn->ipf_nat_stats.ns_side[1].ns_bucketlen,
459 softn->ipf_nat_table_sz * sizeof(u_int)); 459 softn->ipf_nat_table_sz * sizeof(u_int));
460 460
461 if (softn->ipf_nat_maxbucket == 0) { 461 if (softn->ipf_nat_maxbucket == 0) {
462 for (i = softn->ipf_nat_table_sz; i > 0; i >>= 1) 462 for (i = softn->ipf_nat_table_sz; i > 0; i >>= 1)
463 softn->ipf_nat_maxbucket++; 463 softn->ipf_nat_maxbucket++;
464 softn->ipf_nat_maxbucket *= 2; 464 softn->ipf_nat_maxbucket *= 2;
465 } 465 }
466 466
467 ipf_sttab_init(softc, softn->ipf_nat_tcptq); 467 ipf_sttab_init(softc, softn->ipf_nat_tcptq);
468 /* 468 /*
469 * Increase this because we may have "keep state" following this too 469 * Increase this because we may have "keep state" following this too
470 * and packet storms can occur if this is removed too quickly. 470 * and packet storms can occur if this is removed too quickly.
471 */ 471 */
472 softn->ipf_nat_tcptq[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcplastack; 472 softn->ipf_nat_tcptq[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcplastack;
473 softn->ipf_nat_tcptq[IPF_TCP_NSTATES - 1].ifq_next = 473 softn->ipf_nat_tcptq[IPF_TCP_NSTATES - 1].ifq_next =
474 &softn->ipf_nat_udptq; 474 &softn->ipf_nat_udptq;
475 475
476 IPFTQ_INIT(&softn->ipf_nat_udptq, softn->ipf_nat_defage, 476 IPFTQ_INIT(&softn->ipf_nat_udptq, softn->ipf_nat_defage,
477 "nat ipftq udp tab"); 477 "nat ipftq udp tab");
478 softn->ipf_nat_udptq.ifq_next = &softn->ipf_nat_udpacktq; 478 softn->ipf_nat_udptq.ifq_next = &softn->ipf_nat_udpacktq;
479 479
480 IPFTQ_INIT(&softn->ipf_nat_udpacktq, softn->ipf_nat_defage, 480 IPFTQ_INIT(&softn->ipf_nat_udpacktq, softn->ipf_nat_defage,
481 "nat ipftq udpack tab"); 481 "nat ipftq udpack tab");
482 softn->ipf_nat_udpacktq.ifq_next = &softn->ipf_nat_icmptq; 482 softn->ipf_nat_udpacktq.ifq_next = &softn->ipf_nat_icmptq;
483 483
484 IPFTQ_INIT(&softn->ipf_nat_icmptq, softn->ipf_nat_deficmpage, 484 IPFTQ_INIT(&softn->ipf_nat_icmptq, softn->ipf_nat_deficmpage,
485 "nat icmp ipftq tab"); 485 "nat icmp ipftq tab");
486 softn->ipf_nat_icmptq.ifq_next = &softn->ipf_nat_icmpacktq; 486 softn->ipf_nat_icmptq.ifq_next = &softn->ipf_nat_icmpacktq;
487 487
488 IPFTQ_INIT(&softn->ipf_nat_icmpacktq, softn->ipf_nat_defage, 488 IPFTQ_INIT(&softn->ipf_nat_icmpacktq, softn->ipf_nat_defage,
489 "nat icmpack ipftq tab"); 489 "nat icmpack ipftq tab");
490 softn->ipf_nat_icmpacktq.ifq_next = &softn->ipf_nat_iptq; 490 softn->ipf_nat_icmpacktq.ifq_next = &softn->ipf_nat_iptq;
491 491
492 IPFTQ_INIT(&softn->ipf_nat_iptq, softn->ipf_nat_defipage, 492 IPFTQ_INIT(&softn->ipf_nat_iptq, softn->ipf_nat_defipage,
493 "nat ip ipftq tab"); 493 "nat ip ipftq tab");
494 softn->ipf_nat_iptq.ifq_next = &softn->ipf_nat_pending; 494 softn->ipf_nat_iptq.ifq_next = &softn->ipf_nat_pending;
495 495
496 IPFTQ_INIT(&softn->ipf_nat_pending, 1, "nat pending ipftq tab"); 496 IPFTQ_INIT(&softn->ipf_nat_pending, 1, "nat pending ipftq tab");
497 softn->ipf_nat_pending.ifq_next = NULL; 497 softn->ipf_nat_pending.ifq_next = NULL;
498 498
499 for (i = 0, tq = softn->ipf_nat_tcptq; i < IPF_TCP_NSTATES; i++, tq++) { 499 for (i = 0, tq = softn->ipf_nat_tcptq; i < IPF_TCP_NSTATES; i++, tq++) {
500 if (tq->ifq_ttl < softn->ipf_nat_deficmpage) 500 if (tq->ifq_ttl < softn->ipf_nat_deficmpage)
501 tq->ifq_ttl = softn->ipf_nat_deficmpage; 501 tq->ifq_ttl = softn->ipf_nat_deficmpage;
502#ifdef LARGE_NAT 502#ifdef LARGE_NAT
503 else if (tq->ifq_ttl > softn->ipf_nat_defage) 503 else if (tq->ifq_ttl > softn->ipf_nat_defage)
504 tq->ifq_ttl = softn->ipf_nat_defage; 504 tq->ifq_ttl = softn->ipf_nat_defage;
505#endif 505#endif
506 } 506 }
507 507
508 /* 508 /*
509 * Increase this because we may have "keep state" following 509 * Increase this because we may have "keep state" following
510 * this too and packet storms can occur if this is removed 510 * this too and packet storms can occur if this is removed
511 * too quickly. 511 * too quickly.
512 */ 512 */
513 softn->ipf_nat_tcptq[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcplastack; 513 softn->ipf_nat_tcptq[IPF_TCPS_CLOSED].ifq_ttl = softc->ipf_tcplastack;
514 514
515 MUTEX_INIT(&softn->ipf_nat_new, "ipf nat new mutex"); 515 MUTEX_INIT(&softn->ipf_nat_new, "ipf nat new mutex");
516 MUTEX_INIT(&softn->ipf_nat_io, "ipf nat io mutex"); 516 MUTEX_INIT(&softn->ipf_nat_io, "ipf nat io mutex");
517 517
518 softn->ipf_nat_inited = 1; 518 softn->ipf_nat_inited = 1;
519 519
520 return 0; 520 return 0;
521} 521}
522 522
523 523
524/* ------------------------------------------------------------------------ */ 524/* ------------------------------------------------------------------------ */
525/* Function: ipf_nat_soft_fini */ 525/* Function: ipf_nat_soft_fini */
526/* Returns: Nil */ 526/* Returns: Nil */
527/* Parameters: softc(I) - pointer to soft context main structure */ 527/* Parameters: softc(I) - pointer to soft context main structure */
528/* */ 528/* */
529/* Free all memory used by NAT structures allocated at runtime. */ 529/* Free all memory used by NAT structures allocated at runtime. */
530/* ------------------------------------------------------------------------ */ 530/* ------------------------------------------------------------------------ */
531int 531int
532ipf_nat_soft_fini(ipf_main_softc_t *softc, void *arg) 532ipf_nat_soft_fini(ipf_main_softc_t *softc, void *arg)
533{ 533{
534 ipf_nat_softc_t *softn = arg; 534 ipf_nat_softc_t *softn = arg;
535 ipftq_t *ifq, *ifqnext; 535 ipftq_t *ifq, *ifqnext;
536 536
537 (void) ipf_nat_clearlist(softc, softn); 537 (void) ipf_nat_clearlist(softc, softn);
538 (void) ipf_nat_flushtable(softc, softn); 538 (void) ipf_nat_flushtable(softc, softn);
539 539
540 /* 540 /*
541 * Proxy timeout queues are not cleaned here because although they 541 * Proxy timeout queues are not cleaned here because although they
542 * exist on the NAT list, ipf_proxy_unload is called after unload 542 * exist on the NAT list, ipf_proxy_unload is called after unload
543 * and the proxies actually are responsible for them being created. 543 * and the proxies actually are responsible for them being created.
544 * Should the proxy timeouts have their own list? There's no real 544 * Should the proxy timeouts have their own list? There's no real
545 * justification as this is the only complication. 545 * justification as this is the only complication.
546 */ 546 */
547 for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifqnext) { 547 for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifqnext) {
548 ifqnext = ifq->ifq_next; 548 ifqnext = ifq->ifq_next;
549 if (ipf_deletetimeoutqueue(ifq) == 0) 549 if (ipf_deletetimeoutqueue(ifq) == 0)
550 ipf_freetimeoutqueue(softc, ifq); 550 ipf_freetimeoutqueue(softc, ifq);
551 } 551 }
552 552
553 if (softn->ipf_nat_table[0] != NULL) { 553 if (softn->ipf_nat_table[0] != NULL) {
554 KFREES(softn->ipf_nat_table[0], 554 KFREES(softn->ipf_nat_table[0],
555 sizeof(nat_t *) * softn->ipf_nat_table_sz); 555 sizeof(nat_t *) * softn->ipf_nat_table_sz);
556 softn->ipf_nat_table[0] = NULL; 556 softn->ipf_nat_table[0] = NULL;
557 } 557 }
558 if (softn->ipf_nat_table[1] != NULL) { 558 if (softn->ipf_nat_table[1] != NULL) {
559 KFREES(softn->ipf_nat_table[1], 559 KFREES(softn->ipf_nat_table[1],
560 sizeof(nat_t *) * softn->ipf_nat_table_sz); 560 sizeof(nat_t *) * softn->ipf_nat_table_sz);
561 softn->ipf_nat_table[1] = NULL; 561 softn->ipf_nat_table[1] = NULL;
562 } 562 }
563 if (softn->ipf_nat_map_rules != NULL) { 563 if (softn->ipf_nat_map_rules != NULL) {
564 KFREES(softn->ipf_nat_map_rules, 564 KFREES(softn->ipf_nat_map_rules,
565 sizeof(ipnat_t *) * softn->ipf_nat_maprules_sz); 565 sizeof(ipnat_t *) * softn->ipf_nat_maprules_sz);
566 softn->ipf_nat_map_rules = NULL; 566 softn->ipf_nat_map_rules = NULL;
567 } 567 }
568 if (softn->ipf_nat_rdr_rules != NULL) { 568 if (softn->ipf_nat_rdr_rules != NULL) {
569 KFREES(softn->ipf_nat_rdr_rules, 569 KFREES(softn->ipf_nat_rdr_rules,
570 sizeof(ipnat_t *) * softn->ipf_nat_rdrrules_sz); 570 sizeof(ipnat_t *) * softn->ipf_nat_rdrrules_sz);
571 softn->ipf_nat_rdr_rules = NULL; 571 softn->ipf_nat_rdr_rules = NULL;
572 } 572 }
573 if (softn->ipf_hm_maptable != NULL) { 573 if (softn->ipf_hm_maptable != NULL) {
574 KFREES(softn->ipf_hm_maptable, 574 KFREES(softn->ipf_hm_maptable,
575 sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz); 575 sizeof(hostmap_t *) * softn->ipf_nat_hostmap_sz);
576 softn->ipf_hm_maptable = NULL; 576 softn->ipf_hm_maptable = NULL;
577 } 577 }
578 if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen != NULL) { 578 if (softn->ipf_nat_stats.ns_side[0].ns_bucketlen != NULL) {
579 KFREES(softn->ipf_nat_stats.ns_side[0].ns_bucketlen, 579 KFREES(softn->ipf_nat_stats.ns_side[0].ns_bucketlen,
580 sizeof(u_int) * softn->ipf_nat_table_sz); 580 sizeof(u_int) * softn->ipf_nat_table_sz);
581 softn->ipf_nat_stats.ns_side[0].ns_bucketlen = NULL; 581 softn->ipf_nat_stats.ns_side[0].ns_bucketlen = NULL;
582 } 582 }
583 if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen != NULL) { 583 if (softn->ipf_nat_stats.ns_side[1].ns_bucketlen != NULL) {
584 KFREES(softn->ipf_nat_stats.ns_side[1].ns_bucketlen, 584 KFREES(softn->ipf_nat_stats.ns_side[1].ns_bucketlen,
585 sizeof(u_int) * softn->ipf_nat_table_sz); 585 sizeof(u_int) * softn->ipf_nat_table_sz);
586 softn->ipf_nat_stats.ns_side[1].ns_bucketlen = NULL; 586 softn->ipf_nat_stats.ns_side[1].ns_bucketlen = NULL;
587 } 587 }
588 588
589 if (softn->ipf_nat_inited == 1) { 589 if (softn->ipf_nat_inited == 1) {
590 softn->ipf_nat_inited = 0; 590 softn->ipf_nat_inited = 0;
591 ipf_sttab_destroy(softn->ipf_nat_tcptq); 591 ipf_sttab_destroy(softn->ipf_nat_tcptq);
592 592
593 MUTEX_DESTROY(&softn->ipf_nat_new); 593 MUTEX_DESTROY(&softn->ipf_nat_new);
594 MUTEX_DESTROY(&softn->ipf_nat_io); 594 MUTEX_DESTROY(&softn->ipf_nat_io);
595 595
596 MUTEX_DESTROY(&softn->ipf_nat_udptq.ifq_lock); 596 MUTEX_DESTROY(&softn->ipf_nat_udptq.ifq_lock);
597 MUTEX_DESTROY(&softn->ipf_nat_udpacktq.ifq_lock); 597 MUTEX_DESTROY(&softn->ipf_nat_udpacktq.ifq_lock);
598 MUTEX_DESTROY(&softn->ipf_nat_icmptq.ifq_lock); 598 MUTEX_DESTROY(&softn->ipf_nat_icmptq.ifq_lock);
599 MUTEX_DESTROY(&softn->ipf_nat_icmpacktq.ifq_lock); 599 MUTEX_DESTROY(&softn->ipf_nat_icmpacktq.ifq_lock);
600 MUTEX_DESTROY(&softn->ipf_nat_iptq.ifq_lock); 600 MUTEX_DESTROY(&softn->ipf_nat_iptq.ifq_lock);
601 MUTEX_DESTROY(&softn->ipf_nat_pending.ifq_lock); 601 MUTEX_DESTROY(&softn->ipf_nat_pending.ifq_lock);
602 } 602 }
603 603
604 return 0; 604 return 0;
605} 605}
606 606
607 607
608/* ------------------------------------------------------------------------ */ 608/* ------------------------------------------------------------------------ */
609/* Function: ipf_nat_setlock */ 609/* Function: ipf_nat_setlock */
610/* Returns: Nil */ 610/* Returns: Nil */
611/* Parameters: arg(I) - pointer to soft state information */ 611/* Parameters: arg(I) - pointer to soft state information */
612/* tmp(I) - new lock value */ 612/* tmp(I) - new lock value */
613/* */ 613/* */
614/* Set the "lock status" of NAT to the value in tmp. */ 614/* Set the "lock status" of NAT to the value in tmp. */
615/* ------------------------------------------------------------------------ */ 615/* ------------------------------------------------------------------------ */
616void 616void
617ipf_nat_setlock(void *arg, int tmp) 617ipf_nat_setlock(void *arg, int tmp)
618{ 618{
619 ipf_nat_softc_t *softn = arg; 619 ipf_nat_softc_t *softn = arg;
620 620
621 softn->ipf_nat_lock = tmp; 621 softn->ipf_nat_lock = tmp;
622} 622}
623 623
624 624
625/* ------------------------------------------------------------------------ */ 625/* ------------------------------------------------------------------------ */
626/* Function: ipf_nat_addrdr */ 626/* Function: ipf_nat_addrdr */
627/* Returns: Nil */ 627/* Returns: Nil */
628/* Parameters: n(I) - pointer to NAT rule to add */ 628/* Parameters: n(I) - pointer to NAT rule to add */
629/* */ 629/* */
630/* Adds a redirect rule to the hash table of redirect rules and the list of */ 630/* Adds a redirect rule to the hash table of redirect rules and the list of */
631/* loaded NAT rules. Updates the bitmask indicating which netmasks are in */ 631/* loaded NAT rules. Updates the bitmask indicating which netmasks are in */
632/* use by redirect rules. */ 632/* use by redirect rules. */
633/* ------------------------------------------------------------------------ */ 633/* ------------------------------------------------------------------------ */
634static void 634static void
635ipf_nat_addrdr(ipf_nat_softc_t *softn, ipnat_t *n) 635ipf_nat_addrdr(ipf_nat_softc_t *softn, ipnat_t *n)
636{ 636{
637 ipnat_t **np; 637 ipnat_t **np;
638 u_32_t j; 638 u_32_t j;
639 u_int hv; 639 u_int hv;
640 u_int rhv; 640 u_int rhv;
641 int k; 641 int k;
642 642
643 if (n->in_odstatype == FRI_NORMAL) { 643 if (n->in_odstatype == FRI_NORMAL) {
644 k = count4bits(n->in_odstmsk); 644 k = count4bits(n->in_odstmsk);
645 ipf_inet_mask_add(k, &softn->ipf_nat_rdr_mask); 645 ipf_inet_mask_add(k, &softn->ipf_nat_rdr_mask);
646 j = (n->in_odstaddr & n->in_odstmsk); 646 j = (n->in_odstaddr & n->in_odstmsk);
647 rhv = NAT_HASH_FN(j, 0, 0xffffffff); 647 rhv = NAT_HASH_FN(j, 0, 0xffffffff);
648 } else { 648 } else {
649 ipf_inet_mask_add(0, &softn->ipf_nat_rdr_mask); 649 ipf_inet_mask_add(0, &softn->ipf_nat_rdr_mask);
650 j = 0; 650 j = 0;
651 rhv = 0; 651 rhv = 0;
652 } 652 }
653 hv = rhv % softn->ipf_nat_rdrrules_sz; 653 hv = rhv % softn->ipf_nat_rdrrules_sz;
654 np = softn->ipf_nat_rdr_rules + hv; 654 np = softn->ipf_nat_rdr_rules + hv;
655 while (*np != NULL) 655 while (*np != NULL)
656 np = &(*np)->in_rnext; 656 np = &(*np)->in_rnext;
657 n->in_rnext = NULL; 657 n->in_rnext = NULL;
658 n->in_prnext = np; 658 n->in_prnext = np;
659 n->in_hv[0] = hv; 659 n->in_hv[0] = hv;
660 n->in_use++; 660 n->in_use++;
661 *np = n; 661 *np = n;
662} 662}
663 663
664 664
665/* ------------------------------------------------------------------------ */ 665/* ------------------------------------------------------------------------ */
666/* Function: ipf_nat_addmap */ 666/* Function: ipf_nat_addmap */
667/* Returns: Nil */ 667/* Returns: Nil */
668/* Parameters: n(I) - pointer to NAT rule to add */ 668/* Parameters: n(I) - pointer to NAT rule to add */
669/* */ 669/* */
670/* Adds a NAT map rule to the hash table of rules and the list of loaded */ 670/* Adds a NAT map rule to the hash table of rules and the list of loaded */
671/* NAT rules. Updates the bitmask indicating which netmasks are in use by */ 671/* NAT rules. Updates the bitmask indicating which netmasks are in use by */
672/* redirect rules. */ 672/* redirect rules. */
673/* ------------------------------------------------------------------------ */ 673/* ------------------------------------------------------------------------ */
674static void 674static void
675ipf_nat_addmap(ipf_nat_softc_t *softn, ipnat_t *n) 675ipf_nat_addmap(ipf_nat_softc_t *softn, ipnat_t *n)
676{ 676{
677 ipnat_t **np; 677 ipnat_t **np;
678 u_32_t j; 678 u_32_t j;
679 u_int hv; 679 u_int hv;
680 u_int rhv; 680 u_int rhv;
681 int k; 681 int k;
682 682
683 if (n->in_osrcatype == FRI_NORMAL) { 683 if (n->in_osrcatype == FRI_NORMAL) {
684 k = count4bits(n->in_osrcmsk); 684 k = count4bits(n->in_osrcmsk);
685 ipf_inet_mask_add(k, &softn->ipf_nat_map_mask); 685 ipf_inet_mask_add(k, &softn->ipf_nat_map_mask);
686 j = (n->in_osrcaddr & n->in_osrcmsk); 686 j = (n->in_osrcaddr & n->in_osrcmsk);
687 rhv = NAT_HASH_FN(j, 0, 0xffffffff); 687 rhv = NAT_HASH_FN(j, 0, 0xffffffff);
688 } else { 688 } else {
689 ipf_inet_mask_add(0, &softn->ipf_nat_map_mask); 689 ipf_inet_mask_add(0, &softn->ipf_nat_map_mask);
690 j = 0; 690 j = 0;
691 rhv = 0; 691 rhv = 0;
692 } 692 }
693 hv = rhv % softn->ipf_nat_maprules_sz; 693 hv = rhv % softn->ipf_nat_maprules_sz;
694 np = softn->ipf_nat_map_rules + hv; 694 np = softn->ipf_nat_map_rules + hv;
695 while (*np != NULL) 695 while (*np != NULL)
696 np = &(*np)->in_mnext; 696 np = &(*np)->in_mnext;
697 n->in_mnext = NULL; 697 n->in_mnext = NULL;
698 n->in_pmnext = np; 698 n->in_pmnext = np;
699 n->in_hv[1] = rhv; 699 n->in_hv[1] = rhv;
700 n->in_use++; 700 n->in_use++;
701 *np = n; 701 *np = n;
702} 702}
703 703
704 704
705/* ------------------------------------------------------------------------ */ 705/* ------------------------------------------------------------------------ */
706/* Function: ipf_nat_delrdr */ 706/* Function: ipf_nat_delrdr */
707/* Returns: Nil */ 707/* Returns: Nil */
708/* Parameters: n(I) - pointer to NAT rule to delete */ 708/* Parameters: n(I) - pointer to NAT rule to delete */
709/* */ 709/* */
710/* Removes a redirect rule from the hash table of redirect rules. */ 710/* Removes a redirect rule from the hash table of redirect rules. */
711/* ------------------------------------------------------------------------ */ 711/* ------------------------------------------------------------------------ */
712void 712void
713ipf_nat_delrdr(ipf_nat_softc_t *softn, ipnat_t *n) 713ipf_nat_delrdr(ipf_nat_softc_t *softn, ipnat_t *n)
714{ 714{
715 if (n->in_odstatype == FRI_NORMAL) { 715 if (n->in_odstatype == FRI_NORMAL) {
716 int k = count4bits(n->in_odstmsk); 716 int k = count4bits(n->in_odstmsk);
717 ipf_inet_mask_del(k, &softn->ipf_nat_rdr_mask); 717 ipf_inet_mask_del(k, &softn->ipf_nat_rdr_mask);
718 } else { 718 } else {
719 ipf_inet_mask_del(0, &softn->ipf_nat_rdr_mask); 719 ipf_inet_mask_del(0, &softn->ipf_nat_rdr_mask);
720 } 720 }
721 if (n->in_rnext) 721 if (n->in_rnext)
722 n->in_rnext->in_prnext = n->in_prnext; 722 n->in_rnext->in_prnext = n->in_prnext;
723 *n->in_prnext = n->in_rnext; 723 *n->in_prnext = n->in_rnext;
724 n->in_use--; 724 n->in_use--;
725} 725}
726 726
727 727
728/* ------------------------------------------------------------------------ */ 728/* ------------------------------------------------------------------------ */
729/* Function: ipf_nat_delmap */ 729/* Function: ipf_nat_delmap */
730/* Returns: Nil */ 730/* Returns: Nil */
731/* Parameters: n(I) - pointer to NAT rule to delete */ 731/* Parameters: n(I) - pointer to NAT rule to delete */
732/* */ 732/* */
733/* Removes a NAT map rule from the hash table of NAT map rules. */ 733/* Removes a NAT map rule from the hash table of NAT map rules. */
734/* ------------------------------------------------------------------------ */ 734/* ------------------------------------------------------------------------ */
735void 735void
736ipf_nat_delmap(ipf_nat_softc_t *softn, ipnat_t *n) 736ipf_nat_delmap(ipf_nat_softc_t *softn, ipnat_t *n)
737{ 737{
738 if (n->in_osrcatype == FRI_NORMAL) { 738 if (n->in_osrcatype == FRI_NORMAL) {
739 int k = count4bits(n->in_osrcmsk); 739 int k = count4bits(n->in_osrcmsk);
740 ipf_inet_mask_del(k, &softn->ipf_nat_map_mask); 740 ipf_inet_mask_del(k, &softn->ipf_nat_map_mask);
741 } else { 741 } else {
742 ipf_inet_mask_del(0, &softn->ipf_nat_map_mask); 742 ipf_inet_mask_del(0, &softn->ipf_nat_map_mask);
743 } 743 }
744 if (n->in_mnext != NULL) 744 if (n->in_mnext != NULL)
745 n->in_mnext->in_pmnext = n->in_pmnext; 745 n->in_mnext->in_pmnext = n->in_pmnext;
746 *n->in_pmnext = n->in_mnext; 746 *n->in_pmnext = n->in_mnext;
747 n->in_use--; 747 n->in_use--;
748} 748}
749 749
750 750
751/* ------------------------------------------------------------------------ */ 751/* ------------------------------------------------------------------------ */
752/* Function: ipf_nat_hostmap */ 752/* Function: ipf_nat_hostmap */
753/* Returns: struct hostmap* - NULL if no hostmap could be created, */ 753/* Returns: struct hostmap* - NULL if no hostmap could be created, */
754/* else a pointer to the hostmapping to use */ 754/* else a pointer to the hostmapping to use */
755/* Parameters: np(I) - pointer to NAT rule */ 755/* Parameters: np(I) - pointer to NAT rule */
756/* real(I) - real IP address */ 756/* real(I) - real IP address */
757/* map(I) - mapped IP address */ 757/* map(I) - mapped IP address */
758/* port(I) - destination port number */ 758/* port(I) - destination port number */
759/* Write Locks: ipf_nat */ 759/* Write Locks: ipf_nat */
760/* */ 760/* */
761/* Check if an ip address has already been allocated for a given mapping */ 761/* Check if an ip address has already been allocated for a given mapping */
762/* that is not doing port based translation. If is not yet allocated, then */ 762/* that is not doing port based translation. If is not yet allocated, then */
763/* create a new entry if a non-NULL NAT rule pointer has been supplied. */ 763/* create a new entry if a non-NULL NAT rule pointer has been supplied. */
764/* ------------------------------------------------------------------------ */ 764/* ------------------------------------------------------------------------ */
765static struct hostmap * 765static struct hostmap *
766ipf_nat_hostmap(ipf_nat_softc_t *softn, ipnat_t *np, struct in_addr src, 766ipf_nat_hostmap(ipf_nat_softc_t *softn, ipnat_t *np, struct in_addr src,
767 struct in_addr dst, struct in_addr map, u_32_t port) 767 struct in_addr dst, struct in_addr map, u_32_t port)
768{ 768{
769 hostmap_t *hm; 769 hostmap_t *hm;
770 u_int hv, rhv; 770 u_int hv, rhv;
771 771
772 hv = (src.s_addr ^ dst.s_addr); 772 hv = (src.s_addr ^ dst.s_addr);
773 hv += src.s_addr; 773 hv += src.s_addr;
774 hv += dst.s_addr; 774 hv += dst.s_addr;
775 rhv = hv; 775 rhv = hv;
776 hv %= softn->ipf_nat_hostmap_sz; 776 hv %= softn->ipf_nat_hostmap_sz;
777 for (hm = softn->ipf_hm_maptable[hv]; hm; hm = hm->hm_hnext) 777 for (hm = softn->ipf_hm_maptable[hv]; hm; hm = hm->hm_hnext)
778 if ((hm->hm_osrcip.s_addr == src.s_addr) && 778 if ((hm->hm_osrcip.s_addr == src.s_addr) &&
779 (hm->hm_odstip.s_addr == dst.s_addr) && 779 (hm->hm_odstip.s_addr == dst.s_addr) &&
780 ((np == NULL) || (np == hm->hm_ipnat)) && 780 ((np == NULL) || (np == hm->hm_ipnat)) &&
781 ((port == 0) || (port == hm->hm_port))) { 781 ((port == 0) || (port == hm->hm_port))) {
782 softn->ipf_nat_stats.ns_hm_addref++; 782 softn->ipf_nat_stats.ns_hm_addref++;
783 hm->hm_ref++; 783 hm->hm_ref++;
784 return hm; 784 return hm;
785 } 785 }
786 786
787 if (np == NULL) { 787 if (np == NULL) {
788 softn->ipf_nat_stats.ns_hm_nullnp++; 788 softn->ipf_nat_stats.ns_hm_nullnp++;
789 return NULL; 789 return NULL;
790 } 790 }
791 791
792 KMALLOC(hm, hostmap_t *); 792 KMALLOC(hm, hostmap_t *);
793 if (hm) { 793 if (hm) {
794 hm->hm_next = softn->ipf_hm_maplist; 794 hm->hm_next = softn->ipf_hm_maplist;
795 hm->hm_pnext = &softn->ipf_hm_maplist; 795 hm->hm_pnext = &softn->ipf_hm_maplist;
796 if (softn->ipf_hm_maplist != NULL) 796 if (softn->ipf_hm_maplist != NULL)
797 softn->ipf_hm_maplist->hm_pnext = &hm->hm_next; 797 softn->ipf_hm_maplist->hm_pnext = &hm->hm_next;
798 softn->ipf_hm_maplist = hm; 798 softn->ipf_hm_maplist = hm;
799 hm->hm_hnext = softn->ipf_hm_maptable[hv]; 799 hm->hm_hnext = softn->ipf_hm_maptable[hv];
800 hm->hm_phnext = softn->ipf_hm_maptable + hv; 800 hm->hm_phnext = softn->ipf_hm_maptable + hv;
801 if (softn->ipf_hm_maptable[hv] != NULL) 801 if (softn->ipf_hm_maptable[hv] != NULL)
802 softn->ipf_hm_maptable[hv]->hm_phnext = &hm->hm_hnext; 802 softn->ipf_hm_maptable[hv]->hm_phnext = &hm->hm_hnext;
803 softn->ipf_hm_maptable[hv] = hm; 803 softn->ipf_hm_maptable[hv] = hm;
804 hm->hm_ipnat = np; 804 hm->hm_ipnat = np;
805 np->in_use++; 805 np->in_use++;
806 hm->hm_osrcip = src; 806 hm->hm_osrcip = src;
807 hm->hm_odstip = dst; 807 hm->hm_odstip = dst;
808 hm->hm_nsrcip = map; 808 hm->hm_nsrcip = map;
809 hm->hm_ndstip.s_addr = 0; 809 hm->hm_ndstip.s_addr = 0;
810 hm->hm_ref = 1; 810 hm->hm_ref = 1;
811 hm->hm_port = port; 811 hm->hm_port = port;
812 hm->hm_hv = rhv; 812 hm->hm_hv = rhv;
813 hm->hm_v = 4; 813 hm->hm_v = 4;
814 softn->ipf_nat_stats.ns_hm_new++; 814 softn->ipf_nat_stats.ns_hm_new++;
815 } else { 815 } else {
816 softn->ipf_nat_stats.ns_hm_newfail++; 816 softn->ipf_nat_stats.ns_hm_newfail++;
817 } 817 }
818 return hm; 818 return hm;
819} 819}
820 820
821 821
822/* ------------------------------------------------------------------------ */ 822/* ------------------------------------------------------------------------ */
823/* Function: ipf_nat_hostmapdel */ 823/* Function: ipf_nat_hostmapdel */
824/* Returns: Nil */ 824/* Returns: Nil */
825/* Parameters: hmp(I) - pointer to hostmap structure pointer */ 825/* Parameters: hmp(I) - pointer to hostmap structure pointer */
826/* Write Locks: ipf_nat */ 826/* Write Locks: ipf_nat */
827/* */ 827/* */
828/* Decrement the references to this hostmap structure by one. If this */ 828/* Decrement the references to this hostmap structure by one. If this */
829/* reaches zero then remove it and free it. */ 829/* reaches zero then remove it and free it. */
830/* ------------------------------------------------------------------------ */ 830/* ------------------------------------------------------------------------ */
831void 831void
832ipf_nat_hostmapdel(ipf_main_softc_t *softc, struct hostmap **hmp) 832ipf_nat_hostmapdel(ipf_main_softc_t *softc, struct hostmap **hmp)
833{ 833{
834 struct hostmap *hm; 834 struct hostmap *hm;
835 835
836 hm = *hmp; 836 hm = *hmp;
837 *hmp = NULL; 837 *hmp = NULL;
838 838
839 hm->hm_ref--; 839 hm->hm_ref--;
840 if (hm->hm_ref == 0) { 840 if (hm->hm_ref == 0) {
841 ipf_nat_rule_deref(softc, &hm->hm_ipnat); 841 ipf_nat_rule_deref(softc, &hm->hm_ipnat);
842 if (hm->hm_hnext) 842 if (hm->hm_hnext)
843 hm->hm_hnext->hm_phnext = hm->hm_phnext; 843 hm->hm_hnext->hm_phnext = hm->hm_phnext;
844 *hm->hm_phnext = hm->hm_hnext; 844 *hm->hm_phnext = hm->hm_hnext;
845 if (hm->hm_next) 845 if (hm->hm_next)
846 hm->hm_next->hm_pnext = hm->hm_pnext; 846 hm->hm_next->hm_pnext = hm->hm_pnext;
847 *hm->hm_pnext = hm->hm_next; 847 *hm->hm_pnext = hm->hm_next;
848 KFREE(hm); 848 KFREE(hm);
849 } 849 }
850} 850}
851 851
852 852
853/* ------------------------------------------------------------------------ */ 853/* ------------------------------------------------------------------------ */
854/* Function: ipf_fix_outcksum */ 854/* Function: ipf_fix_outcksum */
855/* Returns: Nil */ 855/* Returns: Nil */
856/* Parameters: fin(I) - pointer to packet information */ 856/* Parameters: fin(I) - pointer to packet information */
857/* sp(I) - location of 16bit checksum to update */ 857/* sp(I) - location of 16bit checksum to update */
858/* n((I) - amount to adjust checksum by */ 858/* n((I) - amount to adjust checksum by */
859/* */ 859/* */
860/* Adjusts the 16bit checksum by "n" for packets going out. */ 860/* Adjusts the 16bit checksum by "n" for packets going out. */
861/* ------------------------------------------------------------------------ */ 861/* ------------------------------------------------------------------------ */
862void 862void
863ipf_fix_outcksum(int cksum, u_short *sp, u_32_t n, u_32_t partial) 863ipf_fix_outcksum(int cksum, u_short *sp, u_32_t n, u_32_t partial)
864{ 864{
865 u_short sumshort; 865 u_short sumshort;
866 u_32_t sum1; 866 u_32_t sum1;
867 867
868 if (n == 0) 868 if (n == 0)
869 return; 869 return;
870 870
871 if (cksum == 4) { 871 if (cksum == 4) {
872 *sp = 0; 872 *sp = 0;
873 return; 873 return;
874 } 874 }
875 if (cksum == 2) { 875 if (cksum == 2) {
876 sum1 = partial; 876 sum1 = partial;
877 sum1 = (sum1 & 0xffff) + (sum1 >> 16); 877 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
878 *sp = htons(sum1); 878 *sp = htons(sum1);
879 return; 879 return;
880 } 880 }
881 sum1 = (~ntohs(*sp)) & 0xffff; 881 sum1 = (~ntohs(*sp)) & 0xffff;
882 sum1 += (n); 882 sum1 += (n);
883 sum1 = (sum1 >> 16) + (sum1 & 0xffff); 883 sum1 = (sum1 >> 16) + (sum1 & 0xffff);
884 /* Again */ 884 /* Again */
885 sum1 = (sum1 >> 16) + (sum1 & 0xffff); 885 sum1 = (sum1 >> 16) + (sum1 & 0xffff);
886 sumshort = ~(u_short)sum1; 886 sumshort = ~(u_short)sum1;
887 *(sp) = htons(sumshort); 887 *(sp) = htons(sumshort);
888} 888}
889 889
890 890
891/* ------------------------------------------------------------------------ */ 891/* ------------------------------------------------------------------------ */
892/* Function: ipf_fix_incksum */ 892/* Function: ipf_fix_incksum */
893/* Returns: Nil */ 893/* Returns: Nil */
894/* Parameters: fin(I) - pointer to packet information */ 894/* Parameters: fin(I) - pointer to packet information */
895/* sp(I) - location of 16bit checksum to update */ 895/* sp(I) - location of 16bit checksum to update */
896/* n((I) - amount to adjust checksum by */ 896/* n((I) - amount to adjust checksum by */
897/* */ 897/* */
898/* Adjusts the 16bit checksum by "n" for packets going in. */ 898/* Adjusts the 16bit checksum by "n" for packets going in. */
899/* ------------------------------------------------------------------------ */ 899/* ------------------------------------------------------------------------ */
900void 900void
901ipf_fix_incksum(int cksum, u_short *sp, u_32_t n, u_32_t partial) 901ipf_fix_incksum(int cksum, u_short *sp, u_32_t n, u_32_t partial)
902{ 902{
903 u_short sumshort; 903 u_short sumshort;
904 u_32_t sum1; 904 u_32_t sum1;
905 905
906 if (n == 0) 906 if (n == 0)
907 return; 907 return;
908 908
909 if (cksum == 4) { 909 if (cksum == 4) {
910 *sp = 0; 910 *sp = 0;
911 return; 911 return;
912 } 912 }
913 if (cksum == 2) { 913 if (cksum == 2) {
914 sum1 = partial; 914 sum1 = partial;
915 sum1 = (sum1 & 0xffff) + (sum1 >> 16); 915 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
916 *sp = htons(sum1); 916 *sp = htons(sum1);
917 return; 917 return;
918 } 918 }
919 919
920 sum1 = (~ntohs(*sp)) & 0xffff; 920 sum1 = (~ntohs(*sp)) & 0xffff;
921 sum1 += ~(n) & 0xffff; 921 sum1 += ~(n) & 0xffff;
922 sum1 = (sum1 >> 16) + (sum1 & 0xffff); 922 sum1 = (sum1 >> 16) + (sum1 & 0xffff);
923 /* Again */ 923 /* Again */
924 sum1 = (sum1 >> 16) + (sum1 & 0xffff); 924 sum1 = (sum1 >> 16) + (sum1 & 0xffff);
925 sumshort = ~(u_short)sum1; 925 sumshort = ~(u_short)sum1;
926 *(sp) = htons(sumshort); 926 *(sp) = htons(sumshort);
927} 927}
928 928
929 929
930/* ------------------------------------------------------------------------ */ 930/* ------------------------------------------------------------------------ */
931/* Function: ipf_fix_datacksum */ 931/* Function: ipf_fix_datacksum */
932/* Returns: Nil */ 932/* Returns: Nil */
933/* Parameters: sp(I) - location of 16bit checksum to update */ 933/* Parameters: sp(I) - location of 16bit checksum to update */
934/* n((I) - amount to adjust checksum by */ 934/* n((I) - amount to adjust checksum by */
935/* */ 935/* */
936/* Fix_datacksum is used *only* for the adjustments of checksums in the */ 936/* Fix_datacksum is used *only* for the adjustments of checksums in the */
937/* data section of an IP packet. */ 937/* data section of an IP packet. */
938/* */ 938/* */
939/* The only situation in which you need to do this is when NAT'ing an */ 939/* The only situation in which you need to do this is when NAT'ing an */
940/* ICMP error message. Such a message, contains in its body the IP header */ 940/* ICMP error message. Such a message, contains in its body the IP header */
941/* of the original IP packet, that causes the error. */ 941/* of the original IP packet, that causes the error. */
942/* */ 942/* */
943/* You can't use fix_incksum or fix_outcksum in that case, because for the */ 943/* You can't use fix_incksum or fix_outcksum in that case, because for the */
944/* kernel the data section of the ICMP error is just data, and no special */ 944/* kernel the data section of the ICMP error is just data, and no special */
945/* processing like hardware cksum or ntohs processing have been done by the */ 945/* processing like hardware cksum or ntohs processing have been done by the */
946/* kernel on the data section. */ 946/* kernel on the data section. */
947/* ------------------------------------------------------------------------ */ 947/* ------------------------------------------------------------------------ */
948void 948void
949ipf_fix_datacksum(u_short *sp, u_32_t n) 949ipf_fix_datacksum(u_short *sp, u_32_t n)
950{ 950{
951 u_short sumshort; 951 u_short sumshort;
952 u_32_t sum1; 952 u_32_t sum1;
953 953
954 if (n == 0) 954 if (n == 0)
955 return; 955 return;
956 956
957 sum1 = (~ntohs(*sp)) & 0xffff; 957 sum1 = (~ntohs(*sp)) & 0xffff;
958 sum1 += (n); 958 sum1 += (n);
959 sum1 = (sum1 >> 16) + (sum1 & 0xffff); 959 sum1 = (sum1 >> 16) + (sum1 & 0xffff);
960 /* Again */ 960 /* Again */
961 sum1 = (sum1 >> 16) + (sum1 & 0xffff); 961 sum1 = (sum1 >> 16) + (sum1 & 0xffff);
962 sumshort = ~(u_short)sum1; 962 sumshort = ~(u_short)sum1;
963 *(sp) = htons(sumshort); 963 *(sp) = htons(sumshort);
964} 964}
965 965
966 966
967/* ------------------------------------------------------------------------ */ 967/* ------------------------------------------------------------------------ */
968/* Function: ipf_nat_ioctl */ 968/* Function: ipf_nat_ioctl */
969/* Returns: int - 0 == success, != 0 == failure */ 969/* Returns: int - 0 == success, != 0 == failure */
970/* Parameters: softc(I) - pointer to soft context main structure */ 970/* Parameters: softc(I) - pointer to soft context main structure */
971/* data(I) - pointer to ioctl data */ 971/* data(I) - pointer to ioctl data */
972/* cmd(I) - ioctl command integer */ 972/* cmd(I) - ioctl command integer */
973/* mode(I) - file mode bits used with open */ 973/* mode(I) - file mode bits used with open */
974/* uid(I) - uid of calling process */ 974/* uid(I) - uid of calling process */
975/* ctx(I) - pointer used as key for finding context */ 975/* ctx(I) - pointer used as key for finding context */
976/* */ 976/* */
977/* Processes an ioctl call made to operate on the IP Filter NAT device. */ 977/* Processes an ioctl call made to operate on the IP Filter NAT device. */
978/* ------------------------------------------------------------------------ */ 978/* ------------------------------------------------------------------------ */
979int 979int
980ipf_nat_ioctl(ipf_main_softc_t *softc, void *data, ioctlcmd_t cmd, int mode, 980ipf_nat_ioctl(ipf_main_softc_t *softc, void *data, ioctlcmd_t cmd, int mode,
981 int uid, void *ctx) 981 int uid, void *ctx)
982{ 982{
983 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 983 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
984 int error = 0, ret, arg, getlock; 984 int error = 0, ret, arg, getlock;
985 ipnat_t *nat, *nt, *n; 985 ipnat_t *nat, *nt, *n;
986 ipnat_t *natd = NULL; 986 ipnat_t *natd = NULL;
987 SPL_INT(s); 987 SPL_INT(s);
988 988
989#if BSD_GE_YEAR(199306) && defined(_KERNEL) 989#if BSD_GE_YEAR(199306) && defined(_KERNEL)
990# if NETBSD_GE_REV(399002000) 990# if NETBSD_GE_REV(399002000)
991 if ((mode & FWRITE) && 991 if ((mode & FWRITE) &&
992 kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_FIREWALL, 992 kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_FIREWALL,
993 KAUTH_REQ_NETWORK_FIREWALL_FW, 993 KAUTH_REQ_NETWORK_FIREWALL_FW,
994 NULL, NULL, NULL)) 994 NULL, NULL, NULL))
995# else 995# else
996# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500034) 996# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500034)
997 if (securelevel_ge(curthread->td_ucred, 3) && (mode & FWRITE)) 997 if (securelevel_ge(curthread->td_ucred, 3) && (mode & FWRITE))
998# else 998# else
999 if ((securelevel >= 3) && (mode & FWRITE)) 999 if ((securelevel >= 3) && (mode & FWRITE))
1000# endif 1000# endif
1001# endif 1001# endif
1002 { 1002 {
1003 IPFERROR(60001); 1003 IPFERROR(60001);
1004 return EPERM; 1004 return EPERM;
1005 } 1005 }
1006#endif 1006#endif
1007 1007
1008#if defined(__osf__) && defined(_KERNEL) 1008#if defined(__osf__) && defined(_KERNEL)
1009 getlock = 0; 1009 getlock = 0;
1010#else 1010#else
1011 getlock = (mode & NAT_LOCKHELD) ? 0 : 1; 1011 getlock = (mode & NAT_LOCKHELD) ? 0 : 1;
1012#endif 1012#endif
1013 1013
1014 n = NULL; 1014 n = NULL;
1015 nt = NULL; 1015 nt = NULL;
1016 nat = NULL; 1016 nat = NULL;
1017 1017
1018 if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT) || 1018 if ((cmd == (ioctlcmd_t)SIOCADNAT) || (cmd == (ioctlcmd_t)SIOCRMNAT) ||
1019 (cmd == (ioctlcmd_t)SIOCPURGENAT)) { 1019 (cmd == (ioctlcmd_t)SIOCPURGENAT)) {
1020 KMALLOC(natd, ipnat_t *); 1020 KMALLOC(natd, ipnat_t *);
1021 if (natd == NULL) { 1021 if (natd == NULL) {
1022 error = ENOMEM; 1022 error = ENOMEM;
1023 goto done; 1023 goto done;
1024 } 1024 }
1025 if (mode & NAT_SYSSPACE) { 1025 if (mode & NAT_SYSSPACE) {
1026 bcopy(data, natd, sizeof(*natd)); 1026 bcopy(data, natd, sizeof(*natd));
1027 nat = natd; 1027 nat = natd;
1028 error = 0; 1028 error = 0;
1029 } else { 1029 } else {
1030 bzero(natd, sizeof(*natd)); 1030 bzero(natd, sizeof(*natd));
1031 error = ipf_inobj(softc, data, NULL, natd, 1031 error = ipf_inobj(softc, data, NULL, natd,
1032 IPFOBJ_IPNAT); 1032 IPFOBJ_IPNAT);
1033 if (error != 0) 1033 if (error != 0)
1034 goto done; 1034 goto done;
1035 1035
1036 if (natd->in_size < sizeof(ipnat_t)) { 1036 if (natd->in_size < sizeof(ipnat_t)) {
1037 error = EINVAL; 1037 error = EINVAL;
1038 goto done; 1038 goto done;
1039 } 1039 }
1040 KMALLOCS(nt, ipnat_t *, natd->in_size); 1040 KMALLOCS(nt, ipnat_t *, natd->in_size);
1041 if (nt == NULL) { 1041 if (nt == NULL) {
1042 IPFERROR(60070); 1042 IPFERROR(60070);
1043 error = ENOMEM; 1043 error = ENOMEM;
1044 goto done; 1044 goto done;
1045 } 1045 }
1046 bzero(nt, natd->in_size); 1046 bzero(nt, natd->in_size);
1047 error = ipf_inobjsz(softc, data, nt, IPFOBJ_IPNAT, 1047 error = ipf_inobjsz(softc, data, nt, IPFOBJ_IPNAT,
1048 natd->in_size); 1048 natd->in_size);
1049 if (error) 1049 if (error)
1050 goto done; 1050 goto done;
1051 nat = nt; 1051 nat = nt;
1052 } 1052 }
1053 1053
1054 /* 1054 /*
1055 * For add/delete, look to see if the NAT entry is 1055 * For add/delete, look to see if the NAT entry is
1056 * already present 1056 * already present
1057 */ 1057 */
1058 nat->in_flags &= IPN_USERFLAGS; 1058 nat->in_flags &= IPN_USERFLAGS;
1059 if ((nat->in_redir & NAT_MAPBLK) == 0) { 1059 if ((nat->in_redir & NAT_MAPBLK) == 0) {
1060 if (nat->in_osrcatype == FRI_NORMAL || 1060 if (nat->in_osrcatype == FRI_NORMAL ||
1061 nat->in_osrcatype == FRI_NONE) 1061 nat->in_osrcatype == FRI_NONE)
1062 nat->in_osrcaddr &= nat->in_osrcmsk; 1062 nat->in_osrcaddr &= nat->in_osrcmsk;
1063 if (nat->in_odstatype == FRI_NORMAL || 1063 if (nat->in_odstatype == FRI_NORMAL ||
1064 nat->in_odstatype == FRI_NONE) 1064 nat->in_odstatype == FRI_NONE)
1065 nat->in_odstaddr &= nat->in_odstmsk; 1065 nat->in_odstaddr &= nat->in_odstmsk;
1066 if ((nat->in_flags & (IPN_SPLIT|IPN_SIPRANGE)) == 0) { 1066 if ((nat->in_flags & (IPN_SPLIT|IPN_SIPRANGE)) == 0) {
1067 if (nat->in_nsrcatype == FRI_NORMAL) 1067 if (nat->in_nsrcatype == FRI_NORMAL)
1068 nat->in_nsrcaddr &= nat->in_nsrcmsk; 1068 nat->in_nsrcaddr &= nat->in_nsrcmsk;
1069 if (nat->in_ndstatype == FRI_NORMAL) 1069 if (nat->in_ndstatype == FRI_NORMAL)
1070 nat->in_ndstaddr &= nat->in_ndstmsk; 1070 nat->in_ndstaddr &= nat->in_ndstmsk;
1071 } 1071 }
1072 } 1072 }
1073 1073
1074 error = ipf_nat_rule_init(softc, softn, nat); 1074 error = ipf_nat_rule_init(softc, softn, nat);
1075 if (error != 0) 1075 if (error != 0)
1076 goto done; 1076 goto done;
1077 1077
1078 MUTEX_ENTER(&softn->ipf_nat_io); 1078 MUTEX_ENTER(&softn->ipf_nat_io);
1079 for (n = softn->ipf_nat_list; n != NULL; n = n->in_next) 1079 for (n = softn->ipf_nat_list; n != NULL; n = n->in_next)
1080 if (ipf_nat_cmp_rules(nat, n) == 0) 1080 if (ipf_nat_cmp_rules(nat, n) == 0)
1081 break; 1081 break;
1082 } 1082 }
1083 1083
1084 switch (cmd) 1084 switch (cmd)
1085 { 1085 {
1086#ifdef IPFILTER_LOG 1086#ifdef IPFILTER_LOG
1087 case SIOCIPFFB : 1087 case SIOCIPFFB :
1088 { 1088 {
1089 int tmp; 1089 int tmp;
1090 1090
1091 if (!(mode & FWRITE)) { 1091 if (!(mode & FWRITE)) {
1092 IPFERROR(60002); 1092 IPFERROR(60002);
1093 error = EPERM; 1093 error = EPERM;
1094 } else { 1094 } else {
1095 tmp = ipf_log_clear(softc, IPL_LOGNAT); 1095 tmp = ipf_log_clear(softc, IPL_LOGNAT);
1096 error = BCOPYOUT(&tmp, data, sizeof(tmp)); 1096 error = BCOPYOUT(&tmp, data, sizeof(tmp));
1097 if (error != 0) { 1097 if (error != 0) {
1098 IPFERROR(60057); 1098 IPFERROR(60057);
1099 error = EFAULT; 1099 error = EFAULT;
1100 } 1100 }
1101 } 1101 }
1102 break; 1102 break;
1103 } 1103 }
1104 1104
1105 case SIOCSETLG : 1105 case SIOCSETLG :
1106 if (!(mode & FWRITE)) { 1106 if (!(mode & FWRITE)) {
1107 IPFERROR(60003); 1107 IPFERROR(60003);
1108 error = EPERM; 1108 error = EPERM;
1109 } else { 1109 } else {
1110 error = BCOPYIN(data, &softn->ipf_nat_logging, 1110 error = BCOPYIN(data, &softn->ipf_nat_logging,
1111 sizeof(softn->ipf_nat_logging)); 1111 sizeof(softn->ipf_nat_logging));
1112 if (error != 0) 1112 if (error != 0)
1113 error = EFAULT; 1113 error = EFAULT;
1114 } 1114 }
@@ -5182,1999 +5182,1999 @@ ipf_nat_out(fr_info_t *fin, nat_t *nat,  @@ -5182,1999 +5182,1999 @@ ipf_nat_out(fr_info_t *fin, nat_t *nat,
5182 tcp->th_dport = nat->nat_ndport; 5182 tcp->th_dport = nat->nat_ndport;
5183 fin->fin_data[1] = ntohs(nat->nat_ndport); 5183 fin->fin_data[1] = ntohs(nat->nat_ndport);
5184 break; 5184 break;
5185 5185
5186 case NAT_INBOUND : 5186 case NAT_INBOUND :
5187 tcp->th_sport = nat->nat_odport; 5187 tcp->th_sport = nat->nat_odport;
5188 fin->fin_data[0] = ntohs(nat->nat_odport); 5188 fin->fin_data[0] = ntohs(nat->nat_odport);
5189 tcp->th_dport = nat->nat_osport; 5189 tcp->th_dport = nat->nat_osport;
5190 fin->fin_data[1] = ntohs(nat->nat_osport); 5190 fin->fin_data[1] = ntohs(nat->nat_osport);
5191 break; 5191 break;
5192 } 5192 }
5193 } 5193 }
5194 5194
5195 if ((nat->nat_oicmpid != 0) && (nflags & IPN_ICMPQUERY)) { 5195 if ((nat->nat_oicmpid != 0) && (nflags & IPN_ICMPQUERY)) {
5196 icmp = fin->fin_dp; 5196 icmp = fin->fin_dp;
5197 5197
5198 switch (nat->nat_dir) 5198 switch (nat->nat_dir)
5199 { 5199 {
5200 case NAT_OUTBOUND : 5200 case NAT_OUTBOUND :
5201 icmp->icmp_id = nat->nat_nicmpid; 5201 icmp->icmp_id = nat->nat_nicmpid;
5202 break; 5202 break;
5203 case NAT_INBOUND : 5203 case NAT_INBOUND :
5204 icmp->icmp_id = nat->nat_oicmpid; 5204 icmp->icmp_id = nat->nat_oicmpid;
5205 break; 5205 break;
5206 } 5206 }
5207 } 5207 }
5208 5208
5209 csump = ipf_nat_proto(fin, nat, nflags); 5209 csump = ipf_nat_proto(fin, nat, nflags);
5210 5210
5211 /* 5211 /*
5212 * The above comments do not hold for layer 4 (or higher) 5212 * The above comments do not hold for layer 4 (or higher)
5213 * checksums... 5213 * checksums...
5214 */ 5214 */
5215 if (csump != NULL) { 5215 if (csump != NULL) {
5216 if (nat->nat_dir == NAT_OUTBOUND) 5216 if (nat->nat_dir == NAT_OUTBOUND)
5217 ipf_fix_outcksum(fin->fin_cksum, csump, 5217 ipf_fix_outcksum(fin->fin_cksum, csump,
5218 nat->nat_sumd[0], 5218 nat->nat_sumd[0],
5219 nat->nat_sumd[1] + 5219 nat->nat_sumd[1] +
5220 fin->fin_dlen); 5220 fin->fin_dlen);
5221 else 5221 else
5222 ipf_fix_incksum(fin->fin_cksum, csump, 5222 ipf_fix_incksum(fin->fin_cksum, csump,
5223 nat->nat_sumd[0], 5223 nat->nat_sumd[0],
5224 nat->nat_sumd[1] + 5224 nat->nat_sumd[1] +
5225 fin->fin_dlen); 5225 fin->fin_dlen);
5226 } 5226 }
5227 } 5227 }
5228 5228
5229 ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync); 5229 ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync);
5230 /* ------------------------------------------------------------- */ 5230 /* ------------------------------------------------------------- */
5231 /* A few quick notes: */ 5231 /* A few quick notes: */
5232 /* Following are test conditions prior to calling the */ 5232 /* Following are test conditions prior to calling the */
5233 /* ipf_proxy_check routine. */ 5233 /* ipf_proxy_check routine. */
5234 /* */ 5234 /* */
5235 /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ 5235 /* A NULL tcp indicates a non TCP/UDP packet. When dealing */
5236 /* with a redirect rule, we attempt to match the packet's */ 5236 /* with a redirect rule, we attempt to match the packet's */
5237 /* source port against in_dport, otherwise we'd compare the */ 5237 /* source port against in_dport, otherwise we'd compare the */
5238 /* packet's destination. */ 5238 /* packet's destination. */
5239 /* ------------------------------------------------------------- */ 5239 /* ------------------------------------------------------------- */
5240 if ((np != NULL) && (np->in_apr != NULL)) { 5240 if ((np != NULL) && (np->in_apr != NULL)) {
5241 i = ipf_proxy_check(fin, nat); 5241 i = ipf_proxy_check(fin, nat);
5242 if (i == 0) { 5242 if (i == 0) {
5243 i = 1; 5243 i = 1;
5244 } else if (i == -1) { 5244 } else if (i == -1) {
5245 NBUMPSIDED(1, ns_ipf_proxy_fail); 5245 NBUMPSIDED(1, ns_ipf_proxy_fail);
5246 } 5246 }
5247 } else { 5247 } else {
5248 i = 1; 5248 i = 1;
5249 } 5249 }
5250 fin->fin_flx |= FI_NATED; 5250 fin->fin_flx |= FI_NATED;
5251 return i; 5251 return i;
5252} 5252}
5253 5253
5254 5254
5255/* ------------------------------------------------------------------------ */ 5255/* ------------------------------------------------------------------------ */
5256/* Function: ipf_nat_checkin */ 5256/* Function: ipf_nat_checkin */
5257/* Returns: int - -1 == packet failed NAT checks so block it, */ 5257/* Returns: int - -1 == packet failed NAT checks so block it, */
5258/* 0 == no packet translation occurred, */ 5258/* 0 == no packet translation occurred, */
5259/* 1 == packet was successfully translated. */ 5259/* 1 == packet was successfully translated. */
5260/* Parameters: fin(I) - pointer to packet information */ 5260/* Parameters: fin(I) - pointer to packet information */
5261/* passp(I) - pointer to filtering result flags */ 5261/* passp(I) - pointer to filtering result flags */
5262/* */ 5262/* */
5263/* Check to see if an incoming packet should be changed. ICMP packets are */ 5263/* Check to see if an incoming packet should be changed. ICMP packets are */
5264/* first checked to see if they match an existing entry (if an error), */ 5264/* first checked to see if they match an existing entry (if an error), */
5265/* otherwise a search of the current NAT table is made. If neither results */ 5265/* otherwise a search of the current NAT table is made. If neither results */
5266/* in a match then a search for a matching NAT rule is made. Create a new */ 5266/* in a match then a search for a matching NAT rule is made. Create a new */
5267/* NAT entry if a we matched a NAT rule. Lastly, actually change the */ 5267/* NAT entry if a we matched a NAT rule. Lastly, actually change the */
5268/* packet header(s) as required. */ 5268/* packet header(s) as required. */
5269/* ------------------------------------------------------------------------ */ 5269/* ------------------------------------------------------------------------ */
5270int 5270int
5271ipf_nat_checkin(fr_info_t *fin, u_32_t *passp) 5271ipf_nat_checkin(fr_info_t *fin, u_32_t *passp)
5272{ 5272{
5273 ipf_main_softc_t *softc; 5273 ipf_main_softc_t *softc;
5274 ipf_nat_softc_t *softn; 5274 ipf_nat_softc_t *softn;
5275 u_int nflags, natadd; 5275 u_int nflags, natadd;
5276 ipnat_t *np, *npnext; 5276 ipnat_t *np, *npnext;
5277 int rval, natfailed; 5277 int rval, natfailed;
5278 struct ifnet *ifp; 5278 struct ifnet *ifp;
5279 struct in_addr in; 5279 struct in_addr in;
5280 icmphdr_t *icmp; 5280 icmphdr_t *icmp;
5281 tcphdr_t *tcp; 5281 tcphdr_t *tcp;
5282 u_short dport; 5282 u_short dport;
5283 nat_t *nat; 5283 nat_t *nat;
5284 u_32_t iph; 5284 u_32_t iph;
5285 5285
5286 softc = fin->fin_main_soft; 5286 softc = fin->fin_main_soft;
5287 softn = softc->ipf_nat_soft; 5287 softn = softc->ipf_nat_soft;
5288 5288
5289 if (softn->ipf_nat_lock != 0) 5289 if (softn->ipf_nat_lock != 0)
5290 return 0; 5290 return 0;
5291 if (softn->ipf_nat_stats.ns_rules == 0 && 5291 if (softn->ipf_nat_stats.ns_rules == 0 &&
5292 softn->ipf_nat_instances == NULL) 5292 softn->ipf_nat_instances == NULL)
5293 return 0; 5293 return 0;
5294 5294
5295 tcp = NULL; 5295 tcp = NULL;
5296 icmp = NULL; 5296 icmp = NULL;
5297 dport = 0; 5297 dport = 0;
5298 natadd = 1; 5298 natadd = 1;
5299 nflags = 0; 5299 nflags = 0;
5300 natfailed = 0; 5300 natfailed = 0;
5301 ifp = fin->fin_ifp; 5301 ifp = fin->fin_ifp;
5302 5302
5303 if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { 5303 if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) {
5304 switch (fin->fin_p) 5304 switch (fin->fin_p)
5305 { 5305 {
5306 case IPPROTO_TCP : 5306 case IPPROTO_TCP :
5307 nflags = IPN_TCP; 5307 nflags = IPN_TCP;
5308 break; 5308 break;
5309 case IPPROTO_UDP : 5309 case IPPROTO_UDP :
5310 nflags = IPN_UDP; 5310 nflags = IPN_UDP;
5311 break; 5311 break;
5312 case IPPROTO_ICMP : 5312 case IPPROTO_ICMP :
5313 icmp = fin->fin_dp; 5313 icmp = fin->fin_dp;
5314 5314
5315 /* 5315 /*
5316 * This is an incoming packet, so the destination is 5316 * This is an incoming packet, so the destination is
5317 * the icmp_id and the source port equals 0 5317 * the icmp_id and the source port equals 0
5318 */ 5318 */
5319 if ((fin->fin_flx & FI_ICMPQUERY) != 0) { 5319 if ((fin->fin_flx & FI_ICMPQUERY) != 0) {
5320 nflags = IPN_ICMPQUERY; 5320 nflags = IPN_ICMPQUERY;
5321 dport = icmp->icmp_id; 5321 dport = icmp->icmp_id;
5322 } break; 5322 } break;
5323 default : 5323 default :
5324 break; 5324 break;
5325 } 5325 }
5326 5326
5327 if ((nflags & IPN_TCPUDP)) { 5327 if ((nflags & IPN_TCPUDP)) {
5328 tcp = fin->fin_dp; 5328 tcp = fin->fin_dp;
5329 dport = fin->fin_data[1]; 5329 dport = fin->fin_data[1];
5330 } 5330 }
5331 } 5331 }
5332 5332
5333 in = fin->fin_dst; 5333 in = fin->fin_dst;
5334 5334
5335 READ_ENTER(&softc->ipf_nat); 5335 READ_ENTER(&softc->ipf_nat);
5336 5336
5337 if ((fin->fin_p == IPPROTO_ICMP) && !(nflags & IPN_ICMPQUERY) && 5337 if ((fin->fin_p == IPPROTO_ICMP) && !(nflags & IPN_ICMPQUERY) &&
5338 (nat = ipf_nat_icmperror(fin, &nflags, NAT_INBOUND))) 5338 (nat = ipf_nat_icmperror(fin, &nflags, NAT_INBOUND)))
5339 /*EMPTY*/; 5339 /*EMPTY*/;
5340 else if ((fin->fin_flx & FI_FRAG) && (nat = ipf_frag_natknown(fin))) 5340 else if ((fin->fin_flx & FI_FRAG) && (nat = ipf_frag_natknown(fin)))
5341 natadd = 0; 5341 natadd = 0;
5342 else if ((nat = ipf_nat_inlookup(fin, nflags|NAT_SEARCH, 5342 else if ((nat = ipf_nat_inlookup(fin, nflags|NAT_SEARCH,
5343 (u_int)fin->fin_p, 5343 (u_int)fin->fin_p,
5344 fin->fin_src, in))) { 5344 fin->fin_src, in))) {
5345 nflags = nat->nat_flags; 5345 nflags = nat->nat_flags;
5346 } else if (fin->fin_off == 0) { 5346 } else if (fin->fin_off == 0) {
5347 u_32_t hv, msk, rmsk = 0; 5347 u_32_t hv, msk, rmsk = 0;
5348 5348
5349 /* 5349 /*
5350 * If there is no current entry in the nat table for this IP#, 5350 * If there is no current entry in the nat table for this IP#,
5351 * create one for it (if there is a matching rule). 5351 * create one for it (if there is a matching rule).
5352 */ 5352 */
5353maskloop: 5353maskloop:
5354 msk = softn->ipf_nat_rdr_active_masks[rmsk]; 5354 msk = softn->ipf_nat_rdr_active_masks[rmsk];
5355 iph = in.s_addr & msk; 5355 iph = in.s_addr & msk;
5356 hv = NAT_HASH_FN(iph, 0, softn->ipf_nat_rdrrules_sz); 5356 hv = NAT_HASH_FN(iph, 0, softn->ipf_nat_rdrrules_sz);
5357retry_roundrobin: 5357retry_roundrobin:
5358 /* TRACE (iph,msk,rmsk,hv,softn->ipf_nat_rdrrules_sz) */ 5358 /* TRACE (iph,msk,rmsk,hv,softn->ipf_nat_rdrrules_sz) */
5359 for (np = softn->ipf_nat_rdr_rules[hv]; np; np = npnext) { 5359 for (np = softn->ipf_nat_rdr_rules[hv]; np; np = npnext) {
5360 npnext = np->in_rnext; 5360 npnext = np->in_rnext;
5361 if (np->in_ifps[0] && (np->in_ifps[0] != ifp)) 5361 if (np->in_ifps[0] && (np->in_ifps[0] != ifp))
5362 continue; 5362 continue;
5363 if (np->in_v[0] != 4) 5363 if (np->in_v[0] != 4)
5364 continue; 5364 continue;
5365 if (np->in_pr[0] && (np->in_pr[0] != fin->fin_p)) 5365 if (np->in_pr[0] && (np->in_pr[0] != fin->fin_p))
5366 continue; 5366 continue;
5367 if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags)) 5367 if ((np->in_flags & IPN_RF) && !(np->in_flags & nflags))
5368 continue; 5368 continue;
5369 if (np->in_flags & IPN_FILTER) { 5369 if (np->in_flags & IPN_FILTER) {
5370 switch (ipf_nat_match(fin, np)) 5370 switch (ipf_nat_match(fin, np))
5371 { 5371 {
5372 case 0 : 5372 case 0 :
5373 continue; 5373 continue;
5374 case -1 : 5374 case -1 :
5375 rval = -1; 5375 rval = -1;
5376 goto inmatchfail; 5376 goto inmatchfail;
5377 case 1 : 5377 case 1 :
5378 default : 5378 default :
5379 break; 5379 break;
5380 } 5380 }
5381 } else { 5381 } else {
5382 if ((in.s_addr & np->in_odstmsk) != 5382 if ((in.s_addr & np->in_odstmsk) !=
5383 np->in_odstaddr) 5383 np->in_odstaddr)
5384 continue; 5384 continue;
5385 if (np->in_odport && 5385 if (np->in_odport &&
5386 ((np->in_dtop < dport) || 5386 ((np->in_dtop < dport) ||
5387 (dport < np->in_odport))) 5387 (dport < np->in_odport)))
5388 continue; 5388 continue;
5389 } 5389 }
5390 5390
5391 if (np->in_plabel != -1) { 5391 if (np->in_plabel != -1) {
5392 if (!ipf_proxy_ok(fin, tcp, np)) { 5392 if (!ipf_proxy_ok(fin, tcp, np)) {
5393 continue; 5393 continue;
5394 } 5394 }
5395 } 5395 }
5396 5396
5397 if (np->in_flags & IPN_NO) { 5397 if (np->in_flags & IPN_NO) {
5398 np->in_hits++; 5398 np->in_hits++;
5399 break; 5399 break;
5400 } 5400 }
5401 5401
5402 MUTEX_ENTER(&softn->ipf_nat_new); 5402 MUTEX_ENTER(&softn->ipf_nat_new);
5403 /* 5403 /*
5404 * If we've matched a round-robin rule but it has 5404 * If we've matched a round-robin rule but it has
5405 * moved in the list since we got it, start over as 5405 * moved in the list since we got it, start over as
5406 * this is now no longer correct. 5406 * this is now no longer correct.
5407 */ 5407 */
5408 if (npnext != np->in_rnext) { 5408 if (npnext != np->in_rnext) {
5409 if ((np->in_flags & IPN_ROUNDR) != 0) { 5409 if ((np->in_flags & IPN_ROUNDR) != 0) {
5410 MUTEX_EXIT(&softn->ipf_nat_new); 5410 MUTEX_EXIT(&softn->ipf_nat_new);
5411 goto retry_roundrobin; 5411 goto retry_roundrobin;
5412 } 5412 }
5413 npnext = np->in_rnext; 5413 npnext = np->in_rnext;
5414 } 5414 }
5415 5415
5416 nat = ipf_nat_add(fin, np, NULL, nflags, NAT_INBOUND); 5416 nat = ipf_nat_add(fin, np, NULL, nflags, NAT_INBOUND);
5417 MUTEX_EXIT(&softn->ipf_nat_new); 5417 MUTEX_EXIT(&softn->ipf_nat_new);
5418 if (nat != NULL) { 5418 if (nat != NULL) {
5419 natfailed = 0; 5419 natfailed = 0;
5420 break; 5420 break;
5421 } 5421 }
5422 natfailed = -1; 5422 natfailed = -1;
5423 } 5423 }
5424 if ((np == NULL) && (rmsk < softn->ipf_nat_rdr_max)) { 5424 if ((np == NULL) && (rmsk < softn->ipf_nat_rdr_max)) {
5425 rmsk++; 5425 rmsk++;
5426 goto maskloop; 5426 goto maskloop;
5427 } 5427 }
5428 } 5428 }
5429 5429
5430 if (nat != NULL) { 5430 if (nat != NULL) {
5431 rval = ipf_nat_in(fin, nat, natadd, nflags); 5431 rval = ipf_nat_in(fin, nat, natadd, nflags);
5432 if (rval == 1) { 5432 if (rval == 1) {
5433 MUTEX_ENTER(&nat->nat_lock); 5433 MUTEX_ENTER(&nat->nat_lock);
5434 ipf_nat_update(fin, nat); 5434 ipf_nat_update(fin, nat);
5435 nat->nat_bytes[0] += fin->fin_plen; 5435 nat->nat_bytes[0] += fin->fin_plen;
5436 nat->nat_pkts[0]++; 5436 nat->nat_pkts[0]++;
5437 fin->fin_pktnum = nat->nat_pkts[0]; 5437 fin->fin_pktnum = nat->nat_pkts[0];
5438 MUTEX_EXIT(&nat->nat_lock); 5438 MUTEX_EXIT(&nat->nat_lock);
5439 } 5439 }
5440 } else 5440 } else
5441 rval = natfailed; 5441 rval = natfailed;
5442inmatchfail: 5442inmatchfail:
5443 RWLOCK_EXIT(&softc->ipf_nat); 5443 RWLOCK_EXIT(&softc->ipf_nat);
5444 5444
5445 switch (rval) 5445 switch (rval)
5446 { 5446 {
5447 case -1 : 5447 case -1 :
5448 if (passp != NULL) { 5448 if (passp != NULL) {
5449 DT1(frb_natv4in, fr_info_t *, fin); 5449 DT1(frb_natv4in, fr_info_t *, fin);
5450 NBUMPSIDED(0, ns_drop); 5450 NBUMPSIDED(0, ns_drop);
5451 *passp = FR_BLOCK; 5451 *passp = FR_BLOCK;
5452 fin->fin_reason = FRB_NATV4; 5452 fin->fin_reason = FRB_NATV4;
5453 } 5453 }
5454 fin->fin_flx |= FI_BADNAT; 5454 fin->fin_flx |= FI_BADNAT;
5455 NBUMPSIDED(0, ns_badnat); 5455 NBUMPSIDED(0, ns_badnat);
5456 break; 5456 break;
5457 case 0 : 5457 case 0 :
5458 NBUMPSIDE(0, ns_ignored); 5458 NBUMPSIDE(0, ns_ignored);
5459 break; 5459 break;
5460 case 1 : 5460 case 1 :
5461 NBUMPSIDE(0, ns_translated); 5461 NBUMPSIDE(0, ns_translated);
5462 break; 5462 break;
5463 } 5463 }
5464 return rval; 5464 return rval;
5465} 5465}
5466 5466
5467 5467
5468/* ------------------------------------------------------------------------ */ 5468/* ------------------------------------------------------------------------ */
5469/* Function: ipf_nat_in */ 5469/* Function: ipf_nat_in */
5470/* Returns: int - -1 == packet failed NAT checks so block it, */ 5470/* Returns: int - -1 == packet failed NAT checks so block it, */
5471/* 1 == packet was successfully translated. */ 5471/* 1 == packet was successfully translated. */
5472/* Parameters: fin(I) - pointer to packet information */ 5472/* Parameters: fin(I) - pointer to packet information */
5473/* nat(I) - pointer to NAT structure */ 5473/* nat(I) - pointer to NAT structure */
5474/* natadd(I) - flag indicating if it is safe to add frag cache */ 5474/* natadd(I) - flag indicating if it is safe to add frag cache */
5475/* nflags(I) - NAT flags set for this packet */ 5475/* nflags(I) - NAT flags set for this packet */
5476/* Locks Held: ipf_nat(READ) */ 5476/* Locks Held: ipf_nat(READ) */
5477/* */ 5477/* */
5478/* Translate a packet coming "in" on an interface. */ 5478/* Translate a packet coming "in" on an interface. */
5479/* ------------------------------------------------------------------------ */ 5479/* ------------------------------------------------------------------------ */
5480int 5480int
5481ipf_nat_in(fr_info_t *fin, nat_t *nat, int natadd, u_32_t nflags) 5481ipf_nat_in(fr_info_t *fin, nat_t *nat, int natadd, u_32_t nflags)
5482{ 5482{
5483 ipf_main_softc_t *softc = fin->fin_main_soft; 5483 ipf_main_softc_t *softc = fin->fin_main_soft;
5484 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 5484 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
5485 u_32_t sumd, ipsumd, sum1, sum2; 5485 u_32_t sumd, ipsumd, sum1, sum2;
5486 icmphdr_t *icmp; 5486 icmphdr_t *icmp;
5487 tcphdr_t *tcp; 5487 tcphdr_t *tcp;
5488 ipnat_t *np; 5488 ipnat_t *np;
5489 int skip; 5489 int skip;
5490 int i; 5490 int i;
5491 5491
5492 tcp = NULL; 5492 tcp = NULL;
5493 np = nat->nat_ptr; 5493 np = nat->nat_ptr;
5494 fin->fin_fr = nat->nat_fr; 5494 fin->fin_fr = nat->nat_fr;
5495 5495
5496 if (np != NULL) { 5496 if (np != NULL) {
5497 if ((natadd != 0) && (fin->fin_flx & FI_FRAG)) 5497 if ((natadd != 0) && (fin->fin_flx & FI_FRAG))
5498 (void) ipf_frag_natnew(softc, fin, 0, nat); 5498 (void) ipf_frag_natnew(softc, fin, 0, nat);
5499 5499
5500 /* ------------------------------------------------------------- */ 5500 /* ------------------------------------------------------------- */
5501 /* A few quick notes: */ 5501 /* A few quick notes: */
5502 /* Following are test conditions prior to calling the */ 5502 /* Following are test conditions prior to calling the */
5503 /* ipf_proxy_check routine. */ 5503 /* ipf_proxy_check routine. */
5504 /* */ 5504 /* */
5505 /* A NULL tcp indicates a non TCP/UDP packet. When dealing */ 5505 /* A NULL tcp indicates a non TCP/UDP packet. When dealing */
5506 /* with a map rule, we attempt to match the packet's */ 5506 /* with a map rule, we attempt to match the packet's */
5507 /* source port against in_dport, otherwise we'd compare the */ 5507 /* source port against in_dport, otherwise we'd compare the */
5508 /* packet's destination. */ 5508 /* packet's destination. */
5509 /* ------------------------------------------------------------- */ 5509 /* ------------------------------------------------------------- */
5510 if (np->in_apr != NULL) { 5510 if (np->in_apr != NULL) {
5511 i = ipf_proxy_check(fin, nat); 5511 i = ipf_proxy_check(fin, nat);
5512 if (i == -1) { 5512 if (i == -1) {
5513 NBUMPSIDED(0, ns_ipf_proxy_fail); 5513 NBUMPSIDED(0, ns_ipf_proxy_fail);
5514 return -1; 5514 return -1;
5515 } 5515 }
5516 } 5516 }
5517 } 5517 }
5518 5518
5519 ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync); 5519 ipf_sync_update(softc, SMC_NAT, fin, nat->nat_sync);
5520 5520
5521 ipsumd = nat->nat_ipsumd; 5521 ipsumd = nat->nat_ipsumd;
5522 /* 5522 /*
5523 * Fix up checksums, not by recalculating them, but 5523 * Fix up checksums, not by recalculating them, but
5524 * simply computing adjustments. 5524 * simply computing adjustments.
5525 * Why only do this for some platforms on inbound packets ? 5525 * Why only do this for some platforms on inbound packets ?
5526 * Because for those that it is done, IP processing is yet to happen 5526 * Because for those that it is done, IP processing is yet to happen
5527 * and so the IPv4 header checksum has not yet been evaluated. 5527 * and so the IPv4 header checksum has not yet been evaluated.
5528 * Perhaps it should always be done for the benefit of things like 5528 * Perhaps it should always be done for the benefit of things like
5529 * fast forwarding (so that it doesn't need to be recomputed) but with 5529 * fast forwarding (so that it doesn't need to be recomputed) but with
5530 * header checksum offloading, perhaps it is a moot point. 5530 * header checksum offloading, perhaps it is a moot point.
5531 */ 5531 */
5532 5532
5533 switch (nat->nat_dir) 5533 switch (nat->nat_dir)
5534 { 5534 {
5535 case NAT_INBOUND : 5535 case NAT_INBOUND :
5536 if ((fin->fin_flx & FI_ICMPERR) == 0) { 5536 if ((fin->fin_flx & FI_ICMPERR) == 0) {
5537 fin->fin_ip->ip_src = nat->nat_nsrcip; 5537 fin->fin_ip->ip_src = nat->nat_nsrcip;
5538 fin->fin_saddr = nat->nat_nsrcaddr; 5538 fin->fin_saddr = nat->nat_nsrcaddr;
5539 } else { 5539 } else {
5540 sum1 = nat->nat_osrcaddr; 5540 sum1 = nat->nat_osrcaddr;
5541 sum2 = nat->nat_nsrcaddr; 5541 sum2 = nat->nat_nsrcaddr;
5542 CALC_SUMD(sum1, sum2, sumd); 5542 CALC_SUMD(sum1, sum2, sumd);
5543 ipsumd -= sumd; 5543 ipsumd -= sumd;
5544 } 5544 }
5545 fin->fin_ip->ip_dst = nat->nat_ndstip; 5545 fin->fin_ip->ip_dst = nat->nat_ndstip;
5546 fin->fin_daddr = nat->nat_ndstaddr; 5546 fin->fin_daddr = nat->nat_ndstaddr;
5547#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ 5547#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
5548 defined(__osf__) || defined(linux) 5548 defined(__osf__) || defined(linux)
5549 ipf_fix_outcksum(0, &fin->fin_ip->ip_sum, ipsumd, 0); 5549 ipf_fix_outcksum(0, &fin->fin_ip->ip_sum, ipsumd, 0);
5550#endif 5550#endif
5551 break; 5551 break;
5552 5552
5553 case NAT_OUTBOUND : 5553 case NAT_OUTBOUND :
5554 if ((fin->fin_flx & FI_ICMPERR) == 0) { 5554 if ((fin->fin_flx & FI_ICMPERR) == 0) {
5555 fin->fin_ip->ip_src = nat->nat_odstip; 5555 fin->fin_ip->ip_src = nat->nat_odstip;
5556 fin->fin_saddr = nat->nat_odstaddr; 5556 fin->fin_saddr = nat->nat_odstaddr;
5557 } else { 5557 } else {
5558 sum1 = nat->nat_odstaddr; 5558 sum1 = nat->nat_odstaddr;
5559 sum2 = nat->nat_ndstaddr; 5559 sum2 = nat->nat_ndstaddr;
5560 CALC_SUMD(sum1, sum2, sumd); 5560 CALC_SUMD(sum1, sum2, sumd);
5561 ipsumd -= sumd; 5561 ipsumd -= sumd;
5562 } 5562 }
5563 fin->fin_ip->ip_dst = nat->nat_osrcip; 5563 fin->fin_ip->ip_dst = nat->nat_osrcip;
5564 fin->fin_daddr = nat->nat_osrcaddr; 5564 fin->fin_daddr = nat->nat_osrcaddr;
5565#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ 5565#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
5566 defined(__osf__) || defined(linux) 5566 defined(__osf__) || defined(linux)
5567 ipf_fix_incksum(0, &fin->fin_ip->ip_sum, ipsumd, 0); 5567 ipf_fix_incksum(0, &fin->fin_ip->ip_sum, ipsumd, 0);
5568#endif 5568#endif
5569 break; 5569 break;
5570 5570
5571 case NAT_DIVERTIN : 5571 case NAT_DIVERTIN :
5572 { 5572 {
5573 udphdr_t *uh; 5573 udphdr_t *uh;
5574 ip_t *ip; 5574 ip_t *ip;
5575 mb_t *m; 5575 mb_t *m;
5576 5576
5577 m = M_DUP(np->in_divmp); 5577 m = M_DUP(np->in_divmp);
5578 if (m == NULL) { 5578 if (m == NULL) {
5579 NBUMPSIDED(0, ns_divert_dup); 5579 NBUMPSIDED(0, ns_divert_dup);
5580 return -1; 5580 return -1;
5581 } 5581 }
5582 5582
5583 ip = MTOD(m, ip_t *); 5583 ip = MTOD(m, ip_t *);
5584 ip->ip_id = htons(ipf_nextipid(fin)); 5584 ip->ip_id = htons(ipf_nextipid(fin));
5585 sum1 = ntohs(ip->ip_len); 5585 sum1 = ntohs(ip->ip_len);
5586 ip->ip_len = ntohs(ip->ip_len); 5586 ip->ip_len = ntohs(ip->ip_len);
5587 ip->ip_len += fin->fin_plen; 5587 ip->ip_len += fin->fin_plen;
5588 ip->ip_len = htons(ip->ip_len); 5588 ip->ip_len = htons(ip->ip_len);
5589 5589
5590 uh = (udphdr_t *)(ip + 1); 5590 uh = (udphdr_t *)(ip + 1);
5591 uh->uh_ulen += fin->fin_plen; 5591 uh->uh_ulen += fin->fin_plen;
5592 uh->uh_ulen = htons(uh->uh_ulen); 5592 uh->uh_ulen = htons(uh->uh_ulen);
5593 5593
5594 sum2 = ntohs(ip->ip_id) + ntohs(ip->ip_len); 5594 sum2 = ntohs(ip->ip_id) + ntohs(ip->ip_len);
5595 sum2 += ntohs(ip->ip_off) & IP_DF; 5595 sum2 += ntohs(ip->ip_off) & IP_DF;
5596 CALC_SUMD(sum1, sum2, sumd); 5596 CALC_SUMD(sum1, sum2, sumd);
5597 5597
5598#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \ 5598#if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi) || \
5599 defined(__osf__) || defined(linux) 5599 defined(__osf__) || defined(linux)
5600 ipf_fix_outcksum(0, &ip->ip_sum, sumd, 0); 5600 ipf_fix_outcksum(0, &ip->ip_sum, sumd, 0);
5601#endif 5601#endif
5602 PREP_MB_T(fin, m); 5602 PREP_MB_T(fin, m);
5603 5603
5604 fin->fin_ip = ip; 5604 fin->fin_ip = ip;
5605 fin->fin_plen += sizeof(ip_t) + 8; /* UDP + new IPv4 hdr */ 5605 fin->fin_plen += sizeof(ip_t) + 8; /* UDP + new IPv4 hdr */
5606 fin->fin_dlen += sizeof(ip_t) + 8; /* UDP + old IPv4 hdr */ 5606 fin->fin_dlen += sizeof(ip_t) + 8; /* UDP + old IPv4 hdr */
5607 5607
5608 nflags &= ~IPN_TCPUDPICMP; 5608 nflags &= ~IPN_TCPUDPICMP;
5609 5609
5610 break; 5610 break;
5611 } 5611 }
5612 5612
5613 case NAT_DIVERTOUT : 5613 case NAT_DIVERTOUT :
5614 { 5614 {
5615 mb_t *m; 5615 mb_t *m;
5616 5616
5617 skip = ipf_nat_decap(fin, nat); 5617 skip = ipf_nat_decap(fin, nat);
5618 if (skip <= 0) { 5618 if (skip <= 0) {
5619 NBUMPSIDED(0, ns_decap_fail); 5619 NBUMPSIDED(0, ns_decap_fail);
5620 return -1; 5620 return -1;
5621 } 5621 }
5622 5622
5623 m = fin->fin_m; 5623 m = fin->fin_m;
5624 5624
5625#if defined(MENTAT) && defined(_KERNEL) 5625#if defined(MENTAT) && defined(_KERNEL)
5626 m->b_rptr += skip; 5626 m->b_rptr += skip;
5627#else 5627#else
5628 m->m_data += skip; 5628 m->m_data += skip;
5629 m->m_len -= skip; 5629 m->m_len -= skip;
5630 5630
5631# ifdef M_PKTHDR 5631# ifdef M_PKTHDR
5632 if (m->m_flags & M_PKTHDR) 5632 if (m->m_flags & M_PKTHDR)
5633 m->m_pkthdr.len -= skip; 5633 m->m_pkthdr.len -= skip;
5634# endif 5634# endif
5635#endif 5635#endif
5636 5636
5637 ipf_nat_update(fin, nat); 5637 ipf_nat_update(fin, nat);
5638 nflags &= ~IPN_TCPUDPICMP; 5638 nflags &= ~IPN_TCPUDPICMP;
5639 fin->fin_flx |= FI_NATED; 5639 fin->fin_flx |= FI_NATED;
5640 if (np != NULL && np->in_tag.ipt_num[0] != 0) 5640 if (np != NULL && np->in_tag.ipt_num[0] != 0)
5641 fin->fin_nattag = &np->in_tag; 5641 fin->fin_nattag = &np->in_tag;
5642 return 1; 5642 return 1;
5643 /* NOTREACHED */ 5643 /* NOTREACHED */
5644 } 5644 }
5645 } 5645 }
5646 if (nflags & IPN_TCPUDP) 5646 if (nflags & IPN_TCPUDP)
5647 tcp = fin->fin_dp; 5647 tcp = fin->fin_dp;
5648 5648
5649 if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) { 5649 if (!(fin->fin_flx & FI_SHORT) && (fin->fin_off == 0)) {
5650 u_short *csump; 5650 u_short *csump;
5651 5651
5652 if ((nat->nat_odport != 0) && (nflags & IPN_TCPUDP)) { 5652 if ((nat->nat_odport != 0) && (nflags & IPN_TCPUDP)) {
5653 switch (nat->nat_dir) 5653 switch (nat->nat_dir)
5654 { 5654 {
5655 case NAT_INBOUND : 5655 case NAT_INBOUND :
5656 tcp->th_sport = nat->nat_nsport; 5656 tcp->th_sport = nat->nat_nsport;
5657 fin->fin_data[0] = ntohs(nat->nat_nsport); 5657 fin->fin_data[0] = ntohs(nat->nat_nsport);
5658 tcp->th_dport = nat->nat_ndport; 5658 tcp->th_dport = nat->nat_ndport;
5659 fin->fin_data[1] = ntohs(nat->nat_ndport); 5659 fin->fin_data[1] = ntohs(nat->nat_ndport);
5660 break; 5660 break;
5661 5661
5662 case NAT_OUTBOUND : 5662 case NAT_OUTBOUND :
5663 tcp->th_sport = nat->nat_odport; 5663 tcp->th_sport = nat->nat_odport;
5664 fin->fin_data[0] = ntohs(nat->nat_odport); 5664 fin->fin_data[0] = ntohs(nat->nat_odport);
5665 tcp->th_dport = nat->nat_osport; 5665 tcp->th_dport = nat->nat_osport;
5666 fin->fin_data[1] = ntohs(nat->nat_osport); 5666 fin->fin_data[1] = ntohs(nat->nat_osport);
5667 break; 5667 break;
5668 } 5668 }
5669 } 5669 }
5670 5670
5671 5671
5672 if ((nat->nat_oicmpid != 0) && (nflags & IPN_ICMPQUERY)) { 5672 if ((nat->nat_oicmpid != 0) && (nflags & IPN_ICMPQUERY)) {
5673 icmp = fin->fin_dp; 5673 icmp = fin->fin_dp;
5674 5674
5675 switch (nat->nat_dir) 5675 switch (nat->nat_dir)
5676 { 5676 {
5677 case NAT_INBOUND : 5677 case NAT_INBOUND :
5678 icmp->icmp_id = nat->nat_nicmpid; 5678 icmp->icmp_id = nat->nat_nicmpid;
5679 break; 5679 break;
5680 case NAT_OUTBOUND : 5680 case NAT_OUTBOUND :
5681 icmp->icmp_id = nat->nat_oicmpid; 5681 icmp->icmp_id = nat->nat_oicmpid;
5682 break; 5682 break;
5683 } 5683 }
5684 } 5684 }
5685 5685
5686 csump = ipf_nat_proto(fin, nat, nflags); 5686 csump = ipf_nat_proto(fin, nat, nflags);
5687 5687
5688 /* 5688 /*
5689 * The above comments do not hold for layer 4 (or higher) 5689 * The above comments do not hold for layer 4 (or higher)
5690 * checksums... 5690 * checksums...
5691 */ 5691 */
5692 if (csump != NULL) { 5692 if (csump != NULL) {
5693 if (nat->nat_dir == NAT_OUTBOUND) 5693 if (nat->nat_dir == NAT_OUTBOUND)
5694 ipf_fix_incksum(0, csump, nat->nat_sumd[0], 0); 5694 ipf_fix_incksum(0, csump, nat->nat_sumd[0], 0);
5695 else 5695 else
5696 ipf_fix_outcksum(0, csump, nat->nat_sumd[0], 0); 5696 ipf_fix_outcksum(0, csump, nat->nat_sumd[0], 0);
5697 } 5697 }
5698 } 5698 }
5699 5699
5700 fin->fin_flx |= FI_NATED; 5700 fin->fin_flx |= FI_NATED;
5701 if (np != NULL && np->in_tag.ipt_num[0] != 0) 5701 if (np != NULL && np->in_tag.ipt_num[0] != 0)
5702 fin->fin_nattag = &np->in_tag; 5702 fin->fin_nattag = &np->in_tag;
5703 return 1; 5703 return 1;
5704} 5704}
5705 5705
5706 5706
5707/* ------------------------------------------------------------------------ */ 5707/* ------------------------------------------------------------------------ */
5708/* Function: ipf_nat_proto */ 5708/* Function: ipf_nat_proto */
5709/* Returns: u_short* - pointer to transport header checksum to update, */ 5709/* Returns: u_short* - pointer to transport header checksum to update, */
5710/* NULL if the transport protocol is not recognised */ 5710/* NULL if the transport protocol is not recognised */
5711/* as needing a checksum update. */ 5711/* as needing a checksum update. */
5712/* Parameters: fin(I) - pointer to packet information */ 5712/* Parameters: fin(I) - pointer to packet information */
5713/* nat(I) - pointer to NAT structure */ 5713/* nat(I) - pointer to NAT structure */
5714/* nflags(I) - NAT flags set for this packet */ 5714/* nflags(I) - NAT flags set for this packet */
5715/* */ 5715/* */
5716/* Return the pointer to the checksum field for each protocol so understood.*/ 5716/* Return the pointer to the checksum field for each protocol so understood.*/
5717/* If support for making other changes to a protocol header is required, */ 5717/* If support for making other changes to a protocol header is required, */
5718/* that is not strictly 'address' translation, such as clamping the MSS in */ 5718/* that is not strictly 'address' translation, such as clamping the MSS in */
5719/* TCP down to a specific value, then do it from here. */ 5719/* TCP down to a specific value, then do it from here. */
5720/* ------------------------------------------------------------------------ */ 5720/* ------------------------------------------------------------------------ */
5721u_short * 5721u_short *
5722ipf_nat_proto(fr_info_t *fin, nat_t *nat, u_int nflags) 5722ipf_nat_proto(fr_info_t *fin, nat_t *nat, u_int nflags)
5723{ 5723{
5724 icmphdr_t *icmp; 5724 icmphdr_t *icmp;
5725 u_short *csump; 5725 u_short *csump;
5726 tcphdr_t *tcp; 5726 tcphdr_t *tcp;
5727 udphdr_t *udp; 5727 udphdr_t *udp;
5728 5728
5729 csump = NULL; 5729 csump = NULL;
5730 if (fin->fin_out == 0) { 5730 if (fin->fin_out == 0) {
5731 fin->fin_rev = (nat->nat_dir & NAT_OUTBOUND); 5731 fin->fin_rev = (nat->nat_dir & NAT_OUTBOUND);
5732 } else { 5732 } else {
5733 fin->fin_rev = ((nat->nat_dir & NAT_OUTBOUND) == 0); 5733 fin->fin_rev = ((nat->nat_dir & NAT_OUTBOUND) == 0);
5734 } 5734 }
5735 5735
5736 switch (fin->fin_p) 5736 switch (fin->fin_p)
5737 { 5737 {
5738 case IPPROTO_TCP : 5738 case IPPROTO_TCP :
5739 tcp = fin->fin_dp; 5739 tcp = fin->fin_dp;
5740 5740
5741 if ((nflags & IPN_TCP) != 0) 5741 if ((nflags & IPN_TCP) != 0)
5742 csump = &tcp->th_sum; 5742 csump = &tcp->th_sum;
5743 5743
5744 /* 5744 /*
5745 * Do a MSS CLAMPING on a SYN packet, 5745 * Do a MSS CLAMPING on a SYN packet,
5746 * only deal IPv4 for now. 5746 * only deal IPv4 for now.
5747 */ 5747 */
5748 if ((nat->nat_mssclamp != 0) && (tcp->th_flags & TH_SYN) != 0) 5748 if ((nat->nat_mssclamp != 0) && (tcp->th_flags & TH_SYN) != 0)
5749 ipf_nat_mssclamp(tcp, nat->nat_mssclamp, fin, csump); 5749 ipf_nat_mssclamp(tcp, nat->nat_mssclamp, fin, csump);
5750 5750
5751 break; 5751 break;
5752 5752
5753 case IPPROTO_UDP : 5753 case IPPROTO_UDP :
5754 udp = fin->fin_dp; 5754 udp = fin->fin_dp;
5755 5755
5756 if ((nflags & IPN_UDP) != 0) { 5756 if ((nflags & IPN_UDP) != 0) {
5757 if (udp->uh_sum != 0) 5757 if (udp->uh_sum != 0)
5758 csump = &udp->uh_sum; 5758 csump = &udp->uh_sum;
5759 } 5759 }
5760 break; 5760 break;
5761 5761
5762 case IPPROTO_ICMP : 5762 case IPPROTO_ICMP :
5763 icmp = fin->fin_dp; 5763 icmp = fin->fin_dp;
5764 5764
5765 if ((nflags & IPN_ICMPQUERY) != 0) { 5765 if ((nflags & IPN_ICMPQUERY) != 0) {
5766 if (icmp->icmp_cksum != 0) 5766 if (icmp->icmp_cksum != 0)
5767 csump = &icmp->icmp_cksum; 5767 csump = &icmp->icmp_cksum;
5768 } 5768 }
5769 break; 5769 break;
5770 5770
5771#ifdef USE_INET6 5771#ifdef USE_INET6
5772 case IPPROTO_ICMPV6 : 5772 case IPPROTO_ICMPV6 :
5773 { 5773 {
5774 struct icmp6_hdr *icmp6 = (struct icmp6_hdr *)fin->fin_dp; 5774 struct icmp6_hdr *icmp6 = (struct icmp6_hdr *)fin->fin_dp;
5775 5775
5776 icmp6 = fin->fin_dp; 5776 icmp6 = fin->fin_dp;
5777 5777
5778 if ((nflags & IPN_ICMPQUERY) != 0) { 5778 if ((nflags & IPN_ICMPQUERY) != 0) {
5779 if (icmp6->icmp6_cksum != 0) 5779 if (icmp6->icmp6_cksum != 0)
5780 csump = &icmp6->icmp6_cksum; 5780 csump = &icmp6->icmp6_cksum;
5781 } 5781 }
5782 break; 5782 break;
5783 } 5783 }
5784#endif 5784#endif
5785 } 5785 }
5786 return csump; 5786 return csump;
5787} 5787}
5788 5788
5789 5789
5790/* ------------------------------------------------------------------------ */ 5790/* ------------------------------------------------------------------------ */
5791/* Function: ipf_nat_expire */ 5791/* Function: ipf_nat_expire */
5792/* Returns: Nil */ 5792/* Returns: Nil */
5793/* Parameters: softc(I) - pointer to soft context main structure */ 5793/* Parameters: softc(I) - pointer to soft context main structure */
5794/* */ 5794/* */
5795/* Check all of the timeout queues for entries at the top which need to be */ 5795/* Check all of the timeout queues for entries at the top which need to be */
5796/* expired. */ 5796/* expired. */
5797/* ------------------------------------------------------------------------ */ 5797/* ------------------------------------------------------------------------ */
5798void 5798void
5799ipf_nat_expire(ipf_main_softc_t *softc) 5799ipf_nat_expire(ipf_main_softc_t *softc)
5800{ 5800{
5801 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 5801 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
5802 ipftq_t *ifq, *ifqnext; 5802 ipftq_t *ifq, *ifqnext;
5803 ipftqent_t *tqe, *tqn; 5803 ipftqent_t *tqe, *tqn;
5804 int i; 5804 int i;
5805 SPL_INT(s); 5805 SPL_INT(s);
5806 5806
5807 SPL_NET(s); 5807 SPL_NET(s);
5808 WRITE_ENTER(&softc->ipf_nat); 5808 WRITE_ENTER(&softc->ipf_nat);
5809 for (ifq = softn->ipf_nat_tcptq, i = 0; ifq != NULL; 5809 for (ifq = softn->ipf_nat_tcptq, i = 0; ifq != NULL;
5810 ifq = ifq->ifq_next) { 5810 ifq = ifq->ifq_next) {
5811 for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); i++) { 5811 for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); i++) {
5812 if (tqe->tqe_die > softc->ipf_ticks) 5812 if (tqe->tqe_die > softc->ipf_ticks)
5813 break; 5813 break;
5814 tqn = tqe->tqe_next; 5814 tqn = tqe->tqe_next;
5815 ipf_nat_delete(softc, tqe->tqe_parent, NL_EXPIRE); 5815 ipf_nat_delete(softc, tqe->tqe_parent, NL_EXPIRE);
5816 } 5816 }
5817 } 5817 }
5818 5818
5819 for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifq->ifq_next) { 5819 for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifq->ifq_next) {
5820 for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); i++) { 5820 for (tqn = ifq->ifq_head; ((tqe = tqn) != NULL); i++) {
5821 if (tqe->tqe_die > softc->ipf_ticks) 5821 if (tqe->tqe_die > softc->ipf_ticks)
5822 break; 5822 break;
5823 tqn = tqe->tqe_next; 5823 tqn = tqe->tqe_next;
5824 ipf_nat_delete(softc, tqe->tqe_parent, NL_EXPIRE); 5824 ipf_nat_delete(softc, tqe->tqe_parent, NL_EXPIRE);
5825 } 5825 }
5826 } 5826 }
5827 5827
5828 for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifqnext) { 5828 for (ifq = softn->ipf_nat_utqe; ifq != NULL; ifq = ifqnext) {
5829 ifqnext = ifq->ifq_next; 5829 ifqnext = ifq->ifq_next;
5830 5830
5831 if (((ifq->ifq_flags & IFQF_DELETE) != 0) && 5831 if (((ifq->ifq_flags & IFQF_DELETE) != 0) &&
5832 (ifq->ifq_ref == 0)) { 5832 (ifq->ifq_ref == 0)) {
5833 ipf_freetimeoutqueue(softc, ifq); 5833 ipf_freetimeoutqueue(softc, ifq);
5834 } 5834 }
5835 } 5835 }
5836 5836
5837 if (softn->ipf_nat_doflush != 0) { 5837 if (softn->ipf_nat_doflush != 0) {
5838 ipf_nat_extraflush(softc, softn, 2); 5838 ipf_nat_extraflush(softc, softn, 2);
5839 softn->ipf_nat_doflush = 0; 5839 softn->ipf_nat_doflush = 0;
5840 } 5840 }
5841 5841
5842 RWLOCK_EXIT(&softc->ipf_nat); 5842 RWLOCK_EXIT(&softc->ipf_nat);
5843 SPL_X(s); 5843 SPL_X(s);
5844} 5844}
5845 5845
5846 5846
5847/* ------------------------------------------------------------------------ */ 5847/* ------------------------------------------------------------------------ */
5848/* Function: ipf_nat_sync */ 5848/* Function: ipf_nat_sync */
5849/* Returns: Nil */ 5849/* Returns: Nil */
5850/* Parameters: softc(I) - pointer to soft context main structure */ 5850/* Parameters: softc(I) - pointer to soft context main structure */
5851/* ifp(I) - pointer to network interface */ 5851/* ifp(I) - pointer to network interface */
5852/* */ 5852/* */
5853/* Walk through all of the currently active NAT sessions, looking for those */ 5853/* Walk through all of the currently active NAT sessions, looking for those */
5854/* which need to have their translated address updated. */ 5854/* which need to have their translated address updated. */
5855/* ------------------------------------------------------------------------ */ 5855/* ------------------------------------------------------------------------ */
5856void 5856void
5857ipf_nat_sync(ipf_main_softc_t *softc, void *ifp) 5857ipf_nat_sync(ipf_main_softc_t *softc, void *ifp)
5858{ 5858{
5859 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 5859 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
5860 u_32_t sum1, sum2, sumd; 5860 u_32_t sum1, sum2, sumd;
5861 i6addr_t in; 5861 i6addr_t in;
5862 ipnat_t *n; 5862 ipnat_t *n;
5863 nat_t *nat; 5863 nat_t *nat;
5864 void *ifp2; 5864 void *ifp2;
5865 int idx; 5865 int idx;
5866 SPL_INT(s); 5866 SPL_INT(s);
5867 5867
5868 if (softc->ipf_running <= 0) 5868 if (softc->ipf_running <= 0)
5869 return; 5869 return;
5870 5870
5871 /* 5871 /*
5872 * Change IP addresses for NAT sessions for any protocol except TCP 5872 * Change IP addresses for NAT sessions for any protocol except TCP
5873 * since it will break the TCP connection anyway. The only rules 5873 * since it will break the TCP connection anyway. The only rules
5874 * which will get changed are those which are "map ... -> 0/32", 5874 * which will get changed are those which are "map ... -> 0/32",
5875 * where the rule specifies the address is taken from the interface. 5875 * where the rule specifies the address is taken from the interface.
5876 */ 5876 */
5877 SPL_NET(s); 5877 SPL_NET(s);
5878 WRITE_ENTER(&softc->ipf_nat); 5878 WRITE_ENTER(&softc->ipf_nat);
5879 5879
5880 if (softc->ipf_running <= 0) { 5880 if (softc->ipf_running <= 0) {
5881 RWLOCK_EXIT(&softc->ipf_nat); 5881 RWLOCK_EXIT(&softc->ipf_nat);
5882 return; 5882 return;
5883 } 5883 }
5884 5884
5885 for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) { 5885 for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) {
5886 if ((nat->nat_flags & IPN_TCP) != 0) 5886 if ((nat->nat_flags & IPN_TCP) != 0)
5887 continue; 5887 continue;
5888 5888
5889 n = nat->nat_ptr; 5889 n = nat->nat_ptr;
5890 if (n != NULL) { 5890 if (n != NULL) {
5891 if (n->in_v[1] == 4) { 5891 if (n->in_v[1] == 4) {
5892 if (n->in_redir & NAT_MAP) { 5892 if (n->in_redir & NAT_MAP) {
5893 if ((n->in_nsrcaddr != 0) || 5893 if ((n->in_nsrcaddr != 0) ||
5894 (n->in_nsrcmsk != 0xffffffff)) 5894 (n->in_nsrcmsk != 0xffffffff))
5895 continue; 5895 continue;
5896 } else if (n->in_redir & NAT_REDIRECT) { 5896 } else if (n->in_redir & NAT_REDIRECT) {
5897 if ((n->in_ndstaddr != 0) || 5897 if ((n->in_ndstaddr != 0) ||
5898 (n->in_ndstmsk != 0xffffffff)) 5898 (n->in_ndstmsk != 0xffffffff))
5899 continue; 5899 continue;
5900 } 5900 }
5901 } 5901 }
5902#ifdef USE_INET6 5902#ifdef USE_INET6
5903 if (n->in_v[1] == 4) { 5903 if (n->in_v[1] == 4) {
5904 if (n->in_redir & NAT_MAP) { 5904 if (n->in_redir & NAT_MAP) {
5905 if (!IP6_ISZERO(&n->in_nsrcaddr) || 5905 if (!IP6_ISZERO(&n->in_nsrcaddr) ||
5906 !IP6_ISONES(&n->in_nsrcmsk)) 5906 !IP6_ISONES(&n->in_nsrcmsk))
5907 continue; 5907 continue;
5908 } else if (n->in_redir & NAT_REDIRECT) { 5908 } else if (n->in_redir & NAT_REDIRECT) {
5909 if (!IP6_ISZERO(&n->in_ndstaddr) || 5909 if (!IP6_ISZERO(&n->in_ndstaddr) ||
5910 !IP6_ISONES(&n->in_ndstmsk)) 5910 !IP6_ISONES(&n->in_ndstmsk))
5911 continue; 5911 continue;
5912 } 5912 }
5913 } 5913 }
5914#endif 5914#endif
5915 } 5915 }
5916 5916
5917 if (((ifp == NULL) || (ifp == nat->nat_ifps[0]) || 5917 if (((ifp == NULL) || (ifp == nat->nat_ifps[0]) ||
5918 (ifp == nat->nat_ifps[1]))) { 5918 (ifp == nat->nat_ifps[1]))) {
5919 nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0], 5919 nat->nat_ifps[0] = GETIFP(nat->nat_ifnames[0],
5920 nat->nat_v[0]); 5920 nat->nat_v[0]);
5921 if ((nat->nat_ifps[0] != NULL) && 5921 if ((nat->nat_ifps[0] != NULL) &&
5922 (nat->nat_ifps[0] != (void *)-1)) { 5922 (nat->nat_ifps[0] != (void *)-1)) {
5923 nat->nat_mtu[0] = GETIFMTU_4(nat->nat_ifps[0]); 5923 nat->nat_mtu[0] = GETIFMTU_4(nat->nat_ifps[0]);
5924 } 5924 }
5925 if (nat->nat_ifnames[1][0] != '\0') { 5925 if (nat->nat_ifnames[1][0] != '\0') {
5926 nat->nat_ifps[1] = GETIFP(nat->nat_ifnames[1], 5926 nat->nat_ifps[1] = GETIFP(nat->nat_ifnames[1],
5927 nat->nat_v[1]); 5927 nat->nat_v[1]);
5928 } else { 5928 } else {
5929 nat->nat_ifps[1] = nat->nat_ifps[0]; 5929 nat->nat_ifps[1] = nat->nat_ifps[0];
5930 } 5930 }
5931 if ((nat->nat_ifps[1] != NULL) && 5931 if ((nat->nat_ifps[1] != NULL) &&
5932 (nat->nat_ifps[1] != (void *)-1)) { 5932 (nat->nat_ifps[1] != (void *)-1)) {
5933 nat->nat_mtu[1] = GETIFMTU_4(nat->nat_ifps[1]); 5933 nat->nat_mtu[1] = GETIFMTU_4(nat->nat_ifps[1]);
5934 } 5934 }
5935 ifp2 = nat->nat_ifps[0]; 5935 ifp2 = nat->nat_ifps[0];
5936 if (ifp2 == NULL) 5936 if (ifp2 == NULL)
5937 continue; 5937 continue;
5938 5938
5939 /* 5939 /*
5940 * Change the map-to address to be the same as the 5940 * Change the map-to address to be the same as the
5941 * new one. 5941 * new one.
5942 */ 5942 */
5943 sum1 = NATFSUM(nat, nat->nat_v[1], nat_nsrc6); 5943 sum1 = NATFSUM(nat, nat->nat_v[1], nat_nsrc6);
5944 if (ipf_ifpaddr(softc, nat->nat_v[0], FRI_NORMAL, ifp2, 5944 if (ipf_ifpaddr(softc, nat->nat_v[0], FRI_NORMAL, ifp2,
5945 &in, NULL) != -1) { 5945 &in, NULL) != -1) {
5946 if (nat->nat_v[0] == 4) 5946 if (nat->nat_v[0] == 4)
5947 nat->nat_nsrcip = in.in4; 5947 nat->nat_nsrcip = in.in4;
5948 } 5948 }
5949 sum2 = NATFSUM(nat, nat->nat_v[1], nat_nsrc6); 5949 sum2 = NATFSUM(nat, nat->nat_v[1], nat_nsrc6);
5950 5950
5951 if (sum1 == sum2) 5951 if (sum1 == sum2)
5952 continue; 5952 continue;
5953 /* 5953 /*
5954 * Readjust the checksum adjustment to take into 5954 * Readjust the checksum adjustment to take into
5955 * account the new IP#. 5955 * account the new IP#.
5956 */ 5956 */
5957 CALC_SUMD(sum1, sum2, sumd); 5957 CALC_SUMD(sum1, sum2, sumd);
5958 /* XXX - dont change for TCP when solaris does 5958 /* XXX - dont change for TCP when solaris does
5959 * hardware checksumming. 5959 * hardware checksumming.
5960 */ 5960 */
5961 sumd += nat->nat_sumd[0]; 5961 sumd += nat->nat_sumd[0];
5962 nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16); 5962 nat->nat_sumd[0] = (sumd & 0xffff) + (sumd >> 16);
5963 nat->nat_sumd[1] = nat->nat_sumd[0]; 5963 nat->nat_sumd[1] = nat->nat_sumd[0];
5964 } 5964 }
5965 } 5965 }
5966 5966
5967 for (n = softn->ipf_nat_list; (n != NULL); n = n->in_next) { 5967 for (n = softn->ipf_nat_list; (n != NULL); n = n->in_next) {
5968 char *base = n->in_names; 5968 char *base = n->in_names;
5969 5969
5970 if ((ifp == NULL) || (n->in_ifps[0] == ifp)) 5970 if ((ifp == NULL) || (n->in_ifps[0] == ifp))
5971 n->in_ifps[0] = ipf_resolvenic(softc, 5971 n->in_ifps[0] = ipf_resolvenic(softc,
5972 base + n->in_ifnames[0], 5972 base + n->in_ifnames[0],
5973 n->in_v[0]); 5973 n->in_v[0]);
5974 if ((ifp == NULL) || (n->in_ifps[1] == ifp)) 5974 if ((ifp == NULL) || (n->in_ifps[1] == ifp))
5975 n->in_ifps[1] = ipf_resolvenic(softc, 5975 n->in_ifps[1] = ipf_resolvenic(softc,
5976 base + n->in_ifnames[1], 5976 base + n->in_ifnames[1],
5977 n->in_v[1]); 5977 n->in_v[1]);
5978 5978
5979 if (n->in_redir & NAT_REDIRECT) 5979 if (n->in_redir & NAT_REDIRECT)
5980 idx = 1; 5980 idx = 1;
5981 else 5981 else
5982 idx = 0; 5982 idx = 0;
5983 5983
5984 if (((ifp == NULL) || (n->in_ifps[idx] == ifp)) && 5984 if (((ifp == NULL) || (n->in_ifps[idx] == ifp)) &&
5985 (n->in_ifps[idx] != NULL && 5985 (n->in_ifps[idx] != NULL &&
5986 n->in_ifps[idx] != (void *)-1)) { 5986 n->in_ifps[idx] != (void *)-1)) {
5987 5987
5988 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_osrc, 5988 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_osrc,
5989 0, n->in_ifps[idx]); 5989 0, n->in_ifps[idx]);
5990 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_odst, 5990 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_odst,
5991 0, n->in_ifps[idx]); 5991 0, n->in_ifps[idx]);
5992 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_nsrc, 5992 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_nsrc,
5993 0, n->in_ifps[idx]); 5993 0, n->in_ifps[idx]);
5994 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_ndst, 5994 ipf_nat_nextaddrinit(softc, n->in_names, &n->in_ndst,
5995 0, n->in_ifps[idx]); 5995 0, n->in_ifps[idx]);
5996 } 5996 }
5997 } 5997 }
5998 RWLOCK_EXIT(&softc->ipf_nat); 5998 RWLOCK_EXIT(&softc->ipf_nat);
5999 SPL_X(s); 5999 SPL_X(s);
6000} 6000}
6001 6001
6002 6002
6003/* ------------------------------------------------------------------------ */ 6003/* ------------------------------------------------------------------------ */
6004/* Function: ipf_nat_icmpquerytype */ 6004/* Function: ipf_nat_icmpquerytype */
6005/* Returns: int - 1 == success, 0 == failure */ 6005/* Returns: int - 1 == success, 0 == failure */
6006/* Parameters: icmptype(I) - ICMP type number */ 6006/* Parameters: icmptype(I) - ICMP type number */
6007/* */ 6007/* */
6008/* Tests to see if the ICMP type number passed is a query/response type or */ 6008/* Tests to see if the ICMP type number passed is a query/response type or */
6009/* not. */ 6009/* not. */
6010/* ------------------------------------------------------------------------ */ 6010/* ------------------------------------------------------------------------ */
6011static int 6011static int
6012ipf_nat_icmpquerytype(int icmptype) 6012ipf_nat_icmpquerytype(int icmptype)
6013{ 6013{
6014 6014
6015 /* 6015 /*
6016 * For the ICMP query NAT code, it is essential that both the query 6016 * For the ICMP query NAT code, it is essential that both the query
6017 * and the reply match on the NAT rule. Because the NAT structure 6017 * and the reply match on the NAT rule. Because the NAT structure
6018 * does not keep track of the icmptype, and a single NAT structure 6018 * does not keep track of the icmptype, and a single NAT structure
6019 * is used for all icmp types with the same src, dest and id, we 6019 * is used for all icmp types with the same src, dest and id, we
6020 * simply define the replies as queries as well. The funny thing is, 6020 * simply define the replies as queries as well. The funny thing is,
6021 * although it seems silly to call a reply a query, this is exactly 6021 * although it seems silly to call a reply a query, this is exactly
6022 * as it is defined in the IPv4 specification 6022 * as it is defined in the IPv4 specification
6023 */ 6023 */
6024 switch (icmptype) 6024 switch (icmptype)
6025 { 6025 {
6026 case ICMP_ECHOREPLY: 6026 case ICMP_ECHOREPLY:
6027 case ICMP_ECHO: 6027 case ICMP_ECHO:
6028 /* route advertisement/sollicitation is currently unsupported: */ 6028 /* route advertisement/sollicitation is currently unsupported: */
6029 /* it would require rewriting the ICMP data section */ 6029 /* it would require rewriting the ICMP data section */
6030 case ICMP_TSTAMP: 6030 case ICMP_TSTAMP:
6031 case ICMP_TSTAMPREPLY: 6031 case ICMP_TSTAMPREPLY:
6032 case ICMP_IREQ: 6032 case ICMP_IREQ:
6033 case ICMP_IREQREPLY: 6033 case ICMP_IREQREPLY:
6034 case ICMP_MASKREQ: 6034 case ICMP_MASKREQ:
6035 case ICMP_MASKREPLY: 6035 case ICMP_MASKREPLY:
6036 return 1; 6036 return 1;
6037 default: 6037 default:
6038 return 0; 6038 return 0;
6039 } 6039 }
6040} 6040}
6041 6041
6042 6042
6043/* ------------------------------------------------------------------------ */ 6043/* ------------------------------------------------------------------------ */
6044/* Function: nat_log */ 6044/* Function: nat_log */
6045/* Returns: Nil */ 6045/* Returns: Nil */
6046/* Parameters: softc(I) - pointer to soft context main structure */ 6046/* Parameters: softc(I) - pointer to soft context main structure */
6047/* softn(I) - pointer to NAT context structure */ 6047/* softn(I) - pointer to NAT context structure */
6048/* nat(I) - pointer to NAT structure */ 6048/* nat(I) - pointer to NAT structure */
6049/* action(I) - action related to NAT structure being performed */ 6049/* action(I) - action related to NAT structure being performed */
6050/* */ 6050/* */
6051/* Creates a NAT log entry. */ 6051/* Creates a NAT log entry. */
6052/* ------------------------------------------------------------------------ */ 6052/* ------------------------------------------------------------------------ */
6053void 6053void
6054ipf_nat_log(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, struct nat *nat, 6054ipf_nat_log(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, struct nat *nat,
6055 u_int action) 6055 u_int action)
6056{ 6056{
6057#ifdef IPFILTER_LOG 6057#ifdef IPFILTER_LOG
6058# ifndef LARGE_NAT 6058# ifndef LARGE_NAT
6059 struct ipnat *np; 6059 struct ipnat *np;
6060 int rulen; 6060 int rulen;
6061# endif 6061# endif
6062 struct natlog natl; 6062 struct natlog natl;
6063 void *items[1]; 6063 void *items[1];
6064 size_t sizes[1]; 6064 size_t sizes[1];
6065 int types[1]; 6065 int types[1];
6066 6066
6067 bcopy((char *)&nat->nat_osrc6, (char *)&natl.nl_osrcip, 6067 bcopy((char *)&nat->nat_osrc6, (char *)&natl.nl_osrcip,
6068 sizeof(natl.nl_osrcip)); 6068 sizeof(natl.nl_osrcip));
6069 bcopy((char *)&nat->nat_nsrc6, (char *)&natl.nl_nsrcip, 6069 bcopy((char *)&nat->nat_nsrc6, (char *)&natl.nl_nsrcip,
6070 sizeof(natl.nl_nsrcip)); 6070 sizeof(natl.nl_nsrcip));
6071 bcopy((char *)&nat->nat_odst6, (char *)&natl.nl_odstip, 6071 bcopy((char *)&nat->nat_odst6, (char *)&natl.nl_odstip,
6072 sizeof(natl.nl_odstip)); 6072 sizeof(natl.nl_odstip));
6073 bcopy((char *)&nat->nat_ndst6, (char *)&natl.nl_ndstip, 6073 bcopy((char *)&nat->nat_ndst6, (char *)&natl.nl_ndstip,
6074 sizeof(natl.nl_ndstip)); 6074 sizeof(natl.nl_ndstip));
6075 6075
6076 natl.nl_bytes[0] = nat->nat_bytes[0]; 6076 natl.nl_bytes[0] = nat->nat_bytes[0];
6077 natl.nl_bytes[1] = nat->nat_bytes[1]; 6077 natl.nl_bytes[1] = nat->nat_bytes[1];
6078 natl.nl_pkts[0] = nat->nat_pkts[0]; 6078 natl.nl_pkts[0] = nat->nat_pkts[0];
6079 natl.nl_pkts[1] = nat->nat_pkts[1]; 6079 natl.nl_pkts[1] = nat->nat_pkts[1];
6080 natl.nl_odstport = nat->nat_odport; 6080 natl.nl_odstport = nat->nat_odport;
6081 natl.nl_osrcport = nat->nat_osport; 6081 natl.nl_osrcport = nat->nat_osport;
6082 natl.nl_nsrcport = nat->nat_nsport; 6082 natl.nl_nsrcport = nat->nat_nsport;
6083 natl.nl_ndstport = nat->nat_ndport; 6083 natl.nl_ndstport = nat->nat_ndport;
6084 natl.nl_p[0] = nat->nat_pr[0]; 6084 natl.nl_p[0] = nat->nat_pr[0];
6085 natl.nl_p[1] = nat->nat_pr[1]; 6085 natl.nl_p[1] = nat->nat_pr[1];
6086 natl.nl_v[0] = nat->nat_v[0]; 6086 natl.nl_v[0] = nat->nat_v[0];
6087 natl.nl_v[1] = nat->nat_v[1]; 6087 natl.nl_v[1] = nat->nat_v[1];
6088 natl.nl_type = nat->nat_redir; 6088 natl.nl_type = nat->nat_redir;
6089 natl.nl_action = action; 6089 natl.nl_action = action;
6090 natl.nl_rule = -1; 6090 natl.nl_rule = -1;
6091 6091
6092 bcopy(nat->nat_ifnames[0], natl.nl_ifnames[0], 6092 bcopy(nat->nat_ifnames[0], natl.nl_ifnames[0],
6093 sizeof(nat->nat_ifnames[0])); 6093 sizeof(nat->nat_ifnames[0]));
6094 bcopy(nat->nat_ifnames[1], natl.nl_ifnames[1], 6094 bcopy(nat->nat_ifnames[1], natl.nl_ifnames[1],
6095 sizeof(nat->nat_ifnames[1])); 6095 sizeof(nat->nat_ifnames[1]));
6096 6096
6097# ifndef LARGE_NAT 6097# ifndef LARGE_NAT
6098 if (nat->nat_ptr != NULL) { 6098 if (nat->nat_ptr != NULL) {
6099 for (rulen = 0, np = softn->ipf_nat_list; np != NULL; 6099 for (rulen = 0, np = softn->ipf_nat_list; np != NULL;
6100 np = np->in_next, rulen++) 6100 np = np->in_next, rulen++)
6101 if (np == nat->nat_ptr) { 6101 if (np == nat->nat_ptr) {
6102 natl.nl_rule = rulen; 6102 natl.nl_rule = rulen;
6103 break; 6103 break;
6104 } 6104 }
6105 } 6105 }
6106# endif 6106# endif
6107 items[0] = &natl; 6107 items[0] = &natl;
6108 sizes[0] = sizeof(natl); 6108 sizes[0] = sizeof(natl);
6109 types[0] = 0; 6109 types[0] = 0;
6110 6110
6111 (void) ipf_log_items(softc, IPL_LOGNAT, NULL, items, sizes, types, 1); 6111 (void) ipf_log_items(softc, IPL_LOGNAT, NULL, items, sizes, types, 1);
6112#endif 6112#endif
6113} 6113}
6114 6114
6115 6115
6116#if defined(__OpenBSD__) 6116#if defined(__OpenBSD__)
6117/* ------------------------------------------------------------------------ */ 6117/* ------------------------------------------------------------------------ */
6118/* Function: ipf_nat_ifdetach */ 6118/* Function: ipf_nat_ifdetach */
6119/* Returns: Nil */ 6119/* Returns: Nil */
6120/* Parameters: ifp(I) - pointer to network interface */ 6120/* Parameters: ifp(I) - pointer to network interface */
6121/* */ 6121/* */
6122/* Compatibility interface for OpenBSD to trigger the correct updating of */ 6122/* Compatibility interface for OpenBSD to trigger the correct updating of */
6123/* interface references within IPFilter. */ 6123/* interface references within IPFilter. */
6124/* ------------------------------------------------------------------------ */ 6124/* ------------------------------------------------------------------------ */
6125void 6125void
6126ipf_nat_ifdetach(ifp) 6126ipf_nat_ifdetach(ifp)
6127 void *ifp; 6127 void *ifp;
6128{ 6128{
6129 ipf_main_softc_t *softc; 6129 ipf_main_softc_t *softc;
6130 6130
6131 softc = ipf_get_softc(0); 6131 softc = ipf_get_softc(0);
6132 6132
6133 ipf_sync(ifp); 6133 ipf_sync(ifp);
6134 return; 6134 return;
6135} 6135}
6136#endif 6136#endif
6137 6137
6138 6138
6139/* ------------------------------------------------------------------------ */ 6139/* ------------------------------------------------------------------------ */
6140/* Function: ipf_nat_rule_deref */ 6140/* Function: ipf_nat_rule_deref */
6141/* Returns: Nil */ 6141/* Returns: Nil */
6142/* Parameters: softc(I) - pointer to soft context main structure */ 6142/* Parameters: softc(I) - pointer to soft context main structure */
6143/* inp(I) - pointer to pointer to NAT rule */ 6143/* inp(I) - pointer to pointer to NAT rule */
6144/* Write Locks: ipf_nat */ 6144/* Write Locks: ipf_nat */
6145/* */ 6145/* */
6146/* Dropping the refernce count for a rule means that whatever held the */ 6146/* Dropping the refernce count for a rule means that whatever held the */
6147/* pointer to this rule (*inp) is no longer interested in it and when the */ 6147/* pointer to this rule (*inp) is no longer interested in it and when the */
6148/* reference count drops to zero, any resources allocated for the rule can */ 6148/* reference count drops to zero, any resources allocated for the rule can */
6149/* be released and the rule itself free'd. */ 6149/* be released and the rule itself free'd. */
6150/* ------------------------------------------------------------------------ */ 6150/* ------------------------------------------------------------------------ */
6151void 6151void
6152ipf_nat_rule_deref(ipf_main_softc_t *softc, ipnat_t **inp) 6152ipf_nat_rule_deref(ipf_main_softc_t *softc, ipnat_t **inp)
6153{ 6153{
6154 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 6154 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
6155 ipnat_t *n; 6155 ipnat_t *n;
6156 6156
6157 n = *inp; 6157 n = *inp;
6158 *inp = NULL; 6158 *inp = NULL;
6159 n->in_use--; 6159 n->in_use--;
6160 if (n->in_use > 0) 6160 if (n->in_use > 0)
6161 return; 6161 return;
6162 6162
6163 if (n->in_apr != NULL) 6163 if (n->in_apr != NULL)
6164 ipf_proxy_deref(n->in_apr); 6164 ipf_proxy_deref(n->in_apr);
6165 6165
6166 ipf_nat_rule_fini(softc, n); 6166 ipf_nat_rule_fini(softc, n);
6167 6167
6168 if (n->in_redir & NAT_REDIRECT) { 6168 if (n->in_redir & NAT_REDIRECT) {
6169 if ((n->in_flags & IPN_PROXYRULE) == 0) { 6169 if ((n->in_flags & IPN_PROXYRULE) == 0) {
6170 ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules_rdr); 6170 ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules_rdr);
6171 } 6171 }
6172 } 6172 }
6173 if (n->in_redir & (NAT_MAP|NAT_MAPBLK)) { 6173 if (n->in_redir & (NAT_MAP|NAT_MAPBLK)) {
6174 if ((n->in_flags & IPN_PROXYRULE) == 0) { 6174 if ((n->in_flags & IPN_PROXYRULE) == 0) {
6175 ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules_map); 6175 ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules_map);
6176 } 6176 }
6177 } 6177 }
6178 6178
6179 if (n->in_tqehead[0] != NULL) { 6179 if (n->in_tqehead[0] != NULL) {
6180 if (ipf_deletetimeoutqueue(n->in_tqehead[0]) == 0) { 6180 if (ipf_deletetimeoutqueue(n->in_tqehead[0]) == 0) {
6181 ipf_freetimeoutqueue(softc, n->in_tqehead[1]); 6181 ipf_freetimeoutqueue(softc, n->in_tqehead[0]);
6182 } 6182 }
6183 } 6183 }
6184 6184
6185 if (n->in_tqehead[1] != NULL) { 6185 if (n->in_tqehead[1] != NULL) {
6186 if (ipf_deletetimeoutqueue(n->in_tqehead[1]) == 0) { 6186 if (ipf_deletetimeoutqueue(n->in_tqehead[1]) == 0) {
6187 ipf_freetimeoutqueue(softc, n->in_tqehead[1]); 6187 ipf_freetimeoutqueue(softc, n->in_tqehead[1]);
6188 } 6188 }
6189 } 6189 }
6190 6190
6191 if ((n->in_flags & IPN_PROXYRULE) == 0) { 6191 if ((n->in_flags & IPN_PROXYRULE) == 0) {
6192 ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules); 6192 ATOMIC_DEC32(softn->ipf_nat_stats.ns_rules);
6193 } 6193 }
6194 6194
6195 MUTEX_DESTROY(&n->in_lock); 6195 MUTEX_DESTROY(&n->in_lock);
6196 6196
6197 KFREES(n, n->in_size); 6197 KFREES(n, n->in_size);
6198 6198
6199#if SOLARIS && !defined(INSTANCES) 6199#if SOLARIS && !defined(INSTANCES)
6200 if (softn->ipf_nat_stats.ns_rules == 0) 6200 if (softn->ipf_nat_stats.ns_rules == 0)
6201 pfil_delayed_copy = 1; 6201 pfil_delayed_copy = 1;
6202#endif 6202#endif
6203} 6203}
6204 6204
6205 6205
6206/* ------------------------------------------------------------------------ */ 6206/* ------------------------------------------------------------------------ */
6207/* Function: ipf_nat_deref */ 6207/* Function: ipf_nat_deref */
6208/* Returns: Nil */ 6208/* Returns: Nil */
6209/* Parameters: softc(I) - pointer to soft context main structure */ 6209/* Parameters: softc(I) - pointer to soft context main structure */
6210/* natp(I) - pointer to pointer to NAT table entry */ 6210/* natp(I) - pointer to pointer to NAT table entry */
6211/* */ 6211/* */
6212/* Decrement the reference counter for this NAT table entry and free it if */ 6212/* Decrement the reference counter for this NAT table entry and free it if */
6213/* there are no more things using it. */ 6213/* there are no more things using it. */
6214/* */ 6214/* */
6215/* IF nat_ref == 1 when this function is called, then we have an orphan nat */ 6215/* IF nat_ref == 1 when this function is called, then we have an orphan nat */
6216/* structure *because* it only gets called on paths _after_ nat_ref has been*/ 6216/* structure *because* it only gets called on paths _after_ nat_ref has been*/
6217/* incremented. If nat_ref == 1 then we shouldn't decrement it here */ 6217/* incremented. If nat_ref == 1 then we shouldn't decrement it here */
6218/* because nat_delete() will do that and send nat_ref to -1. */ 6218/* because nat_delete() will do that and send nat_ref to -1. */
6219/* */ 6219/* */
6220/* Holding the lock on nat_lock is required to serialise nat_delete() being */ 6220/* Holding the lock on nat_lock is required to serialise nat_delete() being */
6221/* called from a NAT flush ioctl with a deref happening because of a packet.*/ 6221/* called from a NAT flush ioctl with a deref happening because of a packet.*/
6222/* ------------------------------------------------------------------------ */ 6222/* ------------------------------------------------------------------------ */
6223void 6223void
6224ipf_nat_deref(ipf_main_softc_t *softc, nat_t **natp) 6224ipf_nat_deref(ipf_main_softc_t *softc, nat_t **natp)
6225{ 6225{
6226 nat_t *nat; 6226 nat_t *nat;
6227 6227
6228 nat = *natp; 6228 nat = *natp;
6229 *natp = NULL; 6229 *natp = NULL;
6230 6230
6231 MUTEX_ENTER(&nat->nat_lock); 6231 MUTEX_ENTER(&nat->nat_lock);
6232 if (nat->nat_ref > 1) { 6232 if (nat->nat_ref > 1) {
6233 nat->nat_ref--; 6233 nat->nat_ref--;
6234 ASSERT(nat->nat_ref >= 0); 6234 ASSERT(nat->nat_ref >= 0);
6235 MUTEX_EXIT(&nat->nat_lock); 6235 MUTEX_EXIT(&nat->nat_lock);
6236 return; 6236 return;
6237 } 6237 }
6238 MUTEX_EXIT(&nat->nat_lock); 6238 MUTEX_EXIT(&nat->nat_lock);
6239 6239
6240 WRITE_ENTER(&softc->ipf_nat); 6240 WRITE_ENTER(&softc->ipf_nat);
6241 ipf_nat_delete(softc, nat, NL_EXPIRE); 6241 ipf_nat_delete(softc, nat, NL_EXPIRE);
6242 RWLOCK_EXIT(&softc->ipf_nat); 6242 RWLOCK_EXIT(&softc->ipf_nat);
6243} 6243}
6244 6244
6245 6245
6246/* ------------------------------------------------------------------------ */ 6246/* ------------------------------------------------------------------------ */
6247/* Function: ipf_nat_clone */ 6247/* Function: ipf_nat_clone */
6248/* Returns: ipstate_t* - NULL == cloning failed, */ 6248/* Returns: ipstate_t* - NULL == cloning failed, */
6249/* else pointer to new state structure */ 6249/* else pointer to new state structure */
6250/* Parameters: fin(I) - pointer to packet information */ 6250/* Parameters: fin(I) - pointer to packet information */
6251/* is(I) - pointer to master state structure */ 6251/* is(I) - pointer to master state structure */
6252/* Write Lock: ipf_nat */ 6252/* Write Lock: ipf_nat */
6253/* */ 6253/* */
6254/* Create a "duplcate" state table entry from the master. */ 6254/* Create a "duplcate" state table entry from the master. */
6255/* ------------------------------------------------------------------------ */ 6255/* ------------------------------------------------------------------------ */
6256nat_t * 6256nat_t *
6257ipf_nat_clone(fr_info_t *fin, nat_t *nat) 6257ipf_nat_clone(fr_info_t *fin, nat_t *nat)
6258{ 6258{
6259 ipf_main_softc_t *softc = fin->fin_main_soft; 6259 ipf_main_softc_t *softc = fin->fin_main_soft;
6260 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 6260 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
6261 frentry_t *fr; 6261 frentry_t *fr;
6262 nat_t *clone; 6262 nat_t *clone;
6263 ipnat_t *np; 6263 ipnat_t *np;
6264 6264
6265 KMALLOC(clone, nat_t *); 6265 KMALLOC(clone, nat_t *);
6266 if (clone == NULL) { 6266 if (clone == NULL) {
6267 NBUMPSIDED(fin->fin_out, ns_clone_nomem); 6267 NBUMPSIDED(fin->fin_out, ns_clone_nomem);
6268 return NULL; 6268 return NULL;
6269 } 6269 }
6270 bcopy((char *)nat, (char *)clone, sizeof(*clone)); 6270 bcopy((char *)nat, (char *)clone, sizeof(*clone));
6271 6271
6272 MUTEX_NUKE(&clone->nat_lock); 6272 MUTEX_NUKE(&clone->nat_lock);
6273 6273
6274 clone->nat_rev = fin->fin_rev; 6274 clone->nat_rev = fin->fin_rev;
6275 clone->nat_aps = NULL; 6275 clone->nat_aps = NULL;
6276 /* 6276 /*
6277 * Initialize all these so that ipf_nat_delete() doesn't cause a crash. 6277 * Initialize all these so that ipf_nat_delete() doesn't cause a crash.
6278 */ 6278 */
6279 clone->nat_tqe.tqe_pnext = NULL; 6279 clone->nat_tqe.tqe_pnext = NULL;
6280 clone->nat_tqe.tqe_next = NULL; 6280 clone->nat_tqe.tqe_next = NULL;
6281 clone->nat_tqe.tqe_ifq = NULL; 6281 clone->nat_tqe.tqe_ifq = NULL;
6282 clone->nat_tqe.tqe_parent = clone; 6282 clone->nat_tqe.tqe_parent = clone;
6283 6283
6284 clone->nat_flags &= ~SI_CLONE; 6284 clone->nat_flags &= ~SI_CLONE;
6285 clone->nat_flags |= SI_CLONED; 6285 clone->nat_flags |= SI_CLONED;
6286 6286
6287 if (clone->nat_hm) 6287 if (clone->nat_hm)
6288 clone->nat_hm->hm_ref++; 6288 clone->nat_hm->hm_ref++;
6289 6289
6290 if (ipf_nat_insert(softc, softn, clone) == -1) { 6290 if (ipf_nat_insert(softc, softn, clone) == -1) {
6291 KFREE(clone); 6291 KFREE(clone);
6292 NBUMPSIDED(fin->fin_out, ns_insert_fail); 6292 NBUMPSIDED(fin->fin_out, ns_insert_fail);
6293 return NULL; 6293 return NULL;
6294 } 6294 }
6295 6295
6296 np = clone->nat_ptr; 6296 np = clone->nat_ptr;
6297 if (np != NULL) { 6297 if (np != NULL) {
6298 if (softn->ipf_nat_logging) 6298 if (softn->ipf_nat_logging)
6299 ipf_nat_log(softc, softn, clone, NL_CLONE); 6299 ipf_nat_log(softc, softn, clone, NL_CLONE);
6300 np->in_use++; 6300 np->in_use++;
6301 } 6301 }
6302 fr = clone->nat_fr; 6302 fr = clone->nat_fr;
6303 if (fr != NULL) { 6303 if (fr != NULL) {
6304 MUTEX_ENTER(&fr->fr_lock); 6304 MUTEX_ENTER(&fr->fr_lock);
6305 fr->fr_ref++; 6305 fr->fr_ref++;
6306 MUTEX_EXIT(&fr->fr_lock); 6306 MUTEX_EXIT(&fr->fr_lock);
6307 } 6307 }
6308 6308
6309 6309
6310 /* 6310 /*
6311 * Because the clone is created outside the normal loop of things and 6311 * Because the clone is created outside the normal loop of things and
6312 * TCP has special needs in terms of state, initialise the timeout 6312 * TCP has special needs in terms of state, initialise the timeout
6313 * state of the new NAT from here. 6313 * state of the new NAT from here.
6314 */ 6314 */
6315 if (clone->nat_pr[0] == IPPROTO_TCP) { 6315 if (clone->nat_pr[0] == IPPROTO_TCP) {
6316 (void) ipf_tcp_age(&clone->nat_tqe, fin, softn->ipf_nat_tcptq, 6316 (void) ipf_tcp_age(&clone->nat_tqe, fin, softn->ipf_nat_tcptq,
6317 clone->nat_flags, 2); 6317 clone->nat_flags, 2);
6318 } 6318 }
6319 clone->nat_sync = ipf_sync_new(softc, SMC_NAT, fin, clone); 6319 clone->nat_sync = ipf_sync_new(softc, SMC_NAT, fin, clone);
6320 if (softn->ipf_nat_logging) 6320 if (softn->ipf_nat_logging)
6321 ipf_nat_log(softc, softn, clone, NL_CLONE); 6321 ipf_nat_log(softc, softn, clone, NL_CLONE);
6322 return clone; 6322 return clone;
6323} 6323}
6324 6324
6325 6325
6326/* ------------------------------------------------------------------------ */ 6326/* ------------------------------------------------------------------------ */
6327/* Function: ipf_nat_wildok */ 6327/* Function: ipf_nat_wildok */
6328/* Returns: int - 1 == packet's ports match wildcards */ 6328/* Returns: int - 1 == packet's ports match wildcards */
6329/* 0 == packet's ports don't match wildcards */ 6329/* 0 == packet's ports don't match wildcards */
6330/* Parameters: nat(I) - NAT entry */ 6330/* Parameters: nat(I) - NAT entry */
6331/* sport(I) - source port */ 6331/* sport(I) - source port */
6332/* dport(I) - destination port */ 6332/* dport(I) - destination port */
6333/* flags(I) - wildcard flags */ 6333/* flags(I) - wildcard flags */
6334/* dir(I) - packet direction */ 6334/* dir(I) - packet direction */
6335/* */ 6335/* */
6336/* Use NAT entry and packet direction to determine which combination of */ 6336/* Use NAT entry and packet direction to determine which combination of */
6337/* wildcard flags should be used. */ 6337/* wildcard flags should be used. */
6338/* ------------------------------------------------------------------------ */ 6338/* ------------------------------------------------------------------------ */
6339int 6339int
6340ipf_nat_wildok(nat_t *nat, int sport, int dport, int flags, int dir) 6340ipf_nat_wildok(nat_t *nat, int sport, int dport, int flags, int dir)
6341{ 6341{
6342 /* 6342 /*
6343 * When called by dir is set to 6343 * When called by dir is set to
6344 * nat_inlookup NAT_INBOUND (0) 6344 * nat_inlookup NAT_INBOUND (0)
6345 * nat_outlookup NAT_OUTBOUND (1) 6345 * nat_outlookup NAT_OUTBOUND (1)
6346 * 6346 *
6347 * We simply combine the packet's direction in dir with the original 6347 * We simply combine the packet's direction in dir with the original
6348 * "intended" direction of that NAT entry in nat->nat_dir to decide 6348 * "intended" direction of that NAT entry in nat->nat_dir to decide
6349 * which combination of wildcard flags to allow. 6349 * which combination of wildcard flags to allow.
6350 */ 6350 */
6351 switch ((dir << 1) | (nat->nat_dir & (NAT_INBOUND|NAT_OUTBOUND))) 6351 switch ((dir << 1) | (nat->nat_dir & (NAT_INBOUND|NAT_OUTBOUND)))
6352 { 6352 {
6353 case 3: /* outbound packet / outbound entry */ 6353 case 3: /* outbound packet / outbound entry */
6354 if (((nat->nat_osport == sport) || 6354 if (((nat->nat_osport == sport) ||
6355 (flags & SI_W_SPORT)) && 6355 (flags & SI_W_SPORT)) &&
6356 ((nat->nat_odport == dport) || 6356 ((nat->nat_odport == dport) ||
6357 (flags & SI_W_DPORT))) 6357 (flags & SI_W_DPORT)))
6358 return 1; 6358 return 1;
6359 break; 6359 break;
6360 case 2: /* outbound packet / inbound entry */ 6360 case 2: /* outbound packet / inbound entry */
6361 if (((nat->nat_osport == dport) || 6361 if (((nat->nat_osport == dport) ||
6362 (flags & SI_W_SPORT)) && 6362 (flags & SI_W_SPORT)) &&
6363 ((nat->nat_odport == sport) || 6363 ((nat->nat_odport == sport) ||
6364 (flags & SI_W_DPORT))) 6364 (flags & SI_W_DPORT)))
6365 return 1; 6365 return 1;
6366 break; 6366 break;
6367 case 1: /* inbound packet / outbound entry */ 6367 case 1: /* inbound packet / outbound entry */
6368 if (((nat->nat_osport == dport) || 6368 if (((nat->nat_osport == dport) ||
6369 (flags & SI_W_SPORT)) && 6369 (flags & SI_W_SPORT)) &&
6370 ((nat->nat_odport == sport) || 6370 ((nat->nat_odport == sport) ||
6371 (flags & SI_W_DPORT))) 6371 (flags & SI_W_DPORT)))
6372 return 1; 6372 return 1;
6373 break; 6373 break;
6374 case 0: /* inbound packet / inbound entry */ 6374 case 0: /* inbound packet / inbound entry */
6375 if (((nat->nat_osport == sport) || 6375 if (((nat->nat_osport == sport) ||
6376 (flags & SI_W_SPORT)) && 6376 (flags & SI_W_SPORT)) &&
6377 ((nat->nat_odport == dport) || 6377 ((nat->nat_odport == dport) ||
6378 (flags & SI_W_DPORT))) 6378 (flags & SI_W_DPORT)))
6379 return 1; 6379 return 1;
6380 break; 6380 break;
6381 default: 6381 default:
6382 break; 6382 break;
6383 } 6383 }
6384 6384
6385 return(0); 6385 return(0);
6386} 6386}
6387 6387
6388 6388
6389/* ------------------------------------------------------------------------ */ 6389/* ------------------------------------------------------------------------ */
6390/* Function: nat_mssclamp */ 6390/* Function: nat_mssclamp */
6391/* Returns: Nil */ 6391/* Returns: Nil */
6392/* Parameters: tcp(I) - pointer to TCP header */ 6392/* Parameters: tcp(I) - pointer to TCP header */
6393/* maxmss(I) - value to clamp the TCP MSS to */ 6393/* maxmss(I) - value to clamp the TCP MSS to */
6394/* fin(I) - pointer to packet information */ 6394/* fin(I) - pointer to packet information */
6395/* csump(I) - pointer to TCP checksum */ 6395/* csump(I) - pointer to TCP checksum */
6396/* */ 6396/* */
6397/* Check for MSS option and clamp it if necessary. If found and changed, */ 6397/* Check for MSS option and clamp it if necessary. If found and changed, */
6398/* then the TCP header checksum will be updated to reflect the change in */ 6398/* then the TCP header checksum will be updated to reflect the change in */
6399/* the MSS. */ 6399/* the MSS. */
6400/* ------------------------------------------------------------------------ */ 6400/* ------------------------------------------------------------------------ */
6401static void 6401static void
6402ipf_nat_mssclamp(tcphdr_t *tcp, u_32_t maxmss, fr_info_t *fin, u_short *csump) 6402ipf_nat_mssclamp(tcphdr_t *tcp, u_32_t maxmss, fr_info_t *fin, u_short *csump)
6403{ 6403{
6404 u_char *cp, *ep, opt; 6404 u_char *cp, *ep, opt;
6405 int hlen, advance; 6405 int hlen, advance;
6406 u_32_t mss, sumd; 6406 u_32_t mss, sumd;
6407 6407
6408 hlen = TCP_OFF(tcp) << 2; 6408 hlen = TCP_OFF(tcp) << 2;
6409 if (hlen > sizeof(*tcp)) { 6409 if (hlen > sizeof(*tcp)) {
6410 cp = (u_char *)tcp + sizeof(*tcp); 6410 cp = (u_char *)tcp + sizeof(*tcp);
6411 ep = (u_char *)tcp + hlen; 6411 ep = (u_char *)tcp + hlen;
6412 6412
6413 while (cp < ep) { 6413 while (cp < ep) {
6414 opt = cp[0]; 6414 opt = cp[0];
6415 if (opt == TCPOPT_EOL) 6415 if (opt == TCPOPT_EOL)
6416 break; 6416 break;
6417 else if (opt == TCPOPT_NOP) { 6417 else if (opt == TCPOPT_NOP) {
6418 cp++; 6418 cp++;
6419 continue; 6419 continue;
6420 } 6420 }
6421 6421
6422 if (cp + 1 >= ep) 6422 if (cp + 1 >= ep)
6423 break; 6423 break;
6424 advance = cp[1]; 6424 advance = cp[1];
6425 if ((cp + advance > ep) || (advance <= 0)) 6425 if ((cp + advance > ep) || (advance <= 0))
6426 break; 6426 break;
6427 switch (opt) 6427 switch (opt)
6428 { 6428 {
6429 case TCPOPT_MAXSEG: 6429 case TCPOPT_MAXSEG:
6430 if (advance != 4) 6430 if (advance != 4)
6431 break; 6431 break;
6432 mss = cp[2] * 256 + cp[3]; 6432 mss = cp[2] * 256 + cp[3];
6433 if (mss > maxmss) { 6433 if (mss > maxmss) {
6434 cp[2] = maxmss / 256; 6434 cp[2] = maxmss / 256;
6435 cp[3] = maxmss & 0xff; 6435 cp[3] = maxmss & 0xff;
6436 CALC_SUMD(mss, maxmss, sumd); 6436 CALC_SUMD(mss, maxmss, sumd);
6437 ipf_fix_outcksum(0, csump, sumd, 0); 6437 ipf_fix_outcksum(0, csump, sumd, 0);
6438 } 6438 }
6439 break; 6439 break;
6440 default: 6440 default:
6441 /* ignore unknown options */ 6441 /* ignore unknown options */
6442 break; 6442 break;
6443 } 6443 }
6444 6444
6445 cp += advance; 6445 cp += advance;
6446 } 6446 }
6447 } 6447 }
6448} 6448}
6449 6449
6450 6450
6451/* ------------------------------------------------------------------------ */ 6451/* ------------------------------------------------------------------------ */
6452/* Function: ipf_nat_setqueue */ 6452/* Function: ipf_nat_setqueue */
6453/* Returns: Nil */ 6453/* Returns: Nil */
6454/* Parameters: softc(I) - pointer to soft context main structure */ 6454/* Parameters: softc(I) - pointer to soft context main structure */
6455/* softn(I) - pointer to NAT context structure */ 6455/* softn(I) - pointer to NAT context structure */
6456/* nat(I)- pointer to NAT structure */ 6456/* nat(I)- pointer to NAT structure */
6457/* Locks: ipf_nat (read or write) */ 6457/* Locks: ipf_nat (read or write) */
6458/* */ 6458/* */
6459/* Put the NAT entry on its default queue entry, using rev as a helped in */ 6459/* Put the NAT entry on its default queue entry, using rev as a helped in */
6460/* determining which queue it should be placed on. */ 6460/* determining which queue it should be placed on. */
6461/* ------------------------------------------------------------------------ */ 6461/* ------------------------------------------------------------------------ */
6462void 6462void
6463ipf_nat_setqueue(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, nat_t *nat) 6463ipf_nat_setqueue(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, nat_t *nat)
6464{ 6464{
6465 ipftq_t *oifq, *nifq; 6465 ipftq_t *oifq, *nifq;
6466 int rev = nat->nat_rev; 6466 int rev = nat->nat_rev;
6467 6467
6468 if (nat->nat_ptr != NULL) 6468 if (nat->nat_ptr != NULL)
6469 nifq = nat->nat_ptr->in_tqehead[rev]; 6469 nifq = nat->nat_ptr->in_tqehead[rev];
6470 else 6470 else
6471 nifq = NULL; 6471 nifq = NULL;
6472 6472
6473 if (nifq == NULL) { 6473 if (nifq == NULL) {
6474 switch (nat->nat_pr[0]) 6474 switch (nat->nat_pr[0])
6475 { 6475 {
6476 case IPPROTO_UDP : 6476 case IPPROTO_UDP :
6477 nifq = &softn->ipf_nat_udptq; 6477 nifq = &softn->ipf_nat_udptq;
6478 break; 6478 break;
6479 case IPPROTO_ICMP : 6479 case IPPROTO_ICMP :
6480 nifq = &softn->ipf_nat_icmptq; 6480 nifq = &softn->ipf_nat_icmptq;
6481 break; 6481 break;
6482 case IPPROTO_TCP : 6482 case IPPROTO_TCP :
6483 nifq = softn->ipf_nat_tcptq + 6483 nifq = softn->ipf_nat_tcptq +
6484 nat->nat_tqe.tqe_state[rev]; 6484 nat->nat_tqe.tqe_state[rev];
6485 break; 6485 break;
6486 default : 6486 default :
6487 nifq = &softn->ipf_nat_iptq; 6487 nifq = &softn->ipf_nat_iptq;
6488 break; 6488 break;
6489 } 6489 }
6490 } 6490 }
6491 6491
6492 oifq = nat->nat_tqe.tqe_ifq; 6492 oifq = nat->nat_tqe.tqe_ifq;
6493 /* 6493 /*
6494 * If it's currently on a timeout queue, move it from one queue to 6494 * If it's currently on a timeout queue, move it from one queue to
6495 * another, else put it on the end of the newly determined queue. 6495 * another, else put it on the end of the newly determined queue.
6496 */ 6496 */
6497 if (oifq != NULL) 6497 if (oifq != NULL)
6498 ipf_movequeue(softc->ipf_ticks, &nat->nat_tqe, oifq, nifq); 6498 ipf_movequeue(softc->ipf_ticks, &nat->nat_tqe, oifq, nifq);
6499 else 6499 else
6500 ipf_queueappend(softc->ipf_ticks, &nat->nat_tqe, nifq, nat); 6500 ipf_queueappend(softc->ipf_ticks, &nat->nat_tqe, nifq, nat);
6501 return; 6501 return;
6502} 6502}
6503 6503
6504 6504
6505/* ------------------------------------------------------------------------ */ 6505/* ------------------------------------------------------------------------ */
6506/* Function: nat_getnext */ 6506/* Function: nat_getnext */
6507/* Returns: int - 0 == ok, else error */ 6507/* Returns: int - 0 == ok, else error */
6508/* Parameters: softc(I) - pointer to soft context main structure */ 6508/* Parameters: softc(I) - pointer to soft context main structure */
6509/* t(I) - pointer to ipftoken structure */ 6509/* t(I) - pointer to ipftoken structure */
6510/* itp(I) - pointer to ipfgeniter_t structure */ 6510/* itp(I) - pointer to ipfgeniter_t structure */
6511/* */ 6511/* */
6512/* Fetch the next nat/ipnat structure pointer from the linked list and */ 6512/* Fetch the next nat/ipnat structure pointer from the linked list and */
6513/* copy it out to the storage space pointed to by itp_data. The next item */ 6513/* copy it out to the storage space pointed to by itp_data. The next item */
6514/* in the list to look at is put back in the ipftoken struture. */ 6514/* in the list to look at is put back in the ipftoken struture. */
6515/* ------------------------------------------------------------------------ */ 6515/* ------------------------------------------------------------------------ */
6516static int 6516static int
6517ipf_nat_getnext(ipf_main_softc_t *softc, ipftoken_t *t, ipfgeniter_t *itp, 6517ipf_nat_getnext(ipf_main_softc_t *softc, ipftoken_t *t, ipfgeniter_t *itp,
6518 ipfobj_t *objp) 6518 ipfobj_t *objp)
6519{ 6519{
6520 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 6520 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
6521 hostmap_t *hm, *nexthm = NULL, zerohm; 6521 hostmap_t *hm, *nexthm = NULL, zerohm;
6522 ipnat_t *ipn, *nextipnat = NULL, zeroipn; 6522 ipnat_t *ipn, *nextipnat = NULL, zeroipn;
6523 nat_t *nat, *nextnat = NULL, zeronat; 6523 nat_t *nat, *nextnat = NULL, zeronat;
6524 int error = 0; 6524 int error = 0;
6525 void *nnext; 6525 void *nnext;
6526 6526
6527 if (itp->igi_nitems != 1) { 6527 if (itp->igi_nitems != 1) {
6528 IPFERROR(60075); 6528 IPFERROR(60075);
6529 return ENOSPC; 6529 return ENOSPC;
6530 } 6530 }
6531 6531
6532 READ_ENTER(&softc->ipf_nat); 6532 READ_ENTER(&softc->ipf_nat);
6533 6533
6534 switch (itp->igi_type) 6534 switch (itp->igi_type)
6535 { 6535 {
6536 case IPFGENITER_HOSTMAP : 6536 case IPFGENITER_HOSTMAP :
6537 hm = t->ipt_data; 6537 hm = t->ipt_data;
6538 if (hm == NULL) { 6538 if (hm == NULL) {
6539 nexthm = softn->ipf_hm_maplist; 6539 nexthm = softn->ipf_hm_maplist;
6540 } else { 6540 } else {
6541 nexthm = hm->hm_next; 6541 nexthm = hm->hm_next;
6542 } 6542 }
6543 if (nexthm != NULL) { 6543 if (nexthm != NULL) {
6544 ATOMIC_INC32(nexthm->hm_ref); 6544 ATOMIC_INC32(nexthm->hm_ref);
6545 t->ipt_data = nexthm; 6545 t->ipt_data = nexthm;
6546 } else { 6546 } else {
6547 bzero(&zerohm, sizeof(zerohm)); 6547 bzero(&zerohm, sizeof(zerohm));
6548 nexthm = &zerohm; 6548 nexthm = &zerohm;
6549 t->ipt_data = NULL; 6549 t->ipt_data = NULL;
6550 } 6550 }
6551 nnext = nexthm->hm_next; 6551 nnext = nexthm->hm_next;
6552 break; 6552 break;
6553 6553
6554 case IPFGENITER_IPNAT : 6554 case IPFGENITER_IPNAT :
6555 ipn = t->ipt_data; 6555 ipn = t->ipt_data;
6556 if (ipn == NULL) { 6556 if (ipn == NULL) {
6557 nextipnat = softn->ipf_nat_list; 6557 nextipnat = softn->ipf_nat_list;
6558 } else { 6558 } else {
6559 nextipnat = ipn->in_next; 6559 nextipnat = ipn->in_next;
6560 } 6560 }
6561 if (nextipnat != NULL) { 6561 if (nextipnat != NULL) {
6562 ATOMIC_INC32(nextipnat->in_use); 6562 ATOMIC_INC32(nextipnat->in_use);
6563 t->ipt_data = nextipnat; 6563 t->ipt_data = nextipnat;
6564 } else { 6564 } else {
6565 bzero(&zeroipn, sizeof(zeroipn)); 6565 bzero(&zeroipn, sizeof(zeroipn));
6566 nextipnat = &zeroipn; 6566 nextipnat = &zeroipn;
6567 t->ipt_data = NULL; 6567 t->ipt_data = NULL;
6568 } 6568 }
6569 nnext = nextipnat->in_next; 6569 nnext = nextipnat->in_next;
6570 break; 6570 break;
6571 6571
6572 case IPFGENITER_NAT : 6572 case IPFGENITER_NAT :
6573 nat = t->ipt_data; 6573 nat = t->ipt_data;
6574 if (nat == NULL) { 6574 if (nat == NULL) {
6575 nextnat = softn->ipf_nat_instances; 6575 nextnat = softn->ipf_nat_instances;
6576 } else { 6576 } else {
6577 nextnat = nat->nat_next; 6577 nextnat = nat->nat_next;
6578 } 6578 }
6579 if (nextnat != NULL) { 6579 if (nextnat != NULL) {
6580 MUTEX_ENTER(&nextnat->nat_lock); 6580 MUTEX_ENTER(&nextnat->nat_lock);
6581 nextnat->nat_ref++; 6581 nextnat->nat_ref++;
6582 MUTEX_EXIT(&nextnat->nat_lock); 6582 MUTEX_EXIT(&nextnat->nat_lock);
6583 t->ipt_data = nextnat; 6583 t->ipt_data = nextnat;
6584 } else { 6584 } else {
6585 bzero(&zeronat, sizeof(zeronat)); 6585 bzero(&zeronat, sizeof(zeronat));
6586 nextnat = &zeronat; 6586 nextnat = &zeronat;
6587 t->ipt_data = NULL; 6587 t->ipt_data = NULL;
6588 } 6588 }
6589 nnext = nextnat->nat_next; 6589 nnext = nextnat->nat_next;
6590 break; 6590 break;
6591 6591
6592 default : 6592 default :
6593 RWLOCK_EXIT(&softc->ipf_nat); 6593 RWLOCK_EXIT(&softc->ipf_nat);
6594 IPFERROR(60055); 6594 IPFERROR(60055);
6595 return EINVAL; 6595 return EINVAL;
6596 } 6596 }
6597 6597
6598 RWLOCK_EXIT(&softc->ipf_nat); 6598 RWLOCK_EXIT(&softc->ipf_nat);
6599 6599
6600 objp->ipfo_ptr = itp->igi_data; 6600 objp->ipfo_ptr = itp->igi_data;
6601 6601
6602 switch (itp->igi_type) 6602 switch (itp->igi_type)
6603 { 6603 {
6604 case IPFGENITER_HOSTMAP : 6604 case IPFGENITER_HOSTMAP :
6605 error = COPYOUT(nexthm, objp->ipfo_ptr, sizeof(*nexthm)); 6605 error = COPYOUT(nexthm, objp->ipfo_ptr, sizeof(*nexthm));
6606 if (error != 0) { 6606 if (error != 0) {
6607 IPFERROR(60049); 6607 IPFERROR(60049);
6608 error = EFAULT; 6608 error = EFAULT;
6609 } 6609 }
6610 if (hm != NULL) { 6610 if (hm != NULL) {
6611 WRITE_ENTER(&softc->ipf_nat); 6611 WRITE_ENTER(&softc->ipf_nat);
6612 ipf_nat_hostmapdel(softc, &hm); 6612 ipf_nat_hostmapdel(softc, &hm);
6613 RWLOCK_EXIT(&softc->ipf_nat); 6613 RWLOCK_EXIT(&softc->ipf_nat);
6614 } 6614 }
6615 break; 6615 break;
6616 6616
6617 case IPFGENITER_IPNAT : 6617 case IPFGENITER_IPNAT :
6618 objp->ipfo_size = nextipnat->in_size; 6618 objp->ipfo_size = nextipnat->in_size;
6619 objp->ipfo_type = IPFOBJ_IPNAT; 6619 objp->ipfo_type = IPFOBJ_IPNAT;
6620 error = ipf_outobjk(softc, objp, nextipnat); 6620 error = ipf_outobjk(softc, objp, nextipnat);
6621 if (ipn != NULL) { 6621 if (ipn != NULL) {
6622 WRITE_ENTER(&softc->ipf_nat); 6622 WRITE_ENTER(&softc->ipf_nat);
6623 ipf_nat_rule_deref(softc, &ipn); 6623 ipf_nat_rule_deref(softc, &ipn);
6624 RWLOCK_EXIT(&softc->ipf_nat); 6624 RWLOCK_EXIT(&softc->ipf_nat);
6625 } 6625 }
6626 break; 6626 break;
6627 6627
6628 case IPFGENITER_NAT : 6628 case IPFGENITER_NAT :
6629 objp->ipfo_size = sizeof(nat_t); 6629 objp->ipfo_size = sizeof(nat_t);
6630 objp->ipfo_type = IPFOBJ_NAT; 6630 objp->ipfo_type = IPFOBJ_NAT;
6631 error = ipf_outobjk(softc, objp, nextnat); 6631 error = ipf_outobjk(softc, objp, nextnat);
6632 if (nat != NULL) 6632 if (nat != NULL)
6633 ipf_nat_deref(softc, &nat); 6633 ipf_nat_deref(softc, &nat);
6634 6634
6635 break; 6635 break;
6636 } 6636 }
6637 6637
6638 if (nnext == NULL) 6638 if (nnext == NULL)
6639 ipf_token_mark_complete(t); 6639 ipf_token_mark_complete(t);
6640 6640
6641 return error; 6641 return error;
6642} 6642}
6643 6643
6644 6644
6645/* ------------------------------------------------------------------------ */ 6645/* ------------------------------------------------------------------------ */
6646/* Function: nat_extraflush */ 6646/* Function: nat_extraflush */
6647/* Returns: int - 0 == success, -1 == failure */ 6647/* Returns: int - 0 == success, -1 == failure */
6648/* Parameters: softc(I) - pointer to soft context main structure */ 6648/* Parameters: softc(I) - pointer to soft context main structure */
6649/* softn(I) - pointer to NAT context structure */ 6649/* softn(I) - pointer to NAT context structure */
6650/* which(I) - how to flush the active NAT table */ 6650/* which(I) - how to flush the active NAT table */
6651/* Write Locks: ipf_nat */ 6651/* Write Locks: ipf_nat */
6652/* */ 6652/* */
6653/* Flush nat tables. Three actions currently defined: */ 6653/* Flush nat tables. Three actions currently defined: */
6654/* which == 0 : flush all nat table entries */ 6654/* which == 0 : flush all nat table entries */
6655/* which == 1 : flush TCP connections which have started to close but are */ 6655/* which == 1 : flush TCP connections which have started to close but are */
6656/* stuck for some reason. */ 6656/* stuck for some reason. */
6657/* which == 2 : flush TCP connections which have been idle for a long time, */ 6657/* which == 2 : flush TCP connections which have been idle for a long time, */
6658/* starting at > 4 days idle and working back in successive half-*/ 6658/* starting at > 4 days idle and working back in successive half-*/
6659/* days to at most 12 hours old. If this fails to free enough */ 6659/* days to at most 12 hours old. If this fails to free enough */
6660/* slots then work backwards in half hour slots to 30 minutes. */ 6660/* slots then work backwards in half hour slots to 30 minutes. */
6661/* If that too fails, then work backwards in 30 second intervals */ 6661/* If that too fails, then work backwards in 30 second intervals */
6662/* for the last 30 minutes to at worst 30 seconds idle. */ 6662/* for the last 30 minutes to at worst 30 seconds idle. */
6663/* ------------------------------------------------------------------------ */ 6663/* ------------------------------------------------------------------------ */
6664static int 6664static int
6665ipf_nat_extraflush(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, int which) 6665ipf_nat_extraflush(ipf_main_softc_t *softc, ipf_nat_softc_t *softn, int which)
6666{ 6666{
6667 nat_t *nat, **natp; 6667 nat_t *nat, **natp;
6668 ipftqent_t *tqn; 6668 ipftqent_t *tqn;
6669 ipftq_t *ifq; 6669 ipftq_t *ifq;
6670 int removed; 6670 int removed;
6671 SPL_INT(s); 6671 SPL_INT(s);
6672 6672
6673 removed = 0; 6673 removed = 0;
6674 6674
6675 SPL_NET(s); 6675 SPL_NET(s);
6676 switch (which) 6676 switch (which)
6677 { 6677 {
6678 case 0 : 6678 case 0 :
6679 softn->ipf_nat_stats.ns_flush_all++; 6679 softn->ipf_nat_stats.ns_flush_all++;
6680 /* 6680 /*
6681 * Style 0 flush removes everything... 6681 * Style 0 flush removes everything...
6682 */ 6682 */
6683 for (natp = &softn->ipf_nat_instances; 6683 for (natp = &softn->ipf_nat_instances;
6684 ((nat = *natp) != NULL); ) { 6684 ((nat = *natp) != NULL); ) {
6685 ipf_nat_delete(softc, nat, NL_FLUSH); 6685 ipf_nat_delete(softc, nat, NL_FLUSH);
6686 removed++; 6686 removed++;
6687 } 6687 }
6688 break; 6688 break;
6689 6689
6690 case 1 : 6690 case 1 :
6691 softn->ipf_nat_stats.ns_flush_closing++; 6691 softn->ipf_nat_stats.ns_flush_closing++;
6692 /* 6692 /*
6693 * Since we're only interested in things that are closing, 6693 * Since we're only interested in things that are closing,
6694 * we can start with the appropriate timeout queue. 6694 * we can start with the appropriate timeout queue.
6695 */ 6695 */
6696 for (ifq = softn->ipf_nat_tcptq + IPF_TCPS_CLOSE_WAIT; 6696 for (ifq = softn->ipf_nat_tcptq + IPF_TCPS_CLOSE_WAIT;
6697 ifq != NULL; ifq = ifq->ifq_next) { 6697 ifq != NULL; ifq = ifq->ifq_next) {
6698 6698
6699 for (tqn = ifq->ifq_head; tqn != NULL; ) { 6699 for (tqn = ifq->ifq_head; tqn != NULL; ) {
6700 nat = tqn->tqe_parent; 6700 nat = tqn->tqe_parent;
6701 tqn = tqn->tqe_next; 6701 tqn = tqn->tqe_next;
6702 if (nat->nat_pr[0] != IPPROTO_TCP || 6702 if (nat->nat_pr[0] != IPPROTO_TCP ||
6703 nat->nat_pr[1] != IPPROTO_TCP) 6703 nat->nat_pr[1] != IPPROTO_TCP)
6704 break; 6704 break;
6705 ipf_nat_delete(softc, nat, NL_EXPIRE); 6705 ipf_nat_delete(softc, nat, NL_EXPIRE);
6706 removed++; 6706 removed++;
6707 } 6707 }
6708 } 6708 }
6709 6709
6710 /* 6710 /*
6711 * Also need to look through the user defined queues. 6711 * Also need to look through the user defined queues.
6712 */ 6712 */
6713 for (ifq = softn->ipf_nat_utqe; ifq != NULL; 6713 for (ifq = softn->ipf_nat_utqe; ifq != NULL;
6714 ifq = ifq->ifq_next) { 6714 ifq = ifq->ifq_next) {
6715 for (tqn = ifq->ifq_head; tqn != NULL; ) { 6715 for (tqn = ifq->ifq_head; tqn != NULL; ) {
6716 nat = tqn->tqe_parent; 6716 nat = tqn->tqe_parent;
6717 tqn = tqn->tqe_next; 6717 tqn = tqn->tqe_next;
6718 if (nat->nat_pr[0] != IPPROTO_TCP || 6718 if (nat->nat_pr[0] != IPPROTO_TCP ||
6719 nat->nat_pr[1] != IPPROTO_TCP) 6719 nat->nat_pr[1] != IPPROTO_TCP)
6720 continue; 6720 continue;
6721 6721
6722 if ((nat->nat_tcpstate[0] > 6722 if ((nat->nat_tcpstate[0] >
6723 IPF_TCPS_ESTABLISHED) && 6723 IPF_TCPS_ESTABLISHED) &&
6724 (nat->nat_tcpstate[1] > 6724 (nat->nat_tcpstate[1] >
6725 IPF_TCPS_ESTABLISHED)) { 6725 IPF_TCPS_ESTABLISHED)) {
6726 ipf_nat_delete(softc, nat, NL_EXPIRE); 6726 ipf_nat_delete(softc, nat, NL_EXPIRE);
6727 removed++; 6727 removed++;
6728 } 6728 }
6729 } 6729 }
6730 } 6730 }
6731 break; 6731 break;
6732 6732
6733 /* 6733 /*
6734 * Args 5-11 correspond to flushing those particular states 6734 * Args 5-11 correspond to flushing those particular states
6735 * for TCP connections. 6735 * for TCP connections.
6736 */ 6736 */
6737 case IPF_TCPS_CLOSE_WAIT : 6737 case IPF_TCPS_CLOSE_WAIT :
6738 case IPF_TCPS_FIN_WAIT_1 : 6738 case IPF_TCPS_FIN_WAIT_1 :
6739 case IPF_TCPS_CLOSING : 6739 case IPF_TCPS_CLOSING :
6740 case IPF_TCPS_LAST_ACK : 6740 case IPF_TCPS_LAST_ACK :
6741 case IPF_TCPS_FIN_WAIT_2 : 6741 case IPF_TCPS_FIN_WAIT_2 :
6742 case IPF_TCPS_TIME_WAIT : 6742 case IPF_TCPS_TIME_WAIT :
6743 case IPF_TCPS_CLOSED : 6743 case IPF_TCPS_CLOSED :
6744 softn->ipf_nat_stats.ns_flush_state++; 6744 softn->ipf_nat_stats.ns_flush_state++;
6745 tqn = softn->ipf_nat_tcptq[which].ifq_head; 6745 tqn = softn->ipf_nat_tcptq[which].ifq_head;
6746 while (tqn != NULL) { 6746 while (tqn != NULL) {
6747 nat = tqn->tqe_parent; 6747 nat = tqn->tqe_parent;
6748 tqn = tqn->tqe_next; 6748 tqn = tqn->tqe_next;
6749 ipf_nat_delete(softc, nat, NL_FLUSH); 6749 ipf_nat_delete(softc, nat, NL_FLUSH);
6750 removed++; 6750 removed++;
6751 } 6751 }
6752 break; 6752 break;
6753 6753
6754 default : 6754 default :
6755 if (which < 30) 6755 if (which < 30)
6756 break; 6756 break;
6757 6757
6758 softn->ipf_nat_stats.ns_flush_timeout++; 6758 softn->ipf_nat_stats.ns_flush_timeout++;
6759 /* 6759 /*
6760 * Take a large arbitrary number to mean the number of seconds 6760 * Take a large arbitrary number to mean the number of seconds
6761 * for which which consider to be the maximum value we'll allow 6761 * for which which consider to be the maximum value we'll allow
6762 * the expiration to be. 6762 * the expiration to be.
6763 */ 6763 */
6764 which = IPF_TTLVAL(which); 6764 which = IPF_TTLVAL(which);
6765 for (natp = &softn->ipf_nat_instances; 6765 for (natp = &softn->ipf_nat_instances;
6766 ((nat = *natp) != NULL); ) { 6766 ((nat = *natp) != NULL); ) {
6767 if (softc->ipf_ticks - nat->nat_touched > which) { 6767 if (softc->ipf_ticks - nat->nat_touched > which) {
6768 ipf_nat_delete(softc, nat, NL_FLUSH); 6768 ipf_nat_delete(softc, nat, NL_FLUSH);
6769 removed++; 6769 removed++;
6770 } else 6770 } else
6771 natp = &nat->nat_next; 6771 natp = &nat->nat_next;
6772 } 6772 }
6773 break; 6773 break;
6774 } 6774 }
6775 6775
6776 if (which != 2) { 6776 if (which != 2) {
6777 SPL_X(s); 6777 SPL_X(s);
6778 return removed; 6778 return removed;
6779 } 6779 }
6780 6780
6781 softn->ipf_nat_stats.ns_flush_queue++; 6781 softn->ipf_nat_stats.ns_flush_queue++;
6782 6782
6783 /* 6783 /*
6784 * Asked to remove inactive entries because the table is full, try 6784 * Asked to remove inactive entries because the table is full, try
6785 * again, 3 times, if first attempt failed with a different criteria 6785 * again, 3 times, if first attempt failed with a different criteria
6786 * each time. The order tried in must be in decreasing age. 6786 * each time. The order tried in must be in decreasing age.
6787 * Another alternative is to implement random drop and drop N entries 6787 * Another alternative is to implement random drop and drop N entries
6788 * at random until N have been freed up. 6788 * at random until N have been freed up.
6789 */ 6789 */
6790 if (softc->ipf_ticks - softn->ipf_nat_last_force_flush > 6790 if (softc->ipf_ticks - softn->ipf_nat_last_force_flush >
6791 IPF_TTLVAL(5)) { 6791 IPF_TTLVAL(5)) {
6792 softn->ipf_nat_last_force_flush = softc->ipf_ticks; 6792 softn->ipf_nat_last_force_flush = softc->ipf_ticks;
6793 6793
6794 removed = ipf_queueflush(softc, ipf_nat_flush_entry, 6794 removed = ipf_queueflush(softc, ipf_nat_flush_entry,
6795 softn->ipf_nat_tcptq, 6795 softn->ipf_nat_tcptq,
6796 softn->ipf_nat_utqe, 6796 softn->ipf_nat_utqe,
6797 &softn->ipf_nat_stats.ns_active, 6797 &softn->ipf_nat_stats.ns_active,
6798 softn->ipf_nat_table_sz, 6798 softn->ipf_nat_table_sz,
6799 softn->ipf_nat_table_wm_low); 6799 softn->ipf_nat_table_wm_low);
6800 } 6800 }
6801 6801
6802 SPL_X(s); 6802 SPL_X(s);
6803 return removed; 6803 return removed;
6804} 6804}
6805 6805
6806 6806
6807/* ------------------------------------------------------------------------ */ 6807/* ------------------------------------------------------------------------ */
6808/* Function: ipf_nat_flush_entry */ 6808/* Function: ipf_nat_flush_entry */
6809/* Returns: 0 - always succeeds */ 6809/* Returns: 0 - always succeeds */
6810/* Parameters: softc(I) - pointer to soft context main structure */ 6810/* Parameters: softc(I) - pointer to soft context main structure */
6811/* entry(I) - pointer to NAT entry */ 6811/* entry(I) - pointer to NAT entry */
6812/* Write Locks: ipf_nat */ 6812/* Write Locks: ipf_nat */
6813/* */ 6813/* */
6814/* This function is a stepping stone between ipf_queueflush() and */ 6814/* This function is a stepping stone between ipf_queueflush() and */
6815/* nat_dlete(). It is used so we can provide a uniform interface via the */ 6815/* nat_dlete(). It is used so we can provide a uniform interface via the */
6816/* ipf_queueflush() function. Since the nat_delete() function returns void */ 6816/* ipf_queueflush() function. Since the nat_delete() function returns void */
6817/* we translate that to mean it always succeeds in deleting something. */ 6817/* we translate that to mean it always succeeds in deleting something. */
6818/* ------------------------------------------------------------------------ */ 6818/* ------------------------------------------------------------------------ */
6819static int 6819static int
6820ipf_nat_flush_entry(ipf_main_softc_t *softc, void *entry) 6820ipf_nat_flush_entry(ipf_main_softc_t *softc, void *entry)
6821{ 6821{
6822 ipf_nat_delete(softc, entry, NL_FLUSH); 6822 ipf_nat_delete(softc, entry, NL_FLUSH);
6823 return 0; 6823 return 0;
6824} 6824}
6825 6825
6826 6826
6827/* ------------------------------------------------------------------------ */ 6827/* ------------------------------------------------------------------------ */
6828/* Function: ipf_nat_iterator */ 6828/* Function: ipf_nat_iterator */
6829/* Returns: int - 0 == ok, else error */ 6829/* Returns: int - 0 == ok, else error */
6830/* Parameters: softc(I) - pointer to soft context main structure */ 6830/* Parameters: softc(I) - pointer to soft context main structure */
6831/* token(I) - pointer to ipftoken structure */ 6831/* token(I) - pointer to ipftoken structure */
6832/* itp(I) - pointer to ipfgeniter_t structure */ 6832/* itp(I) - pointer to ipfgeniter_t structure */
6833/* obj(I) - pointer to data description structure */ 6833/* obj(I) - pointer to data description structure */
6834/* */ 6834/* */
6835/* This function acts as a handler for the SIOCGENITER ioctls that use a */ 6835/* This function acts as a handler for the SIOCGENITER ioctls that use a */
6836/* generic structure to iterate through a list. There are three different */ 6836/* generic structure to iterate through a list. There are three different */
6837/* linked lists of NAT related information to go through: NAT rules, active */ 6837/* linked lists of NAT related information to go through: NAT rules, active */
6838/* NAT mappings and the NAT fragment cache. */ 6838/* NAT mappings and the NAT fragment cache. */
6839/* ------------------------------------------------------------------------ */ 6839/* ------------------------------------------------------------------------ */
6840static int 6840static int
6841ipf_nat_iterator(ipf_main_softc_t *softc, ipftoken_t *token, ipfgeniter_t *itp, 6841ipf_nat_iterator(ipf_main_softc_t *softc, ipftoken_t *token, ipfgeniter_t *itp,
6842 ipfobj_t *obj) 6842 ipfobj_t *obj)
6843{ 6843{
6844 int error; 6844 int error;
6845 6845
6846 if (itp->igi_data == NULL) { 6846 if (itp->igi_data == NULL) {
6847 IPFERROR(60052); 6847 IPFERROR(60052);
6848 return EFAULT; 6848 return EFAULT;
6849 } 6849 }
6850 6850
6851 switch (itp->igi_type) 6851 switch (itp->igi_type)
6852 { 6852 {
6853 case IPFGENITER_HOSTMAP : 6853 case IPFGENITER_HOSTMAP :
6854 case IPFGENITER_IPNAT : 6854 case IPFGENITER_IPNAT :
6855 case IPFGENITER_NAT : 6855 case IPFGENITER_NAT :
6856 error = ipf_nat_getnext(softc, token, itp, obj); 6856 error = ipf_nat_getnext(softc, token, itp, obj);
6857 break; 6857 break;
6858 6858
6859 case IPFGENITER_NATFRAG : 6859 case IPFGENITER_NATFRAG :
6860 error = ipf_frag_nat_next(softc, token, itp); 6860 error = ipf_frag_nat_next(softc, token, itp);
6861 break; 6861 break;
6862 default : 6862 default :
6863 IPFERROR(60053); 6863 IPFERROR(60053);
6864 error = EINVAL; 6864 error = EINVAL;
6865 break; 6865 break;
6866 } 6866 }
6867 6867
6868 return error; 6868 return error;
6869} 6869}
6870 6870
6871 6871
6872/* ------------------------------------------------------------------------ */ 6872/* ------------------------------------------------------------------------ */
6873/* Function: ipf_nat_setpending */ 6873/* Function: ipf_nat_setpending */
6874/* Returns: Nil */ 6874/* Returns: Nil */
6875/* Parameters: softc(I) - pointer to soft context main structure */ 6875/* Parameters: softc(I) - pointer to soft context main structure */
6876/* nat(I) - pointer to NAT structure */ 6876/* nat(I) - pointer to NAT structure */
6877/* Locks: ipf_nat (read or write) */ 6877/* Locks: ipf_nat (read or write) */
6878/* */ 6878/* */
6879/* Put the NAT entry on to the pending queue - this queue has a very short */ 6879/* Put the NAT entry on to the pending queue - this queue has a very short */
6880/* lifetime where items are put that can't be deleted straight away because */ 6880/* lifetime where items are put that can't be deleted straight away because */
6881/* of locking issues but we want to delete them ASAP, anyway. In calling */ 6881/* of locking issues but we want to delete them ASAP, anyway. In calling */
6882/* this function, it is assumed that the owner (if there is one, as shown */ 6882/* this function, it is assumed that the owner (if there is one, as shown */
6883/* by nat_me) is no longer interested in it. */ 6883/* by nat_me) is no longer interested in it. */
6884/* ------------------------------------------------------------------------ */ 6884/* ------------------------------------------------------------------------ */
6885void 6885void
6886ipf_nat_setpending(ipf_main_softc_t *softc, nat_t *nat) 6886ipf_nat_setpending(ipf_main_softc_t *softc, nat_t *nat)
6887{ 6887{
6888 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 6888 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
6889 ipftq_t *oifq; 6889 ipftq_t *oifq;
6890 6890
6891 oifq = nat->nat_tqe.tqe_ifq; 6891 oifq = nat->nat_tqe.tqe_ifq;
6892 if (oifq != NULL) 6892 if (oifq != NULL)
6893 ipf_movequeue(softc->ipf_ticks, &nat->nat_tqe, oifq, 6893 ipf_movequeue(softc->ipf_ticks, &nat->nat_tqe, oifq,
6894 &softn->ipf_nat_pending); 6894 &softn->ipf_nat_pending);
6895 else 6895 else
6896 ipf_queueappend(softc->ipf_ticks, &nat->nat_tqe, 6896 ipf_queueappend(softc->ipf_ticks, &nat->nat_tqe,
6897 &softn->ipf_nat_pending, nat); 6897 &softn->ipf_nat_pending, nat);
6898 6898
6899 if (nat->nat_me != NULL) { 6899 if (nat->nat_me != NULL) {
6900 *nat->nat_me = NULL; 6900 *nat->nat_me = NULL;
6901 nat->nat_me = NULL; 6901 nat->nat_me = NULL;
6902 nat->nat_ref--; 6902 nat->nat_ref--;
6903 ASSERT(nat->nat_ref >= 0); 6903 ASSERT(nat->nat_ref >= 0);
6904 } 6904 }
6905} 6905}
6906 6906
6907 6907
6908/* ------------------------------------------------------------------------ */ 6908/* ------------------------------------------------------------------------ */
6909/* Function: nat_newrewrite */ 6909/* Function: nat_newrewrite */
6910/* Returns: int - -1 == error, 0 == success (no move), 1 == success and */ 6910/* Returns: int - -1 == error, 0 == success (no move), 1 == success and */
6911/* allow rule to be moved if IPN_ROUNDR is set. */ 6911/* allow rule to be moved if IPN_ROUNDR is set. */
6912/* Parameters: fin(I) - pointer to packet information */ 6912/* Parameters: fin(I) - pointer to packet information */
6913/* nat(I) - pointer to NAT entry */ 6913/* nat(I) - pointer to NAT entry */
6914/* ni(I) - pointer to structure with misc. information needed */ 6914/* ni(I) - pointer to structure with misc. information needed */
6915/* to create new NAT entry. */ 6915/* to create new NAT entry. */
6916/* Write Lock: ipf_nat */ 6916/* Write Lock: ipf_nat */
6917/* */ 6917/* */
6918/* This function is responsible for setting up an active NAT session where */ 6918/* This function is responsible for setting up an active NAT session where */
6919/* we are changing both the source and destination parameters at the same */ 6919/* we are changing both the source and destination parameters at the same */
6920/* time. The loop in here works differently to elsewhere - each iteration */ 6920/* time. The loop in here works differently to elsewhere - each iteration */
6921/* is responsible for changing a single parameter that can be incremented. */ 6921/* is responsible for changing a single parameter that can be incremented. */
6922/* So one pass may increase the source IP#, next source port, next dest. IP#*/ 6922/* So one pass may increase the source IP#, next source port, next dest. IP#*/
6923/* and the last destination port for a total of 4 iterations to try each. */ 6923/* and the last destination port for a total of 4 iterations to try each. */
6924/* This is done to try and exhaustively use the translation space available.*/ 6924/* This is done to try and exhaustively use the translation space available.*/
6925/* ------------------------------------------------------------------------ */ 6925/* ------------------------------------------------------------------------ */
6926static int 6926static int
6927ipf_nat_newrewrite(fr_info_t *fin, nat_t *nat, natinfo_t *nai) 6927ipf_nat_newrewrite(fr_info_t *fin, nat_t *nat, natinfo_t *nai)
6928{ 6928{
6929 int src_search = 1; 6929 int src_search = 1;
6930 int dst_search = 1; 6930 int dst_search = 1;
6931 fr_info_t frnat; 6931 fr_info_t frnat;
6932 u_32_t flags; 6932 u_32_t flags;
6933 u_short swap; 6933 u_short swap;
6934 ipnat_t *np; 6934 ipnat_t *np;
6935 nat_t *natl; 6935 nat_t *natl;
6936 int l = 0; 6936 int l = 0;
6937 int changed; 6937 int changed;
6938 6938
6939 natl = NULL; 6939 natl = NULL;
6940 changed = -1; 6940 changed = -1;
6941 np = nai->nai_np; 6941 np = nai->nai_np;
6942 flags = nat->nat_flags; 6942 flags = nat->nat_flags;
6943 bcopy((char *)fin, (char *)&frnat, sizeof(*fin)); 6943 bcopy((char *)fin, (char *)&frnat, sizeof(*fin));
6944 6944
6945 nat->nat_hm = NULL; 6945 nat->nat_hm = NULL;
6946 6946
6947 do { 6947 do {
6948 changed = -1; 6948 changed = -1;
6949 /* TRACE (l, src_search, dst_search, np) */ 6949 /* TRACE (l, src_search, dst_search, np) */
6950 6950
6951 if ((src_search == 0) && (np->in_spnext == 0) && 6951 if ((src_search == 0) && (np->in_spnext == 0) &&
6952 (dst_search == 0) && (np->in_dpnext == 0)) { 6952 (dst_search == 0) && (np->in_dpnext == 0)) {
6953 if (l > 0) 6953 if (l > 0)
6954 return -1; 6954 return -1;
6955 } 6955 }
6956 6956
6957 /* 6957 /*
6958 * Find a new source address 6958 * Find a new source address
6959 */ 6959 */
6960 if (ipf_nat_nextaddr(fin, &np->in_nsrc, &frnat.fin_saddr, 6960 if (ipf_nat_nextaddr(fin, &np->in_nsrc, &frnat.fin_saddr,
6961 &frnat.fin_saddr) == -1) { 6961 &frnat.fin_saddr) == -1) {
6962 return -1; 6962 return -1;
6963 } 6963 }
6964 6964
6965 if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0xffffffff)) { 6965 if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0xffffffff)) {
6966 src_search = 0; 6966 src_search = 0;
6967 if (np->in_stepnext == 0) 6967 if (np->in_stepnext == 0)
6968 np->in_stepnext = 1; 6968 np->in_stepnext = 1;
6969 6969
6970 } else if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0)) { 6970 } else if ((np->in_nsrcaddr == 0) && (np->in_nsrcmsk == 0)) {
6971 src_search = 0; 6971 src_search = 0;
6972 if (np->in_stepnext == 0) 6972 if (np->in_stepnext == 0)
6973 np->in_stepnext = 1; 6973 np->in_stepnext = 1;
6974 6974
6975 } else if (np->in_nsrcmsk == 0xffffffff) { 6975 } else if (np->in_nsrcmsk == 0xffffffff) {
6976 src_search = 0; 6976 src_search = 0;
6977 if (np->in_stepnext == 0) 6977 if (np->in_stepnext == 0)
6978 np->in_stepnext = 1; 6978 np->in_stepnext = 1;
6979 6979
6980 } else if (np->in_nsrcmsk != 0xffffffff) { 6980 } else if (np->in_nsrcmsk != 0xffffffff) {
6981 if (np->in_stepnext == 0 && changed == -1) { 6981 if (np->in_stepnext == 0 && changed == -1) {
6982 np->in_snip++; 6982 np->in_snip++;
6983 np->in_stepnext++; 6983 np->in_stepnext++;
6984 changed = 0; 6984 changed = 0;
6985 } 6985 }
6986 } 6986 }
6987 6987
6988 if ((flags & IPN_TCPUDPICMP) != 0) { 6988 if ((flags & IPN_TCPUDPICMP) != 0) {
6989 if (np->in_spnext != 0) 6989 if (np->in_spnext != 0)
6990 frnat.fin_data[0] = np->in_spnext; 6990 frnat.fin_data[0] = np->in_spnext;
6991 6991
6992 /* 6992 /*
6993 * Standard port translation. Select next port. 6993 * Standard port translation. Select next port.
6994 */ 6994 */
6995 if ((flags & IPN_FIXEDSPORT) != 0) { 6995 if ((flags & IPN_FIXEDSPORT) != 0) {
6996 np->in_stepnext = 2; 6996 np->in_stepnext = 2;
6997 } else if ((np->in_stepnext == 1) && 6997 } else if ((np->in_stepnext == 1) &&
6998 (changed == -1) && (natl != NULL)) { 6998 (changed == -1) && (natl != NULL)) {
6999 np->in_spnext++; 6999 np->in_spnext++;
7000 np->in_stepnext++; 7000 np->in_stepnext++;
7001 changed = 1; 7001 changed = 1;
7002 if (np->in_spnext > np->in_spmax) 7002 if (np->in_spnext > np->in_spmax)
7003 np->in_spnext = np->in_spmin; 7003 np->in_spnext = np->in_spmin;
7004 } 7004 }
7005 } else { 7005 } else {
7006 np->in_stepnext = 2; 7006 np->in_stepnext = 2;
7007 } 7007 }
7008 np->in_stepnext &= 0x3; 7008 np->in_stepnext &= 0x3;
7009 7009
7010 /* 7010 /*
7011 * Find a new destination address 7011 * Find a new destination address
7012 */ 7012 */
7013 /* TRACE (fin, np, l, frnat) */ 7013 /* TRACE (fin, np, l, frnat) */
7014 7014
7015 if (ipf_nat_nextaddr(fin, &np->in_ndst, &frnat.fin_daddr, 7015 if (ipf_nat_nextaddr(fin, &np->in_ndst, &frnat.fin_daddr,
7016 &frnat.fin_daddr) == -1) 7016 &frnat.fin_daddr) == -1)
7017 return -1; 7017 return -1;
7018 if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0xffffffff)) { 7018 if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0xffffffff)) {
7019 dst_search = 0; 7019 dst_search = 0;
7020 if (np->in_stepnext == 2) 7020 if (np->in_stepnext == 2)
7021 np->in_stepnext = 3; 7021 np->in_stepnext = 3;
7022 7022
7023 } else if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0)) { 7023 } else if ((np->in_ndstaddr == 0) && (np->in_ndstmsk == 0)) {
7024 dst_search = 0; 7024 dst_search = 0;
7025 if (np->in_stepnext == 2) 7025 if (np->in_stepnext == 2)
7026 np->in_stepnext = 3; 7026 np->in_stepnext = 3;
7027 7027
7028 } else if (np->in_ndstmsk == 0xffffffff) { 7028 } else if (np->in_ndstmsk == 0xffffffff) {
7029 dst_search = 0; 7029 dst_search = 0;
7030 if (np->in_stepnext == 2) 7030 if (np->in_stepnext == 2)
7031 np->in_stepnext = 3; 7031 np->in_stepnext = 3;
7032 7032
7033 } else if (np->in_ndstmsk != 0xffffffff) { 7033 } else if (np->in_ndstmsk != 0xffffffff) {
7034 if ((np->in_stepnext == 2) && (changed == -1) && 7034 if ((np->in_stepnext == 2) && (changed == -1) &&
7035 (natl != NULL)) { 7035 (natl != NULL)) {
7036 changed = 2; 7036 changed = 2;
7037 np->in_stepnext++; 7037 np->in_stepnext++;
7038 np->in_dnip++; 7038 np->in_dnip++;
7039 } 7039 }
7040 } 7040 }
7041 7041
7042 if ((flags & IPN_TCPUDPICMP) != 0) { 7042 if ((flags & IPN_TCPUDPICMP) != 0) {
7043 if (np->in_dpnext != 0) 7043 if (np->in_dpnext != 0)
7044 frnat.fin_data[1] = np->in_dpnext; 7044 frnat.fin_data[1] = np->in_dpnext;
7045 7045
7046 /* 7046 /*
7047 * Standard port translation. Select next port. 7047 * Standard port translation. Select next port.
7048 */ 7048 */
7049 if ((flags & IPN_FIXEDDPORT) != 0) { 7049 if ((flags & IPN_FIXEDDPORT) != 0) {
7050 np->in_stepnext = 0; 7050 np->in_stepnext = 0;
7051 } else if (np->in_stepnext == 3 && changed == -1) { 7051 } else if (np->in_stepnext == 3 && changed == -1) {
7052 np->in_dpnext++; 7052 np->in_dpnext++;
7053 np->in_stepnext++; 7053 np->in_stepnext++;
7054 changed = 3; 7054 changed = 3;
7055 if (np->in_dpnext > np->in_dpmax) 7055 if (np->in_dpnext > np->in_dpmax)
7056 np->in_dpnext = np->in_dpmin; 7056 np->in_dpnext = np->in_dpmin;
7057 } 7057 }
7058 } else { 7058 } else {
7059 if (np->in_stepnext == 3) 7059 if (np->in_stepnext == 3)
7060 np->in_stepnext = 0; 7060 np->in_stepnext = 0;
7061 } 7061 }
7062 7062
7063 /* TRACE (frnat) */ 7063 /* TRACE (frnat) */
7064 7064
7065 /* 7065 /*
7066 * Here we do a lookup of the connection as seen from 7066 * Here we do a lookup of the connection as seen from
7067 * the outside. If an IP# pair already exists, try 7067 * the outside. If an IP# pair already exists, try
7068 * again. So if you have A->B becomes C->B, you can 7068 * again. So if you have A->B becomes C->B, you can
7069 * also have D->E become C->E but not D->B causing 7069 * also have D->E become C->E but not D->B causing
7070 * another C->B. Also take protocol and ports into 7070 * another C->B. Also take protocol and ports into
7071 * account when determining whether a pre-existing 7071 * account when determining whether a pre-existing
7072 * NAT setup will cause an external conflict where 7072 * NAT setup will cause an external conflict where
7073 * this is appropriate. 7073 * this is appropriate.
7074 * 7074 *
7075 * fin_data[] is swapped around because we are doing a 7075 * fin_data[] is swapped around because we are doing a
7076 * lookup of the packet is if it were moving in the opposite 7076 * lookup of the packet is if it were moving in the opposite
7077 * direction of the one we are working with now. 7077 * direction of the one we are working with now.
7078 */ 7078 */
7079 if (flags & IPN_TCPUDP) { 7079 if (flags & IPN_TCPUDP) {
7080 swap = frnat.fin_data[0]; 7080 swap = frnat.fin_data[0];
7081 frnat.fin_data[0] = frnat.fin_data[1]; 7081 frnat.fin_data[0] = frnat.fin_data[1];
7082 frnat.fin_data[1] = swap; 7082 frnat.fin_data[1] = swap;
7083 } 7083 }
7084 if (fin->fin_out == 1) { 7084 if (fin->fin_out == 1) {
7085 natl = ipf_nat_inlookup(&frnat, 7085 natl = ipf_nat_inlookup(&frnat,
7086 flags & ~(SI_WILDP|NAT_SEARCH), 7086 flags & ~(SI_WILDP|NAT_SEARCH),
7087 (u_int)frnat.fin_p, 7087 (u_int)frnat.fin_p,
7088 frnat.fin_dst, frnat.fin_src); 7088 frnat.fin_dst, frnat.fin_src);
7089 7089
7090 } else { 7090 } else {
7091 natl = ipf_nat_outlookup(&frnat, 7091 natl = ipf_nat_outlookup(&frnat,
7092 flags & ~(SI_WILDP|NAT_SEARCH), 7092 flags & ~(SI_WILDP|NAT_SEARCH),
7093 (u_int)frnat.fin_p, 7093 (u_int)frnat.fin_p,
7094 frnat.fin_dst, frnat.fin_src); 7094 frnat.fin_dst, frnat.fin_src);
7095 } 7095 }
7096 if (flags & IPN_TCPUDP) { 7096 if (flags & IPN_TCPUDP) {
7097 swap = frnat.fin_data[0]; 7097 swap = frnat.fin_data[0];
7098 frnat.fin_data[0] = frnat.fin_data[1]; 7098 frnat.fin_data[0] = frnat.fin_data[1];
7099 frnat.fin_data[1] = swap; 7099 frnat.fin_data[1] = swap;
7100 } 7100 }
7101 7101
7102 /* TRACE natl, in_stepnext, l */ 7102 /* TRACE natl, in_stepnext, l */
7103 7103
7104 if ((natl != NULL) && (l > 8)) /* XXX 8 is arbitrary */ 7104 if ((natl != NULL) && (l > 8)) /* XXX 8 is arbitrary */
7105 return -1; 7105 return -1;
7106 7106
7107 np->in_stepnext &= 0x3; 7107 np->in_stepnext &= 0x3;
7108 7108
7109 l++; 7109 l++;
7110 changed = -1; 7110 changed = -1;
7111 } while (natl != NULL); 7111 } while (natl != NULL);
7112 7112
7113 nat->nat_osrcip = fin->fin_src; 7113 nat->nat_osrcip = fin->fin_src;
7114 nat->nat_odstip = fin->fin_dst; 7114 nat->nat_odstip = fin->fin_dst;
7115 nat->nat_nsrcip = frnat.fin_src; 7115 nat->nat_nsrcip = frnat.fin_src;
7116 nat->nat_ndstip = frnat.fin_dst; 7116 nat->nat_ndstip = frnat.fin_dst;
7117 7117
7118 if ((flags & IPN_TCPUDP) != 0) { 7118 if ((flags & IPN_TCPUDP) != 0) {
7119 nat->nat_osport = htons(fin->fin_data[0]); 7119 nat->nat_osport = htons(fin->fin_data[0]);
7120 nat->nat_odport = htons(fin->fin_data[1]); 7120 nat->nat_odport = htons(fin->fin_data[1]);
7121 nat->nat_nsport = htons(frnat.fin_data[0]); 7121 nat->nat_nsport = htons(frnat.fin_data[0]);
7122 nat->nat_ndport = htons(frnat.fin_data[1]); 7122 nat->nat_ndport = htons(frnat.fin_data[1]);
7123 } else if ((flags & IPN_ICMPQUERY) != 0) { 7123 } else if ((flags & IPN_ICMPQUERY) != 0) {
7124 nat->nat_oicmpid = fin->fin_data[1]; 7124 nat->nat_oicmpid = fin->fin_data[1];
7125 nat->nat_nicmpid = frnat.fin_data[1]; 7125 nat->nat_nicmpid = frnat.fin_data[1];
7126 } 7126 }
7127 7127
7128 return 0; 7128 return 0;
7129} 7129}
7130 7130
7131 7131
7132/* ------------------------------------------------------------------------ */ 7132/* ------------------------------------------------------------------------ */
7133/* Function: nat_newdivert */ 7133/* Function: nat_newdivert */
7134/* Returns: int - -1 == error, 0 == success */ 7134/* Returns: int - -1 == error, 0 == success */
7135/* Parameters: fin(I) - pointer to packet information */ 7135/* Parameters: fin(I) - pointer to packet information */
7136/* nat(I) - pointer to NAT entry */ 7136/* nat(I) - pointer to NAT entry */
7137/* ni(I) - pointer to structure with misc. information needed */ 7137/* ni(I) - pointer to structure with misc. information needed */
7138/* to create new NAT entry. */ 7138/* to create new NAT entry. */
7139/* Write Lock: ipf_nat */ 7139/* Write Lock: ipf_nat */
7140/* */ 7140/* */
7141/* Create a new NAT divert session as defined by the NAT rule. This is */ 7141/* Create a new NAT divert session as defined by the NAT rule. This is */
7142/* somewhat different to other NAT session creation routines because we */ 7142/* somewhat different to other NAT session creation routines because we */
7143/* do not iterate through either port numbers or IP addresses, searching */ 7143/* do not iterate through either port numbers or IP addresses, searching */
7144/* for a unique mapping, however, a complimentary duplicate check is made. */ 7144/* for a unique mapping, however, a complimentary duplicate check is made. */
7145/* ------------------------------------------------------------------------ */ 7145/* ------------------------------------------------------------------------ */
7146static int 7146static int
7147ipf_nat_newdivert(fr_info_t *fin, nat_t *nat, natinfo_t *nai) 7147ipf_nat_newdivert(fr_info_t *fin, nat_t *nat, natinfo_t *nai)
7148{ 7148{
7149 ipf_main_softc_t *softc = fin->fin_main_soft; 7149 ipf_main_softc_t *softc = fin->fin_main_soft;
7150 ipf_nat_softc_t *softn = softc->ipf_nat_soft; 7150 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
7151 fr_info_t frnat; 7151 fr_info_t frnat;
7152 ipnat_t *np; 7152 ipnat_t *np;
7153 nat_t *natl; 7153 nat_t *natl;
7154 int p; 7154 int p;
7155 7155
7156 np = nai->nai_np; 7156 np = nai->nai_np;
7157 bcopy((char *)fin, (char *)&frnat, sizeof(*fin)); 7157 bcopy((char *)fin, (char *)&frnat, sizeof(*fin));
7158 7158
7159 nat->nat_pr[0] = 0; 7159 nat->nat_pr[0] = 0;
7160 nat->nat_osrcaddr = fin->fin_saddr; 7160 nat->nat_osrcaddr = fin->fin_saddr;
7161 nat->nat_odstaddr = fin->fin_daddr; 7161 nat->nat_odstaddr = fin->fin_daddr;
7162 frnat.fin_saddr = htonl(np->in_snip); 7162 frnat.fin_saddr = htonl(np->in_snip);
7163 frnat.fin_daddr = htonl(np->in_dnip); 7163 frnat.fin_daddr = htonl(np->in_dnip);
7164 if ((nat->nat_flags & IPN_TCPUDP) != 0) { 7164 if ((nat->nat_flags & IPN_TCPUDP) != 0) {
7165 nat->nat_osport = htons(fin->fin_data[0]); 7165 nat->nat_osport = htons(fin->fin_data[0]);
7166 nat->nat_odport = htons(fin->fin_data[1]); 7166 nat->nat_odport = htons(fin->fin_data[1]);
7167 } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) { 7167 } else if ((nat->nat_flags & IPN_ICMPQUERY) != 0) {
7168 nat->nat_oicmpid = fin->fin_data[1]; 7168 nat->nat_oicmpid = fin->fin_data[1];
7169 } 7169 }
7170 7170
7171 if (np->in_redir & NAT_DIVERTUDP) { 7171 if (np->in_redir & NAT_DIVERTUDP) {
7172 frnat.fin_data[0] = np->in_spnext; 7172 frnat.fin_data[0] = np->in_spnext;
7173 frnat.fin_data[1] = np->in_dpnext; 7173 frnat.fin_data[1] = np->in_dpnext;
7174 frnat.fin_flx |= FI_TCPUDP; 7174 frnat.fin_flx |= FI_TCPUDP;
7175 p = IPPROTO_UDP; 7175 p = IPPROTO_UDP;
7176 } else { 7176 } else {
7177 frnat.fin_flx &= ~FI_TCPUDP; 7177 frnat.fin_flx &= ~FI_TCPUDP;
7178 p = IPPROTO_IPIP; 7178 p = IPPROTO_IPIP;
7179 } 7179 }
7180 7180