1 /* $NetBSD: ip_proxy.c,v 1.37.2.1 2004/08/13 03:55:53 jmc Exp $ */
2
3 /*
4 * Copyright (C) 1997-2003 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #if defined(KERNEL) || defined(_KERNEL)
9 # undef KERNEL
10 # undef _KERNEL
11 # define KERNEL 1
12 # define _KERNEL 1
13 #endif
14 #include <sys/errno.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <sys/time.h>
18 #include <sys/file.h>
19 #include <sys/fcntl.h>
20 #if !defined(_KERNEL) && !defined(__KERNEL__)
21 # include <stdio.h>
22 # include <string.h>
23 # include <stdlib.h>
24 # include <ctype.h>
25 # define _KERNEL
26 # ifdef __OpenBSD__
27 struct file;
28 # endif
29 # include <sys/uio.h>
30 # undef _KERNEL
31 #endif
32 #if !defined(linux)
33 # include <sys/protosw.h>
34 #endif
35 #include <sys/socket.h>
36 #if defined(_KERNEL)
37 # if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \
38 !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi)
39 # include <sys/ctype.h>
40 # endif
41 # include <sys/systm.h>
42 # if !defined(__SVR4) && !defined(__svr4__)
43 # include <sys/mbuf.h>
44 # endif
45 #endif
46 #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
47 # include <sys/filio.h>
48 # include <sys/fcntl.h>
49 # if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
50 # include "opt_ipfilter.h"
51 # endif
52 #else
53 # include <sys/ioctl.h>
54 #endif
55 #if defined(__SVR4) || defined(__svr4__)
56 # include <sys/byteorder.h>
57 # ifdef _KERNEL
58 # include <sys/dditypes.h>
59 # endif
60 # include <sys/stream.h>
61 # include <sys/kmem.h>
62 #endif
63 #if __FreeBSD__ > 2
64 # include <sys/queue.h>
65 #endif
66 #include <net/if.h>
67 #ifdef sun
68 # include <net/af.h>
69 #endif
70 #include <net/route.h>
71 #include <netinet/in.h>
72 #include <netinet/in_systm.h>
73 #include <netinet/ip.h>
74 #ifndef linux
75 # include <netinet/ip_var.h>
76 #endif
77 #include <netinet/tcp.h>
78 #include <netinet/udp.h>
79 #include <netinet/ip_icmp.h>
80 #include "netinet/ip_compat.h"
81 #include <netinet/tcpip.h>
82 #include "netinet/ip_fil.h"
83 #include "netinet/ip_nat.h"
84 #include "netinet/ip_state.h"
85 #include "netinet/ip_proxy.h"
86 #if (__FreeBSD_version >= 300000)
87 # include <sys/malloc.h>
88 #endif
89
90 #include "netinet/ip_ftp_pxy.c"
91 #include "netinet/ip_rcmd_pxy.c"
92 #if defined(_KERNEL)
93 # include "netinet/ip_irc_pxy.c"
94 # include "netinet/ip_raudio_pxy.c"
95 # include "netinet/ip_h323_pxy.c"
96 # include "netinet/ip_pptp_pxy.c"
97 # ifdef IPFILTER_PRO
98 # include "netinet/ip_msnrpc_pxy.c"
99 # endif
100 # include "netinet/ip_netbios_pxy.c"
101 #endif
102 #include "netinet/ip_ipsec_pxy.c"
103 #include "netinet/ip_rpcb_pxy.c"
104
105 /* END OF INCLUDES */
106
107 #if !defined(lint)
108 static const char rcsid[] = "@(#)Id: ip_proxy.c,v 2.62.2.7 2004/07/11 10:40:54 darrenr Exp";
109 #endif
110
111 static int appr_fixseqack __P((fr_info_t *, ip_t *, ap_session_t *, int ));
112
113 #define AP_SESS_SIZE 53
114
115 ap_session_t *ap_sess_tab[AP_SESS_SIZE];
116 ap_session_t *ap_sess_list = NULL;
117 aproxy_t *ap_proxylist = NULL;
118 aproxy_t ap_proxies[] = {
119 #ifdef IPF_FTP_PROXY
120 { NULL, "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_fini,
121 ippr_ftp_new, NULL, ippr_ftp_in, ippr_ftp_out, NULL },
122 #endif
123 #ifdef IPF_IRC_PROXY
124 { NULL, "irc", (char)IPPROTO_TCP, 0, 0, ippr_irc_init, ippr_irc_fini,
125 ippr_irc_new, NULL, NULL, ippr_irc_out, NULL, NULL },
126 #endif
127 #ifdef IPF_RCMD_PROXY
128 { NULL, "rcmd", (char)IPPROTO_TCP, 0, 0, ippr_rcmd_init, ippr_rcmd_fini,
129 ippr_rcmd_new, NULL, ippr_rcmd_in, ippr_rcmd_out, NULL, NULL },
130 #endif
131 #ifdef IPF_RAUDIO_PROXY
132 { NULL, "raudio", (char)IPPROTO_TCP, 0, 0, ippr_raudio_init, ippr_raudio_fini,
133 ippr_raudio_new, NULL, ippr_raudio_in, ippr_raudio_out, NULL, NULL },
134 #endif
135 #ifdef IPF_MSNRPC_PROXY
136 { NULL, "msnrpc", (char)IPPROTO_TCP, 0, 0, ippr_msnrpc_init, ippr_msnrpc_fini,
137 ippr_msnrpc_new, NULL, ippr_msnrpc_in, ippr_msnrpc_out, NULL, NULL },
138 #endif
139 #ifdef IPF_NETBIOS_PROXY
140 { NULL, "netbios", (char)IPPROTO_UDP, 0, 0, ippr_netbios_init, ippr_netbios_fini,
141 NULL, NULL, NULL, ippr_netbios_out, NULL, NULL },
142 #endif
143 #ifdef IPF_IPSEC_PROXY
144 { NULL, "ipsec", (char)IPPROTO_UDP, 0, 0,
145 ippr_ipsec_init, ippr_ipsec_fini, ippr_ipsec_new, ippr_ipsec_del,
146 ippr_ipsec_inout, ippr_ipsec_inout, ippr_ipsec_match, NULL },
147 #endif
148 #ifdef IPF_PPTP_PROXY
149 { NULL, "pptp", (char)IPPROTO_TCP, 0, 0,
150 ippr_pptp_init, ippr_pptp_fini, ippr_pptp_new, ippr_pptp_del,
151 ippr_pptp_inout, ippr_pptp_inout, ippr_pptp_match, NULL },
152 #endif
153 #ifdef IPF_H323_PROXY
154 { NULL, "h323", (char)IPPROTO_TCP, 0, 0, ippr_h323_init, ippr_h323_fini,
155 ippr_h323_new, ippr_h323_del, ippr_h323_in, NULL, NULL },
156 { NULL, "h245", (char)IPPROTO_TCP, 0, 0, NULL, NULL,
157 ippr_h245_new, NULL, NULL, ippr_h245_out, NULL },
158 #endif
159 #ifdef IPF_RPCB_PROXY
160 # if 0
161 { NULL, "rpcbt", (char)IPPROTO_TCP, 0, 0,
162 ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del,
163 ippr_rpcb_in, ippr_rpcb_out, NULL, NULL },
164 # endif
165 { NULL, "rpcbu", (char)IPPROTO_UDP, 0, 0,
166 ippr_rpcb_init, ippr_rpcb_fini, ippr_rpcb_new, ippr_rpcb_del,
167 ippr_rpcb_in, ippr_rpcb_out, NULL, NULL },
168 #endif
169 { NULL, "", '\0', 0, 0, NULL, NULL, NULL, NULL }
170 };
171
172 /*
173 * Dynamically add a new kernel proxy. Ensure that it is unique in the
174 * collection compiled in and dynamically added.
175 */
176 int appr_add(ap)
177 aproxy_t *ap;
178 {
179 aproxy_t *a;
180
181 for (a = ap_proxies; a->apr_p; a++)
182 if ((a->apr_p == ap->apr_p) &&
183 !strncmp(a->apr_label, ap->apr_label,
184 sizeof(ap->apr_label)))
185 return -1;
186
187 for (a = ap_proxylist; a->apr_p; a = a->apr_next)
188 if ((a->apr_p == ap->apr_p) &&
189 !strncmp(a->apr_label, ap->apr_label,
190 sizeof(ap->apr_label)))
191 return -1;
192 ap->apr_next = ap_proxylist;
193 ap_proxylist = ap;
194 if (ap->apr_init != NULL)
195 return (*ap->apr_init)();
196 return 0;
197 }
198
199
200 /*
201 * Check to see if the proxy this control request has come through for
202 * exists, and if it does and it has a control function then invoke that
203 * control function.
204 */
205 int appr_ctl(ctl)
206 ap_ctl_t *ctl;
207 {
208 aproxy_t *a;
209 int error;
210
211 a = appr_lookup(ctl->apc_p, ctl->apc_label);
212 if (a == NULL)
213 error = ESRCH;
214 else if (a->apr_ctl == NULL)
215 error = ENXIO;
216 else
217 error = (*a->apr_ctl)(a, ctl);
218 return error;
219 }
220
221
222 /*
223 * Delete a proxy that has been added dynamically from those available.
224 * If it is in use, return 1 (do not destroy NOW), not in use 0 or -1
225 * if it cannot be matched.
226 */
227 int appr_del(ap)
228 aproxy_t *ap;
229 {
230 aproxy_t *a, **app;
231
232 for (app = &ap_proxylist; ((a = *app) != NULL); app = &a->apr_next)
233 if (a == ap) {
234 a->apr_flags |= APR_DELETE;
235 *app = a->apr_next;
236 if (ap->apr_ref != 0)
237 return 1;
238 return 0;
239 }
240 return -1;
241 }
242
243
244 /*
245 * Return 1 if the packet is a good match against a proxy, else 0.
246 */
247 int appr_ok(fin, tcp, nat)
248 fr_info_t *fin;
249 tcphdr_t *tcp;
250 ipnat_t *nat;
251 {
252 aproxy_t *apr = nat->in_apr;
253 u_short dport = nat->in_dport;
254
255 if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
256 (fin->fin_p != apr->apr_p))
257 return 0;
258 if ((tcp == NULL) && dport)
259 return 0;
260 return 1;
261 }
262
263
264 int appr_ioctl(data, cmd, mode)
265 caddr_t data;
266 ioctlcmd_t cmd;
267 int mode;
268 {
269 ap_ctl_t ctl;
270 caddr_t ptr;
271 int error;
272
273 mode = mode; /* LINT */
274
275 switch (cmd)
276 {
277 case SIOCPROXY :
278 BCOPYIN(data, &ctl, sizeof(ctl));
279 ptr = NULL;
280
281 if (ctl.apc_dsize > 0) {
282 KMALLOCS(ptr, caddr_t, ctl.apc_dsize);
283 if (ptr == NULL)
284 error = ENOMEM;
285 else {
286 error = copyinptr(ctl.apc_data, ptr,
287 ctl.apc_dsize);
288 if (error == 0)
289 ctl.apc_data = ptr;
290 }
291 } else {
292 ctl.apc_data = NULL;
293 error = 0;
294 }
295
296 if (error == 0)
297 error = appr_ctl(&ctl);
298
299 if (ctl.apc_dsize > 0 && ptr != NULL && ctl.apc_data == ptr) {
300 KFREES(ptr, ctl.apc_dsize);
301 }
302 break;
303
304 default :
305 error = EINVAL;
306 }
307 return error;
308 }
309
310
311 /*
312 * If a proxy has a match function, call that to do extended packet
313 * matching.
314 */
315 int appr_match(fin, nat)
316 fr_info_t *fin;
317 nat_t *nat;
318 {
319 aproxy_t *apr;
320 ipnat_t *ipn;
321
322 #if PROXY_DEBUG
323 printf("appr_match(%lx,%lx)\n", fin, nat);
324 #endif
325 if ((fin->fin_flx & (FI_SHORT|FI_BAD)) != 0)
326 return -1;
327
328 ipn = nat->nat_ptr;
329 if (ipn == NULL)
330 return -1;
331 apr = ipn->in_apr;
332 if ((apr == NULL) || (apr->apr_flags & APR_DELETE) ||
333 (nat->nat_aps == NULL))
334 return -1;
335 if (apr->apr_match != NULL)
336 if ((*apr->apr_match)(fin, nat->nat_aps, nat) != 0)
337 return -1;
338 return 0;
339 }
340
341
342 /*
343 * Allocate a new application proxy structure and fill it in with the
344 * relevant details. call the init function once complete, prior to
345 * returning.
346 */
347 int appr_new(fin, nat)
348 fr_info_t *fin;
349 nat_t *nat;
350 {
351 register ap_session_t *aps;
352 aproxy_t *apr;
353
354 #if PROXY_DEBUG
355 printf("appr_new(%lx,%lx)\n", fin, nat);
356 #endif
357 if ((nat->nat_ptr == NULL) || (nat->nat_aps != NULL))
358 return -1;
359
360 apr = nat->nat_ptr->in_apr;
361
362 if (!apr || (apr->apr_flags & APR_DELETE) ||
363 (fin->fin_p != apr->apr_p))
364 return -1;
365
366 KMALLOC(aps, ap_session_t *);
367 if (!aps)
368 return -1;
369 bzero((char *)aps, sizeof(*aps));
370 aps->aps_p = fin->fin_p;
371 aps->aps_data = NULL;
372 aps->aps_apr = apr;
373 aps->aps_psiz = 0;
374 if (apr->apr_new != NULL)
375 if ((*apr->apr_new)(fin, aps, nat) == -1) {
376 if ((aps->aps_data != NULL) && (aps->aps_psiz != 0)) {
377 KFREES(aps->aps_data, aps->aps_psiz);
378 }
379 KFREE(aps);
380 return -1;
381 }
382 aps->aps_nat = nat;
383 aps->aps_next = ap_sess_list;
384 ap_sess_list = aps;
385 nat->nat_aps = aps;
386
387 return 0;
388 }
389
390
391 /*
392 * Check to see if a packet should be passed through an active proxy routine
393 * if one has been setup for it. We don't need to check the checksum here if
394 * IPFILTER_CKSUM is defined because if it is, a failed check causes FI_BAD
395 * to be set.
396 */
397 int appr_check(fin, nat)
398 fr_info_t *fin;
399 nat_t *nat;
400 {
401 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
402 # if defined(ICK_VALID)
403 mb_t *m;
404 # endif
405 int dosum = 1;
406 #endif
407 tcphdr_t *tcp = NULL;
408 udphdr_t *udp = NULL;
409 ap_session_t *aps;
410 aproxy_t *apr;
411 ip_t *ip;
412 short rv;
413 int err;
414 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
415 u_32_t s1, s2, sd;
416 #endif
417
418 if (fin->fin_flx & FI_BAD)
419 return -1;
420
421 #ifndef IPFILTER_CKSUM
422 if ((fin->fin_out == 0) && (fr_checkl4sum(fin) == -1)) {
423 # if PROXY_DEBUG || !defined(_KERNEL)
424 printf("proxy l4 checksum failure on %p\n", fin);
425 # endif
426 if (fin->fin_p == IPPROTO_TCP)
427 frstats[fin->fin_out].fr_tcpbad++;
428 return -1;
429 }
430 #endif
431
432 aps = nat->nat_aps;
433 if ((aps != NULL) && (aps->aps_p == fin->fin_p)) {
434 /*
435 * If there is data in this packet to be proxied then try and
436 * get it all into the one buffer, else drop it.
437 */
438 #if defined(MENTAT) || defined(HAVE_M_PULLDOWN)
439 if ((fin->fin_dlen > 0) && !(fin->fin_flx & FI_COALESCE))
440 if (fr_coalesce(fin) == -1)
441 return -1;
442 #endif
443 ip = fin->fin_ip;
444
445 switch (fin->fin_p)
446 {
447 case IPPROTO_TCP :
448 tcp = (tcphdr_t *)fin->fin_dp;
449
450 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
451 m = fin->fin_qfm;
452 if (dohwcksum && (m->b_ick_flag == ICK_VALID))
453 dosum = 0;
454 #endif
455 /*
456 * Don't bother the proxy with these...or in fact,
457 * should we free up proxy stuff when seen?
458 */
459 if ((fin->fin_tcpf & TH_RST) != 0)
460 break;
461 /*FALLTHROUGH*/
462 case IPPROTO_UDP :
463 udp = (udphdr_t *)fin->fin_dp;
464 break;
465 default :
466 break;
467 }
468
469 apr = aps->aps_apr;
470 err = 0;
471 if (fin->fin_out != 0) {
472 if (apr->apr_outpkt != NULL)
473 err = (*apr->apr_outpkt)(fin, aps, nat);
474 } else {
475 if (apr->apr_inpkt != NULL)
476 err = (*apr->apr_inpkt)(fin, aps, nat);
477 }
478
479 rv = APR_EXIT(err);
480 if (rv == 1) {
481 #if PROXY_DEBUG || !defined(_KERNEL)
482 printf("%d:proxy says bad packet received (%x)\n",
483 fin->fin_out, err);
484 #endif
485 return -1;
486 }
487 if (rv == 2) {
488 #if PROXY_DEBUG || !defined(_KERNEL)
489 printf("proxy says free app proxy data (%x)\n", err);
490 #endif
491 appr_free(apr);
492 nat->nat_aps = NULL;
493 return -1;
494 }
495
496 /*
497 * If err != 0 then the data size of the packet has changed
498 * so we need to recalculate the header checksums for the
499 * packet.
500 */
501 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
502 if (err != 0) {
503 short adjlen = err & 0xffff;
504
505 s1 = LONG_SUM(ip->ip_len - adjlen);
506 s2 = LONG_SUM(ip->ip_len);
507 CALC_SUMD(s1, s2, sd);
508 fix_outcksum(fin, &ip->ip_sum, sd);
509 }
510 #endif
511
512 /*
513 * For TCP packets, we may need to adjust the sequence and
514 * acknowledgement numbers to reflect changes in size of the
515 * data stream.
516 *
517 * For both TCP and UDP, recalculate the layer 4 checksum,
518 * regardless, as we can't tell (here) if data has been
519 * changed or not.
520 */
521 if (tcp != NULL) {
522 err = appr_fixseqack(fin, ip, aps, APR_INC(err));
523 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
524 if (dosum)
525 tcp->th_sum = fr_cksum(fin->fin_qfm, ip,
526 IPPROTO_TCP, tcp);
527 #else
528 tcp->th_sum = fr_cksum(fin->fin_m, ip,
529 IPPROTO_TCP, tcp);
530 #endif
531 } else if ((udp != NULL) && (udp->uh_sum != 0)) {
532 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
533 if (dosum)
534 udp->uh_sum = fr_cksum(fin->fin_qfm, ip,
535 IPPROTO_UDP, udp);
536 #else
537 udp->uh_sum = fr_cksum(fin->fin_m, ip,
538 IPPROTO_UDP, udp);
539 #endif
540 }
541 aps->aps_bytes += fin->fin_plen;
542 aps->aps_pkts++;
543 return 1;
544 }
545 return 0;
546 }
547
548
549 /*
550 * Search for an proxy by the protocol it is being used with and its name.
551 */
552 aproxy_t *appr_lookup(pr, name)
553 u_int pr;
554 char *name;
555 {
556 aproxy_t *ap;
557
558 #if PROXY_DEBUG
559 printf("appr_lookup(%d,%s)\n", pr, name);
560 #endif
561
562 for (ap = ap_proxies; ap->apr_p; ap++)
563 if ((ap->apr_p == pr) &&
564 !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
565 ap->apr_ref++;
566 return ap;
567 }
568
569 for (ap = ap_proxylist; ap; ap = ap->apr_next)
570 if ((ap->apr_p == pr) &&
571 !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) {
572 ap->apr_ref++;
573 return ap;
574 }
575 return NULL;
576 }
577
578
579 void appr_free(ap)
580 aproxy_t *ap;
581 {
582 ap->apr_ref--;
583 }
584
585
586 void aps_free(aps)
587 ap_session_t *aps;
588 {
589 ap_session_t *a, **ap;
590 aproxy_t *apr;
591
592 if (!aps)
593 return;
594
595 for (ap = &ap_sess_list; ((a = *ap) != NULL); ap = &a->aps_next)
596 if (a == aps) {
597 *ap = a->aps_next;
598 break;
599 }
600
601 apr = aps->aps_apr;
602 if ((apr != NULL) && (apr->apr_del != NULL))
603 (*apr->apr_del)(aps);
604
605 if ((aps->aps_data != NULL) && (aps->aps_psiz != 0))
606 KFREES(aps->aps_data, aps->aps_psiz);
607 KFREE(aps);
608 }
609
610
611 /*
612 * returns 2 if ack or seq number in TCP header is changed, returns 0 otherwise
613 */
614 static int appr_fixseqack(fin, ip, aps, inc)
615 fr_info_t *fin;
616 ip_t *ip;
617 ap_session_t *aps;
618 int inc;
619 {
620 int sel, ch = 0, out, nlen;
621 u_32_t seq1, seq2;
622 tcphdr_t *tcp;
623 short inc2;
624
625 tcp = (tcphdr_t *)fin->fin_dp;
626 out = fin->fin_out;
627 /*
628 * ip_len has already been adjusted by 'inc'.
629 */
630 nlen = ip->ip_len;
631 nlen -= (IP_HL(ip) << 2) + (TCP_OFF(tcp) << 2);
632
633 inc2 = inc;
634 inc = (int)inc2;
635
636 if (out != 0) {
637 seq1 = (u_32_t)ntohl(tcp->th_seq);
638 sel = aps->aps_sel[out];
639
640 /* switch to other set ? */
641 if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
642 (seq1 > aps->aps_seqmin[!sel])) {
643 #if PROXY_DEBUG
644 printf("proxy out switch set seq %d -> %d %x > %x\n",
645 sel, !sel, seq1, aps->aps_seqmin[!sel]);
646 #endif
647 sel = aps->aps_sel[out] = !sel;
648 }
649
650 if (aps->aps_seqoff[sel]) {
651 seq2 = aps->aps_seqmin[sel] - aps->aps_seqoff[sel];
652 if (seq1 > seq2) {
653 seq2 = aps->aps_seqoff[sel];
654 seq1 += seq2;
655 tcp->th_seq = htonl(seq1);
656 ch = 1;
657 }
658 }
659
660 if (inc && (seq1 > aps->aps_seqmin[!sel])) {
661 aps->aps_seqmin[sel] = seq1 + nlen - 1;
662 aps->aps_seqoff[sel] = aps->aps_seqoff[sel] + inc;
663 #if PROXY_DEBUG
664 printf("proxy seq set %d at %x to %d + %d\n", sel,
665 aps->aps_seqmin[sel], aps->aps_seqoff[sel],
666 inc);
667 #endif
668 }
669
670 /***/
671
672 seq1 = ntohl(tcp->th_ack);
673 sel = aps->aps_sel[1 - out];
674
675 /* switch to other set ? */
676 if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
677 (seq1 > aps->aps_ackmin[!sel])) {
678 #if PROXY_DEBUG
679 printf("proxy out switch set ack %d -> %d %x > %x\n",
680 sel, !sel, seq1, aps->aps_ackmin[!sel]);
681 #endif
682 sel = aps->aps_sel[1 - out] = !sel;
683 }
684
685 if (aps->aps_ackoff[sel] && (seq1 > aps->aps_ackmin[sel])) {
686 seq2 = aps->aps_ackoff[sel];
687 tcp->th_ack = htonl(seq1 - seq2);
688 ch = 1;
689 }
690 } else {
691 seq1 = ntohl(tcp->th_seq);
692 sel = aps->aps_sel[out];
693
694 /* switch to other set ? */
695 if ((aps->aps_ackmin[!sel] > aps->aps_ackmin[sel]) &&
696 (seq1 > aps->aps_ackmin[!sel])) {
697 #if PROXY_DEBUG
698 printf("proxy in switch set ack %d -> %d %x > %x\n",
699 sel, !sel, seq1, aps->aps_ackmin[!sel]);
700 #endif
701 sel = aps->aps_sel[out] = !sel;
702 }
703
704 if (aps->aps_ackoff[sel]) {
705 seq2 = aps->aps_ackmin[sel] - aps->aps_ackoff[sel];
706 if (seq1 > seq2) {
707 seq2 = aps->aps_ackoff[sel];
708 seq1 += seq2;
709 tcp->th_seq = htonl(seq1);
710 ch = 1;
711 }
712 }
713
714 if (inc && (seq1 > aps->aps_ackmin[!sel])) {
715 aps->aps_ackmin[!sel] = seq1 + nlen - 1;
716 aps->aps_ackoff[!sel] = aps->aps_ackoff[sel] + inc;
717 #if PROXY_DEBUG
718 printf("proxy ack set %d at %x to %d + %d\n", !sel,
719 aps->aps_seqmin[!sel], aps->aps_seqoff[sel],
720 inc);
721 #endif
722 }
723
724 /***/
725
726 seq1 = ntohl(tcp->th_ack);
727 sel = aps->aps_sel[1 - out];
728
729 /* switch to other set ? */
730 if ((aps->aps_seqmin[!sel] > aps->aps_seqmin[sel]) &&
731 (seq1 > aps->aps_seqmin[!sel])) {
732 #if PROXY_DEBUG
733 printf("proxy in switch set seq %d -> %d %x > %x\n",
734 sel, !sel, seq1, aps->aps_seqmin[!sel]);
735 #endif
736 sel = aps->aps_sel[1 - out] = !sel;
737 }
738
739 if (aps->aps_seqoff[sel] != 0) {
740 #if PROXY_DEBUG
741 printf("sel %d seqoff %d seq1 %x seqmin %x\n", sel,
742 aps->aps_seqoff[sel], seq1,
743 aps->aps_seqmin[sel]);
744 #endif
745 if (seq1 > aps->aps_seqmin[sel]) {
746 seq2 = aps->aps_seqoff[sel];
747 tcp->th_ack = htonl(seq1 - seq2);
748 ch = 1;
749 }
750 }
751 }
752 #if PROXY_DEBUG
753 printf("appr_fixseqack: seq %lx ack %lx\n", ntohl(tcp->th_seq),
754 ntohl(tcp->th_ack));
755 #endif
756 return ch ? 2 : 0;
757 }
758
759
760 /*
761 * Initialise hook for kernel application proxies.
762 * Call the initialise routine for all the compiled in kernel proxies.
763 */
764 int appr_init()
765 {
766 aproxy_t *ap;
767 int err = 0;
768
769 for (ap = ap_proxies; ap->apr_p; ap++) {
770 if (ap->apr_init != NULL) {
771 err = (*ap->apr_init)();
772 if (err != 0)
773 break;
774 }
775 }
776 return err;
777 }
778
779
780 /*
781 * Unload hook for kernel application proxies.
782 * Call the finialise routine for all the compiled in kernel proxies.
783 */
784 void appr_unload()
785 {
786 aproxy_t *ap;
787
788 for (ap = ap_proxies; ap->apr_p; ap++)
789 if (ap->apr_fini != NULL)
790 (*ap->apr_fini)();
791 for (ap = ap_proxylist; ap; ap = ap->apr_next)
792 if (ap->apr_fini != NULL)
793 (*ap->apr_fini)();
794 }
Cache object: 33b9db0e0a0ea4e06ba366045cb6205d
|