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