ip_proxy.c revision 1.5 1 1.5 darrenr /* $NetBSD: ip_proxy.c,v 1.5 2012/07/22 16:34:04 darrenr Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) 2012 by Darren Reed.
5 1.1 christos *
6 1.1 christos * See the IPFILTER.LICENCE file for details on licencing.
7 1.1 christos */
8 1.1 christos #if defined(KERNEL) || defined(_KERNEL)
9 1.1 christos # undef KERNEL
10 1.1 christos # undef _KERNEL
11 1.1 christos # define KERNEL 1
12 1.1 christos # define _KERNEL 1
13 1.1 christos #endif
14 1.1 christos #include <sys/errno.h>
15 1.1 christos #include <sys/types.h>
16 1.1 christos #include <sys/param.h>
17 1.1 christos #include <sys/time.h>
18 1.1 christos #include <sys/file.h>
19 1.1 christos #if !defined(AIX)
20 1.1 christos # include <sys/fcntl.h>
21 1.1 christos #endif
22 1.1 christos #if !defined(_KERNEL) && !defined(__KERNEL__)
23 1.1 christos # include <stdio.h>
24 1.1 christos # include <string.h>
25 1.1 christos # include <stdlib.h>
26 1.1 christos # include <ctype.h>
27 1.1 christos # define _KERNEL
28 1.1 christos # ifdef __OpenBSD__
29 1.1 christos struct file;
30 1.1 christos # endif
31 1.1 christos # include <sys/uio.h>
32 1.1 christos # undef _KERNEL
33 1.1 christos #endif
34 1.1 christos #if !defined(linux)
35 1.1 christos # include <sys/protosw.h>
36 1.1 christos #endif
37 1.1 christos #include <sys/socket.h>
38 1.1 christos #if defined(_KERNEL)
39 1.1 christos # if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \
40 1.1 christos !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \
41 1.1 christos !defined(AIX)
42 1.1 christos # include <sys/ctype.h>
43 1.1 christos # endif
44 1.1 christos # include <sys/systm.h>
45 1.1 christos # if !defined(__SVR4) && !defined(__svr4__)
46 1.1 christos # include <sys/mbuf.h>
47 1.1 christos # endif
48 1.1 christos #endif
49 1.1 christos #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
50 1.1 christos # include <sys/filio.h>
51 1.1 christos # include <sys/fcntl.h>
52 1.1 christos #else
53 1.1 christos # include <sys/ioctl.h>
54 1.1 christos #endif
55 1.1 christos #if defined(__SVR4) || defined(__svr4__)
56 1.1 christos # include <sys/byteorder.h>
57 1.1 christos # ifdef _KERNEL
58 1.1 christos # include <sys/dditypes.h>
59 1.1 christos # endif
60 1.1 christos # include <sys/stream.h>
61 1.1 christos # include <sys/kmem.h>
62 1.1 christos #endif
63 1.1 christos #if __FreeBSD__ > 2
64 1.1 christos # include <sys/queue.h>
65 1.1 christos #endif
66 1.1 christos #include <net/if.h>
67 1.1 christos #ifdef sun
68 1.1 christos # include <net/af.h>
69 1.1 christos #endif
70 1.1 christos #include <netinet/in.h>
71 1.1 christos #include <netinet/in_systm.h>
72 1.1 christos #include <netinet/ip.h>
73 1.1 christos #ifndef linux
74 1.1 christos # include <netinet/ip_var.h>
75 1.1 christos #endif
76 1.1 christos #include <netinet/tcp.h>
77 1.1 christos #include <netinet/udp.h>
78 1.1 christos #include <netinet/ip_icmp.h>
79 1.1 christos #include "netinet/ip_compat.h"
80 1.1 christos #include <netinet/tcpip.h>
81 1.1 christos #include "netinet/ip_fil.h"
82 1.1 christos #include "netinet/ip_nat.h"
83 1.1 christos #include "netinet/ip_state.h"
84 1.1 christos #include "netinet/ip_proxy.h"
85 1.1 christos #if (__FreeBSD_version >= 300000)
86 1.1 christos # include <sys/malloc.h>
87 1.1 christos #endif
88 1.1 christos
89 1.1 christos /* END OF INCLUDES */
90 1.1 christos
91 1.2 christos #include "netinet/ip_dns_pxy.c"
92 1.1 christos #include "netinet/ip_ftp_pxy.c"
93 1.1 christos #include "netinet/ip_tftp_pxy.c"
94 1.1 christos #include "netinet/ip_rcmd_pxy.c"
95 1.1 christos #include "netinet/ip_pptp_pxy.c"
96 1.1 christos #if defined(_KERNEL)
97 1.1 christos # include "netinet/ip_irc_pxy.c"
98 1.1 christos # include "netinet/ip_raudio_pxy.c"
99 1.1 christos # include "netinet/ip_netbios_pxy.c"
100 1.1 christos #endif
101 1.1 christos #include "netinet/ip_ipsec_pxy.c"
102 1.1 christos #include "netinet/ip_rpcb_pxy.c"
103 1.1 christos
104 1.1 christos #if !defined(lint)
105 1.2 christos #if defined(__NetBSD__)
106 1.2 christos #include <sys/cdefs.h>
107 1.5 darrenr __KERNEL_RCSID(0, "$NetBSD: ip_proxy.c,v 1.5 2012/07/22 16:34:04 darrenr Exp $");
108 1.2 christos #else
109 1.3 darrenr static const char rcsid[] = "@(#)Id: ip_proxy.c,v 1.1.1.2 2012/07/22 13:45:33 darrenr Exp";
110 1.2 christos #endif
111 1.1 christos #endif
112 1.1 christos
113 1.1 christos #define AP_SESS_SIZE 53
114 1.1 christos
115 1.2 christos static int ipf_proxy_fixseqack(fr_info_t *, ip_t *, ap_session_t *, int );
116 1.2 christos static aproxy_t *ipf_proxy_create_clone(ipf_main_softc_t *, aproxy_t *);
117 1.1 christos
118 1.1 christos typedef struct ipf_proxy_softc_s {
119 1.1 christos int ips_proxy_debug;
120 1.1 christos int ips_proxy_session_size;
121 1.1 christos ap_session_t **ips_sess_tab;
122 1.1 christos ap_session_t *ips_sess_list;
123 1.1 christos aproxy_t *ips_proxies;
124 1.1 christos int ips_init_run;
125 1.1 christos ipftuneable_t *ipf_proxy_tune;
126 1.1 christos } ipf_proxy_softc_t;
127 1.1 christos
128 1.1 christos static ipftuneable_t ipf_proxy_tuneables[] = {
129 1.1 christos { { (void *)offsetof(ipf_proxy_softc_t, ips_proxy_debug) },
130 1.3 darrenr "proxy_debug", 0, 0x1f,
131 1.1 christos stsizeof(ipf_proxy_softc_t, ips_proxy_debug),
132 1.1 christos 0, NULL, NULL },
133 1.1 christos { { NULL }, NULL, 0, 0,
134 1.1 christos 0,
135 1.1 christos 0, NULL, NULL}
136 1.1 christos };
137 1.1 christos
138 1.1 christos static aproxy_t *ap_proxylist = NULL;
139 1.1 christos static aproxy_t ips_proxies[] = {
140 1.1 christos #ifdef IPF_FTP_PROXY
141 1.1 christos { NULL, NULL, "ftp", (char)IPPROTO_TCP, 0, 0, 0,
142 1.1 christos ipf_p_ftp_main_load, ipf_p_ftp_main_unload,
143 1.1 christos ipf_p_ftp_soft_create, ipf_p_ftp_soft_destroy,
144 1.1 christos NULL, NULL,
145 1.1 christos ipf_p_ftp_new, ipf_p_ftp_del, ipf_p_ftp_in, ipf_p_ftp_out, NULL,
146 1.1 christos NULL, NULL, NULL, NULL },
147 1.1 christos #endif
148 1.1 christos #ifdef IPF_TFTP_PROXY
149 1.3 darrenr { NULL, NULL, "tftp", (char)IPPROTO_UDP, 0, 0, 0,
150 1.1 christos ipf_p_tftp_main_load, ipf_p_tftp_main_unload,
151 1.3 darrenr ipf_p_tftp_soft_create, ipf_p_tftp_soft_destroy,
152 1.1 christos NULL, NULL,
153 1.3 darrenr ipf_p_tftp_new, ipf_p_tftp_del,
154 1.3 darrenr ipf_p_tftp_in, ipf_p_tftp_out, NULL,
155 1.1 christos NULL, NULL, NULL, NULL },
156 1.1 christos #endif
157 1.1 christos #ifdef IPF_IRC_PROXY
158 1.1 christos { NULL, NULL, "irc", (char)IPPROTO_TCP, 0, 0, 0,
159 1.1 christos ipf_p_irc_main_load, ipf_p_irc_main_unload,
160 1.1 christos NULL, NULL,
161 1.1 christos NULL, NULL,
162 1.1 christos ipf_p_irc_new, NULL, NULL, ipf_p_irc_out, NULL,
163 1.1 christos NULL, NULL, NULL, NULL },
164 1.1 christos #endif
165 1.1 christos #ifdef IPF_RCMD_PROXY
166 1.1 christos { NULL, NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, 0,
167 1.1 christos ipf_p_rcmd_main_load, ipf_p_rcmd_main_unload,
168 1.1 christos NULL, NULL,
169 1.1 christos NULL, NULL,
170 1.1 christos ipf_p_rcmd_new, ipf_p_rcmd_del,
171 1.1 christos ipf_p_rcmd_in, ipf_p_rcmd_out, NULL,
172 1.1 christos NULL, NULL, NULL, NULL },
173 1.1 christos #endif
174 1.1 christos #ifdef IPF_RAUDIO_PROXY
175 1.1 christos { NULL, NULL, "raudio", (char)IPPROTO_TCP, 0, 0, 0,
176 1.1 christos ipf_p_raudio_main_load, ipf_p_raudio_main_unload,
177 1.1 christos NULL, NULL,
178 1.1 christos NULL, NULL,
179 1.1 christos ipf_p_raudio_new, NULL, ipf_p_raudio_in, ipf_p_raudio_out, NULL,
180 1.1 christos NULL, NULL, NULL, NULL },
181 1.1 christos #endif
182 1.1 christos #ifdef IPF_MSNRPC_PROXY
183 1.1 christos { NULL, NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, 0,
184 1.1 christos ipf_p_msnrpc_init, ipf_p_msnrpc_fini,
185 1.1 christos NULL, NULL,
186 1.1 christos NULL, NULL,
187 1.1 christos ipf_p_msnrpc_new, NULL, ipf_p_msnrpc_in, ipf_p_msnrpc_out, NULL,
188 1.1 christos NULL, NULL, NULL, NULL },
189 1.1 christos #endif
190 1.1 christos #ifdef IPF_NETBIOS_PROXY
191 1.1 christos { NULL, NULL, "netbios", (char)IPPROTO_UDP, 0, 0, 0,
192 1.1 christos ipf_p_netbios_main_load, ipf_p_netbios_main_unload,
193 1.1 christos NULL, NULL,
194 1.1 christos NULL, NULL,
195 1.1 christos NULL, NULL, NULL, ipf_p_netbios_out, NULL,
196 1.1 christos NULL, NULL, NULL, NULL },
197 1.1 christos #endif
198 1.1 christos #ifdef IPF_IPSEC_PROXY
199 1.1 christos { NULL, NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 0,
200 1.1 christos NULL, NULL,
201 1.1 christos ipf_p_ipsec_soft_create, ipf_p_ipsec_soft_destroy,
202 1.1 christos ipf_p_ipsec_soft_init, ipf_p_ipsec_soft_fini,
203 1.1 christos ipf_p_ipsec_new, ipf_p_ipsec_del,
204 1.1 christos ipf_p_ipsec_inout, ipf_p_ipsec_inout, ipf_p_ipsec_match,
205 1.1 christos NULL, NULL, NULL, NULL },
206 1.1 christos #endif
207 1.1 christos #ifdef IPF_DNS_PROXY
208 1.1 christos { NULL, NULL, "dns", (char)IPPROTO_UDP, 0, 0, 0,
209 1.1 christos NULL, NULL,
210 1.1 christos ipf_p_dns_soft_create, ipf_p_dns_soft_destroy,
211 1.1 christos NULL, NULL,
212 1.1 christos ipf_p_dns_new, ipf_p_ipsec_del,
213 1.1 christos ipf_p_dns_inout, ipf_p_dns_inout, ipf_p_dns_match,
214 1.1 christos ipf_p_dns_ctl, NULL, NULL, NULL },
215 1.1 christos #endif
216 1.1 christos #ifdef IPF_PPTP_PROXY
217 1.1 christos { NULL, NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 0,
218 1.1 christos ipf_p_pptp_main_load, ipf_p_pptp_main_unload,
219 1.1 christos NULL, NULL,
220 1.1 christos NULL, NULL,
221 1.1 christos ipf_p_pptp_new, ipf_p_pptp_del,
222 1.1 christos ipf_p_pptp_inout, ipf_p_pptp_inout, NULL,
223 1.1 christos NULL, NULL, NULL, NULL },
224 1.1 christos #endif
225 1.2 christos #ifdef IPF_H323_PROXY
226 1.2 christos { NULL, NULL, "h323", (char)IPPROTO_TCP, 0, 0, 0,
227 1.2 christos ipf_p_h323_main_load, ipf_p_h323_main_unload,
228 1.2 christos NULL, NULL,
229 1.2 christos NULL, NULL,
230 1.2 christos ipf_p_h323_new, ipf_p_h323_del,
231 1.2 christos ipf_p_h323_in, NULL, NULL,
232 1.2 christos NULL, NULL, NULL, NULL },
233 1.2 christos { NULL, NULL, "h245", (char)IPPROTO_TCP, 0, 0, 0, NULL, NULL,
234 1.2 christos NULL, NULL,
235 1.2 christos NULL, NULL,
236 1.2 christos ipf_p_h245_new, NULL,
237 1.2 christos NULL, ipf_p_h245_out, NULL,
238 1.2 christos NULL, NULL, NULL, NULL },
239 1.2 christos #endif
240 1.1 christos #ifdef IPF_RPCB_PROXY
241 1.1 christos # ifndef _KERNEL
242 1.1 christos { NULL, NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 0,
243 1.1 christos NULL, NULL,
244 1.1 christos NULL, NULL,
245 1.1 christos NULL, NULL,
246 1.1 christos ipf_p_rpcb_new, ipf_p_rpcb_del,
247 1.1 christos ipf_p_rpcb_in, ipf_p_rpcb_out, NULL,
248 1.1 christos NULL, NULL, NULL, NULL },
249 1.1 christos # endif
250 1.1 christos { NULL, NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 0,
251 1.1 christos ipf_p_rpcb_main_load, ipf_p_rpcb_main_unload,
252 1.1 christos NULL, NULL,
253 1.1 christos NULL, NULL,
254 1.1 christos ipf_p_rpcb_new, ipf_p_rpcb_del,
255 1.1 christos ipf_p_rpcb_in, ipf_p_rpcb_out, NULL,
256 1.1 christos NULL, NULL, NULL, NULL },
257 1.1 christos #endif
258 1.1 christos { NULL, NULL, "", '\0', 0, 0, 0,
259 1.1 christos NULL, NULL,
260 1.1 christos NULL, NULL,
261 1.1 christos NULL, NULL,
262 1.1 christos NULL, NULL,
263 1.1 christos NULL, NULL, NULL,
264 1.1 christos NULL, NULL, NULL, NULL }
265 1.1 christos };
266 1.1 christos
267 1.1 christos
268 1.1 christos /* ------------------------------------------------------------------------ */
269 1.3 darrenr /* Function: ipf_proxy_main_load */
270 1.3 darrenr /* Returns: int - 0 == success, else failure. */
271 1.3 darrenr /* Parameters: Nil */
272 1.1 christos /* */
273 1.1 christos /* Initialise hook for kernel application proxies. */
274 1.1 christos /* Call the initialise routine for all the compiled in kernel proxies. */
275 1.1 christos /* ------------------------------------------------------------------------ */
276 1.1 christos int
277 1.2 christos ipf_proxy_main_load(void)
278 1.1 christos {
279 1.1 christos aproxy_t *ap;
280 1.1 christos
281 1.1 christos for (ap = ips_proxies; ap->apr_p; ap++) {
282 1.1 christos if (ap->apr_load != NULL)
283 1.1 christos (*ap->apr_load)();
284 1.1 christos }
285 1.1 christos return 0;
286 1.1 christos }
287 1.1 christos
288 1.1 christos
289 1.1 christos /* ------------------------------------------------------------------------ */
290 1.3 darrenr /* Function: ipf_proxy_main_unload */
291 1.3 darrenr /* Returns: int - 0 == success, else failure. */
292 1.1 christos /* Parameters: Nil */
293 1.1 christos /* */
294 1.1 christos /* Unload hook for kernel application proxies. */
295 1.1 christos /* Call the finialise routine for all the compiled in kernel proxies. */
296 1.1 christos /* ------------------------------------------------------------------------ */
297 1.1 christos int
298 1.2 christos ipf_proxy_main_unload(void)
299 1.1 christos {
300 1.1 christos aproxy_t *ap;
301 1.1 christos
302 1.1 christos for (ap = ips_proxies; ap->apr_p; ap++)
303 1.1 christos if (ap->apr_unload != NULL)
304 1.1 christos (*ap->apr_unload)();
305 1.1 christos for (ap = ap_proxylist; ap; ap = ap->apr_next)
306 1.1 christos if (ap->apr_unload != NULL)
307 1.1 christos (*ap->apr_unload)();
308 1.1 christos
309 1.1 christos return 0;
310 1.1 christos }
311 1.1 christos
312 1.1 christos
313 1.3 darrenr /* ------------------------------------------------------------------------ */
314 1.3 darrenr /* Function: ipf_proxy_soft_create */
315 1.3 darrenr /* Returns: void * - */
316 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
317 1.3 darrenr /* */
318 1.3 darrenr /* Build the structure to hold all of the run time data to support proxies. */
319 1.3 darrenr /* ------------------------------------------------------------------------ */
320 1.1 christos void *
321 1.2 christos ipf_proxy_soft_create(ipf_main_softc_t *softc)
322 1.1 christos {
323 1.1 christos ipf_proxy_softc_t *softp;
324 1.1 christos aproxy_t *last;
325 1.1 christos aproxy_t *apn;
326 1.1 christos aproxy_t *ap;
327 1.1 christos
328 1.1 christos KMALLOC(softp, ipf_proxy_softc_t *);
329 1.1 christos if (softp == NULL)
330 1.1 christos return softp;
331 1.1 christos
332 1.1 christos bzero((char *)softp, sizeof(*softp));
333 1.1 christos
334 1.1 christos #if defined(_KERNEL)
335 1.1 christos softp->ips_proxy_debug = 0;
336 1.1 christos #else
337 1.1 christos softp->ips_proxy_debug = 2;
338 1.1 christos #endif
339 1.1 christos softp->ips_proxy_session_size = AP_SESS_SIZE;
340 1.1 christos
341 1.1 christos softp->ipf_proxy_tune = ipf_tune_array_copy(softp,
342 1.1 christos sizeof(ipf_proxy_tuneables),
343 1.1 christos ipf_proxy_tuneables);
344 1.1 christos if (softp->ipf_proxy_tune == NULL) {
345 1.1 christos ipf_proxy_soft_destroy(softc, softp);
346 1.1 christos return NULL;
347 1.1 christos }
348 1.1 christos if (ipf_tune_array_link(softc, softp->ipf_proxy_tune) == -1) {
349 1.1 christos ipf_proxy_soft_destroy(softc, softp);
350 1.1 christos return NULL;
351 1.1 christos }
352 1.1 christos
353 1.1 christos last = NULL;
354 1.1 christos for (ap = ips_proxies; ap->apr_p; ap++) {
355 1.1 christos apn = ipf_proxy_create_clone(softc, ap);
356 1.1 christos if (apn == NULL)
357 1.1 christos goto failed;
358 1.1 christos if (last != NULL)
359 1.1 christos last->apr_next = apn;
360 1.1 christos else
361 1.1 christos softp->ips_proxies = apn;
362 1.1 christos last = apn;
363 1.1 christos }
364 1.1 christos for (ap = ips_proxies; ap != NULL; ap = ap->apr_next) {
365 1.1 christos apn = ipf_proxy_create_clone(softc, ap);
366 1.1 christos if (apn == NULL)
367 1.1 christos goto failed;
368 1.1 christos if (last != NULL)
369 1.1 christos last->apr_next = apn;
370 1.1 christos else
371 1.1 christos softp->ips_proxies = apn;
372 1.1 christos last = apn;
373 1.1 christos }
374 1.1 christos
375 1.1 christos return softp;
376 1.1 christos failed:
377 1.1 christos ipf_proxy_soft_destroy(softc, softp);
378 1.1 christos return NULL;
379 1.1 christos }
380 1.1 christos
381 1.1 christos
382 1.3 darrenr /* ------------------------------------------------------------------------ */
383 1.3 darrenr /* Function: ipf_proxy_soft_create */
384 1.3 darrenr /* Returns: void * - */
385 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
386 1.3 darrenr /* orig(I) - pointer to proxy definition to copy */
387 1.3 darrenr /* */
388 1.3 darrenr /* This function clones a proxy definition given by orig and returns a */
389 1.3 darrenr /* a pointer to that copy. */
390 1.3 darrenr /* ------------------------------------------------------------------------ */
391 1.1 christos static aproxy_t *
392 1.2 christos ipf_proxy_create_clone(ipf_main_softc_t *softc, aproxy_t *orig)
393 1.1 christos {
394 1.1 christos aproxy_t *apn;
395 1.1 christos
396 1.1 christos KMALLOC(apn, aproxy_t *);
397 1.1 christos if (apn == NULL)
398 1.1 christos return NULL;
399 1.1 christos
400 1.1 christos bcopy((char *)orig, (char *)apn, sizeof(*apn));
401 1.1 christos apn->apr_next = NULL;
402 1.1 christos apn->apr_soft = NULL;
403 1.1 christos
404 1.1 christos if (apn->apr_create != NULL) {
405 1.1 christos apn->apr_soft = (*apn->apr_create)(softc);
406 1.1 christos if (apn->apr_soft == NULL) {
407 1.1 christos KFREE(apn);
408 1.1 christos return NULL;
409 1.1 christos }
410 1.1 christos }
411 1.1 christos
412 1.1 christos apn->apr_parent = orig;
413 1.1 christos orig->apr_clones++;
414 1.1 christos
415 1.1 christos return apn;
416 1.1 christos }
417 1.1 christos
418 1.1 christos
419 1.3 darrenr /* ------------------------------------------------------------------------ */
420 1.3 darrenr /* Function: ipf_proxy_soft_create */
421 1.3 darrenr /* Returns: int - 0 == success, else failure. */
422 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
423 1.3 darrenr /* arg(I) - pointer to proxy contect data */
424 1.3 darrenr /* */
425 1.3 darrenr /* Initialise the proxy context and walk through each of the proxies and */
426 1.3 darrenr /* call its initialisation function. This allows for proxies to do any */
427 1.3 darrenr /* local setup prior to actual use. */
428 1.3 darrenr /* ------------------------------------------------------------------------ */
429 1.1 christos int
430 1.2 christos ipf_proxy_soft_init(ipf_main_softc_t *softc, void *arg)
431 1.1 christos {
432 1.1 christos ipf_proxy_softc_t *softp;
433 1.1 christos aproxy_t *ap;
434 1.1 christos u_int size;
435 1.1 christos int err;
436 1.1 christos
437 1.1 christos softp = arg;
438 1.1 christos size = softp->ips_proxy_session_size * sizeof(ap_session_t *);
439 1.1 christos
440 1.1 christos KMALLOCS(softp->ips_sess_tab, ap_session_t **, size);
441 1.1 christos
442 1.1 christos if (softp->ips_sess_tab == NULL)
443 1.1 christos return -1;
444 1.1 christos
445 1.1 christos bzero(softp->ips_sess_tab, size);
446 1.1 christos
447 1.1 christos for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) {
448 1.1 christos if (ap->apr_init != NULL) {
449 1.1 christos err = (*ap->apr_init)(softc, ap->apr_soft);
450 1.1 christos if (err != 0)
451 1.1 christos return -2;
452 1.1 christos }
453 1.1 christos }
454 1.1 christos softp->ips_init_run = 1;
455 1.1 christos
456 1.1 christos return 0;
457 1.1 christos }
458 1.1 christos
459 1.1 christos
460 1.3 darrenr /* ------------------------------------------------------------------------ */
461 1.3 darrenr /* Function: ipf_proxy_soft_create */
462 1.3 darrenr /* Returns: int - 0 == success, else failure. */
463 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
464 1.3 darrenr /* arg(I) - pointer to proxy contect data */
465 1.3 darrenr /* */
466 1.3 darrenr /* This function should always succeed. It is responsible for ensuring that */
467 1.3 darrenr /* the proxy context can be safely called when ipf_proxy_soft_destroy is */
468 1.3 darrenr /* called and suring all of the proxies have similarly been instructed. */
469 1.3 darrenr /* ------------------------------------------------------------------------ */
470 1.1 christos int
471 1.2 christos ipf_proxy_soft_fini(ipf_main_softc_t *softc, void *arg)
472 1.1 christos {
473 1.1 christos ipf_proxy_softc_t *softp = arg;
474 1.1 christos aproxy_t *ap;
475 1.1 christos
476 1.1 christos for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) {
477 1.1 christos if (ap->apr_fini != NULL) {
478 1.1 christos (*ap->apr_fini)(softc, ap->apr_soft);
479 1.1 christos }
480 1.1 christos }
481 1.1 christos
482 1.1 christos if (softp->ips_sess_tab != NULL) {
483 1.1 christos KFREES(softp->ips_sess_tab,
484 1.1 christos softp->ips_proxy_session_size * sizeof(ap_session_t *));
485 1.1 christos softp->ips_sess_tab = NULL;
486 1.1 christos }
487 1.1 christos softp->ips_init_run = 0;
488 1.1 christos
489 1.1 christos return 0;
490 1.1 christos }
491 1.1 christos
492 1.1 christos
493 1.3 darrenr /* ------------------------------------------------------------------------ */
494 1.3 darrenr /* Function: ipf_proxy_soft_destroy */
495 1.3 darrenr /* Returns: Nil */
496 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
497 1.3 darrenr /* arg(I) - pointer to proxy contect data */
498 1.3 darrenr /* */
499 1.3 darrenr /* Free up all of the local data structures allocated during creation. */
500 1.3 darrenr /* ------------------------------------------------------------------------ */
501 1.1 christos void
502 1.2 christos ipf_proxy_soft_destroy(ipf_main_softc_t *softc, void *arg)
503 1.1 christos {
504 1.1 christos ipf_proxy_softc_t *softp = arg;
505 1.1 christos aproxy_t *ap;
506 1.1 christos
507 1.1 christos while ((ap = softp->ips_proxies) != NULL) {
508 1.1 christos softp->ips_proxies = ap->apr_next;
509 1.1 christos if (ap->apr_destroy != NULL)
510 1.1 christos (*ap->apr_destroy)(softc, ap->apr_soft);
511 1.1 christos ap->apr_parent->apr_clones--;
512 1.1 christos KFREE(ap);
513 1.1 christos }
514 1.1 christos
515 1.1 christos if (softp->ipf_proxy_tune != NULL) {
516 1.1 christos ipf_tune_array_unlink(softc, softp->ipf_proxy_tune);
517 1.1 christos KFREES(softp->ipf_proxy_tune, sizeof(ipf_proxy_tuneables));
518 1.1 christos softp->ipf_proxy_tune = NULL;
519 1.1 christos }
520 1.1 christos
521 1.1 christos KFREE(softp);
522 1.1 christos }
523 1.1 christos
524 1.1 christos
525 1.1 christos /* ------------------------------------------------------------------------ */
526 1.1 christos /* Function: ipf_proxy_flush */
527 1.1 christos /* Returns: Nil */
528 1.3 darrenr /* Parameters: arg(I) - pointer to proxy contect data */
529 1.3 darrenr /* how(I) - indicates the type of flush operation */
530 1.1 christos /* */
531 1.3 darrenr /* Walk through all of the proxies and pass on the flush command as either */
532 1.3 darrenr /* a flush or a clear. */
533 1.1 christos /* ------------------------------------------------------------------------ */
534 1.1 christos void
535 1.2 christos ipf_proxy_flush(void *arg, int how)
536 1.1 christos {
537 1.1 christos ipf_proxy_softc_t *softp = arg;
538 1.1 christos aproxy_t *ap;
539 1.1 christos
540 1.1 christos switch (how)
541 1.1 christos {
542 1.1 christos case 0 :
543 1.1 christos for (ap = softp->ips_proxies; ap; ap = ap->apr_next)
544 1.1 christos if (ap->apr_flush != NULL)
545 1.1 christos (*ap->apr_flush)(ap, how);
546 1.1 christos break;
547 1.1 christos case 1 :
548 1.1 christos for (ap = softp->ips_proxies; ap; ap = ap->apr_next)
549 1.1 christos if (ap->apr_clear != NULL)
550 1.1 christos (*ap->apr_clear)(ap);
551 1.1 christos break;
552 1.1 christos default :
553 1.1 christos break;
554 1.1 christos }
555 1.1 christos }
556 1.1 christos
557 1.1 christos
558 1.1 christos /* ------------------------------------------------------------------------ */
559 1.1 christos /* Function: ipf_proxy_add */
560 1.3 darrenr /* Returns: int - 0 == success, else failure. */
561 1.1 christos /* Parameters: ap(I) - pointer to proxy structure */
562 1.1 christos /* */
563 1.1 christos /* Dynamically add a new kernel proxy. Ensure that it is unique in the */
564 1.1 christos /* collection compiled in and dynamically added. */
565 1.1 christos /* ------------------------------------------------------------------------ */
566 1.1 christos int
567 1.2 christos ipf_proxy_add(void *arg, aproxy_t *ap)
568 1.1 christos {
569 1.1 christos ipf_proxy_softc_t *softp = arg;
570 1.1 christos
571 1.1 christos aproxy_t *a;
572 1.1 christos
573 1.1 christos for (a = ips_proxies; a->apr_p; a++)
574 1.1 christos if ((a->apr_p == ap->apr_p) &&
575 1.1 christos !strncmp(a->apr_label, ap->apr_label,
576 1.1 christos sizeof(ap->apr_label))) {
577 1.3 darrenr if (softp->ips_proxy_debug & 0x01)
578 1.1 christos printf("ipf_proxy_add: %s/%d present (B)\n",
579 1.1 christos a->apr_label, a->apr_p);
580 1.1 christos return -1;
581 1.1 christos }
582 1.1 christos
583 1.1 christos for (a = ap_proxylist; (a != NULL); a = a->apr_next)
584 1.1 christos if ((a->apr_p == ap->apr_p) &&
585 1.1 christos !strncmp(a->apr_label, ap->apr_label,
586 1.1 christos sizeof(ap->apr_label))) {
587 1.3 darrenr if (softp->ips_proxy_debug & 0x01)
588 1.1 christos printf("ipf_proxy_add: %s/%d present (D)\n",
589 1.1 christos a->apr_label, a->apr_p);
590 1.1 christos return -1;
591 1.1 christos }
592 1.1 christos ap->apr_next = ap_proxylist;
593 1.1 christos ap_proxylist = ap;
594 1.1 christos if (ap->apr_load != NULL)
595 1.1 christos (*ap->apr_load)();
596 1.1 christos return 0;
597 1.1 christos }
598 1.1 christos
599 1.1 christos
600 1.1 christos /* ------------------------------------------------------------------------ */
601 1.1 christos /* Function: ipf_proxy_ctl */
602 1.3 darrenr /* Returns: int - 0 == success, else error */
603 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
604 1.3 darrenr /* arg(I) - pointer to proxy context */
605 1.3 darrenr /* ctl(I) - pointer to proxy control structure */
606 1.1 christos /* */
607 1.1 christos /* Check to see if the proxy this control request has come through for */
608 1.1 christos /* exists, and if it does and it has a control function then invoke that */
609 1.1 christos /* control function. */
610 1.1 christos /* ------------------------------------------------------------------------ */
611 1.1 christos int
612 1.2 christos ipf_proxy_ctl(ipf_main_softc_t *softc, void *arg, ap_ctl_t *ctl)
613 1.1 christos {
614 1.1 christos ipf_proxy_softc_t *softp = arg;
615 1.1 christos aproxy_t *a;
616 1.1 christos int error;
617 1.1 christos
618 1.1 christos a = ipf_proxy_lookup(arg, ctl->apc_p, ctl->apc_label);
619 1.1 christos if (a == NULL) {
620 1.3 darrenr if (softp->ips_proxy_debug & 0x01)
621 1.1 christos printf("ipf_proxy_ctl: can't find %s/%d\n",
622 1.1 christos ctl->apc_label, ctl->apc_p);
623 1.1 christos IPFERROR(80001);
624 1.1 christos error = ESRCH;
625 1.1 christos } else if (a->apr_ctl == NULL) {
626 1.3 darrenr if (softp->ips_proxy_debug & 0x01)
627 1.1 christos printf("ipf_proxy_ctl: no ctl function for %s/%d\n",
628 1.1 christos ctl->apc_label, ctl->apc_p);
629 1.1 christos IPFERROR(80002);
630 1.1 christos error = ENXIO;
631 1.1 christos } else {
632 1.1 christos error = (*a->apr_ctl)(softc, a->apr_soft, ctl);
633 1.3 darrenr if ((error != 0) && (softp->ips_proxy_debug & 0x02))
634 1.1 christos printf("ipf_proxy_ctl: %s/%d ctl error %d\n",
635 1.1 christos a->apr_label, a->apr_p, error);
636 1.1 christos }
637 1.1 christos return error;
638 1.1 christos }
639 1.1 christos
640 1.1 christos
641 1.1 christos /* ------------------------------------------------------------------------ */
642 1.1 christos /* Function: ipf_proxy_del */
643 1.3 darrenr /* Returns: int - 0 == success, else failure. */
644 1.1 christos /* Parameters: ap(I) - pointer to proxy structure */
645 1.1 christos /* */
646 1.1 christos /* Delete a proxy that has been added dynamically from those available. */
647 1.1 christos /* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 */
648 1.1 christos /* if it cannot be matched. */
649 1.1 christos /* ------------------------------------------------------------------------ */
650 1.1 christos int
651 1.2 christos ipf_proxy_del(aproxy_t *ap)
652 1.1 christos {
653 1.1 christos aproxy_t *a, **app;
654 1.1 christos
655 1.1 christos for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) {
656 1.1 christos if (a == ap) {
657 1.1 christos a->apr_flags |= APR_DELETE;
658 1.1 christos if (ap->apr_ref == 0 && ap->apr_clones == 0) {
659 1.1 christos *app = a->apr_next;
660 1.1 christos return 0;
661 1.1 christos }
662 1.1 christos return 1;
663 1.1 christos }
664 1.1 christos }
665 1.1 christos
666 1.1 christos return -1;
667 1.1 christos }
668 1.1 christos
669 1.1 christos
670 1.1 christos /* ------------------------------------------------------------------------ */
671 1.1 christos /* Function: ipf_proxy_ok */
672 1.3 darrenr /* Returns: int - 1 == good match else not. */
673 1.1 christos /* Parameters: fin(I) - pointer to packet information */
674 1.3 darrenr /* tcp(I) - pointer to TCP/UDP header */
675 1.1 christos /* nat(I) - pointer to current NAT session */
676 1.1 christos /* */
677 1.3 darrenr /* This function extends the NAT matching to ensure that a packet that has */
678 1.3 darrenr /* arrived matches the proxy information attached to the NAT rule. Notably, */
679 1.3 darrenr /* if the proxy is scheduled to be deleted then packets will not match the */
680 1.3 darrenr /* rule even if the rule is still active. */
681 1.1 christos /* ------------------------------------------------------------------------ */
682 1.1 christos int
683 1.3 darrenr ipf_proxy_ok(fr_info_t *fin, tcphdr_t *tcp, ipnat_t *np)
684 1.1 christos {
685 1.3 darrenr aproxy_t *apr = np->in_apr;
686 1.3 darrenr u_short dport = np->in_odport;
687 1.1 christos
688 1.1 christos if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
689 1.1 christos (fin->fin_p != apr->apr_p))
690 1.1 christos return 0;
691 1.1 christos if ((tcp == NULL) && dport)
692 1.1 christos return 0;
693 1.1 christos return 1;
694 1.1 christos }
695 1.1 christos
696 1.1 christos
697 1.1 christos /* ------------------------------------------------------------------------ */
698 1.1 christos /* Function: ipf_proxy_ioctl */
699 1.3 darrenr /* Returns: int - 0 == success, else error */
700 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
701 1.3 darrenr /* data(I) - pointer to ioctl data */
702 1.3 darrenr /* cmd(I) - ioctl command */
703 1.3 darrenr /* mode(I) - mode bits for device */
704 1.3 darrenr /* ctx(I) - pointer to context information */
705 1.1 christos /* */
706 1.1 christos /* ------------------------------------------------------------------------ */
707 1.1 christos int
708 1.2 christos ipf_proxy_ioctl(ipf_main_softc_t *softc, void *data, ioctlcmd_t cmd, int mode,
709 1.2 christos void *ctx)
710 1.1 christos {
711 1.1 christos ap_ctl_t ctl;
712 1.2 christos void *ptr;
713 1.1 christos int error;
714 1.1 christos
715 1.1 christos mode = mode; /* LINT */
716 1.1 christos
717 1.1 christos switch (cmd)
718 1.1 christos {
719 1.1 christos case SIOCPROXY :
720 1.1 christos error = ipf_inobj(softc, data, NULL, &ctl, IPFOBJ_PROXYCTL);
721 1.1 christos if (error != 0) {
722 1.1 christos return error;
723 1.1 christos }
724 1.1 christos ptr = NULL;
725 1.1 christos
726 1.1 christos if (ctl.apc_dsize > 0) {
727 1.2 christos KMALLOCS(ptr, void *, ctl.apc_dsize);
728 1.1 christos if (ptr == NULL) {
729 1.1 christos IPFERROR(80003);
730 1.1 christos error = ENOMEM;
731 1.1 christos } else {
732 1.1 christos error = copyinptr(softc, ctl.apc_data, ptr,
733 1.1 christos ctl.apc_dsize);
734 1.1 christos if (error == 0)
735 1.1 christos ctl.apc_data = ptr;
736 1.1 christos }
737 1.1 christos } else {
738 1.1 christos ctl.apc_data = NULL;
739 1.1 christos error = 0;
740 1.1 christos }
741 1.1 christos
742 1.1 christos if (error == 0)
743 1.3 darrenr error = ipf_proxy_ctl(softc, softc->ipf_proxy_soft,
744 1.3 darrenr &ctl);
745 1.1 christos
746 1.1 christos if ((error != 0) && (ptr != NULL)) {
747 1.1 christos KFREES(ptr, ctl.apc_dsize);
748 1.1 christos }
749 1.1 christos break;
750 1.1 christos
751 1.1 christos default :
752 1.1 christos IPFERROR(80004);
753 1.1 christos error = EINVAL;
754 1.1 christos }
755 1.1 christos return error;
756 1.1 christos }
757 1.1 christos
758 1.1 christos
759 1.1 christos /* ------------------------------------------------------------------------ */
760 1.1 christos /* Function: ipf_proxy_match */
761 1.3 darrenr /* Returns: int - 0 == success, else error */
762 1.1 christos /* Parameters: fin(I) - pointer to packet information */
763 1.1 christos /* nat(I) - pointer to current NAT session */
764 1.1 christos /* */
765 1.1 christos /* If a proxy has a match function, call that to do extended packet */
766 1.3 darrenr /* matching. Whilst other parts of the NAT code are rather lenient when it */
767 1.3 darrenr /* comes to the quality of the packet that it will transform, the proxy */
768 1.3 darrenr /* matching is not because they need to work with data, not just headers. */
769 1.1 christos /* ------------------------------------------------------------------------ */
770 1.1 christos int
771 1.2 christos ipf_proxy_match(fr_info_t *fin, nat_t *nat)
772 1.1 christos {
773 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
774 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
775 1.1 christos aproxy_t *apr;
776 1.1 christos ipnat_t *ipn;
777 1.1 christos int result;
778 1.1 christos
779 1.1 christos ipn = nat->nat_ptr;
780 1.3 darrenr if (softp->ips_proxy_debug & 0x04)
781 1.1 christos printf("ipf_proxy_match(%lx,%lx) aps %lx ptr %lx\n",
782 1.1 christos (u_long)fin, (u_long)nat, (u_long)nat->nat_aps,
783 1.1 christos (u_long)ipn);
784 1.1 christos
785 1.1 christos if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) {
786 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
787 1.1 christos printf("ipf_proxy_match: flx 0x%x (BAD|SHORT)\n",
788 1.1 christos fin->fin_flx);
789 1.1 christos return -1;
790 1.1 christos }
791 1.1 christos
792 1.1 christos apr = ipn->in_apr;
793 1.1 christos if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) {
794 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
795 1.1 christos printf("ipf_proxy_match:apr %lx apr_flags 0x%x\n",
796 1.1 christos (u_long)apr, apr ? apr->apr_flags : 0);
797 1.1 christos return -1;
798 1.1 christos }
799 1.1 christos
800 1.1 christos if (apr->apr_match != NULL) {
801 1.1 christos result = (*apr->apr_match)(fin, nat->nat_aps, nat);
802 1.1 christos if (result != 0) {
803 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
804 1.1 christos printf("ipf_proxy_match: result %d\n", result);
805 1.1 christos return -1;
806 1.1 christos }
807 1.1 christos }
808 1.1 christos return 0;
809 1.1 christos }
810 1.1 christos
811 1.1 christos
812 1.1 christos /* ------------------------------------------------------------------------ */
813 1.1 christos /* Function: ipf_proxy_new */
814 1.3 darrenr /* Returns: int - 0 == success, else error */
815 1.1 christos /* Parameters: fin(I) - pointer to packet information */
816 1.1 christos /* nat(I) - pointer to current NAT session */
817 1.1 christos /* */
818 1.1 christos /* Allocate a new application proxy structure and fill it in with the */
819 1.1 christos /* relevant details. call the init function once complete, prior to */
820 1.1 christos /* returning. */
821 1.1 christos /* ------------------------------------------------------------------------ */
822 1.1 christos int
823 1.2 christos ipf_proxy_new(fr_info_t *fin, nat_t *nat)
824 1.1 christos {
825 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
826 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
827 1.1 christos register ap_session_t *aps;
828 1.1 christos aproxy_t *apr;
829 1.1 christos
830 1.3 darrenr if (softp->ips_proxy_debug & 0x04)
831 1.1 christos printf("ipf_proxy_new(%lx,%lx) \n", (u_long)fin, (u_long)nat);
832 1.1 christos
833 1.1 christos if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) {
834 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
835 1.1 christos printf("ipf_proxy_new: nat_ptr %lx nat_aps %lx\n",
836 1.1 christos (u_long)nat->nat_ptr, (u_long)nat->nat_aps);
837 1.1 christos return -1;
838 1.1 christos }
839 1.1 christos
840 1.1 christos apr = nat->nat_ptr->in_apr;
841 1.1 christos
842 1.1 christos if ((apr->apr_flags & APR_DELETE) ||
843 1.1 christos (fin->fin_p != apr->apr_p)) {
844 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
845 1.1 christos printf("ipf_proxy_new: apr_flags 0x%x p %d/%d\n",
846 1.1 christos apr->apr_flags, fin->fin_p, apr->apr_p);
847 1.1 christos return -1;
848 1.1 christos }
849 1.1 christos
850 1.1 christos KMALLOC(aps, ap_session_t *);
851 1.1 christos if (!aps) {
852 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
853 1.1 christos printf("ipf_proxy_new: malloc failed (%lu)\n",
854 1.1 christos (u_long)sizeof(ap_session_t));
855 1.1 christos return -1;
856 1.1 christos }
857 1.1 christos
858 1.1 christos bzero((char *)aps, sizeof(*aps));
859 1.1 christos aps->aps_data = NULL;
860 1.1 christos aps->aps_apr = apr;
861 1.1 christos aps->aps_psiz = 0;
862 1.1 christos if (apr->apr_new != NULL)
863 1.1 christos if ((*apr->apr_new)(apr->apr_soft, fin, aps, nat) == -1) {
864 1.1 christos if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) {
865 1.1 christos KFREES(aps->aps_data, aps->aps_psiz);
866 1.1 christos }
867 1.1 christos KFREE(aps);
868 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
869 1.1 christos printf("ipf_proxy_new: new(%lx) failed\n",
870 1.1 christos (u_long)apr->apr_new);
871 1.1 christos return -1;
872 1.1 christos }
873 1.1 christos aps->aps_nat = nat;
874 1.1 christos aps->aps_next = softp->ips_sess_list;
875 1.1 christos softp->ips_sess_list = aps;
876 1.1 christos nat->nat_aps = aps;
877 1.1 christos
878 1.1 christos return 0;
879 1.1 christos }
880 1.1 christos
881 1.1 christos
882 1.1 christos /* ------------------------------------------------------------------------ */
883 1.1 christos /* Function: ipf_proxy_check */
884 1.1 christos /* Returns: int - -1 == error, 0 == success */
885 1.1 christos /* Parameters: fin(I) - pointer to packet information */
886 1.1 christos /* nat(I) - pointer to current NAT session */
887 1.1 christos /* */
888 1.1 christos /* Check to see if a packet should be passed through an active proxy */
889 1.1 christos /* routine if one has been setup for it. We don't need to check the */
890 1.1 christos /* checksum here if IPFILTER_CKSUM is defined because if it is, a failed */
891 1.1 christos /* check causes FI_BAD to be set. */
892 1.1 christos /* ------------------------------------------------------------------------ */
893 1.1 christos int
894 1.2 christos ipf_proxy_check(fr_info_t *fin, nat_t *nat)
895 1.1 christos {
896 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
897 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
898 1.3 darrenr #if SOLARIS && defined(_KERNEL) && defined(ICK_VALID)
899 1.1 christos mb_t *m;
900 1.1 christos #endif
901 1.1 christos tcphdr_t *tcp = NULL;
902 1.1 christos udphdr_t *udp = NULL;
903 1.1 christos ap_session_t *aps;
904 1.1 christos aproxy_t *apr;
905 1.3 darrenr short adjlen;
906 1.3 darrenr int dosum;
907 1.1 christos ip_t *ip;
908 1.1 christos short rv;
909 1.1 christos int err;
910 1.1 christos #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
911 1.1 christos u_32_t s1, s2, sd;
912 1.1 christos #endif
913 1.1 christos
914 1.1 christos if (fin->fin_flx & FI_BAD) {
915 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
916 1.3 darrenr printf("ipf_proxy_check: flx 0x%x (BAD)\n",
917 1.3 darrenr fin->fin_flx);
918 1.1 christos return -1;
919 1.1 christos }
920 1.1 christos
921 1.1 christos #ifndef IPFILTER_CKSUM
922 1.1 christos if ((fin->fin_out == 0) && (ipf_checkl4sum(fin) == -1)) {
923 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
924 1.1 christos printf("ipf_proxy_check: l4 checksum failure %d\n",
925 1.1 christos fin->fin_p);
926 1.1 christos if (fin->fin_p == IPPROTO_TCP)
927 1.1 christos softc->ipf_stats[fin->fin_out].fr_tcpbad++;
928 1.1 christos return -1;
929 1.1 christos }
930 1.1 christos #endif
931 1.1 christos
932 1.1 christos aps = nat->nat_aps;
933 1.1 christos if (aps != NULL) {
934 1.1 christos /*
935 1.1 christos * If there is data in this packet to be proxied then try and
936 1.1 christos * get it all into the one buffer, else drop it.
937 1.1 christos */
938 1.1 christos #if defined(MENTAT) || defined(HAVE_M_PULLDOWN)
939 1.1 christos if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE))
940 1.1 christos if (ipf_coalesce(fin) == -1) {
941 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
942 1.3 darrenr printf("ipf_proxy_check: %s %x\n",
943 1.3 darrenr "coalesce failed", fin->fin_flx);
944 1.1 christos return -1;
945 1.1 christos }
946 1.1 christos #endif
947 1.1 christos ip = fin->fin_ip;
948 1.3 darrenr if (fin->fin_cksum > FI_CK_SUMOK)
949 1.3 darrenr dosum = 0;
950 1.3 darrenr else
951 1.3 darrenr dosum = 1;
952 1.1 christos
953 1.1 christos switch (fin->fin_p)
954 1.1 christos {
955 1.1 christos case IPPROTO_TCP :
956 1.1 christos tcp = (tcphdr_t *)fin->fin_dp;
957 1.3 darrenr #if SOLARIS && defined(_KERNEL) && defined(ICK_VALID)
958 1.1 christos m = fin->fin_qfm;
959 1.1 christos if (dohwcksum && (m->b_ick_flag == ICK_VALID))
960 1.1 christos dosum = 0;
961 1.1 christos #endif
962 1.3 darrenr break;
963 1.1 christos case IPPROTO_UDP :
964 1.1 christos udp = (udphdr_t *)fin->fin_dp;
965 1.1 christos break;
966 1.1 christos default :
967 1.1 christos break;
968 1.1 christos }
969 1.1 christos
970 1.1 christos apr = aps->aps_apr;
971 1.1 christos err = 0;
972 1.1 christos if (fin->fin_out != 0) {
973 1.1 christos if (apr->apr_outpkt != NULL)
974 1.3 darrenr err = (*apr->apr_outpkt)(apr->apr_soft, fin,
975 1.3 darrenr aps, nat);
976 1.1 christos } else {
977 1.1 christos if (apr->apr_inpkt != NULL)
978 1.3 darrenr err = (*apr->apr_inpkt)(apr->apr_soft, fin,
979 1.3 darrenr aps, nat);
980 1.1 christos }
981 1.1 christos
982 1.1 christos rv = APR_EXIT(err);
983 1.3 darrenr if (((softp->ips_proxy_debug & 0x08) && (rv != 0)) ||
984 1.3 darrenr (softp->ips_proxy_debug & 0x04))
985 1.1 christos printf("ipf_proxy_check: out %d err %x rv %d\n",
986 1.1 christos fin->fin_out, err, rv);
987 1.1 christos if (rv == 1)
988 1.1 christos return -1;
989 1.1 christos
990 1.1 christos if (rv == 2) {
991 1.3 darrenr ipf_proxy_deref(apr);
992 1.1 christos nat->nat_aps = NULL;
993 1.1 christos return -1;
994 1.1 christos }
995 1.1 christos
996 1.1 christos /*
997 1.1 christos * If err != 0 then the data size of the packet has changed
998 1.1 christos * so we need to recalculate the header checksums for the
999 1.1 christos * packet.
1000 1.1 christos */
1001 1.3 darrenr adjlen = APR_INC(err);
1002 1.1 christos #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
1003 1.3 darrenr s1 = LONG_SUM(fin->fin_plen - adjlen);
1004 1.3 darrenr s2 = LONG_SUM(fin->fin_plen);
1005 1.3 darrenr CALC_SUMD(s1, s2, sd);
1006 1.3 darrenr if ((err != 0) && (fin->fin_cksum < FI_CK_L4PART) &&
1007 1.3 darrenr fin->fin_v == 4)
1008 1.3 darrenr ipf_fix_outcksum(0, &ip->ip_sum, sd, 0);
1009 1.1 christos #endif
1010 1.3 darrenr if (fin->fin_flx & FI_DOCKSUM)
1011 1.3 darrenr dosum = 1;
1012 1.1 christos
1013 1.2 christos #ifdef INET
1014 1.1 christos /*
1015 1.1 christos * For TCP packets, we may need to adjust the sequence and
1016 1.1 christos * acknowledgement numbers to reflect changes in size of the
1017 1.1 christos * data stream.
1018 1.1 christos *
1019 1.1 christos * For both TCP and UDP, recalculate the layer 4 checksum,
1020 1.1 christos * regardless, as we can't tell (here) if data has been
1021 1.1 christos * changed or not.
1022 1.1 christos */
1023 1.1 christos if (tcp != NULL) {
1024 1.3 darrenr err = ipf_proxy_fixseqack(fin, ip, aps, adjlen);
1025 1.3 darrenr if (fin->fin_cksum == FI_CK_L4PART) {
1026 1.3 darrenr u_short sum = ntohs(tcp->th_sum);
1027 1.3 darrenr sum += adjlen;
1028 1.3 darrenr tcp->th_sum = htons(sum);
1029 1.3 darrenr } else if (fin->fin_cksum < FI_CK_L4PART) {
1030 1.1 christos tcp->th_sum = fr_cksum(fin, ip,
1031 1.1 christos IPPROTO_TCP, tcp);
1032 1.3 darrenr }
1033 1.1 christos } else if ((udp != NULL) && (udp->uh_sum != 0)) {
1034 1.3 darrenr if (fin->fin_cksum == FI_CK_L4PART) {
1035 1.3 darrenr u_short sum = ntohs(udp->uh_sum);
1036 1.3 darrenr sum += adjlen;
1037 1.3 darrenr udp->uh_sum = htons(sum);
1038 1.3 darrenr } else if (dosum) {
1039 1.1 christos udp->uh_sum = fr_cksum(fin, ip,
1040 1.1 christos IPPROTO_UDP, udp);
1041 1.3 darrenr }
1042 1.1 christos }
1043 1.2 christos #endif
1044 1.1 christos aps->aps_bytes += fin->fin_plen;
1045 1.1 christos aps->aps_pkts++;
1046 1.1 christos return 1;
1047 1.1 christos }
1048 1.1 christos return 0;
1049 1.1 christos }
1050 1.1 christos
1051 1.1 christos
1052 1.1 christos /* ------------------------------------------------------------------------ */
1053 1.1 christos /* Function: ipf_proxy_lookup */
1054 1.1 christos /* Returns: int - -1 == error, 0 == success */
1055 1.3 darrenr /* Parameters: arg(I) - pointer to proxy context information */
1056 1.3 darrenr /* pr(I) - protocol number for proxy */
1057 1.3 darrenr /* name(I) - proxy name */
1058 1.1 christos /* */
1059 1.1 christos /* Search for an proxy by the protocol it is being used with and its name. */
1060 1.1 christos /* ------------------------------------------------------------------------ */
1061 1.1 christos aproxy_t *
1062 1.2 christos ipf_proxy_lookup(void *arg, u_int pr, char *name)
1063 1.1 christos {
1064 1.1 christos ipf_proxy_softc_t *softp = arg;
1065 1.1 christos aproxy_t *ap;
1066 1.1 christos
1067 1.3 darrenr if (softp->ips_proxy_debug & 0x04)
1068 1.1 christos printf("ipf_proxy_lookup(%d,%s)\n", pr, name);
1069 1.1 christos
1070 1.1 christos for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next)
1071 1.1 christos if ((ap->apr_p == pr) &&
1072 1.1 christos !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
1073 1.1 christos ap->apr_ref++;
1074 1.1 christos return ap;
1075 1.1 christos }
1076 1.1 christos
1077 1.3 darrenr if (softp->ips_proxy_debug & 0x08)
1078 1.1 christos printf("ipf_proxy_lookup: failed for %d/%s\n", pr, name);
1079 1.1 christos return NULL;
1080 1.1 christos }
1081 1.1 christos
1082 1.1 christos
1083 1.1 christos /* ------------------------------------------------------------------------ */
1084 1.3 darrenr /* Function: ipf_proxy_deref */
1085 1.1 christos /* Returns: Nil */
1086 1.1 christos /* Parameters: ap(I) - pointer to proxy structure */
1087 1.1 christos /* */
1088 1.3 darrenr /* Drop the reference counter associated with the proxy. */
1089 1.1 christos /* ------------------------------------------------------------------------ */
1090 1.1 christos void
1091 1.3 darrenr ipf_proxy_deref(aproxy_t *ap)
1092 1.1 christos {
1093 1.1 christos ap->apr_ref--;
1094 1.1 christos }
1095 1.1 christos
1096 1.1 christos
1097 1.1 christos /* ------------------------------------------------------------------------ */
1098 1.3 darrenr /* Function: ipf_proxy_free */
1099 1.1 christos /* Returns: Nil */
1100 1.3 darrenr /* Parameters: softc(I) - pointer to soft context main structure */
1101 1.3 darrenr /* aps(I) - pointer to current proxy session */
1102 1.3 darrenr /* Locks Held: ipf_nat_new, ipf_nat(W) */
1103 1.1 christos /* */
1104 1.3 darrenr /* Free up proxy session information allocated to be used with a NAT */
1105 1.3 darrenr /* session. */
1106 1.1 christos /* ------------------------------------------------------------------------ */
1107 1.1 christos void
1108 1.3 darrenr ipf_proxy_free(ipf_main_softc_t *softc, ap_session_t *aps)
1109 1.1 christos {
1110 1.3 darrenr ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
1111 1.1 christos ap_session_t *a, **ap;
1112 1.1 christos aproxy_t *apr;
1113 1.1 christos
1114 1.1 christos if (!aps)
1115 1.1 christos return;
1116 1.1 christos
1117 1.1 christos for (ap = &softp->ips_sess_list; ((a = *ap) != NULL); ap = &a->aps_next)
1118 1.1 christos if (a == aps) {
1119 1.1 christos *ap = a->aps_next;
1120 1.1 christos break;
1121 1.1 christos }
1122 1.1 christos
1123 1.1 christos apr = aps->aps_apr;
1124 1.1 christos if ((apr != NULL) && (apr->apr_del != NULL))
1125 1.1 christos (*apr->apr_del)(softc, aps);
1126 1.1 christos
1127 1.1 christos if ((aps->aps_data != NULL) && (aps->aps_psiz != 0))
1128 1.1 christos KFREES(aps->aps_data, aps->aps_psiz);
1129 1.1 christos KFREE(aps);
1130 1.1 christos }
1131 1.1 christos
1132 1.1 christos
1133 1.1 christos /* ------------------------------------------------------------------------ */
1134 1.1 christos /* Function: ipf_proxy_fixseqack */
1135 1.3 darrenr /* Returns: int - 2 if TCP ack/seq is changed, else 0 */
1136 1.1 christos /* Parameters: fin(I) - pointer to packet information */
1137 1.3 darrenr /* ip(I) - pointer to IP header */
1138 1.1 christos /* nat(I) - pointer to current NAT session */
1139 1.3 darrenr /* inc(I) - delta to apply to TCP sequence numbering */
1140 1.1 christos /* */
1141 1.3 darrenr /* Adjust the TCP sequence/acknowledge numbers in the TCP header based on */
1142 1.3 darrenr /* whether or not the new header is past the point at which an adjustment */
1143 1.3 darrenr /* occurred. This might happen because of (say) an FTP string being changed */
1144 1.3 darrenr /* and the new string being a different length to the old. */
1145 1.1 christos /* ------------------------------------------------------------------------ */
1146 1.1 christos static int
1147 1.2 christos ipf_proxy_fixseqack(fr_info_t *fin, ip_t *ip, ap_session_t *aps, int inc)
1148 1.1 christos {
1149 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
1150 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
1151 1.1 christos int sel, ch = 0, out, nlen;
1152 1.1 christos u_32_t seq1, seq2;
1153 1.1 christos tcphdr_t *tcp;
1154 1.1 christos short inc2;
1155 1.1 christos
1156 1.1 christos tcp = (tcphdr_t *)fin->fin_dp;
1157 1.1 christos out = fin->fin_out;
1158 1.1 christos /*
1159 1.1 christos * ip_len has already been adjusted by 'inc'.
1160 1.1 christos */
1161 1.3 darrenr nlen = fin->fin_dlen;
1162 1.3 darrenr nlen -= (TCP_OFF(tcp) << 2);
1163 1.1 christos
1164 1.1 christos inc2 = inc;
1165 1.1 christos inc = (int)inc2;
1166 1.1 christos
1167 1.1 christos if (out != 0) {
1168 1.1 christos seq1 = (u_32_t)ntohl(tcp->th_seq);
1169 1.1 christos sel = aps->aps_sel[out];
1170 1.1 christos
1171 1.1 christos /* switch to other set ? */
1172 1.1 christos if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
1173 1.1 christos (seq1 > aps->aps_seqmin[!sel])) {
1174 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1175 1.1 christos printf("proxy out switch set seq %d -> %d %x > %x\n",
1176 1.1 christos sel, !sel, seq1,
1177 1.1 christos aps->aps_seqmin[!sel]);
1178 1.1 christos sel = aps->aps_sel[out] = !sel;
1179 1.1 christos }
1180 1.1 christos
1181 1.1 christos if (aps->aps_seqoff[sel]) {
1182 1.1 christos seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel];
1183 1.1 christos if (seq1 > seq2) {
1184 1.1 christos seq2 = aps->aps_seqoff[sel];
1185 1.1 christos seq1 += seq2;
1186 1.1 christos tcp->th_seq = htonl(seq1);
1187 1.1 christos ch = 1;
1188 1.1 christos }
1189 1.1 christos }
1190 1.1 christos
1191 1.1 christos if (inc && (seq1 > aps->aps_seqmin[!sel])) {
1192 1.1 christos aps->aps_seqmin[sel] = seq1 + nlen - 1;
1193 1.1 christos aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc;
1194 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1195 1.1 christos printf("proxy seq set %d at %x to %d + %d\n",
1196 1.1 christos sel, aps->aps_seqmin[sel],
1197 1.1 christos aps->aps_seqoff[sel], inc);
1198 1.1 christos }
1199 1.1 christos
1200 1.1 christos /***/
1201 1.1 christos
1202 1.1 christos seq1 = ntohl(tcp->th_ack);
1203 1.1 christos sel = aps->aps_sel[1 - out];
1204 1.1 christos
1205 1.1 christos /* switch to other set ? */
1206 1.1 christos if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
1207 1.1 christos (seq1 > aps->aps_ackmin[!sel])) {
1208 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1209 1.1 christos printf("proxy out switch set ack %d -> %d %x > %x\n",
1210 1.1 christos sel, !sel, seq1,
1211 1.1 christos aps->aps_ackmin[!sel]);
1212 1.1 christos sel = aps->aps_sel[1 - out] = !sel;
1213 1.1 christos }
1214 1.1 christos
1215 1.1 christos if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) {
1216 1.1 christos seq2 = aps->aps_ackoff[sel];
1217 1.1 christos tcp->th_ack = htonl(seq1 - seq2);
1218 1.1 christos ch = 1;
1219 1.1 christos }
1220 1.1 christos } else {
1221 1.1 christos seq1 = ntohl(tcp->th_seq);
1222 1.1 christos sel = aps->aps_sel[out];
1223 1.1 christos
1224 1.1 christos /* switch to other set ? */
1225 1.1 christos if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
1226 1.1 christos (seq1 > aps->aps_ackmin[!sel])) {
1227 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1228 1.1 christos printf("proxy in switch set ack %d -> %d %x > %x\n",
1229 1.1 christos sel, !sel, seq1, aps->aps_ackmin[!sel]);
1230 1.1 christos sel = aps->aps_sel[out] = !sel;
1231 1.1 christos }
1232 1.1 christos
1233 1.1 christos if (aps->aps_ackoff[sel]) {
1234 1.1 christos seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel];
1235 1.1 christos if (seq1 > seq2) {
1236 1.1 christos seq2 = aps->aps_ackoff[sel];
1237 1.1 christos seq1 += seq2;
1238 1.1 christos tcp->th_seq = htonl(seq1);
1239 1.1 christos ch = 1;
1240 1.1 christos }
1241 1.1 christos }
1242 1.1 christos
1243 1.1 christos if (inc && (seq1 > aps->aps_ackmin[!sel])) {
1244 1.1 christos aps->aps_ackmin[!sel] = seq1 + nlen - 1;
1245 1.1 christos aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc;
1246 1.1 christos
1247 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1248 1.1 christos printf("proxy ack set %d at %x to %d + %d\n",
1249 1.1 christos !sel, aps->aps_seqmin[!sel],
1250 1.1 christos aps->aps_seqoff[sel], inc);
1251 1.1 christos }
1252 1.1 christos
1253 1.1 christos /***/
1254 1.1 christos
1255 1.1 christos seq1 = ntohl(tcp->th_ack);
1256 1.1 christos sel = aps->aps_sel[1 - out];
1257 1.1 christos
1258 1.1 christos /* switch to other set ? */
1259 1.1 christos if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
1260 1.1 christos (seq1 > aps->aps_seqmin[!sel])) {
1261 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1262 1.1 christos printf("proxy in switch set seq %d -> %d %x > %x\n",
1263 1.1 christos sel, !sel, seq1, aps->aps_seqmin[!sel]);
1264 1.1 christos sel = aps->aps_sel[1 - out] = !sel;
1265 1.1 christos }
1266 1.1 christos
1267 1.1 christos if (aps->aps_seqoff[sel] != 0) {
1268 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1269 1.1 christos printf("sel %d seqoff %d seq1 %x seqmin %x\n",
1270 1.1 christos sel, aps->aps_seqoff[sel], seq1,
1271 1.1 christos aps->aps_seqmin[sel]);
1272 1.1 christos if (seq1 > aps->aps_seqmin[sel]) {
1273 1.1 christos seq2 = aps->aps_seqoff[sel];
1274 1.1 christos tcp->th_ack = htonl(seq1 - seq2);
1275 1.1 christos ch = 1;
1276 1.1 christos }
1277 1.1 christos }
1278 1.1 christos }
1279 1.1 christos
1280 1.3 darrenr if (softp->ips_proxy_debug & 0x10)
1281 1.3 darrenr printf("ipf_proxy_fixseqack: seq %u ack %u\n",
1282 1.1 christos (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack));
1283 1.1 christos return ch ? 2 : 0;
1284 1.1 christos }
1285 1.3 darrenr
1286 1.3 darrenr
1287 1.3 darrenr /* ------------------------------------------------------------------------ */
1288 1.3 darrenr /* Function: ipf_proxy_rule_rev */
1289 1.3 darrenr /* Returns: ipnat_t * - NULL = failure, else pointer to new rule */
1290 1.3 darrenr /* Parameters: nat(I) - pointer to NAT session to create rule from */
1291 1.3 darrenr /* */
1292 1.3 darrenr /* This function creates a NAT rule that is based upon the reverse packet */
1293 1.3 darrenr /* flow associated with this NAT session. Thus if this NAT session was */
1294 1.3 darrenr /* created with a map rule then this function will create a rdr rule. */
1295 1.3 darrenr /* Only address fields and network interfaces are assigned in this function */
1296 1.3 darrenr /* and the address fields are formed such that an exact is required. If the */
1297 1.3 darrenr /* original rule had a netmask, that is not replicated here not is it */
1298 1.3 darrenr /* desired. The ultimate goal here is to create a NAT rule to support a NAT */
1299 1.3 darrenr /* session being created that does not have a user configured rule. The */
1300 1.3 darrenr /* classic example is supporting the FTP proxy, where a data channel needs */
1301 1.3 darrenr /* to be setup, based on the addresses used for the control connection. In */
1302 1.3 darrenr /* that case, this function is used to handle creating NAT rules to support */
1303 1.3 darrenr /* data connections with the PORT and EPRT commands. */
1304 1.3 darrenr /* ------------------------------------------------------------------------ */
1305 1.3 darrenr ipnat_t *
1306 1.5 darrenr ipf_proxy_rule_rev(nat_t *nat)
1307 1.3 darrenr {
1308 1.3 darrenr ipnat_t *old;
1309 1.3 darrenr ipnat_t *ipn;
1310 1.3 darrenr int size;
1311 1.3 darrenr
1312 1.3 darrenr old = nat->nat_ptr;
1313 1.3 darrenr size = old->in_size;
1314 1.3 darrenr
1315 1.3 darrenr KMALLOCS(ipn, ipnat_t *, size);
1316 1.3 darrenr if (ipn == NULL)
1317 1.3 darrenr return NULL;
1318 1.3 darrenr
1319 1.3 darrenr bzero((char *)ipn, size);
1320 1.3 darrenr
1321 1.3 darrenr ipn->in_use = 1;
1322 1.3 darrenr ipn->in_hits = 1;
1323 1.3 darrenr ipn->in_ippip = 1;
1324 1.3 darrenr ipn->in_apr = NULL;
1325 1.3 darrenr ipn->in_size = size;
1326 1.3 darrenr ipn->in_pr[0] = old->in_pr[1];
1327 1.3 darrenr ipn->in_pr[1] = old->in_pr[0];
1328 1.3 darrenr ipn->in_v[0] = old->in_v[1];
1329 1.3 darrenr ipn->in_v[1] = old->in_v[0];
1330 1.3 darrenr ipn->in_ifps[0] = old->in_ifps[1];
1331 1.3 darrenr ipn->in_ifps[1] = old->in_ifps[0];
1332 1.3 darrenr ipn->in_flags = (old->in_flags | IPN_PROXYRULE);
1333 1.3 darrenr
1334 1.3 darrenr ipn->in_nsrcip6 = nat->nat_odst6;
1335 1.3 darrenr ipn->in_osrcip6 = nat->nat_ndst6;
1336 1.3 darrenr
1337 1.3 darrenr if ((old->in_redir & NAT_REDIRECT) != 0) {
1338 1.3 darrenr ipn->in_redir = NAT_MAP;
1339 1.3 darrenr if (ipn->in_v[0] == 4) {
1340 1.3 darrenr ipn->in_snip = ntohl(nat->nat_odstaddr);
1341 1.3 darrenr ipn->in_dnip = ntohl(nat->nat_nsrcaddr);
1342 1.3 darrenr } else {
1343 1.3 darrenr #ifdef USE_INET6
1344 1.3 darrenr ipn->in_snip6 = nat->nat_odst6;
1345 1.3 darrenr ipn->in_dnip6 = nat->nat_nsrc6;
1346 1.3 darrenr #endif
1347 1.3 darrenr }
1348 1.3 darrenr ipn->in_ndstip6 = nat->nat_nsrc6;
1349 1.3 darrenr ipn->in_odstip6 = nat->nat_osrc6;
1350 1.3 darrenr } else {
1351 1.3 darrenr ipn->in_redir = NAT_REDIRECT;
1352 1.3 darrenr if (ipn->in_v[0] == 4) {
1353 1.3 darrenr ipn->in_snip = ntohl(nat->nat_odstaddr);
1354 1.3 darrenr ipn->in_dnip = ntohl(nat->nat_osrcaddr);
1355 1.3 darrenr } else {
1356 1.3 darrenr #ifdef USE_INET6
1357 1.3 darrenr ipn->in_snip6 = nat->nat_odst6;
1358 1.3 darrenr ipn->in_dnip6 = nat->nat_osrc6;
1359 1.3 darrenr #endif
1360 1.3 darrenr }
1361 1.3 darrenr ipn->in_ndstip6 = nat->nat_osrc6;
1362 1.3 darrenr ipn->in_odstip6 = nat->nat_nsrc6;
1363 1.3 darrenr }
1364 1.3 darrenr
1365 1.3 darrenr IP6_SETONES(&ipn->in_osrcmsk6);
1366 1.3 darrenr IP6_SETONES(&ipn->in_nsrcmsk6);
1367 1.3 darrenr IP6_SETONES(&ipn->in_odstmsk6);
1368 1.3 darrenr IP6_SETONES(&ipn->in_ndstmsk6);
1369 1.3 darrenr
1370 1.3 darrenr ipn->in_namelen = old->in_namelen;
1371 1.3 darrenr ipn->in_ifnames[0] = old->in_ifnames[1];
1372 1.3 darrenr ipn->in_ifnames[1] = old->in_ifnames[0];
1373 1.3 darrenr bcopy(old->in_names, ipn->in_names, ipn->in_namelen);
1374 1.3 darrenr MUTEX_INIT(&ipn->in_lock, "ipnat rev rule lock");
1375 1.3 darrenr
1376 1.3 darrenr return ipn;
1377 1.3 darrenr }
1378 1.3 darrenr
1379 1.3 darrenr
1380 1.3 darrenr /* ------------------------------------------------------------------------ */
1381 1.3 darrenr /* Function: ipf_proxy_rule_fwd */
1382 1.3 darrenr /* Returns: ipnat_t * - NULL = failure, else pointer to new rule */
1383 1.3 darrenr /* Parameters: nat(I) - pointer to NAT session to create rule from */
1384 1.3 darrenr /* */
1385 1.3 darrenr /* The purpose and rationale of this function is much the same as the above */
1386 1.3 darrenr /* function, ipf_proxy_rule_rev, except that a rule is created that matches */
1387 1.3 darrenr /* the same direction as that of the existing NAT session. Thus if this NAT */
1388 1.3 darrenr /* session was created with a map rule then this function will also create */
1389 1.3 darrenr /* a data structure to represent a map rule. Whereas ipf_proxy_rule_rev is */
1390 1.3 darrenr /* used to support PORT/EPRT, this function supports PASV/EPSV. */
1391 1.3 darrenr /* ------------------------------------------------------------------------ */
1392 1.3 darrenr ipnat_t *
1393 1.5 darrenr ipf_proxy_rule_fwd(nat_t *nat)
1394 1.3 darrenr {
1395 1.3 darrenr ipnat_t *old;
1396 1.3 darrenr ipnat_t *ipn;
1397 1.3 darrenr int size;
1398 1.3 darrenr
1399 1.3 darrenr old = nat->nat_ptr;
1400 1.3 darrenr size = old->in_size;
1401 1.3 darrenr
1402 1.3 darrenr KMALLOCS(ipn, ipnat_t *, size);
1403 1.3 darrenr if (ipn == NULL)
1404 1.3 darrenr return NULL;
1405 1.3 darrenr
1406 1.3 darrenr bzero((char *)ipn, size);
1407 1.3 darrenr
1408 1.3 darrenr ipn->in_use = 1;
1409 1.3 darrenr ipn->in_hits = 1;
1410 1.3 darrenr ipn->in_ippip = 1;
1411 1.3 darrenr ipn->in_apr = NULL;
1412 1.3 darrenr ipn->in_size = size;
1413 1.3 darrenr ipn->in_pr[0] = old->in_pr[0];
1414 1.3 darrenr ipn->in_pr[1] = old->in_pr[1];
1415 1.3 darrenr ipn->in_v[0] = old->in_v[0];
1416 1.3 darrenr ipn->in_v[1] = old->in_v[1];
1417 1.3 darrenr ipn->in_ifps[0] = nat->nat_ifps[0];
1418 1.3 darrenr ipn->in_ifps[1] = nat->nat_ifps[1];
1419 1.3 darrenr ipn->in_flags = (old->in_flags | IPN_PROXYRULE);
1420 1.3 darrenr
1421 1.3 darrenr ipn->in_nsrcip6 = nat->nat_nsrc6;
1422 1.3 darrenr ipn->in_osrcip6 = nat->nat_osrc6;
1423 1.3 darrenr ipn->in_ndstip6 = nat->nat_ndst6;
1424 1.3 darrenr ipn->in_odstip6 = nat->nat_odst6;
1425 1.3 darrenr ipn->in_redir = old->in_redir;
1426 1.3 darrenr
1427 1.3 darrenr if (ipn->in_v[0] == 4) {
1428 1.3 darrenr ipn->in_snip = ntohl(nat->nat_nsrcaddr);
1429 1.3 darrenr ipn->in_dnip = ntohl(nat->nat_ndstaddr);
1430 1.3 darrenr } else {
1431 1.3 darrenr #ifdef USE_INET6
1432 1.3 darrenr ipn->in_snip6 = nat->nat_nsrc6;
1433 1.3 darrenr ipn->in_dnip6 = nat->nat_ndst6;
1434 1.3 darrenr #endif
1435 1.3 darrenr }
1436 1.3 darrenr
1437 1.3 darrenr IP6_SETONES(&ipn->in_osrcmsk6);
1438 1.3 darrenr IP6_SETONES(&ipn->in_nsrcmsk6);
1439 1.3 darrenr IP6_SETONES(&ipn->in_odstmsk6);
1440 1.3 darrenr IP6_SETONES(&ipn->in_ndstmsk6);
1441 1.3 darrenr
1442 1.3 darrenr ipn->in_namelen = old->in_namelen;
1443 1.3 darrenr ipn->in_ifnames[0] = old->in_ifnames[0];
1444 1.3 darrenr ipn->in_ifnames[1] = old->in_ifnames[1];
1445 1.3 darrenr bcopy(old->in_names, ipn->in_names, ipn->in_namelen);
1446 1.3 darrenr MUTEX_INIT(&ipn->in_lock, "ipnat fwd rule lock");
1447 1.3 darrenr
1448 1.3 darrenr return ipn;
1449 1.3 darrenr }
1450