]>
git.saurik.com Git - apple/xnu.git/blob - bsd/net/kext_net.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (C) 1999 Apple Computer, Inc. */
31 * Support for Network Kernel Extensions: Socket Filters
33 * Justin C. Walker, 990319
36 #include <sys/types.h>
37 #include <sys/queue.h>
38 #include <sys/malloc.h>
39 #include <sys/param.h>
41 #include <sys/domain.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <machine/spl.h>
47 /* List of kernel extensions (networking) known to kernel */
48 struct nf_list nf_list
;
50 static int sockfilter_fix_symantec_bug(struct NFDescriptor
* theirDesc
);
53 * Register a global filter for the specified protocol
54 * Make a few checks and then insert the new descriptor in the
55 * filter list and, if global, in its protosw's chain.
58 register_sockfilter(struct NFDescriptor
*nfp
, struct NFDescriptor
*nfp1
,
59 struct protosw
*pr
, int flags
)
61 static int NF_initted
= 0;
66 /* Fix Symantec's broken NPC kext */
67 if (nfp
->nf_handle
== 0xf1ab02de) {
68 int err
= sockfilter_fix_symantec_bug(nfp
);
80 * Install the extension:
81 * First, put it in the global list of all filters
82 * Then, if global, install in the protosw's list
84 TAILQ_INSERT_TAIL(&nf_list
, nfp
, nf_list
);
85 if (nfp
->nf_flags
& NFD_GLOBAL
)
86 { if (flags
& NFF_BEFORE
)
88 { TAILQ_INSERT_HEAD(&pr
->pr_sfilter
,
91 TAILQ_INSERT_BEFORE(nfp1
, nfp
, nf_next
);
92 } else /* Default: AFTER */
94 { TAILQ_INSERT_TAIL(&pr
->pr_sfilter
,
97 TAILQ_INSERT_AFTER(&pr
->pr_sfilter
, nfp1
,
106 unregister_sockfilter(struct NFDescriptor
*nfp
, struct protosw
*pr
, __unused
int flags
)
110 TAILQ_REMOVE(&nf_list
, nfp
, nf_list
);
111 /* Only globals are attached to the protosw entry */
112 if (nfp
->nf_flags
& NFD_GLOBAL
)
113 TAILQ_REMOVE(&pr
->pr_sfilter
, nfp
, nf_next
);
118 struct NFDescriptor
*
119 find_nke(unsigned int handle
)
120 { struct NFDescriptor
*nfp
;
122 nfp
= nf_list
.tqh_first
;
124 { if (nfp
->nf_handle
== handle
)
126 nfp
= nfp
->nf_list
.tqe_next
;
132 * Insert a previously registered, non-global, NKE into the list of
133 * active NKEs for this socket. Then invoke its "attach/create" entry.
134 * Assumed called with protection in place (spl/mutex/whatever)
135 * XXX: How to which extension is not found, on error.
138 nke_insert(struct socket
*so
, struct so_nke
*np
)
140 struct kextcb
*kp
, *kp1
;
141 struct NFDescriptor
*nf1
, *nf2
= NULL
;
143 if (np
->nke_where
!= NULL
)
144 { if ((nf2
= find_nke(np
->nke_where
)) == NULL
)
146 return(ENXIO
);/* XXX */
150 if ((nf1
= find_nke(np
->nke_handle
)) == NULL
)
152 return(ENXIO
);/* XXX */
157 if (np
->nke_flags
& NFF_BEFORE
)
160 { if (kp
->e_nfd
== nf2
)
166 return(ENXIO
);/* XXX */
171 { if (kp
->e_nfd
== nf2
)
177 return(ENXIO
);/* XXX */
182 * Here with kp1 pointing to the insertion point.
183 * If null, this is first entry.
184 * Now, create and insert the descriptor.
187 MALLOC(kp
, struct kextcb
*, sizeof(*kp
), M_TEMP
, M_WAITOK
);
189 return(ENOBUFS
); /* so_free will clean up */
190 bzero(kp
, sizeof (*kp
));
192 { kp
->e_next
= so
->so_ext
;
195 { kp
->e_next
= kp1
->e_next
;
200 kp
->e_soif
= nf1
->nf_soif
;
201 kp
->e_sout
= nf1
->nf_soutil
;
203 * Ignore return value for create
204 * Everyone gets a chance at startup
206 if (kp
->e_soif
&& kp
->e_soif
->sf_socreate
)
207 (*kp
->e_soif
->sf_socreate
)(so
, so
->so_proto
, kp
);
212 * The following gunk is a fix for Symantec's broken NPC kext
213 * Symantec's NPC kext does not check that the kextcb->e_fcb
214 * is not NULL before derefing it. The result is a panic in
215 * the very few cases where the e_fcb is actually NULL.
217 * This gross chunk of code copies the old function ptrs
218 * supplied by the kext and wraps a few select ones in
219 * our own functions that just check for NULL before
220 * calling in to the kext.
223 static struct sockif
* g_symantec_if_funcs
= NULL
;
224 static struct sockutil
* g_symantec_util_funcs
= NULL
;
225 static int sym_fix_sbflush(struct sockbuf
*, struct kextcb
*);
226 static int sym_fix_sbappend(struct sockbuf
*, struct mbuf
*, struct kextcb
*);
227 static int sym_fix_soclose(struct socket
*, struct kextcb
*);
228 static int sym_fix_sofree(struct socket
*, struct kextcb
*);
229 static int sym_fix_soconnect(struct socket
*, struct sockaddr
*, struct kextcb
*);
230 static int sym_fix_soisconnected(struct socket
*, struct kextcb
*);
231 static int sym_fix_sosend(struct socket
*, struct sockaddr
**, struct uio
**, struct mbuf
**,
232 struct mbuf
**, int *, struct kextcb
*);
233 static int sym_fix_socantrcvmore(struct socket
*, struct kextcb
*);
234 static int sym_fix_socontrol(struct socket
*, struct sockopt
*, struct kextcb
*);
236 static int sockfilter_fix_symantec_bug(struct NFDescriptor
* theirDesc
)
238 if (!g_symantec_if_funcs
) {
239 MALLOC(g_symantec_if_funcs
, struct sockif
*, sizeof(*g_symantec_if_funcs
), M_TEMP
, M_WAITOK
);
241 if (!g_symantec_if_funcs
)
244 *g_symantec_if_funcs
= *theirDesc
->nf_soif
;
247 if (!g_symantec_util_funcs
) {
248 MALLOC(g_symantec_util_funcs
, struct sockutil
*, sizeof(*g_symantec_util_funcs
), M_TEMP
, M_WAITOK
);
250 if (!g_symantec_util_funcs
)
253 *g_symantec_util_funcs
= *theirDesc
->nf_soutil
;
256 if (theirDesc
->nf_soutil
->su_sbflush
)
257 theirDesc
->nf_soutil
->su_sbflush
= sym_fix_sbflush
;
258 if (theirDesc
->nf_soutil
->su_sbappend
)
259 theirDesc
->nf_soutil
->su_sbappend
= sym_fix_sbappend
;
260 if (theirDesc
->nf_soif
->sf_soclose
)
261 theirDesc
->nf_soif
->sf_soclose
= sym_fix_soclose
;
262 if (theirDesc
->nf_soif
->sf_sofree
)
263 theirDesc
->nf_soif
->sf_sofree
= sym_fix_sofree
;
264 if (theirDesc
->nf_soif
->sf_soconnect
)
265 theirDesc
->nf_soif
->sf_soconnect
= sym_fix_soconnect
;
266 if (theirDesc
->nf_soif
->sf_soisconnected
)
267 theirDesc
->nf_soif
->sf_soisconnected
= sym_fix_soisconnected
;
268 if (theirDesc
->nf_soif
->sf_sosend
)
269 theirDesc
->nf_soif
->sf_sosend
= sym_fix_sosend
;
270 if (theirDesc
->nf_soif
->sf_socantrcvmore
)
271 theirDesc
->nf_soif
->sf_socantrcvmore
= sym_fix_socantrcvmore
;
272 if (theirDesc
->nf_soif
->sf_socontrol
)
273 theirDesc
->nf_soif
->sf_socontrol
= sym_fix_socontrol
;
278 static int sym_fix_sbflush(struct sockbuf
*p1
, struct kextcb
*p2
)
280 if (p2
->e_fcb
!= NULL
&& g_symantec_util_funcs
)
281 return g_symantec_util_funcs
->su_sbflush(p1
, p2
);
286 static int sym_fix_sbappend(struct sockbuf
*p1
, struct mbuf
*p2
, struct kextcb
*p3
)
288 if (p3
->e_fcb
!= NULL
&& g_symantec_util_funcs
)
289 return g_symantec_util_funcs
->su_sbappend(p1
, p2
, p3
);
294 static int sym_fix_soclose(struct socket
*p1
, struct kextcb
*p2
)
296 if (p2
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
297 return g_symantec_if_funcs
->sf_soclose(p1
, p2
);
302 static int sym_fix_sofree(struct socket
*p1
, struct kextcb
*p2
)
304 if (p2
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
305 return g_symantec_if_funcs
->sf_sofree(p1
, p2
);
310 static int sym_fix_soconnect(struct socket
*p1
, struct sockaddr
*p2
, struct kextcb
*p3
)
312 if (p3
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
313 return g_symantec_if_funcs
->sf_soconnect(p1
, p2
, p3
);
318 static int sym_fix_soisconnected(struct socket
*p1
, struct kextcb
*p2
)
320 if (p2
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
321 return g_symantec_if_funcs
->sf_soisconnected(p1
, p2
);
326 static int sym_fix_sosend(struct socket
*p1
, struct sockaddr
**p2
, struct uio
**p3
, struct mbuf
**p4
,
327 struct mbuf
**p5
, int *p6
, struct kextcb
*p7
)
329 if (p7
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
330 return g_symantec_if_funcs
->sf_sosend(p1
, p2
, p3
, p4
, p5
, p6
, p7
);
335 static int sym_fix_socantrcvmore(struct socket
*p1
, struct kextcb
*p2
)
337 if (p2
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
338 return g_symantec_if_funcs
->sf_socantrcvmore(p1
, p2
);
343 static int sym_fix_socontrol(struct socket
*p1
, struct sockopt
*p2
, struct kextcb
*p3
)
345 if (p3
->e_fcb
!= NULL
&& g_symantec_if_funcs
)
346 return g_symantec_if_funcs
->sf_socontrol(p1
, p2
, p3
);