]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/kext_net.c
xnu-201.tar.gz
[apple/xnu.git] / bsd / net / kext_net.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (C) 1999 Apple Computer, Inc. */
23
24 /*
25 * Support for Network Kernel Extensions: Socket Filters
26 *
27 * Justin C. Walker, 990319
28 */
29
30 #include <sys/types.h>
31 #include <sys/queue.h>
32 #include <sys/malloc.h>
33 #include <sys/param.h>
34 #include <sys/mbuf.h>
35 #include <sys/domain.h>
36 #include <sys/protosw.h>
37 #include <sys/socket.h>
38 #include <machine/spl.h>
39 #include "kext_net.h"
40
41 /* List of kernel extensions (networking) known to kernel */
42 struct nf_list nf_list;
43
44 /*
45 * Register a global filter for the specified protocol
46 * Make a few checks and then insert the new descriptor in the
47 * filter list and, if global, in its protosw's chain.
48 */
49 int
50 register_sockfilter(struct NFDescriptor *nfp, struct NFDescriptor *nfp1,
51 struct protosw *pr, int flags)
52 { int s;
53 static int NF_initted = 0;
54
55 if (nfp == NULL)
56 return(EINVAL);
57
58 s = splhigh();
59 if (!NF_initted)
60 { NF_initted = 1;
61 TAILQ_INIT(&nf_list);
62 }
63
64 /*
65 * Install the extension:
66 * First, put it in the global list of all filters
67 * Then, if global, install in the protosw's list
68 */
69 TAILQ_INSERT_TAIL(&nf_list, nfp, nf_list);
70 if (nfp->nf_flags & NFD_GLOBAL)
71 { if (flags & NFF_BEFORE)
72 { if (nfp1 == NULL)
73 { TAILQ_INSERT_HEAD(&pr->pr_sfilter,
74 nfp, nf_next);
75 } else
76 TAILQ_INSERT_BEFORE(nfp1, nfp, nf_next);
77 } else /* Default: AFTER */
78 { if (nfp1 == NULL)
79 { TAILQ_INSERT_TAIL(&pr->pr_sfilter,
80 nfp, nf_next);
81 } else
82 TAILQ_INSERT_AFTER(&pr->pr_sfilter, nfp1,
83 nfp, nf_next);
84 }
85 }
86 splx(s);
87 return(0);
88 }
89
90 unregister_sockfilter(struct NFDescriptor *nfp, struct protosw *pr, int flags)
91 { int s;
92
93 s = splhigh();
94 TAILQ_REMOVE(&nf_list, nfp, nf_list);
95 /* Only globals are attached to the protosw entry */
96 if (nfp->nf_flags & NFD_GLOBAL)
97 TAILQ_REMOVE(&pr->pr_sfilter, nfp, nf_next);
98 splx(s);
99 return(0);
100 }
101
102 struct NFDescriptor *
103 find_nke(unsigned int handle)
104 { struct NFDescriptor *nfp;
105
106 nfp = nf_list.tqh_first;
107 while (nfp)
108 { if (nfp->nf_handle == handle)
109 return(nfp);
110 nfp = nfp->nf_list.tqe_next;
111 }
112 return(NULL);
113 }
114
115 /*
116 * Insert a previously registered, non-global, NKE into the list of
117 * active NKEs for this socket. Then invoke its "attach/create" entry.
118 * Assumed called with protection in place (spl/mutex/whatever)
119 * XXX: How to which extension is not found, on error.
120 */
121 int
122 nke_insert(struct socket *so, struct so_nke *np)
123 { int s, error;
124 struct kextcb *kp, *kp1;
125 struct NFDescriptor *nf1, *nf2 = NULL;
126
127 if (np->nke_where != NULL)
128 { if ((nf2 = find_nke(np->nke_where)) == NULL)
129 { /* ??? */
130 return(ENXIO);/* XXX */
131 }
132 }
133
134 if ((nf1 = find_nke(np->nke_handle)) == NULL)
135 { /* ??? */
136 return(ENXIO);/* XXX */
137 }
138
139 kp = so->so_ext;
140 kp1 = NULL;
141 if (np->nke_flags & NFF_BEFORE)
142 { if (nf2)
143 { while (kp)
144 { if (kp->e_nfd == nf2)
145 break;
146 kp1 = kp;
147 kp = kp->e_next;
148 }
149 if (kp == NULL)
150 return(ENXIO);/* XXX */
151 }
152 } else
153 { if (nf2)
154 { while (kp)
155 { if (kp->e_nfd == nf2)
156 break;
157 kp1 = kp;
158 kp = kp->e_next;
159 }
160 if (kp == NULL)
161 return(ENXIO);/* XXX */
162 }
163 kp1 = kp;
164 }
165 /*
166 * Here with kp1 pointing to the insertion point.
167 * If null, this is first entry.
168 * Now, create and insert the descriptor.
169 */
170
171 MALLOC(kp, struct kextcb *, sizeof(*kp), M_TEMP, M_WAITOK);
172 if (kp == NULL)
173 return(ENOBUFS); /* so_free will clean up */
174 bzero(kp, sizeof (*kp));
175 if (kp1 == NULL)
176 { kp->e_next = so->so_ext;
177 so->so_ext = kp;
178 } else
179 { kp->e_next = kp1->e_next;
180 kp1->e_next = kp;
181 }
182 kp->e_fcb = NULL;
183 kp->e_nfd = nf1;
184 kp->e_soif = nf1->nf_soif;
185 kp->e_sout = nf1->nf_soutil;
186 /*
187 * Ignore return value for create
188 * Everyone gets a chance at startup
189 */
190 if (kp->e_soif && kp->e_soif->sf_socreate)
191 (*kp->e_soif->sf_socreate)(so, so->so_proto, kp);
192 return(0);
193 }