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