ip_proxy.c revision 1.2 1 1.2 christos /* $NetBSD: ip_proxy.c,v 1.2 2012/03/23 20:39:50 christos 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.2 christos __KERNEL_RCSID(0, "$NetBSD: ip_proxy.c,v 1.2 2012/03/23 20:39:50 christos Exp $");
109 1.2 christos #else
110 1.2 christos static const char rcsid[] = "@(#)Id: ip_proxy.c,v 2.102.2.7 2012/01/29 05:30:36 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.1 christos "ips_proxy_debug", 0, 10,
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.1 christos { NULL, NULL, "tftp", (char)IPPROTO_TCP, 0, 0, 0,
151 1.1 christos ipf_p_tftp_main_load, ipf_p_tftp_main_unload,
152 1.1 christos NULL, NULL,
153 1.1 christos NULL, NULL,
154 1.1 christos ipf_p_tftp_new, NULL, ipf_p_tftp_in, ipf_p_tftp_out, NULL,
155 1.1 christos NULL, NULL, NULL, NULL },
156 1.1 christos #endif
157 1.1 christos #ifdef IPF_IRC_PROXY
158 1.1 christos { NULL, NULL, "irc", (char)IPPROTO_TCP, 0, 0, 0,
159 1.1 christos ipf_p_irc_main_load, ipf_p_irc_main_unload,
160 1.1 christos NULL, NULL,
161 1.1 christos NULL, NULL,
162 1.1 christos ipf_p_irc_new, NULL, NULL, ipf_p_irc_out, NULL,
163 1.1 christos NULL, NULL, NULL, NULL },
164 1.1 christos #endif
165 1.1 christos #ifdef IPF_RCMD_PROXY
166 1.1 christos { NULL, NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, 0,
167 1.1 christos ipf_p_rcmd_main_load, ipf_p_rcmd_main_unload,
168 1.1 christos NULL, NULL,
169 1.1 christos NULL, NULL,
170 1.1 christos ipf_p_rcmd_new, ipf_p_rcmd_del,
171 1.1 christos ipf_p_rcmd_in, ipf_p_rcmd_out, NULL,
172 1.1 christos NULL, NULL, NULL, NULL },
173 1.1 christos #endif
174 1.1 christos #ifdef IPF_RAUDIO_PROXY
175 1.1 christos { NULL, NULL, "raudio", (char)IPPROTO_TCP, 0, 0, 0,
176 1.1 christos ipf_p_raudio_main_load, ipf_p_raudio_main_unload,
177 1.1 christos NULL, NULL,
178 1.1 christos NULL, NULL,
179 1.1 christos ipf_p_raudio_new, NULL, ipf_p_raudio_in, ipf_p_raudio_out, NULL,
180 1.1 christos NULL, NULL, NULL, NULL },
181 1.1 christos #endif
182 1.1 christos #ifdef IPF_MSNRPC_PROXY
183 1.1 christos { NULL, NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, 0,
184 1.1 christos ipf_p_msnrpc_init, ipf_p_msnrpc_fini,
185 1.1 christos NULL, NULL,
186 1.1 christos NULL, NULL,
187 1.1 christos ipf_p_msnrpc_new, NULL, ipf_p_msnrpc_in, ipf_p_msnrpc_out, NULL,
188 1.1 christos NULL, NULL, NULL, NULL },
189 1.1 christos #endif
190 1.1 christos #ifdef IPF_NETBIOS_PROXY
191 1.1 christos { NULL, NULL, "netbios", (char)IPPROTO_UDP, 0, 0, 0,
192 1.1 christos ipf_p_netbios_main_load, ipf_p_netbios_main_unload,
193 1.1 christos NULL, NULL,
194 1.1 christos NULL, NULL,
195 1.1 christos NULL, NULL, NULL, ipf_p_netbios_out, NULL,
196 1.1 christos NULL, NULL, NULL, NULL },
197 1.1 christos #endif
198 1.1 christos #ifdef IPF_IPSEC_PROXY
199 1.1 christos { NULL, NULL, "ipsec", (char)IPPROTO_UDP, 0, 0, 0,
200 1.1 christos NULL, NULL,
201 1.1 christos ipf_p_ipsec_soft_create, ipf_p_ipsec_soft_destroy,
202 1.1 christos ipf_p_ipsec_soft_init, ipf_p_ipsec_soft_fini,
203 1.1 christos ipf_p_ipsec_new, ipf_p_ipsec_del,
204 1.1 christos ipf_p_ipsec_inout, ipf_p_ipsec_inout, ipf_p_ipsec_match,
205 1.1 christos NULL, NULL, NULL, NULL },
206 1.1 christos #endif
207 1.1 christos #ifdef IPF_DNS_PROXY
208 1.1 christos { NULL, NULL, "dns", (char)IPPROTO_UDP, 0, 0, 0,
209 1.1 christos NULL, NULL,
210 1.1 christos ipf_p_dns_soft_create, ipf_p_dns_soft_destroy,
211 1.1 christos NULL, NULL,
212 1.1 christos ipf_p_dns_new, ipf_p_ipsec_del,
213 1.1 christos ipf_p_dns_inout, ipf_p_dns_inout, ipf_p_dns_match,
214 1.1 christos ipf_p_dns_ctl, NULL, NULL, NULL },
215 1.1 christos #endif
216 1.1 christos #ifdef IPF_PPTP_PROXY
217 1.1 christos { NULL, NULL, "pptp", (char)IPPROTO_TCP, 0, 0, 0,
218 1.1 christos ipf_p_pptp_main_load, ipf_p_pptp_main_unload,
219 1.1 christos NULL, NULL,
220 1.1 christos NULL, NULL,
221 1.1 christos ipf_p_pptp_new, ipf_p_pptp_del,
222 1.1 christos ipf_p_pptp_inout, ipf_p_pptp_inout, NULL,
223 1.1 christos NULL, NULL, NULL, NULL },
224 1.1 christos #endif
225 1.2 christos #ifdef IPF_H323_PROXY
226 1.2 christos { NULL, NULL, "h323", (char)IPPROTO_TCP, 0, 0, 0,
227 1.2 christos ipf_p_h323_main_load, ipf_p_h323_main_unload,
228 1.2 christos NULL, NULL,
229 1.2 christos NULL, NULL,
230 1.2 christos ipf_p_h323_new, ipf_p_h323_del,
231 1.2 christos ipf_p_h323_in, NULL, NULL,
232 1.2 christos NULL, NULL, NULL, NULL },
233 1.2 christos { NULL, NULL, "h245", (char)IPPROTO_TCP, 0, 0, 0, NULL, NULL,
234 1.2 christos NULL, NULL,
235 1.2 christos NULL, NULL,
236 1.2 christos ipf_p_h245_new, NULL,
237 1.2 christos NULL, ipf_p_h245_out, NULL,
238 1.2 christos NULL, NULL, NULL, NULL },
239 1.2 christos #endif
240 1.1 christos #ifdef IPF_RPCB_PROXY
241 1.1 christos # ifndef _KERNEL
242 1.1 christos { NULL, NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0, 0,
243 1.1 christos NULL, NULL,
244 1.1 christos NULL, NULL,
245 1.1 christos NULL, NULL,
246 1.1 christos ipf_p_rpcb_new, ipf_p_rpcb_del,
247 1.1 christos ipf_p_rpcb_in, ipf_p_rpcb_out, NULL,
248 1.1 christos NULL, NULL, NULL, NULL },
249 1.1 christos # endif
250 1.1 christos { NULL, NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0, 0,
251 1.1 christos ipf_p_rpcb_main_load, ipf_p_rpcb_main_unload,
252 1.1 christos NULL, NULL,
253 1.1 christos NULL, NULL,
254 1.1 christos ipf_p_rpcb_new, ipf_p_rpcb_del,
255 1.1 christos ipf_p_rpcb_in, ipf_p_rpcb_out, NULL,
256 1.1 christos NULL, NULL, NULL, NULL },
257 1.1 christos #endif
258 1.1 christos { NULL, NULL, "", '\0', 0, 0, 0,
259 1.1 christos NULL, NULL,
260 1.1 christos NULL, NULL,
261 1.1 christos NULL, NULL,
262 1.1 christos NULL, NULL,
263 1.1 christos NULL, NULL, NULL,
264 1.1 christos NULL, NULL, NULL, NULL }
265 1.1 christos };
266 1.1 christos
267 1.1 christos
268 1.1 christos /* ------------------------------------------------------------------------ */
269 1.1 christos /* Function: ipf_proxy_init */
270 1.1 christos /* Returns: int - -1 == error, 0 == success */
271 1.1 christos /* Parameters: fin(I) - pointer to packet information */
272 1.1 christos /* nat(I) - pointer to current NAT session */
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.1 christos /* Function: ipf_proxy_unload */
292 1.1 christos /* Returns: Nil */
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.1 christos void *
315 1.2 christos ipf_proxy_soft_create(ipf_main_softc_t *softc)
316 1.1 christos {
317 1.1 christos ipf_proxy_softc_t *softp;
318 1.1 christos aproxy_t *last;
319 1.1 christos aproxy_t *apn;
320 1.1 christos aproxy_t *ap;
321 1.1 christos
322 1.1 christos KMALLOC(softp, ipf_proxy_softc_t *);
323 1.1 christos if (softp == NULL)
324 1.1 christos return softp;
325 1.1 christos
326 1.1 christos bzero((char *)softp, sizeof(*softp));
327 1.1 christos
328 1.1 christos #if defined(_KERNEL)
329 1.1 christos softp->ips_proxy_debug = 0;
330 1.1 christos #else
331 1.1 christos softp->ips_proxy_debug = 2;
332 1.1 christos #endif
333 1.1 christos softp->ips_proxy_session_size = AP_SESS_SIZE;
334 1.1 christos
335 1.1 christos softp->ipf_proxy_tune = ipf_tune_array_copy(softp,
336 1.1 christos sizeof(ipf_proxy_tuneables),
337 1.1 christos ipf_proxy_tuneables);
338 1.1 christos if (softp->ipf_proxy_tune == NULL) {
339 1.1 christos ipf_proxy_soft_destroy(softc, softp);
340 1.1 christos return NULL;
341 1.1 christos }
342 1.1 christos if (ipf_tune_array_link(softc, softp->ipf_proxy_tune) == -1) {
343 1.1 christos ipf_proxy_soft_destroy(softc, softp);
344 1.1 christos return NULL;
345 1.1 christos }
346 1.1 christos
347 1.1 christos last = NULL;
348 1.1 christos for (ap = ips_proxies; ap->apr_p; ap++) {
349 1.1 christos apn = ipf_proxy_create_clone(softc, ap);
350 1.1 christos if (apn == NULL)
351 1.1 christos goto failed;
352 1.1 christos if (last != NULL)
353 1.1 christos last->apr_next = apn;
354 1.1 christos else
355 1.1 christos softp->ips_proxies = apn;
356 1.1 christos last = apn;
357 1.1 christos }
358 1.1 christos for (ap = ips_proxies; ap != NULL; ap = ap->apr_next) {
359 1.1 christos apn = ipf_proxy_create_clone(softc, ap);
360 1.1 christos if (apn == NULL)
361 1.1 christos goto failed;
362 1.1 christos if (last != NULL)
363 1.1 christos last->apr_next = apn;
364 1.1 christos else
365 1.1 christos softp->ips_proxies = apn;
366 1.1 christos last = apn;
367 1.1 christos }
368 1.1 christos
369 1.1 christos return softp;
370 1.1 christos failed:
371 1.1 christos ipf_proxy_soft_destroy(softc, softp);
372 1.1 christos return NULL;
373 1.1 christos }
374 1.1 christos
375 1.1 christos
376 1.1 christos static aproxy_t *
377 1.2 christos ipf_proxy_create_clone(ipf_main_softc_t *softc, aproxy_t *orig)
378 1.1 christos {
379 1.1 christos aproxy_t *apn;
380 1.1 christos
381 1.1 christos KMALLOC(apn, aproxy_t *);
382 1.1 christos if (apn == NULL)
383 1.1 christos return NULL;
384 1.1 christos
385 1.1 christos bcopy((char *)orig, (char *)apn, sizeof(*apn));
386 1.1 christos apn->apr_next = NULL;
387 1.1 christos apn->apr_soft = NULL;
388 1.1 christos
389 1.1 christos if (apn->apr_create != NULL) {
390 1.1 christos apn->apr_soft = (*apn->apr_create)(softc);
391 1.1 christos if (apn->apr_soft == NULL) {
392 1.1 christos KFREE(apn);
393 1.1 christos return NULL;
394 1.1 christos }
395 1.1 christos }
396 1.1 christos
397 1.1 christos apn->apr_parent = orig;
398 1.1 christos orig->apr_clones++;
399 1.1 christos
400 1.1 christos return apn;
401 1.1 christos }
402 1.1 christos
403 1.1 christos
404 1.1 christos int
405 1.2 christos ipf_proxy_soft_init(ipf_main_softc_t *softc, void *arg)
406 1.1 christos {
407 1.1 christos ipf_proxy_softc_t *softp;
408 1.1 christos aproxy_t *ap;
409 1.1 christos u_int size;
410 1.1 christos int err;
411 1.1 christos
412 1.1 christos softp = arg;
413 1.1 christos size = softp->ips_proxy_session_size * sizeof(ap_session_t *);
414 1.1 christos
415 1.1 christos KMALLOCS(softp->ips_sess_tab, ap_session_t **, size);
416 1.1 christos
417 1.1 christos if (softp->ips_sess_tab == NULL)
418 1.1 christos return -1;
419 1.1 christos
420 1.1 christos bzero(softp->ips_sess_tab, size);
421 1.1 christos
422 1.1 christos for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) {
423 1.1 christos if (ap->apr_init != NULL) {
424 1.1 christos err = (*ap->apr_init)(softc, ap->apr_soft);
425 1.1 christos if (err != 0)
426 1.1 christos return -2;
427 1.1 christos }
428 1.1 christos }
429 1.1 christos softp->ips_init_run = 1;
430 1.1 christos
431 1.1 christos return 0;
432 1.1 christos }
433 1.1 christos
434 1.1 christos
435 1.1 christos int
436 1.2 christos ipf_proxy_soft_fini(ipf_main_softc_t *softc, void *arg)
437 1.1 christos {
438 1.1 christos ipf_proxy_softc_t *softp = arg;
439 1.1 christos aproxy_t *ap;
440 1.1 christos
441 1.1 christos for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next) {
442 1.1 christos if (ap->apr_fini != NULL) {
443 1.1 christos (*ap->apr_fini)(softc, ap->apr_soft);
444 1.1 christos }
445 1.1 christos }
446 1.1 christos
447 1.1 christos if (softp->ips_sess_tab != NULL) {
448 1.1 christos KFREES(softp->ips_sess_tab,
449 1.1 christos softp->ips_proxy_session_size * sizeof(ap_session_t *));
450 1.1 christos softp->ips_sess_tab = NULL;
451 1.1 christos }
452 1.1 christos softp->ips_init_run = 0;
453 1.1 christos
454 1.1 christos return 0;
455 1.1 christos }
456 1.1 christos
457 1.1 christos
458 1.1 christos void
459 1.2 christos ipf_proxy_soft_destroy(ipf_main_softc_t *softc, void *arg)
460 1.1 christos {
461 1.1 christos ipf_proxy_softc_t *softp = arg;
462 1.1 christos aproxy_t *ap;
463 1.1 christos
464 1.1 christos while ((ap = softp->ips_proxies) != NULL) {
465 1.1 christos softp->ips_proxies = ap->apr_next;
466 1.1 christos if (ap->apr_destroy != NULL)
467 1.1 christos (*ap->apr_destroy)(softc, ap->apr_soft);
468 1.1 christos ap->apr_parent->apr_clones--;
469 1.1 christos KFREE(ap);
470 1.1 christos }
471 1.1 christos
472 1.1 christos if (softp->ipf_proxy_tune != NULL) {
473 1.1 christos ipf_tune_array_unlink(softc, softp->ipf_proxy_tune);
474 1.1 christos KFREES(softp->ipf_proxy_tune, sizeof(ipf_proxy_tuneables));
475 1.1 christos softp->ipf_proxy_tune = NULL;
476 1.1 christos }
477 1.1 christos
478 1.1 christos KFREE(softp);
479 1.1 christos }
480 1.1 christos
481 1.1 christos
482 1.1 christos /* ------------------------------------------------------------------------ */
483 1.1 christos /* Function: ipf_proxy_flush */
484 1.1 christos /* Returns: Nil */
485 1.1 christos /* Parameters: fin(I) - pointer to packet information */
486 1.1 christos /* nat(I) - pointer to current NAT session */
487 1.1 christos /* */
488 1.1 christos /* ------------------------------------------------------------------------ */
489 1.1 christos void
490 1.2 christos ipf_proxy_flush(void *arg, int how)
491 1.1 christos {
492 1.1 christos ipf_proxy_softc_t *softp = arg;
493 1.1 christos aproxy_t *ap;
494 1.1 christos
495 1.1 christos switch (how)
496 1.1 christos {
497 1.1 christos case 0 :
498 1.1 christos for (ap = softp->ips_proxies; ap; ap = ap->apr_next)
499 1.1 christos if (ap->apr_flush != NULL)
500 1.1 christos (*ap->apr_flush)(ap, how);
501 1.1 christos break;
502 1.1 christos case 1 :
503 1.1 christos for (ap = softp->ips_proxies; ap; ap = ap->apr_next)
504 1.1 christos if (ap->apr_clear != NULL)
505 1.1 christos (*ap->apr_clear)(ap);
506 1.1 christos break;
507 1.1 christos default :
508 1.1 christos break;
509 1.1 christos }
510 1.1 christos }
511 1.1 christos
512 1.1 christos
513 1.1 christos /* ------------------------------------------------------------------------ */
514 1.1 christos /* Function: ipf_proxy_add */
515 1.1 christos /* Returns: int - -1 == error, 0 == success */
516 1.1 christos /* Parameters: ap(I) - pointer to proxy structure */
517 1.1 christos /* */
518 1.1 christos /* Dynamically add a new kernel proxy. Ensure that it is unique in the */
519 1.1 christos /* collection compiled in and dynamically added. */
520 1.1 christos /* ------------------------------------------------------------------------ */
521 1.1 christos int
522 1.2 christos ipf_proxy_add(void *arg, aproxy_t *ap)
523 1.1 christos {
524 1.1 christos ipf_proxy_softc_t *softp = arg;
525 1.1 christos
526 1.1 christos aproxy_t *a;
527 1.1 christos
528 1.1 christos for (a = ips_proxies; a->apr_p; a++)
529 1.1 christos if ((a->apr_p == ap->apr_p) &&
530 1.1 christos !strncmp(a->apr_label, ap->apr_label,
531 1.1 christos sizeof(ap->apr_label))) {
532 1.1 christos if (softp->ips_proxy_debug > 1)
533 1.1 christos printf("ipf_proxy_add: %s/%d present (B)\n",
534 1.1 christos a->apr_label, a->apr_p);
535 1.1 christos return -1;
536 1.1 christos }
537 1.1 christos
538 1.1 christos for (a = ap_proxylist; (a != NULL); a = a->apr_next)
539 1.1 christos if ((a->apr_p == ap->apr_p) &&
540 1.1 christos !strncmp(a->apr_label, ap->apr_label,
541 1.1 christos sizeof(ap->apr_label))) {
542 1.1 christos if (softp->ips_proxy_debug > 1)
543 1.1 christos printf("ipf_proxy_add: %s/%d present (D)\n",
544 1.1 christos a->apr_label, a->apr_p);
545 1.1 christos return -1;
546 1.1 christos }
547 1.1 christos ap->apr_next = ap_proxylist;
548 1.1 christos ap_proxylist = ap;
549 1.1 christos if (ap->apr_load != NULL)
550 1.1 christos (*ap->apr_load)();
551 1.1 christos return 0;
552 1.1 christos }
553 1.1 christos
554 1.1 christos
555 1.1 christos /* ------------------------------------------------------------------------ */
556 1.1 christos /* Function: ipf_proxy_ctl */
557 1.1 christos /* Returns: int - 0 == success, else error */
558 1.1 christos /* Parameters: ctl(I) - pointer to proxy control structure */
559 1.1 christos /* */
560 1.1 christos /* Check to see if the proxy this control request has come through for */
561 1.1 christos /* exists, and if it does and it has a control function then invoke that */
562 1.1 christos /* control function. */
563 1.1 christos /* ------------------------------------------------------------------------ */
564 1.1 christos int
565 1.2 christos ipf_proxy_ctl(ipf_main_softc_t *softc, void *arg, ap_ctl_t *ctl)
566 1.1 christos {
567 1.1 christos ipf_proxy_softc_t *softp = arg;
568 1.1 christos aproxy_t *a;
569 1.1 christos int error;
570 1.1 christos
571 1.1 christos a = ipf_proxy_lookup(arg, ctl->apc_p, ctl->apc_label);
572 1.1 christos if (a == NULL) {
573 1.1 christos if (softp->ips_proxy_debug > 1)
574 1.1 christos printf("ipf_proxy_ctl: can't find %s/%d\n",
575 1.1 christos ctl->apc_label, ctl->apc_p);
576 1.1 christos IPFERROR(80001);
577 1.1 christos error = ESRCH;
578 1.1 christos } else if (a->apr_ctl == NULL) {
579 1.1 christos if (softp->ips_proxy_debug > 1)
580 1.1 christos printf("ipf_proxy_ctl: no ctl function for %s/%d\n",
581 1.1 christos ctl->apc_label, ctl->apc_p);
582 1.1 christos IPFERROR(80002);
583 1.1 christos error = ENXIO;
584 1.1 christos } else {
585 1.1 christos error = (*a->apr_ctl)(softc, a->apr_soft, ctl);
586 1.1 christos if ((error != 0) && (softp->ips_proxy_debug > 1))
587 1.1 christos printf("ipf_proxy_ctl: %s/%d ctl error %d\n",
588 1.1 christos a->apr_label, a->apr_p, error);
589 1.1 christos }
590 1.1 christos return error;
591 1.1 christos }
592 1.1 christos
593 1.1 christos
594 1.1 christos /* ------------------------------------------------------------------------ */
595 1.1 christos /* Function: ipf_proxy_del */
596 1.1 christos /* Returns: int - -1 == error, 0 == success */
597 1.1 christos /* Parameters: ap(I) - pointer to proxy structure */
598 1.1 christos /* */
599 1.1 christos /* Delete a proxy that has been added dynamically from those available. */
600 1.1 christos /* If it is in use, return 1 (do not destroy NOW), not in use 0 or -1 */
601 1.1 christos /* if it cannot be matched. */
602 1.1 christos /* ------------------------------------------------------------------------ */
603 1.1 christos int
604 1.2 christos ipf_proxy_del(aproxy_t *ap)
605 1.1 christos {
606 1.1 christos aproxy_t *a, **app;
607 1.1 christos
608 1.1 christos for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next) {
609 1.1 christos if (a == ap) {
610 1.1 christos a->apr_flags |= APR_DELETE;
611 1.1 christos if (ap->apr_ref == 0 && ap->apr_clones == 0) {
612 1.1 christos *app = a->apr_next;
613 1.1 christos return 0;
614 1.1 christos }
615 1.1 christos return 1;
616 1.1 christos }
617 1.1 christos }
618 1.1 christos
619 1.1 christos return -1;
620 1.1 christos }
621 1.1 christos
622 1.1 christos
623 1.1 christos /* ------------------------------------------------------------------------ */
624 1.1 christos /* Function: ipf_proxy_ok */
625 1.1 christos /* Returns: int - 1 == good match else not. */
626 1.1 christos /* Parameters: fin(I) - pointer to packet information */
627 1.1 christos /* nat(I) - pointer to current NAT session */
628 1.1 christos /* */
629 1.1 christos /* ------------------------------------------------------------------------ */
630 1.1 christos int
631 1.2 christos ipf_proxy_ok(fr_info_t *fin, tcphdr_t *tcp, ipnat_t *nat)
632 1.1 christos {
633 1.1 christos aproxy_t *apr = nat->in_apr;
634 1.1 christos u_short dport = nat->in_odport;
635 1.1 christos
636 1.1 christos if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
637 1.1 christos (fin->fin_p != apr->apr_p))
638 1.1 christos return 0;
639 1.1 christos if ((tcp == NULL) && dport)
640 1.1 christos return 0;
641 1.1 christos return 1;
642 1.1 christos }
643 1.1 christos
644 1.1 christos
645 1.1 christos /* ------------------------------------------------------------------------ */
646 1.1 christos /* Function: ipf_proxy_ioctl */
647 1.1 christos /* Returns: int - 0 == success, else error */
648 1.1 christos /* Parameters: fin(I) - pointer to packet information */
649 1.1 christos /* nat(I) - pointer to current NAT session */
650 1.1 christos /* */
651 1.1 christos /* ------------------------------------------------------------------------ */
652 1.1 christos int
653 1.2 christos ipf_proxy_ioctl(ipf_main_softc_t *softc, void *data, ioctlcmd_t cmd, int mode,
654 1.2 christos void *ctx)
655 1.1 christos {
656 1.1 christos ap_ctl_t ctl;
657 1.2 christos void *ptr;
658 1.1 christos int error;
659 1.1 christos
660 1.1 christos mode = mode; /* LINT */
661 1.1 christos
662 1.1 christos switch (cmd)
663 1.1 christos {
664 1.1 christos case SIOCPROXY :
665 1.1 christos error = ipf_inobj(softc, data, NULL, &ctl, IPFOBJ_PROXYCTL);
666 1.1 christos if (error != 0) {
667 1.1 christos return error;
668 1.1 christos }
669 1.1 christos ptr = NULL;
670 1.1 christos
671 1.1 christos if (ctl.apc_dsize > 0) {
672 1.2 christos KMALLOCS(ptr, void *, ctl.apc_dsize);
673 1.1 christos if (ptr == NULL) {
674 1.1 christos IPFERROR(80003);
675 1.1 christos error = ENOMEM;
676 1.1 christos } else {
677 1.1 christos error = copyinptr(softc, ctl.apc_data, ptr,
678 1.1 christos ctl.apc_dsize);
679 1.1 christos if (error == 0)
680 1.1 christos ctl.apc_data = ptr;
681 1.1 christos }
682 1.1 christos } else {
683 1.1 christos ctl.apc_data = NULL;
684 1.1 christos error = 0;
685 1.1 christos }
686 1.1 christos
687 1.1 christos if (error == 0)
688 1.1 christos error = ipf_proxy_ctl(softc, softc->ipf_proxy_soft, &ctl);
689 1.1 christos
690 1.1 christos if ((error != 0) && (ptr != NULL)) {
691 1.1 christos KFREES(ptr, ctl.apc_dsize);
692 1.1 christos }
693 1.1 christos break;
694 1.1 christos
695 1.1 christos default :
696 1.1 christos IPFERROR(80004);
697 1.1 christos error = EINVAL;
698 1.1 christos }
699 1.1 christos return error;
700 1.1 christos }
701 1.1 christos
702 1.1 christos
703 1.1 christos /* ------------------------------------------------------------------------ */
704 1.1 christos /* Function: ipf_proxy_match */
705 1.1 christos /* Returns: int - -1 == error, 0 == success */
706 1.1 christos /* Parameters: fin(I) - pointer to packet information */
707 1.1 christos /* nat(I) - pointer to current NAT session */
708 1.1 christos /* */
709 1.1 christos /* If a proxy has a match function, call that to do extended packet */
710 1.1 christos /* matching. */
711 1.1 christos /* ------------------------------------------------------------------------ */
712 1.1 christos int
713 1.2 christos ipf_proxy_match(fr_info_t *fin, nat_t *nat)
714 1.1 christos {
715 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
716 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
717 1.1 christos aproxy_t *apr;
718 1.1 christos ipnat_t *ipn;
719 1.1 christos int result;
720 1.1 christos
721 1.1 christos ipn = nat->nat_ptr;
722 1.1 christos if (softp->ips_proxy_debug > 8)
723 1.1 christos printf("ipf_proxy_match(%lx,%lx) aps %lx ptr %lx\n",
724 1.1 christos (u_long)fin, (u_long)nat, (u_long)nat->nat_aps,
725 1.1 christos (u_long)ipn);
726 1.1 christos
727 1.1 christos if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0) {
728 1.1 christos if (softp->ips_proxy_debug > 0)
729 1.1 christos printf("ipf_proxy_match: flx 0x%x (BAD|SHORT)\n",
730 1.1 christos fin->fin_flx);
731 1.1 christos return -1;
732 1.1 christos }
733 1.1 christos
734 1.1 christos apr = ipn->in_apr;
735 1.1 christos if ((apr == NULL) || (apr->apr_flags & APR_DELETE)) {
736 1.1 christos if (softp->ips_proxy_debug > 0)
737 1.1 christos printf("ipf_proxy_match:apr %lx apr_flags 0x%x\n",
738 1.1 christos (u_long)apr, apr ? apr->apr_flags : 0);
739 1.1 christos return -1;
740 1.1 christos }
741 1.1 christos
742 1.1 christos if (apr->apr_match != NULL) {
743 1.1 christos result = (*apr->apr_match)(fin, nat->nat_aps, nat);
744 1.1 christos if (result != 0) {
745 1.1 christos if (softp->ips_proxy_debug > 4)
746 1.1 christos printf("ipf_proxy_match: result %d\n", result);
747 1.1 christos return -1;
748 1.1 christos }
749 1.1 christos }
750 1.1 christos return 0;
751 1.1 christos }
752 1.1 christos
753 1.1 christos
754 1.1 christos /* ------------------------------------------------------------------------ */
755 1.1 christos /* Function: ipf_proxy_new */
756 1.1 christos /* Returns: int - -1 == error, 0 == success */
757 1.1 christos /* Parameters: fin(I) - pointer to packet information */
758 1.1 christos /* nat(I) - pointer to current NAT session */
759 1.1 christos /* */
760 1.1 christos /* Allocate a new application proxy structure and fill it in with the */
761 1.1 christos /* relevant details. call the init function once complete, prior to */
762 1.1 christos /* returning. */
763 1.1 christos /* ------------------------------------------------------------------------ */
764 1.1 christos int
765 1.2 christos ipf_proxy_new(fr_info_t *fin, nat_t *nat)
766 1.1 christos {
767 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
768 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
769 1.1 christos register ap_session_t *aps;
770 1.1 christos aproxy_t *apr;
771 1.1 christos
772 1.1 christos if (softp->ips_proxy_debug > 8)
773 1.1 christos printf("ipf_proxy_new(%lx,%lx) \n", (u_long)fin, (u_long)nat);
774 1.1 christos
775 1.1 christos if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL)) {
776 1.1 christos if (softp->ips_proxy_debug > 0)
777 1.1 christos printf("ipf_proxy_new: nat_ptr %lx nat_aps %lx\n",
778 1.1 christos (u_long)nat->nat_ptr, (u_long)nat->nat_aps);
779 1.1 christos return -1;
780 1.1 christos }
781 1.1 christos
782 1.1 christos apr = nat->nat_ptr->in_apr;
783 1.1 christos
784 1.1 christos if ((apr->apr_flags & APR_DELETE) ||
785 1.1 christos (fin->fin_p != apr->apr_p)) {
786 1.1 christos if (softp->ips_proxy_debug > 2)
787 1.1 christos printf("ipf_proxy_new: apr_flags 0x%x p %d/%d\n",
788 1.1 christos apr->apr_flags, fin->fin_p, apr->apr_p);
789 1.1 christos return -1;
790 1.1 christos }
791 1.1 christos
792 1.1 christos KMALLOC(aps, ap_session_t *);
793 1.1 christos if (!aps) {
794 1.1 christos if (softp->ips_proxy_debug > 0)
795 1.1 christos printf("ipf_proxy_new: malloc failed (%lu)\n",
796 1.1 christos (u_long)sizeof(ap_session_t));
797 1.1 christos return -1;
798 1.1 christos }
799 1.1 christos
800 1.1 christos bzero((char *)aps, sizeof(*aps));
801 1.1 christos aps->aps_data = NULL;
802 1.1 christos aps->aps_apr = apr;
803 1.1 christos aps->aps_psiz = 0;
804 1.1 christos if (apr->apr_new != NULL)
805 1.1 christos if ((*apr->apr_new)(apr->apr_soft, fin, aps, nat) == -1) {
806 1.1 christos if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) {
807 1.1 christos KFREES(aps->aps_data, aps->aps_psiz);
808 1.1 christos }
809 1.1 christos KFREE(aps);
810 1.1 christos if (softp->ips_proxy_debug > 2)
811 1.1 christos printf("ipf_proxy_new: new(%lx) failed\n",
812 1.1 christos (u_long)apr->apr_new);
813 1.1 christos return -1;
814 1.1 christos }
815 1.1 christos aps->aps_nat = nat;
816 1.1 christos aps->aps_next = softp->ips_sess_list;
817 1.1 christos softp->ips_sess_list = aps;
818 1.1 christos nat->nat_aps = aps;
819 1.1 christos
820 1.1 christos return 0;
821 1.1 christos }
822 1.1 christos
823 1.1 christos
824 1.1 christos /* ------------------------------------------------------------------------ */
825 1.1 christos /* Function: ipf_proxy_check */
826 1.1 christos /* Returns: int - -1 == error, 0 == success */
827 1.1 christos /* Parameters: fin(I) - pointer to packet information */
828 1.1 christos /* nat(I) - pointer to current NAT session */
829 1.1 christos /* */
830 1.1 christos /* Check to see if a packet should be passed through an active proxy */
831 1.1 christos /* routine if one has been setup for it. We don't need to check the */
832 1.1 christos /* checksum here if IPFILTER_CKSUM is defined because if it is, a failed */
833 1.1 christos /* check causes FI_BAD to be set. */
834 1.1 christos /* ------------------------------------------------------------------------ */
835 1.1 christos int
836 1.2 christos ipf_proxy_check(fr_info_t *fin, nat_t *nat)
837 1.1 christos {
838 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
839 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
840 1.1 christos #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
841 1.1 christos # if defined(ICK_VALID)
842 1.1 christos mb_t *m;
843 1.1 christos # endif
844 1.1 christos int dosum = 1;
845 1.1 christos #endif
846 1.1 christos tcphdr_t *tcp = NULL;
847 1.1 christos udphdr_t *udp = NULL;
848 1.1 christos ap_session_t *aps;
849 1.1 christos aproxy_t *apr;
850 1.1 christos ip_t *ip;
851 1.1 christos short rv;
852 1.1 christos int err;
853 1.1 christos #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
854 1.1 christos u_32_t s1, s2, sd;
855 1.1 christos #endif
856 1.1 christos
857 1.1 christos if (fin->fin_flx & FI_BAD) {
858 1.1 christos if (softp->ips_proxy_debug > 0)
859 1.1 christos printf("ipf_proxy_check: flx 0x%x (BAD)\n", fin->fin_flx);
860 1.1 christos return -1;
861 1.1 christos }
862 1.1 christos
863 1.1 christos #ifndef IPFILTER_CKSUM
864 1.1 christos if ((fin->fin_out == 0) && (ipf_checkl4sum(fin) == -1)) {
865 1.1 christos if (softp->ips_proxy_debug > 0)
866 1.1 christos printf("ipf_proxy_check: l4 checksum failure %d\n",
867 1.1 christos fin->fin_p);
868 1.1 christos if (fin->fin_p == IPPROTO_TCP)
869 1.1 christos softc->ipf_stats[fin->fin_out].fr_tcpbad++;
870 1.1 christos return -1;
871 1.1 christos }
872 1.1 christos #endif
873 1.1 christos
874 1.1 christos aps = nat->nat_aps;
875 1.1 christos if (aps != NULL) {
876 1.1 christos /*
877 1.1 christos * If there is data in this packet to be proxied then try and
878 1.1 christos * get it all into the one buffer, else drop it.
879 1.1 christos */
880 1.1 christos #if defined(MENTAT) || defined(HAVE_M_PULLDOWN)
881 1.1 christos if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE))
882 1.1 christos if (ipf_coalesce(fin) == -1) {
883 1.1 christos if (softp->ips_proxy_debug > 0)
884 1.1 christos printf("ipf_proxy_check: coalesce failed %x\n", fin->fin_flx);
885 1.1 christos return -1;
886 1.1 christos }
887 1.1 christos #endif
888 1.1 christos ip = fin->fin_ip;
889 1.1 christos
890 1.1 christos switch (fin->fin_p)
891 1.1 christos {
892 1.1 christos case IPPROTO_TCP :
893 1.1 christos tcp = (tcphdr_t *)fin->fin_dp;
894 1.1 christos
895 1.1 christos #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
896 1.1 christos m = fin->fin_qfm;
897 1.1 christos if (dohwcksum && (m->b_ick_flag == ICK_VALID))
898 1.1 christos dosum = 0;
899 1.1 christos #endif
900 1.1 christos /*
901 1.1 christos * Don't bother the proxy with these...or in fact,
902 1.1 christos * should we free up proxy stuff when seen?
903 1.1 christos */
904 1.1 christos if ((fin->fin_tcpf & TH_RST) != 0)
905 1.1 christos break;
906 1.1 christos /*FALLTHROUGH*/
907 1.1 christos case IPPROTO_UDP :
908 1.1 christos udp = (udphdr_t *)fin->fin_dp;
909 1.1 christos break;
910 1.1 christos default :
911 1.1 christos break;
912 1.1 christos }
913 1.1 christos
914 1.1 christos apr = aps->aps_apr;
915 1.1 christos err = 0;
916 1.1 christos if (fin->fin_out != 0) {
917 1.1 christos if (apr->apr_outpkt != NULL)
918 1.1 christos err = (*apr->apr_outpkt)(apr->apr_soft, fin, aps, nat);
919 1.1 christos } else {
920 1.1 christos if (apr->apr_inpkt != NULL)
921 1.1 christos err = (*apr->apr_inpkt)(apr->apr_soft, fin, aps, nat);
922 1.1 christos }
923 1.1 christos
924 1.1 christos rv = APR_EXIT(err);
925 1.1 christos if (((softp->ips_proxy_debug > 0) && (rv != 0)) ||
926 1.1 christos (softp->ips_proxy_debug > 8))
927 1.1 christos printf("ipf_proxy_check: out %d err %x rv %d\n",
928 1.1 christos fin->fin_out, err, rv);
929 1.1 christos if (rv == 1)
930 1.1 christos return -1;
931 1.1 christos
932 1.1 christos if (rv == 2) {
933 1.1 christos ipf_proxy_free(apr);
934 1.1 christos nat->nat_aps = NULL;
935 1.1 christos return -1;
936 1.1 christos }
937 1.1 christos
938 1.1 christos /*
939 1.1 christos * If err != 0 then the data size of the packet has changed
940 1.1 christos * so we need to recalculate the header checksums for the
941 1.1 christos * packet.
942 1.1 christos */
943 1.1 christos #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
944 1.1 christos if (err != 0) {
945 1.1 christos short adjlen = err & 0xffff;
946 1.1 christos
947 1.1 christos s1 = LONG_SUM(fin->fin_plen - adjlen);
948 1.1 christos s2 = LONG_SUM(fin->fin_plen);
949 1.1 christos CALC_SUMD(s1, s2, sd);
950 1.1 christos ipf_fix_outcksum(fin, &ip->ip_sum, sd);
951 1.1 christos }
952 1.1 christos #endif
953 1.1 christos
954 1.2 christos #ifdef INET
955 1.1 christos /*
956 1.1 christos * For TCP packets, we may need to adjust the sequence and
957 1.1 christos * acknowledgement numbers to reflect changes in size of the
958 1.1 christos * data stream.
959 1.1 christos *
960 1.1 christos * For both TCP and UDP, recalculate the layer 4 checksum,
961 1.1 christos * regardless, as we can't tell (here) if data has been
962 1.1 christos * changed or not.
963 1.1 christos */
964 1.1 christos if (tcp != NULL) {
965 1.1 christos err = ipf_proxy_fixseqack(fin, ip, aps, APR_INC(err));
966 1.1 christos #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
967 1.1 christos if (dosum)
968 1.1 christos #endif
969 1.1 christos tcp->th_sum = fr_cksum(fin, ip,
970 1.1 christos IPPROTO_TCP, tcp);
971 1.1 christos } else if ((udp != NULL) && (udp->uh_sum != 0)) {
972 1.1 christos #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
973 1.1 christos if (dosum)
974 1.1 christos #endif
975 1.1 christos udp->uh_sum = fr_cksum(fin, ip,
976 1.1 christos IPPROTO_UDP, udp);
977 1.1 christos }
978 1.2 christos #endif
979 1.1 christos aps->aps_bytes += fin->fin_plen;
980 1.1 christos aps->aps_pkts++;
981 1.1 christos return 1;
982 1.1 christos }
983 1.1 christos return 0;
984 1.1 christos }
985 1.1 christos
986 1.1 christos
987 1.1 christos /* ------------------------------------------------------------------------ */
988 1.1 christos /* Function: ipf_proxy_lookup */
989 1.1 christos /* Returns: int - -1 == error, 0 == success */
990 1.1 christos /* Parameters: fin(I) - pointer to packet information */
991 1.1 christos /* nat(I) - pointer to current NAT session */
992 1.1 christos /* */
993 1.1 christos /* Search for an proxy by the protocol it is being used with and its name. */
994 1.1 christos /* ------------------------------------------------------------------------ */
995 1.1 christos aproxy_t *
996 1.2 christos ipf_proxy_lookup(void *arg, u_int pr, char *name)
997 1.1 christos {
998 1.1 christos ipf_proxy_softc_t *softp = arg;
999 1.1 christos aproxy_t *ap;
1000 1.1 christos
1001 1.1 christos if (softp->ips_proxy_debug > 8)
1002 1.1 christos printf("ipf_proxy_lookup(%d,%s)\n", pr, name);
1003 1.1 christos
1004 1.1 christos for (ap = softp->ips_proxies; ap != NULL; ap = ap->apr_next)
1005 1.1 christos if ((ap->apr_p == pr) &&
1006 1.1 christos !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
1007 1.1 christos ap->apr_ref++;
1008 1.1 christos return ap;
1009 1.1 christos }
1010 1.1 christos
1011 1.1 christos if (softp->ips_proxy_debug > 2)
1012 1.1 christos printf("ipf_proxy_lookup: failed for %d/%s\n", pr, name);
1013 1.1 christos return NULL;
1014 1.1 christos }
1015 1.1 christos
1016 1.1 christos
1017 1.1 christos /* ------------------------------------------------------------------------ */
1018 1.1 christos /* Function: ipf_proxy_free */
1019 1.1 christos /* Returns: Nil */
1020 1.1 christos /* Parameters: ap(I) - pointer to proxy structure */
1021 1.1 christos /* */
1022 1.1 christos /* ------------------------------------------------------------------------ */
1023 1.1 christos void
1024 1.2 christos ipf_proxy_free(aproxy_t *ap)
1025 1.1 christos {
1026 1.1 christos ap->apr_ref--;
1027 1.1 christos }
1028 1.1 christos
1029 1.1 christos
1030 1.1 christos /* ------------------------------------------------------------------------ */
1031 1.1 christos /* Function: aps_free */
1032 1.1 christos /* Returns: Nil */
1033 1.1 christos /* Parameters: fin(I) - pointer to packet information */
1034 1.1 christos /* nat(I) - pointer to current NAT session */
1035 1.1 christos /* */
1036 1.1 christos /* Locks Held: ipf_nat_new, ipf_nat(W) */
1037 1.1 christos /* ------------------------------------------------------------------------ */
1038 1.1 christos void
1039 1.2 christos aps_free(ipf_main_softc_t *softc, void *arg, ap_session_t *aps)
1040 1.1 christos {
1041 1.1 christos ipf_proxy_softc_t *softp = arg;
1042 1.1 christos ap_session_t *a, **ap;
1043 1.1 christos aproxy_t *apr;
1044 1.1 christos
1045 1.1 christos if (!aps)
1046 1.1 christos return;
1047 1.1 christos
1048 1.1 christos for (ap = &softp->ips_sess_list; ((a = *ap) != NULL); ap = &a->aps_next)
1049 1.1 christos if (a == aps) {
1050 1.1 christos *ap = a->aps_next;
1051 1.1 christos break;
1052 1.1 christos }
1053 1.1 christos
1054 1.1 christos apr = aps->aps_apr;
1055 1.1 christos if ((apr != NULL) && (apr->apr_del != NULL))
1056 1.1 christos (*apr->apr_del)(softc, aps);
1057 1.1 christos
1058 1.1 christos if ((aps->aps_data != NULL) && (aps->aps_psiz != 0))
1059 1.1 christos KFREES(aps->aps_data, aps->aps_psiz);
1060 1.1 christos KFREE(aps);
1061 1.1 christos }
1062 1.1 christos
1063 1.1 christos
1064 1.1 christos /* ------------------------------------------------------------------------ */
1065 1.1 christos /* Function: ipf_proxy_fixseqack */
1066 1.1 christos /* Returns: int - 2 if TCP ack/seq is changed, else 0 */
1067 1.1 christos /* Parameters: fin(I) - pointer to packet information */
1068 1.1 christos /* nat(I) - pointer to current NAT session */
1069 1.1 christos /* */
1070 1.1 christos /* ------------------------------------------------------------------------ */
1071 1.1 christos static int
1072 1.2 christos ipf_proxy_fixseqack(fr_info_t *fin, ip_t *ip, ap_session_t *aps, int inc)
1073 1.1 christos {
1074 1.1 christos ipf_main_softc_t *softc = fin->fin_main_soft;
1075 1.1 christos ipf_proxy_softc_t *softp = softc->ipf_proxy_soft;
1076 1.1 christos int sel, ch = 0, out, nlen;
1077 1.1 christos u_32_t seq1, seq2;
1078 1.1 christos tcphdr_t *tcp;
1079 1.1 christos short inc2;
1080 1.1 christos
1081 1.1 christos tcp = (tcphdr_t *)fin->fin_dp;
1082 1.1 christos out = fin->fin_out;
1083 1.1 christos /*
1084 1.1 christos * ip_len has already been adjusted by 'inc'.
1085 1.1 christos */
1086 1.1 christos nlen = fin->fin_plen;
1087 1.1 christos nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2);
1088 1.1 christos
1089 1.1 christos inc2 = inc;
1090 1.1 christos inc = (int)inc2;
1091 1.1 christos
1092 1.1 christos if (out != 0) {
1093 1.1 christos seq1 = (u_32_t)ntohl(tcp->th_seq);
1094 1.1 christos sel = aps->aps_sel[out];
1095 1.1 christos
1096 1.1 christos /* switch to other set ? */
1097 1.1 christos if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
1098 1.1 christos (seq1 > aps->aps_seqmin[!sel])) {
1099 1.1 christos if (softp->ips_proxy_debug > 7)
1100 1.1 christos printf("proxy out switch set seq %d -> %d %x > %x\n",
1101 1.1 christos sel, !sel, seq1,
1102 1.1 christos aps->aps_seqmin[!sel]);
1103 1.1 christos sel = aps->aps_sel[out] = !sel;
1104 1.1 christos }
1105 1.1 christos
1106 1.1 christos if (aps->aps_seqoff[sel]) {
1107 1.1 christos seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel];
1108 1.1 christos if (seq1 > seq2) {
1109 1.1 christos seq2 = aps->aps_seqoff[sel];
1110 1.1 christos seq1 += seq2;
1111 1.1 christos tcp->th_seq = htonl(seq1);
1112 1.1 christos ch = 1;
1113 1.1 christos }
1114 1.1 christos }
1115 1.1 christos
1116 1.1 christos if (inc && (seq1 > aps->aps_seqmin[!sel])) {
1117 1.1 christos aps->aps_seqmin[sel] = seq1 + nlen - 1;
1118 1.1 christos aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc;
1119 1.1 christos if (softp->ips_proxy_debug > 7)
1120 1.1 christos printf("proxy seq set %d at %x to %d + %d\n",
1121 1.1 christos sel, aps->aps_seqmin[sel],
1122 1.1 christos aps->aps_seqoff[sel], inc);
1123 1.1 christos }
1124 1.1 christos
1125 1.1 christos /***/
1126 1.1 christos
1127 1.1 christos seq1 = ntohl(tcp->th_ack);
1128 1.1 christos sel = aps->aps_sel[1 - out];
1129 1.1 christos
1130 1.1 christos /* switch to other set ? */
1131 1.1 christos if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
1132 1.1 christos (seq1 > aps->aps_ackmin[!sel])) {
1133 1.1 christos if (softp->ips_proxy_debug > 7)
1134 1.1 christos printf("proxy out switch set ack %d -> %d %x > %x\n",
1135 1.1 christos sel, !sel, seq1,
1136 1.1 christos aps->aps_ackmin[!sel]);
1137 1.1 christos sel = aps->aps_sel[1 - out] = !sel;
1138 1.1 christos }
1139 1.1 christos
1140 1.1 christos if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) {
1141 1.1 christos seq2 = aps->aps_ackoff[sel];
1142 1.1 christos tcp->th_ack = htonl(seq1 - seq2);
1143 1.1 christos ch = 1;
1144 1.1 christos }
1145 1.1 christos } else {
1146 1.1 christos seq1 = ntohl(tcp->th_seq);
1147 1.1 christos sel = aps->aps_sel[out];
1148 1.1 christos
1149 1.1 christos /* switch to other set ? */
1150 1.1 christos if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
1151 1.1 christos (seq1 > aps->aps_ackmin[!sel])) {
1152 1.1 christos if (softp->ips_proxy_debug > 7)
1153 1.1 christos printf("proxy in switch set ack %d -> %d %x > %x\n",
1154 1.1 christos sel, !sel, seq1, aps->aps_ackmin[!sel]);
1155 1.1 christos sel = aps->aps_sel[out] = !sel;
1156 1.1 christos }
1157 1.1 christos
1158 1.1 christos if (aps->aps_ackoff[sel]) {
1159 1.1 christos seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel];
1160 1.1 christos if (seq1 > seq2) {
1161 1.1 christos seq2 = aps->aps_ackoff[sel];
1162 1.1 christos seq1 += seq2;
1163 1.1 christos tcp->th_seq = htonl(seq1);
1164 1.1 christos ch = 1;
1165 1.1 christos }
1166 1.1 christos }
1167 1.1 christos
1168 1.1 christos if (inc && (seq1 > aps->aps_ackmin[!sel])) {
1169 1.1 christos aps->aps_ackmin[!sel] = seq1 + nlen - 1;
1170 1.1 christos aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc;
1171 1.1 christos
1172 1.1 christos if (softp->ips_proxy_debug > 7)
1173 1.1 christos printf("proxy ack set %d at %x to %d + %d\n",
1174 1.1 christos !sel, aps->aps_seqmin[!sel],
1175 1.1 christos aps->aps_seqoff[sel], inc);
1176 1.1 christos }
1177 1.1 christos
1178 1.1 christos /***/
1179 1.1 christos
1180 1.1 christos seq1 = ntohl(tcp->th_ack);
1181 1.1 christos sel = aps->aps_sel[1 - out];
1182 1.1 christos
1183 1.1 christos /* switch to other set ? */
1184 1.1 christos if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
1185 1.1 christos (seq1 > aps->aps_seqmin[!sel])) {
1186 1.1 christos if (softp->ips_proxy_debug > 7)
1187 1.1 christos printf("proxy in switch set seq %d -> %d %x > %x\n",
1188 1.1 christos sel, !sel, seq1, aps->aps_seqmin[!sel]);
1189 1.1 christos sel = aps->aps_sel[1 - out] = !sel;
1190 1.1 christos }
1191 1.1 christos
1192 1.1 christos if (aps->aps_seqoff[sel] != 0) {
1193 1.1 christos if (softp->ips_proxy_debug > 7)
1194 1.1 christos printf("sel %d seqoff %d seq1 %x seqmin %x\n",
1195 1.1 christos sel, aps->aps_seqoff[sel], seq1,
1196 1.1 christos aps->aps_seqmin[sel]);
1197 1.1 christos if (seq1 > aps->aps_seqmin[sel]) {
1198 1.1 christos seq2 = aps->aps_seqoff[sel];
1199 1.1 christos tcp->th_ack = htonl(seq1 - seq2);
1200 1.1 christos ch = 1;
1201 1.1 christos }
1202 1.1 christos }
1203 1.1 christos }
1204 1.1 christos
1205 1.1 christos if (softp->ips_proxy_debug > 8)
1206 1.1 christos printf("ipf_proxy_fixseqack: seq %x ack %x\n",
1207 1.1 christos (u_32_t)ntohl(tcp->th_seq), (u_32_t)ntohl(tcp->th_ack));
1208 1.1 christos return ch ? 2 : 0;
1209 1.1 christos }
1210