4 * Copyright (C) 1997-2003 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 #if defined(KERNEL) || defined(_KERNEL)
14 #include <sys/errno.h>
15 #include <sys/types.h>
16 #include <sys/param.h>
20 # include <sys/fcntl.h>
22 #if !defined(_KERNEL) && !defined(__KERNEL__)
35 # include <sys/protosw.h>
37 #include <sys/socket.h>
39 # if !defined(__NetBSD__) && !defined(sun) && !defined(__osf__) && \
40 !defined(__OpenBSD__) && !defined(__hpux) && !defined(__sgi) && \
42 # include <sys/ctype.h>
44 # include <sys/systm.h>
45 # if !defined(__SVR4) && !defined(__svr4__)
46 # include <sys/mbuf.h>
49 #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
50 # include <sys/filio.h>
51 # include <sys/fcntl.h>
52 # if (__FreeBSD_version >= 300000) && !defined(IPFILTER_LKM)
53 # include "opt_ipfilter.h"
56 # include <sys/ioctl.h>
58 #if defined(__SVR4) || defined(__svr4__)
59 # include <sys/byteorder.h>
61 # include <sys/dditypes.h>
63 # include <sys/stream.h>
64 # include <sys/kmem.h>
67 # include <sys/queue.h>
73 #include <netinet/in.h>
74 #include <netinet/in_systm.h>
75 #include <netinet/ip.h>
77 # include <netinet/ip_var.h>
79 #include <netinet/tcp.h>
80 #include <netinet/udp.h>
81 #include <netinet/ip_icmp.h>
82 #include "netinet/ip_compat.h"
83 #include <netinet/tcpip.h>
84 #include "netinet/ip_fil.h"
85 #include "netinet/ip_nat.h"
86 #include "netinet/ip_state.h"
87 #include "netinet/ip_proxy.h"
88 #if (__FreeBSD_version >= 300000)
89 # include <sys/malloc.h>
94 #include "netinet/ip_ftp_pxy.c"
95 #include "netinet/ip_rcmd_pxy.c"
96 # include "netinet/ip_pptp_pxy.c"
98 # include "netinet/ip_irc_pxy.c"
99 # include "netinet/ip_raudio_pxy.c"
100 # include "netinet/ip_h323_pxy.c"
101 # include "netinet/ip_netbios_pxy.c"
103 #include "netinet/ip_ipsec_pxy.c"
104 #include "netinet/ip_rpcb_pxy.c"
107 #if defined(__NetBSD__)
108 #include <sys/cdefs.h>
109 __KERNEL_RCSID(0, "$NetBSD$");
111 static const char rcsid
[] = "@(#)Id: ip_proxy.c,v 2.62.2.23 2009/07/22 01:41:14 darrenr Exp";
116 static int appr_fixseqack
__P((fr_info_t
*, ip_t
*, ap_session_t
*, int ));
119 #define AP_SESS_SIZE 53
122 int ipf_proxy_debug
= 0;
124 int ipf_proxy_debug
= 2;
126 ap_session_t
*ap_sess_tab
[AP_SESS_SIZE
];
127 ap_session_t
*ap_sess_list
= NULL
;
128 aproxy_t
*ap_proxylist
= NULL
;
129 aproxy_t ap_proxies
[] = {
131 { NULL
, "ftp", (char)IPPROTO_TCP
, 0, 0, ippr_ftp_init
, ippr_ftp_fini
,
132 ippr_ftp_new
, NULL
, ippr_ftp_in
, ippr_ftp_out
, NULL
, NULL
},
135 { NULL
, "irc", (char)IPPROTO_TCP
, 0, 0, ippr_irc_init
, ippr_irc_fini
,
136 ippr_irc_new
, NULL
, NULL
, ippr_irc_out
, NULL
, NULL
},
138 #ifdef IPF_RCMD_PROXY
139 { NULL
, "rcmd", (char)IPPROTO_TCP
, 0, 0, ippr_rcmd_init
, ippr_rcmd_fini
,
140 ippr_rcmd_new
, NULL
, ippr_rcmd_in
, ippr_rcmd_out
, NULL
, NULL
},
142 #ifdef IPF_RAUDIO_PROXY
143 { NULL
, "raudio", (char)IPPROTO_TCP
, 0, 0, ippr_raudio_init
, ippr_raudio_fini
,
144 ippr_raudio_new
, NULL
, ippr_raudio_in
, ippr_raudio_out
, NULL
, NULL
},
146 #ifdef IPF_MSNRPC_PROXY
147 { NULL
, "msnrpc", (char)IPPROTO_TCP
, 0, 0, ippr_msnrpc_init
, ippr_msnrpc_fini
,
148 ippr_msnrpc_new
, NULL
, ippr_msnrpc_in
, ippr_msnrpc_out
, NULL
, NULL
},
150 #ifdef IPF_NETBIOS_PROXY
151 { NULL
, "netbios", (char)IPPROTO_UDP
, 0, 0, ippr_netbios_init
, ippr_netbios_fini
,
152 NULL
, NULL
, NULL
, ippr_netbios_out
, NULL
, NULL
},
154 #ifdef IPF_IPSEC_PROXY
155 { NULL
, "ipsec", (char)IPPROTO_UDP
, 0, 0,
156 ippr_ipsec_init
, ippr_ipsec_fini
, ippr_ipsec_new
, ippr_ipsec_del
,
157 ippr_ipsec_inout
, ippr_ipsec_inout
, ippr_ipsec_match
, NULL
},
159 #ifdef IPF_PPTP_PROXY
160 { NULL
, "pptp", (char)IPPROTO_TCP
, 0, 0,
161 ippr_pptp_init
, ippr_pptp_fini
, ippr_pptp_new
, ippr_pptp_del
,
162 ippr_pptp_inout
, ippr_pptp_inout
, NULL
, NULL
},
164 #ifdef IPF_H323_PROXY
165 { NULL
, "h323", (char)IPPROTO_TCP
, 0, 0, ippr_h323_init
, ippr_h323_fini
,
166 ippr_h323_new
, ippr_h323_del
, ippr_h323_in
, NULL
, NULL
, NULL
},
167 { NULL
, "h245", (char)IPPROTO_TCP
, 0, 0, NULL
, NULL
,
168 ippr_h245_new
, NULL
, NULL
, ippr_h245_out
, NULL
, NULL
},
170 #ifdef IPF_RPCB_PROXY
172 { NULL
, "rpcbt", (char)IPPROTO_TCP
, 0, 0,
173 ippr_rpcb_init
, ippr_rpcb_fini
, ippr_rpcb_new
, ippr_rpcb_del
,
174 ippr_rpcb_in
, ippr_rpcb_out
, NULL
, NULL
},
176 { NULL
, "rpcbu", (char)IPPROTO_UDP
, 0, 0,
177 ippr_rpcb_init
, ippr_rpcb_fini
, ippr_rpcb_new
, ippr_rpcb_del
,
178 ippr_rpcb_in
, ippr_rpcb_out
, NULL
, NULL
},
180 { NULL
, "", '\0', 0, 0, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
}
184 * Dynamically add a new kernel proxy. Ensure that it is unique in the
185 * collection compiled in and dynamically added.
192 for (a
= ap_proxies
; a
->apr_p
; a
++)
193 if ((a
->apr_p
== ap
->apr_p
) &&
194 !strncmp(a
->apr_label
, ap
->apr_label
,
195 sizeof(ap
->apr_label
))) {
196 if (ipf_proxy_debug
> 1)
197 printf("appr_add: %s/%d already present (B)\n",
198 a
->apr_label
, a
->apr_p
);
202 for (a
= ap_proxylist
; (a
!= NULL
); a
= a
->apr_next
)
203 if ((a
->apr_p
== ap
->apr_p
) &&
204 !strncmp(a
->apr_label
, ap
->apr_label
,
205 sizeof(ap
->apr_label
))) {
206 if (ipf_proxy_debug
> 1)
207 printf("appr_add: %s/%d already present (D)\n",
208 a
->apr_label
, a
->apr_p
);
211 ap
->apr_next
= ap_proxylist
;
213 if (ap
->apr_init
!= NULL
)
214 return (*ap
->apr_init
)();
220 * Check to see if the proxy this control request has come through for
221 * exists, and if it does and it has a control function then invoke that
230 a
= appr_lookup(ctl
->apc_p
, ctl
->apc_label
);
232 if (ipf_proxy_debug
> 1)
233 printf("appr_ctl: can't find %s/%d\n",
234 ctl
->apc_label
, ctl
->apc_p
);
236 } else if (a
->apr_ctl
== NULL
) {
237 if (ipf_proxy_debug
> 1)
238 printf("appr_ctl: no ctl function for %s/%d\n",
239 ctl
->apc_label
, ctl
->apc_p
);
242 error
= (*a
->apr_ctl
)(a
, ctl
);
243 if ((error
!= 0) && (ipf_proxy_debug
> 1))
244 printf("appr_ctl: %s/%d ctl error %d\n",
245 a
->apr_label
, a
->apr_p
, error
);
252 * Delete a proxy that has been added dynamically from those available.
253 * If it is in use, return 1 (do not destroy NOW), not in use 0 or -1
254 * if it cannot be matched.
261 for (app
= &ap_proxylist
; ((a
= *app
) != NULL
); app
= &a
->apr_next
)
263 a
->apr_flags
|= APR_DELETE
;
265 if (ap
->apr_ref
!= 0) {
266 if (ipf_proxy_debug
> 2)
267 printf("appr_del: orphaning %s/%d\n",
268 ap
->apr_label
, ap
->apr_p
);
273 if (ipf_proxy_debug
> 1)
274 printf("appr_del: proxy %lx not found\n", (u_long
)ap
);
280 * Return 1 if the packet is a good match against a proxy, else 0.
282 int appr_ok(fin
, tcp
, nat
)
287 aproxy_t
*apr
= nat
->in_apr
;
288 u_short dport
= nat
->in_dport
;
290 if ((apr
== NULL
) || (apr
->apr_flags
& APR_DELETE
) ||
291 (fin
->fin_p
!= apr
->apr_p
))
293 if ((tcp
== NULL
) && dport
)
299 int appr_ioctl(data
, cmd
, mode
, ctx
)
309 mode
= mode
; /* LINT */
314 error
= BCOPYIN(data
, &ctl
, sizeof(ctl
));
319 if (ctl
.apc_dsize
> 0) {
320 KMALLOCS(ptr
, void *, ctl
.apc_dsize
);
324 error
= copyinptr(ctl
.apc_data
, ptr
,
335 error
= appr_ctl(&ctl
);
338 KFREES(ptr
, ctl
.apc_dsize
);
350 * If a proxy has a match function, call that to do extended packet
353 int appr_match(fin
, nat
)
362 if (ipf_proxy_debug
> 8)
363 printf("appr_match(%lx,%lx) aps %lx ptr %lx\n",
364 (u_long
)fin
, (u_long
)nat
, (u_long
)nat
->nat_aps
,
367 if ((fin
->fin_flx
& (FI_SHORT
|FI_BAD
)) != 0) {
368 if (ipf_proxy_debug
> 0)
369 printf("appr_match: flx 0x%x (BAD|SHORT)\n",
375 if ((apr
== NULL
) || (apr
->apr_flags
& APR_DELETE
)) {
376 if (ipf_proxy_debug
> 0)
377 printf("appr_match:apr %lx apr_flags 0x%x\n",
378 (u_long
)apr
, apr
? apr
->apr_flags
: 0);
382 if (apr
->apr_match
!= NULL
) {
383 result
= (*apr
->apr_match
)(fin
, nat
->nat_aps
, nat
);
385 if (ipf_proxy_debug
> 4)
386 printf("appr_match: result %d\n", result
);
395 * Allocate a new application proxy structure and fill it in with the
396 * relevant details. call the init function once complete, prior to
399 int appr_new(fin
, nat
)
403 register ap_session_t
*aps
;
406 if (ipf_proxy_debug
> 8)
407 printf("appr_new(%lx,%lx) \n", (u_long
)fin
, (u_long
)nat
);
409 if ((nat
->nat_ptr
== NULL
) || (nat
->nat_aps
!= NULL
)) {
410 if (ipf_proxy_debug
> 0)
411 printf("appr_new: nat_ptr %lx nat_aps %lx\n",
412 (u_long
)nat
->nat_ptr
, (u_long
)nat
->nat_aps
);
416 apr
= nat
->nat_ptr
->in_apr
;
418 if ((apr
->apr_flags
& APR_DELETE
) ||
419 (fin
->fin_p
!= apr
->apr_p
)) {
420 if (ipf_proxy_debug
> 2)
421 printf("appr_new: apr_flags 0x%x p %d/%d\n",
422 apr
->apr_flags
, fin
->fin_p
, apr
->apr_p
);
426 KMALLOC(aps
, ap_session_t
*);
428 if (ipf_proxy_debug
> 0)
429 printf("appr_new: malloc failed (%lu)\n",
430 (u_long
)sizeof(ap_session_t
));
434 bzero((char *)aps
, sizeof(*aps
));
435 aps
->aps_p
= fin
->fin_p
;
436 aps
->aps_data
= NULL
;
439 if (apr
->apr_new
!= NULL
)
440 if ((*apr
->apr_new
)(fin
, aps
, nat
) == -1) {
441 if ((aps
->aps_data
!= NULL
) && (aps
->aps_psiz
!= 0)) {
442 KFREES(aps
->aps_data
, aps
->aps_psiz
);
445 if (ipf_proxy_debug
> 2)
446 printf("appr_new: new(%lx) failed\n",
447 (u_long
)apr
->apr_new
);
451 aps
->aps_next
= ap_sess_list
;
460 * Check to see if a packet should be passed through an active proxy routine
461 * if one has been setup for it. We don't need to check the checksum here if
462 * IPFILTER_CKSUM is defined because if it is, a failed check causes FI_BAD
465 int appr_check(fin
, nat
)
469 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
470 # if defined(ICK_VALID)
475 tcphdr_t
*tcp
= NULL
;
476 udphdr_t
*udp
= NULL
;
482 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
486 if (fin
->fin_flx
& FI_BAD
) {
487 if (ipf_proxy_debug
> 0)
488 printf("appr_check: flx 0x%x (BAD)\n", fin
->fin_flx
);
492 #ifndef IPFILTER_CKSUM
493 if ((fin
->fin_out
== 0) && (fr_checkl4sum(fin
) == -1)) {
494 if (ipf_proxy_debug
> 0)
495 printf("appr_check: l4 checksum failure %d\n",
497 if (fin
->fin_p
== IPPROTO_TCP
)
498 frstats
[fin
->fin_out
].fr_tcpbad
++;
504 if ((aps
!= NULL
) && (aps
->aps_p
== fin
->fin_p
)) {
506 * If there is data in this packet to be proxied then try and
507 * get it all into the one buffer, else drop it.
509 #if defined(MENTAT) || defined(HAVE_M_PULLDOWN)
510 if ((fin
->fin_dlen
> 0) && !(fin
->fin_flx
& FI_COALESCE
))
511 if (fr_coalesce(fin
) == -1) {
512 if (ipf_proxy_debug
> 0)
513 printf("appr_check: fr_coalesce failed %x\n", fin
->fin_flx
);
522 tcp
= (tcphdr_t
*)fin
->fin_dp
;
524 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6) && defined(ICK_VALID)
526 if (dohwcksum
&& (m
->b_ick_flag
== ICK_VALID
))
530 * Don't bother the proxy with these...or in fact,
531 * should we free up proxy stuff when seen?
533 if ((fin
->fin_tcpf
& TH_RST
) != 0)
537 udp
= (udphdr_t
*)fin
->fin_dp
;
545 if (fin
->fin_out
!= 0) {
546 if (apr
->apr_outpkt
!= NULL
)
547 err
= (*apr
->apr_outpkt
)(fin
, aps
, nat
);
549 if (apr
->apr_inpkt
!= NULL
)
550 err
= (*apr
->apr_inpkt
)(fin
, aps
, nat
);
554 if (((ipf_proxy_debug
> 0) && (rv
!= 0)) ||
555 (ipf_proxy_debug
> 8))
556 printf("appr_check: out %d err %x rv %d\n",
557 fin
->fin_out
, err
, rv
);
568 * If err != 0 then the data size of the packet has changed
569 * so we need to recalculate the header checksums for the
572 #if !defined(_KERNEL) || defined(MENTAT) || defined(__sgi)
574 short adjlen
= err
& 0xffff;
576 s1
= LONG_SUM(fin
->fin_plen
- adjlen
);
577 s2
= LONG_SUM(fin
->fin_plen
);
578 CALC_SUMD(s1
, s2
, sd
);
579 fix_outcksum(fin
, &ip
->ip_sum
, sd
);
585 * For TCP packets, we may need to adjust the sequence and
586 * acknowledgement numbers to reflect changes in size of the
589 * For both TCP and UDP, recalculate the layer 4 checksum,
590 * regardless, as we can't tell (here) if data has been
594 err
= appr_fixseqack(fin
, ip
, aps
, APR_INC(err
));
595 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
597 tcp
->th_sum
= fr_cksum(fin
->fin_qfm
, ip
,
601 tcp
->th_sum
= fr_cksum(fin
->fin_m
, ip
,
605 } else if ((udp
!= NULL
) && (udp
->uh_sum
!= 0)) {
606 #if SOLARIS && defined(_KERNEL) && (SOLARIS2 >= 6)
608 udp
->uh_sum
= fr_cksum(fin
->fin_qfm
, ip
,
612 udp
->uh_sum
= fr_cksum(fin
->fin_m
, ip
,
618 aps
->aps_bytes
+= fin
->fin_plen
;
627 * Search for an proxy by the protocol it is being used with and its name.
629 aproxy_t
*appr_lookup(pr
, name
)
635 if (ipf_proxy_debug
> 8)
636 printf("appr_lookup(%d,%s)\n", pr
, name
);
638 for (ap
= ap_proxies
; ap
->apr_p
; ap
++)
639 if ((ap
->apr_p
== pr
) &&
640 !strncmp(name
, ap
->apr_label
, sizeof(ap
->apr_label
))) {
645 for (ap
= ap_proxylist
; ap
; ap
= ap
->apr_next
)
646 if ((ap
->apr_p
== pr
) &&
647 !strncmp(name
, ap
->apr_label
, sizeof(ap
->apr_label
))) {
651 if (ipf_proxy_debug
> 2)
652 printf("appr_lookup: failed for %d/%s\n", pr
, name
);
667 ap_session_t
*a
, **ap
;
673 for (ap
= &ap_sess_list
; ((a
= *ap
) != NULL
); ap
= &a
->aps_next
)
680 if ((apr
!= NULL
) && (apr
->apr_del
!= NULL
))
681 (*apr
->apr_del
)(aps
);
683 if ((aps
->aps_data
!= NULL
) && (aps
->aps_psiz
!= 0))
684 KFREES(aps
->aps_data
, aps
->aps_psiz
);
691 * returns 2 if ack or seq number in TCP header is changed, returns 0 otherwise
693 static int appr_fixseqack(fin
, ip
, aps
, inc
)
699 int sel
, ch
= 0, out
, nlen
;
704 tcp
= (tcphdr_t
*)fin
->fin_dp
;
707 * fin->fin_plen has already been adjusted by 'inc'.
709 nlen
= fin
->fin_plen
;
710 nlen
-= (IP_HL(ip
) << 2) + (TCP_OFF(tcp
) << 2);
716 seq1
= (u_32_t
)ntohl(tcp
->th_seq
);
717 sel
= aps
->aps_sel
[out
];
719 /* switch to other set ? */
720 if ((aps
->aps_seqmin
[!sel
] > aps
->aps_seqmin
[sel
]) &&
721 (seq1
> aps
->aps_seqmin
[!sel
])) {
722 if (ipf_proxy_debug
> 7)
723 printf("proxy out switch set seq %d -> %d %x > %x\n",
725 aps
->aps_seqmin
[!sel
]);
726 sel
= aps
->aps_sel
[out
] = !sel
;
729 if (aps
->aps_seqoff
[sel
]) {
730 seq2
= aps
->aps_seqmin
[sel
] - aps
->aps_seqoff
[sel
];
732 seq2
= aps
->aps_seqoff
[sel
];
734 tcp
->th_seq
= htonl(seq1
);
739 if (inc
&& (seq1
> aps
->aps_seqmin
[!sel
])) {
740 aps
->aps_seqmin
[sel
] = seq1
+ nlen
- 1;
741 aps
->aps_seqoff
[sel
] = aps
->aps_seqoff
[sel
] + inc
;
742 if (ipf_proxy_debug
> 7)
743 printf("proxy seq set %d at %x to %d + %d\n",
744 sel
, aps
->aps_seqmin
[sel
],
745 aps
->aps_seqoff
[sel
], inc
);
750 seq1
= ntohl(tcp
->th_ack
);
751 sel
= aps
->aps_sel
[1 - out
];
753 /* switch to other set ? */
754 if ((aps
->aps_ackmin
[!sel
] > aps
->aps_ackmin
[sel
]) &&
755 (seq1
> aps
->aps_ackmin
[!sel
])) {
756 if (ipf_proxy_debug
> 7)
757 printf("proxy out switch set ack %d -> %d %x > %x\n",
759 aps
->aps_ackmin
[!sel
]);
760 sel
= aps
->aps_sel
[1 - out
] = !sel
;
763 if (aps
->aps_ackoff
[sel
] && (seq1
> aps
->aps_ackmin
[sel
])) {
764 seq2
= aps
->aps_ackoff
[sel
];
765 tcp
->th_ack
= htonl(seq1
- seq2
);
769 seq1
= ntohl(tcp
->th_seq
);
770 sel
= aps
->aps_sel
[out
];
772 /* switch to other set ? */
773 if ((aps
->aps_ackmin
[!sel
] > aps
->aps_ackmin
[sel
]) &&
774 (seq1
> aps
->aps_ackmin
[!sel
])) {
775 if (ipf_proxy_debug
> 7)
776 printf("proxy in switch set ack %d -> %d %x > %x\n",
777 sel
, !sel
, seq1
, aps
->aps_ackmin
[!sel
]);
778 sel
= aps
->aps_sel
[out
] = !sel
;
781 if (aps
->aps_ackoff
[sel
]) {
782 seq2
= aps
->aps_ackmin
[sel
] - aps
->aps_ackoff
[sel
];
784 seq2
= aps
->aps_ackoff
[sel
];
786 tcp
->th_seq
= htonl(seq1
);
791 if (inc
&& (seq1
> aps
->aps_ackmin
[!sel
])) {
792 aps
->aps_ackmin
[!sel
] = seq1
+ nlen
- 1;
793 aps
->aps_ackoff
[!sel
] = aps
->aps_ackoff
[sel
] + inc
;
795 if (ipf_proxy_debug
> 7)
796 printf("proxy ack set %d at %x to %d + %d\n",
797 !sel
, aps
->aps_seqmin
[!sel
],
798 aps
->aps_seqoff
[sel
], inc
);
803 seq1
= ntohl(tcp
->th_ack
);
804 sel
= aps
->aps_sel
[1 - out
];
806 /* switch to other set ? */
807 if ((aps
->aps_seqmin
[!sel
] > aps
->aps_seqmin
[sel
]) &&
808 (seq1
> aps
->aps_seqmin
[!sel
])) {
809 if (ipf_proxy_debug
> 7)
810 printf("proxy in switch set seq %d -> %d %x > %x\n",
811 sel
, !sel
, seq1
, aps
->aps_seqmin
[!sel
]);
812 sel
= aps
->aps_sel
[1 - out
] = !sel
;
815 if (aps
->aps_seqoff
[sel
] != 0) {
816 if (ipf_proxy_debug
> 7)
817 printf("sel %d seqoff %d seq1 %x seqmin %x\n",
818 sel
, aps
->aps_seqoff
[sel
], seq1
,
819 aps
->aps_seqmin
[sel
]);
820 if (seq1
> aps
->aps_seqmin
[sel
]) {
821 seq2
= aps
->aps_seqoff
[sel
];
822 tcp
->th_ack
= htonl(seq1
- seq2
);
828 if (ipf_proxy_debug
> 8)
829 printf("appr_fixseqack: seq %x ack %x\n",
830 (u_32_t
)ntohl(tcp
->th_seq
), (u_32_t
)ntohl(tcp
->th_ack
));
837 * Initialise hook for kernel application proxies.
838 * Call the initialise routine for all the compiled in kernel proxies.
845 for (ap
= ap_proxies
; ap
->apr_p
; ap
++) {
846 if (ap
->apr_init
!= NULL
) {
847 err
= (*ap
->apr_init
)();
857 * Unload hook for kernel application proxies.
858 * Call the finialise routine for all the compiled in kernel proxies.
864 for (ap
= ap_proxies
; ap
->apr_p
; ap
++)
865 if (ap
->apr_fini
!= NULL
)
867 for (ap
= ap_proxylist
; ap
; ap
= ap
->apr_next
)
868 if (ap
->apr_fini
!= NULL
)