| @@ -1,547 +1,547 @@ | | | @@ -1,547 +1,547 @@ |
1 | /* $NetBSD: natm.c,v 1.49 2015/05/02 17:18:04 rtr Exp $ */ | | 1 | /* $NetBSD: natm.c,v 1.50 2015/11/06 21:33:07 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996 Charles D. Cranor and Washington University. | | 4 | * Copyright (c) 1996 Charles D. Cranor and Washington University. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | /* | | 28 | /* |
29 | * natm.c: native mode ATM access (both aal0 and aal5). | | 29 | * natm.c: native mode ATM access (both aal0 and aal5). |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.49 2015/05/02 17:18:04 rtr Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.50 2015/11/06 21:33:07 christos Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/kmem.h> | | 36 | #include <sys/kmem.h> |
37 | #include <sys/systm.h> | | 37 | #include <sys/systm.h> |
38 | #include <sys/kernel.h> | | 38 | #include <sys/kernel.h> |
39 | #include <sys/domain.h> | | 39 | #include <sys/domain.h> |
40 | #include <sys/ioctl.h> | | 40 | #include <sys/ioctl.h> |
41 | #include <sys/protosw.h> | | 41 | #include <sys/protosw.h> |
42 | #include <sys/mbuf.h> | | 42 | #include <sys/mbuf.h> |
43 | #include <sys/socket.h> | | 43 | #include <sys/socket.h> |
44 | #include <sys/socketvar.h> | | 44 | #include <sys/socketvar.h> |
45 | | | 45 | |
46 | #include <net/if.h> | | 46 | #include <net/if.h> |
47 | #include <net/if_atm.h> | | 47 | #include <net/if_atm.h> |
48 | #include <net/netisr.h> | | 48 | #include <net/netisr.h> |
49 | #include <net/route.h> | | 49 | #include <net/route.h> |
50 | | | 50 | |
51 | #include <netinet/in.h> | | 51 | #include <netinet/in.h> |
52 | | | 52 | |
53 | #include <netnatm/natm.h> | | 53 | #include <netnatm/natm.h> |
54 | | | 54 | |
55 | u_long natm5_sendspace = 16*1024; | | 55 | u_long natm5_sendspace = 16*1024; |
56 | u_long natm5_recvspace = 16*1024; | | 56 | u_long natm5_recvspace = 16*1024; |
57 | | | 57 | |
58 | u_long natm0_sendspace = 16*1024; | | 58 | u_long natm0_sendspace = 16*1024; |
59 | u_long natm0_recvspace = 16*1024; | | 59 | u_long natm0_recvspace = 16*1024; |
60 | | | 60 | |
61 | static int | | 61 | static int |
62 | natm_attach(struct socket *so, int proto) | | 62 | natm_attach(struct socket *so, int proto) |
63 | { | | 63 | { |
64 | int error = 0; | | 64 | int error = 0; |
65 | struct natmpcb *npcb; | | 65 | struct natmpcb *npcb; |
66 | | | 66 | |
67 | KASSERT(so->so_pcb == NULL); | | 67 | KASSERT(so->so_pcb == NULL); |
68 | sosetlock(so); | | 68 | sosetlock(so); |
69 | | | 69 | |
70 | if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { | | 70 | if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { |
71 | if (proto == PROTO_NATMAAL5) | | 71 | if (proto == PROTO_NATMAAL5) |
72 | error = soreserve(so, natm5_sendspace, natm5_recvspace); | | 72 | error = soreserve(so, natm5_sendspace, natm5_recvspace); |
73 | else | | 73 | else |
74 | error = soreserve(so, natm0_sendspace, natm0_recvspace); | | 74 | error = soreserve(so, natm0_sendspace, natm0_recvspace); |
75 | if (error) | | 75 | if (error) |
76 | return error; | | 76 | return error; |
77 | } | | 77 | } |
78 | npcb = npcb_alloc(true); | | 78 | npcb = npcb_alloc(true); |
79 | npcb->npcb_socket = so; | | 79 | npcb->npcb_socket = so; |
80 | so->so_pcb = npcb; | | 80 | so->so_pcb = npcb; |
81 | return error; | | 81 | return error; |
82 | } | | 82 | } |
83 | | | 83 | |
84 | static void | | 84 | static void |
85 | natm_detach(struct socket *so) | | 85 | natm_detach(struct socket *so) |
86 | { | | 86 | { |
87 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; | | 87 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; |
88 | | | 88 | |
89 | /* | | 89 | /* |
90 | * we turn on 'drain' *before* we sofree. | | 90 | * we turn on 'drain' *before* we sofree. |
91 | */ | | 91 | */ |
92 | | | 92 | |
93 | npcb_free(npcb, NPCB_DESTROY); /* drain */ | | 93 | npcb_free(npcb, NPCB_DESTROY); /* drain */ |
94 | so->so_pcb = NULL; | | 94 | so->so_pcb = NULL; |
95 | /* sofree drops the lock */ | | 95 | /* sofree drops the lock */ |
96 | sofree(so); | | 96 | sofree(so); |
97 | mutex_enter(softnet_lock); | | 97 | mutex_enter(softnet_lock); |
98 | } | | 98 | } |
99 | | | 99 | |
100 | static int | | 100 | static int |
101 | natm_accept(struct socket *so, struct sockaddr *nam) | | 101 | natm_accept(struct socket *so, struct sockaddr *nam) |
102 | { | | 102 | { |
103 | KASSERT(solocked(so)); | | 103 | KASSERT(solocked(so)); |
104 | | | 104 | |
105 | return EOPNOTSUPP; | | 105 | return EOPNOTSUPP; |
106 | } | | 106 | } |
107 | | | 107 | |
108 | static int | | 108 | static int |
109 | natm_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) | | 109 | natm_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) |
110 | { | | 110 | { |
111 | KASSERT(solocked(so)); | | 111 | KASSERT(solocked(so)); |
112 | | | 112 | |
113 | return EOPNOTSUPP; | | 113 | return EOPNOTSUPP; |
114 | } | | 114 | } |
115 | | | 115 | |
116 | static int | | 116 | static int |
117 | natm_listen(struct socket *so, struct lwp *l) | | 117 | natm_listen(struct socket *so, struct lwp *l) |
118 | { | | 118 | { |
119 | KASSERT(solocked(so)); | | 119 | KASSERT(solocked(so)); |
120 | | | 120 | |
121 | return EOPNOTSUPP; | | 121 | return EOPNOTSUPP; |
122 | } | | 122 | } |
123 | | | 123 | |
124 | static int | | 124 | static int |
125 | natm_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) | | 125 | natm_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) |
126 | { | | 126 | { |
127 | int error = 0, s2; | | 127 | int error = 0, s2; |
128 | struct natmpcb *npcb; | | 128 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; |
129 | struct sockaddr_natm *snatm = (struct sockaddr_natm *)nam; | | 129 | struct sockaddr_natm *snatm = (struct sockaddr_natm *)nam; |
130 | struct atm_pseudoioctl api; | | 130 | struct atm_pseudoioctl api; |
131 | struct atm_pseudohdr *aph; | | 131 | struct atm_pseudohdr *aph; |
132 | struct ifnet *ifp; | | 132 | struct ifnet *ifp; |
133 | int proto = so->so_proto->pr_protocol; | | 133 | int proto = so->so_proto->pr_protocol; |
134 | | | 134 | |
135 | KASSERT(solocked(so)); | | 135 | KASSERT(solocked(so)); |
136 | | | 136 | |
137 | /* | | 137 | /* |
138 | * validate nam and npcb | | 138 | * validate snatm and npcb |
139 | */ | | 139 | */ |
140 | | | 140 | |
141 | if (snatm->snatm_len != sizeof(*snatm) || | | 141 | if (snatm->snatm_len != sizeof(*snatm) || |
142 | (npcb->npcb_flags & NPCB_FREE) == 0) | | 142 | (npcb->npcb_flags & NPCB_FREE) == 0) |
143 | return EINVAL; | | 143 | return EINVAL; |
144 | if (snatm->snatm_family != AF_NATM) | | 144 | if (snatm->snatm_family != AF_NATM) |
145 | return EAFNOSUPPORT; | | 145 | return EAFNOSUPPORT; |
146 | | | 146 | |
147 | snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination | | 147 | snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination |
148 | since ifunit() uses strcmp */ | | 148 | since ifunit() uses strcmp */ |
149 | | | 149 | |
150 | /* | | 150 | /* |
151 | * convert interface string to ifp, validate. | | 151 | * convert interface string to ifp, validate. |
152 | */ | | 152 | */ |
153 | | | 153 | |
154 | ifp = ifunit(snatm->snatm_if); | | 154 | ifp = ifunit(snatm->snatm_if); |
155 | if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { | | 155 | if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) { |
156 | return ENXIO; | | 156 | return ENXIO; |
157 | } | | 157 | } |
158 | if (ifp->if_output != atm_output) { | | 158 | if (ifp->if_output != atm_output) { |
159 | return EAFNOSUPPORT; | | 159 | return EAFNOSUPPORT; |
160 | } | | 160 | } |
161 | | | 161 | |
162 | /* | | 162 | /* |
163 | * register us with the NATM PCB layer | | 163 | * register us with the NATM PCB layer |
164 | */ | | 164 | */ |
165 | | | 165 | |
166 | if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) | | 166 | if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) |
167 | return EADDRINUSE; | | 167 | return EADDRINUSE; |
168 | | | 168 | |
169 | /* | | 169 | /* |
170 | * enable rx | | 170 | * enable rx |
171 | */ | | 171 | */ |
172 | | | 172 | |
173 | ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; | | 173 | ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; |
174 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; | | 174 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; |
175 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); | | 175 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); |
176 | api.rxhand = npcb; | | 176 | api.rxhand = npcb; |
177 | s2 = splnet(); | | 177 | s2 = splnet(); |
178 | if (ifp->if_ioctl(ifp, SIOCATMENA, &api) != 0) { | | 178 | if (ifp->if_ioctl(ifp, SIOCATMENA, &api) != 0) { |
179 | splx(s2); | | 179 | splx(s2); |
180 | npcb_free(npcb, NPCB_REMOVE); | | 180 | npcb_free(npcb, NPCB_REMOVE); |
181 | return EIO; | | 181 | return EIO; |
182 | } | | 182 | } |
183 | splx(s2); | | 183 | splx(s2); |
184 | | | 184 | |
185 | soisconnected(so); | | 185 | soisconnected(so); |
186 | return error; | | 186 | return error; |
187 | } | | 187 | } |
188 | | | 188 | |
189 | static int | | 189 | static int |
190 | natm_connect2(struct socket *so, struct socket *so2) | | 190 | natm_connect2(struct socket *so, struct socket *so2) |
191 | { | | 191 | { |
192 | KASSERT(solocked(so)); | | 192 | KASSERT(solocked(so)); |
193 | | | 193 | |
194 | return EOPNOTSUPP; | | 194 | return EOPNOTSUPP; |
195 | } | | 195 | } |
196 | | | 196 | |
197 | static int | | 197 | static int |
198 | natm_disconnect(struct socket *so) | | 198 | natm_disconnect(struct socket *so) |
199 | { | | 199 | { |
200 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; | | 200 | struct natmpcb *npcb = (struct natmpcb *)so->so_pcb; |
201 | | | 201 | |
202 | KASSERT(solocked(so)); | | 202 | KASSERT(solocked(so)); |
203 | KASSERT(npcb != NULL); | | 203 | KASSERT(npcb != NULL); |
204 | | | 204 | |
205 | if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { | | 205 | if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) { |
206 | printf("natm: disconnected check\n"); | | 206 | printf("natm: disconnected check\n"); |
207 | return EIO; | | 207 | return EIO; |
208 | } | | 208 | } |
209 | ifp = npcb->npcb_ifp; | | 209 | ifp = npcb->npcb_ifp; |
210 | | | 210 | |
211 | /* | | 211 | /* |
212 | * disable rx | | 212 | * disable rx |
213 | */ | | 213 | */ |
214 | ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; | | 214 | ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5; |
215 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; | | 215 | ATM_PH_VPI(&api.aph) = npcb->npcb_vpi; |
216 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); | | 216 | ATM_PH_SETVCI(&api.aph, npcb->npcb_vci); |
217 | api.rxhand = npcb; | | 217 | api.rxhand = npcb; |
218 | | | 218 | |
219 | s2 = splnet(); | | 219 | s2 = splnet(); |
220 | ifp->if_ioctl(ifp, SIOCATMDIS, &api); | | 220 | ifp->if_ioctl(ifp, SIOCATMDIS, &api); |
221 | splx(s); | | 221 | splx(s); |
222 | | | 222 | |
223 | npcb_free(npcb, NPCB_REMOVE); | | 223 | npcb_free(npcb, NPCB_REMOVE); |
224 | soisdisconnected(so); | | 224 | soisdisconnected(so); |
225 | return 0; | | 225 | return 0; |
226 | } | | 226 | } |
227 | | | 227 | |
228 | static int | | 228 | static int |
229 | natm_shutdown(struct socket *so) | | 229 | natm_shutdown(struct socket *so) |
230 | { | | 230 | { |
231 | int s; | | 231 | int s; |
232 | | | 232 | |
233 | KASSERT(solocked(so)); | | 233 | KASSERT(solocked(so)); |
234 | | | 234 | |
235 | s = splsoftnet(); | | 235 | s = splsoftnet(); |
236 | socantsendmore(so); | | 236 | socantsendmore(so); |
237 | splx(s); | | 237 | splx(s); |
238 | | | 238 | |
239 | return 0; | | 239 | return 0; |
240 | } | | 240 | } |
241 | | | 241 | |
242 | static int | | 242 | static int |
243 | natm_abort(struct socket *so) | | 243 | natm_abort(struct socket *so) |
244 | { | | 244 | { |
245 | KASSERT(solocked(so)); | | 245 | KASSERT(solocked(so)); |
246 | | | 246 | |
247 | return EOPNOTSUPP; | | 247 | return EOPNOTSUPP; |
248 | } | | 248 | } |
249 | | | 249 | |
250 | static int | | 250 | static int |
251 | natm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) | | 251 | natm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) |
252 | { | | 252 | { |
253 | int error = 0, s; | | 253 | int error = 0, s; |
254 | struct natmpcb *npcb; | | 254 | struct natmpcb *npcb; |
255 | struct atm_rawioctl ario; | | 255 | struct atm_rawioctl ario; |
256 | | | 256 | |
257 | s = SPLSOFTNET(); | | 257 | s = SPLSOFTNET(); |
258 | | | 258 | |
259 | npcb = (struct natmpcb *) so->so_pcb; | | 259 | npcb = (struct natmpcb *) so->so_pcb; |
260 | | | 260 | |
261 | /* | | 261 | /* |
262 | * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to | | 262 | * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to |
263 | * SIOCXRAWATM and pass it to the driver. | | 263 | * SIOCXRAWATM and pass it to the driver. |
264 | */ | | 264 | */ |
265 | if (cmd == SIOCRAWATM) { | | 265 | if (cmd == SIOCRAWATM) { |
266 | if (npcb->npcb_ifp == NULL) { | | 266 | if (npcb->npcb_ifp == NULL) { |
267 | error = ENOTCONN; | | 267 | error = ENOTCONN; |
268 | goto done; | | 268 | goto done; |
269 | } | | 269 | } |
270 | ario.npcb = npcb; | | 270 | ario.npcb = npcb; |
271 | ario.rawvalue = *((int *)nam); | | 271 | ario.rawvalue = *((int *)nam); |
272 | error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, SIOCXRAWATM, &ario); | | 272 | error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, SIOCXRAWATM, &ario); |
273 | if (!error) { | | 273 | if (!error) { |
274 | if (ario.rawvalue) | | 274 | if (ario.rawvalue) |
275 | npcb->npcb_flags |= NPCB_RAW; | | 275 | npcb->npcb_flags |= NPCB_RAW; |
276 | else | | 276 | else |
277 | npcb->npcb_flags &= ~(NPCB_RAW); | | 277 | npcb->npcb_flags &= ~(NPCB_RAW); |
278 | } | | 278 | } |
279 | | | 279 | |
280 | goto done; | | 280 | goto done; |
281 | } | | 281 | } |
282 | | | 282 | |
283 | error = EOPNOTSUPP; | | 283 | error = EOPNOTSUPP; |
284 | | | 284 | |
285 | done: | | 285 | done: |
286 | splx(s); | | 286 | splx(s); |
287 | return(error); | | 287 | return(error); |
288 | } | | 288 | } |
289 | | | 289 | |
290 | static int | | 290 | static int |
291 | natm_stat(struct socket *so, struct stat *ub) | | 291 | natm_stat(struct socket *so, struct stat *ub) |
292 | { | | 292 | { |
293 | KASSERT(solocked(so)); | | 293 | KASSERT(solocked(so)); |
294 | | | 294 | |
295 | return 0; | | 295 | return 0; |
296 | } | | 296 | } |
297 | | | 297 | |
298 | static int | | 298 | static int |
299 | natm_peeraddr(struct socket *so, struct sockaddr *nam) | | 299 | natm_peeraddr(struct socket *so, struct sockaddr *nam) |
300 | { | | 300 | { |
301 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; | | 301 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; |
302 | struct sockaddr_natm *snatm = (struct sockaddr_natm *)nam; | | 302 | struct sockaddr_natm *snatm = (struct sockaddr_natm *)nam; |
303 | | | 303 | |
304 | KASSERT(solocked(so)); | | 304 | KASSERT(solocked(so)); |
305 | KASSERT(pcb != NULL); | | 305 | KASSERT(pcb != NULL); |
306 | KASSERT(nam != NULL); | | 306 | KASSERT(nam != NULL); |
307 | | | 307 | |
308 | memset(snatm, 0, sizeof(*snatm)); | | 308 | memset(snatm, 0, sizeof(*snatm)); |
309 | snatm->snatm_len = sizeof(*snatm); | | 309 | snatm->snatm_len = sizeof(*snatm); |
310 | snatm->snatm_family = AF_NATM; | | 310 | snatm->snatm_family = AF_NATM; |
311 | memcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname, sizeof(snatm->snatm_if)); | | 311 | memcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname, sizeof(snatm->snatm_if)); |
312 | snatm->snatm_vci = npcb->npcb_vci; | | 312 | snatm->snatm_vci = npcb->npcb_vci; |
313 | snatm->snatm_vpi = npcb->npcb_vpi; | | 313 | snatm->snatm_vpi = npcb->npcb_vpi; |
314 | return 0; | | 314 | return 0; |
315 | } | | 315 | } |
316 | | | 316 | |
317 | static int | | 317 | static int |
318 | natm_sockaddr(struct socket *so, struct sockaddr *nam) | | 318 | natm_sockaddr(struct socket *so, struct sockaddr *nam) |
319 | { | | 319 | { |
320 | KASSERT(solocked(so)); | | 320 | KASSERT(solocked(so)); |
321 | | | 321 | |
322 | return EOPNOTSUPP; | | 322 | return EOPNOTSUPP; |
323 | } | | 323 | } |
324 | | | 324 | |
325 | static int | | 325 | static int |
326 | natm_rcvd(struct socket *so, int flags, struct lwp *l) | | 326 | natm_rcvd(struct socket *so, int flags, struct lwp *l) |
327 | { | | 327 | { |
328 | KASSERT(solocked(so)); | | 328 | KASSERT(solocked(so)); |
329 | | | 329 | |
330 | return EOPNOTSUPP; | | 330 | return EOPNOTSUPP; |
331 | } | | 331 | } |
332 | | | 332 | |
333 | static int | | 333 | static int |
334 | natm_recvoob(struct socket *so, struct mbuf *m, int flags) | | 334 | natm_recvoob(struct socket *so, struct mbuf *m, int flags) |
335 | { | | 335 | { |
336 | KASSERT(solocked(so)); | | 336 | KASSERT(solocked(so)); |
337 | | | 337 | |
338 | return EOPNOTSUPP; | | 338 | return EOPNOTSUPP; |
339 | } | | 339 | } |
340 | | | 340 | |
341 | static int | | 341 | static int |
342 | natm_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, | | 342 | natm_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, |
343 | struct mbuf *control) | | 343 | struct mbuf *control) |
344 | { | | 344 | { |
345 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; | | 345 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; |
346 | struct atm_pseudohdr *aph; | | 346 | struct atm_pseudohdr *aph; |
347 | | | 347 | |
348 | KASSERT(solocked(so)); | | 348 | KASSERT(solocked(so)); |
349 | KASSERT(pcb != NULL); | | 349 | KASSERT(pcb != NULL); |
350 | KASSERT(m != NULL); | | 350 | KASSERT(m != NULL); |
351 | | | 351 | |
352 | if (control && control->m_len) { | | 352 | if (control && control->m_len) { |
353 | m_freem(control); | | 353 | m_freem(control); |
354 | m_freem(m); | | 354 | m_freem(m); |
355 | return EINVAL; | | 355 | return EINVAL; |
356 | } | | 356 | } |
357 | | | 357 | |
358 | /* | | 358 | /* |
359 | * send the data. we must put an atm_pseudohdr on first | | 359 | * send the data. we must put an atm_pseudohdr on first |
360 | */ | | 360 | */ |
361 | s = SPLSOFTNET(); | | 361 | s = SPLSOFTNET(); |
362 | M_PREPEND(m, sizeof(*aph), M_WAITOK); | | 362 | M_PREPEND(m, sizeof(*aph), M_WAITOK); |
363 | if (m == NULL) { | | 363 | if (m == NULL) { |
364 | error = ENOBUFS; | | 364 | error = ENOBUFS; |
365 | break; | | 365 | break; |
366 | } | | 366 | } |
367 | aph = mtod(m, struct atm_pseudohdr *); | | 367 | aph = mtod(m, struct atm_pseudohdr *); |
368 | ATM_PH_VPI(aph) = npcb->npcb_vpi; | | 368 | ATM_PH_VPI(aph) = npcb->npcb_vpi; |
369 | ATM_PH_SETVCI(aph, npcb->npcb_vci); | | 369 | ATM_PH_SETVCI(aph, npcb->npcb_vci); |
370 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; | | 370 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; |
371 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); | | 371 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); |
372 | splx(s); | | 372 | splx(s); |
373 | | | 373 | |
374 | return error; | | 374 | return error; |
375 | } | | 375 | } |
376 | | | 376 | |
377 | static int | | 377 | static int |
378 | natm_send(struct socket *so, struct mbuf *m, struct mbuf *nam, | | 378 | natm_send(struct socket *so, struct mbuf *m, struct mbuf *nam, |
379 | struct mbuf *control, struct lwp *l) | | 379 | struct mbuf *control, struct lwp *l) |
380 | { | | 380 | { |
381 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; | | 381 | struct natmpcb *npcb = (struct natmpcb *) so->so_pcb; |
382 | struct atm_pseudohdr *aph; | | 382 | struct atm_pseudohdr *aph; |
383 | | | 383 | |
384 | KASSERT(solocked(so)); | | 384 | KASSERT(solocked(so)); |
385 | KASSERT(pcb != NULL); | | 385 | KASSERT(pcb != NULL); |
386 | KASSERT(m != NULL); | | 386 | KASSERT(m != NULL); |
387 | | | 387 | |
388 | if (control && control->m_len) { | | 388 | if (control && control->m_len) { |
389 | m_freem(control); | | 389 | m_freem(control); |
390 | m_freem(m); | | 390 | m_freem(m); |
391 | return EINVAL; | | 391 | return EINVAL; |
392 | } | | 392 | } |
393 | | | 393 | |
394 | /* | | 394 | /* |
395 | * send the data. we must put an atm_pseudohdr on first | | 395 | * send the data. we must put an atm_pseudohdr on first |
396 | */ | | 396 | */ |
397 | s = SPLSOFTNET(); | | 397 | s = SPLSOFTNET(); |
398 | M_PREPEND(m, sizeof(*aph), M_WAITOK); | | 398 | M_PREPEND(m, sizeof(*aph), M_WAITOK); |
399 | if (m == NULL) { | | 399 | if (m == NULL) { |
400 | error = ENOBUFS; | | 400 | error = ENOBUFS; |
401 | break; | | 401 | break; |
402 | } | | 402 | } |
403 | aph = mtod(m, struct atm_pseudohdr *); | | 403 | aph = mtod(m, struct atm_pseudohdr *); |
404 | ATM_PH_VPI(aph) = npcb->npcb_vpi; | | 404 | ATM_PH_VPI(aph) = npcb->npcb_vpi; |
405 | ATM_PH_SETVCI(aph, npcb->npcb_vci); | | 405 | ATM_PH_SETVCI(aph, npcb->npcb_vci); |
406 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; | | 406 | ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0; |
407 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); | | 407 | error = atm_output(npcb->npcb_ifp, m, NULL, NULL); |
408 | splx(s); | | 408 | splx(s); |
409 | | | 409 | |
410 | return error; | | 410 | return error; |
411 | } | | 411 | } |
412 | | | 412 | |
413 | static int | | 413 | static int |
414 | natm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) | | 414 | natm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) |
415 | { | | 415 | { |
416 | KASSERT(solocked(so)); | | 416 | KASSERT(solocked(so)); |
417 | | | 417 | |
418 | return EOPNOTSUPP; | | 418 | return EOPNOTSUPP; |
419 | } | | 419 | } |
420 | | | 420 | |
421 | static int | | 421 | static int |
422 | natm_purgeif(struct socket *so, struct ifnet *ifp) | | 422 | natm_purgeif(struct socket *so, struct ifnet *ifp) |
423 | { | | 423 | { |
424 | | | 424 | |
425 | return EOPNOTSUPP; | | 425 | return EOPNOTSUPP; |
426 | } | | 426 | } |
427 | | | 427 | |
428 | /* | | 428 | /* |
429 | * natmintr: splsoftnet interrupt | | 429 | * natmintr: splsoftnet interrupt |
430 | * | | 430 | * |
431 | * note: we expect a socket pointer in rcvif rather than an interface | | 431 | * note: we expect a socket pointer in rcvif rather than an interface |
432 | * pointer. we can get the interface pointer from the so's PCB if | | 432 | * pointer. we can get the interface pointer from the so's PCB if |
433 | * we really need it. | | 433 | * we really need it. |
434 | */ | | 434 | */ |
435 | | | 435 | |
436 | void | | 436 | void |
437 | natmintr(void) | | 437 | natmintr(void) |
438 | | | 438 | |
439 | { | | 439 | { |
440 | int s; | | 440 | int s; |
441 | struct mbuf *m; | | 441 | struct mbuf *m; |
442 | struct socket *so; | | 442 | struct socket *so; |
443 | struct natmpcb *npcb; | | 443 | struct natmpcb *npcb; |
444 | | | 444 | |
445 | mutex_enter(softnet_lock); | | 445 | mutex_enter(softnet_lock); |
446 | next: | | 446 | next: |
447 | s = splnet(); | | 447 | s = splnet(); |
448 | IF_DEQUEUE(&natmintrq, m); | | 448 | IF_DEQUEUE(&natmintrq, m); |
449 | splx(s); | | 449 | splx(s); |
450 | if (m == NULL) { | | 450 | if (m == NULL) { |
451 | mutex_exit(softnet_lock); | | 451 | mutex_exit(softnet_lock); |
452 | return; | | 452 | return; |
453 | } | | 453 | } |
454 | | | 454 | |
455 | #ifdef DIAGNOSTIC | | 455 | #ifdef DIAGNOSTIC |
456 | if ((m->m_flags & M_PKTHDR) == 0) | | 456 | if ((m->m_flags & M_PKTHDR) == 0) |
457 | panic("natmintr no HDR"); | | 457 | panic("natmintr no HDR"); |
458 | #endif | | 458 | #endif |
459 | | | 459 | |
460 | npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ | | 460 | npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */ |
461 | so = npcb->npcb_socket; | | 461 | so = npcb->npcb_socket; |
462 | | | 462 | |
463 | s = splnet(); /* could have atm devs @ different levels */ | | 463 | s = splnet(); /* could have atm devs @ different levels */ |
464 | npcb->npcb_inq--; | | 464 | npcb->npcb_inq--; |
465 | splx(s); | | 465 | splx(s); |
466 | | | 466 | |
467 | if (npcb->npcb_flags & NPCB_DRAIN) { | | 467 | if (npcb->npcb_flags & NPCB_DRAIN) { |
468 | m_freem(m); | | 468 | m_freem(m); |
469 | if (npcb->npcb_inq == 0) | | 469 | if (npcb->npcb_inq == 0) |
470 | kmem_intr_free(npcb, sizeof(*npcb)); | | 470 | kmem_intr_free(npcb, sizeof(*npcb)); |
471 | goto next; | | 471 | goto next; |
472 | } | | 472 | } |
473 | | | 473 | |
474 | if (npcb->npcb_flags & NPCB_FREE) { | | 474 | if (npcb->npcb_flags & NPCB_FREE) { |
475 | m_freem(m); /* drop */ | | 475 | m_freem(m); /* drop */ |
476 | goto next; | | 476 | goto next; |
477 | } | | 477 | } |
478 | | | 478 | |
479 | #ifdef NEED_TO_RESTORE_IFP | | 479 | #ifdef NEED_TO_RESTORE_IFP |
480 | m->m_pkthdr.rcvif = npcb->npcb_ifp; | | 480 | m->m_pkthdr.rcvif = npcb->npcb_ifp; |
481 | #else | | 481 | #else |
482 | #ifdef DIAGNOSTIC | | 482 | #ifdef DIAGNOSTIC |
483 | m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ | | 483 | m->m_pkthdr.rcvif = NULL; /* null it out to be safe */ |
484 | #endif | | 484 | #endif |
485 | #endif | | 485 | #endif |
486 | | | 486 | |
487 | if (sbspace(&so->so_rcv) > m->m_pkthdr.len || | | 487 | if (sbspace(&so->so_rcv) > m->m_pkthdr.len || |
488 | ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) { | | 488 | ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) { |
489 | #ifdef NATM_STAT | | 489 | #ifdef NATM_STAT |
490 | natm_sookcnt++; | | 490 | natm_sookcnt++; |
491 | natm_sookbytes += m->m_pkthdr.len; | | 491 | natm_sookbytes += m->m_pkthdr.len; |
492 | #endif | | 492 | #endif |
493 | sbappendrecord(&so->so_rcv, m); | | 493 | sbappendrecord(&so->so_rcv, m); |
494 | sorwakeup(so); | | 494 | sorwakeup(so); |
495 | } else { | | 495 | } else { |
496 | #ifdef NATM_STAT | | 496 | #ifdef NATM_STAT |
497 | natm_sodropcnt++; | | 497 | natm_sodropcnt++; |
498 | natm_sodropbytes += m->m_pkthdr.len; | | 498 | natm_sodropbytes += m->m_pkthdr.len; |
499 | #endif | | 499 | #endif |
500 | m_freem(m); | | 500 | m_freem(m); |
501 | } | | 501 | } |
502 | | | 502 | |
503 | goto next; | | 503 | goto next; |
504 | } | | 504 | } |
505 | | | 505 | |
506 | PR_WRAP_USRREQS(natm) | | 506 | PR_WRAP_USRREQS(natm) |
507 | #define natm_attach natm_attach_wrapper | | 507 | #define natm_attach natm_attach_wrapper |
508 | #define natm_detach natm_detach_wrapper | | 508 | #define natm_detach natm_detach_wrapper |
509 | #define natm_accept natm_accept_wrapper | | 509 | #define natm_accept natm_accept_wrapper |
510 | #define natm_bind natm_bind_wrapper | | 510 | #define natm_bind natm_bind_wrapper |
511 | #define natm_listen natm_listen_wrapper | | 511 | #define natm_listen natm_listen_wrapper |
512 | #define natm_connect natm_connect_wrapper | | 512 | #define natm_connect natm_connect_wrapper |
513 | #define natm_connect2 natm_connect2_wrapper | | 513 | #define natm_connect2 natm_connect2_wrapper |
514 | #define natm_disconnect natm_disconnect_wrapper | | 514 | #define natm_disconnect natm_disconnect_wrapper |
515 | #define natm_shutdown natm_shutdown_wrapper | | 515 | #define natm_shutdown natm_shutdown_wrapper |
516 | #define natm_abort natm_abort_wrapper | | 516 | #define natm_abort natm_abort_wrapper |
517 | #define natm_ioctl natm_ioctl_wrapper | | 517 | #define natm_ioctl natm_ioctl_wrapper |
518 | #define natm_stat natm_stat_wrapper | | 518 | #define natm_stat natm_stat_wrapper |
519 | #define natm_peeraddr natm_peeraddr_wrapper | | 519 | #define natm_peeraddr natm_peeraddr_wrapper |
520 | #define natm_sockaddr natm_sockaddr_wrapper | | 520 | #define natm_sockaddr natm_sockaddr_wrapper |
521 | #define natm_rcvd natm_rcvd_wrapper | | 521 | #define natm_rcvd natm_rcvd_wrapper |
522 | #define natm_recvoob natm_recvoob_wrapper | | 522 | #define natm_recvoob natm_recvoob_wrapper |
523 | #define natm_send natm_send_wrapper | | 523 | #define natm_send natm_send_wrapper |
524 | #define natm_sendoob natm_sendoob_wrapper | | 524 | #define natm_sendoob natm_sendoob_wrapper |
525 | #define natm_purgeif natm_purgeif_wrapper | | 525 | #define natm_purgeif natm_purgeif_wrapper |
526 | | | 526 | |
527 | const struct pr_usrreqs natm_usrreqs = { | | 527 | const struct pr_usrreqs natm_usrreqs = { |
528 | .pr_attach = natm_attach, | | 528 | .pr_attach = natm_attach, |
529 | .pr_detach = natm_detach, | | 529 | .pr_detach = natm_detach, |
530 | .pr_accept = natm_accept, | | 530 | .pr_accept = natm_accept, |
531 | .pr_bind = natm_bind, | | 531 | .pr_bind = natm_bind, |
532 | .pr_listen = natm_listen, | | 532 | .pr_listen = natm_listen, |
533 | .pr_connect = natm_connect, | | 533 | .pr_connect = natm_connect, |
534 | .pr_connect2 = natm_connect2, | | 534 | .pr_connect2 = natm_connect2, |
535 | .pr_disconnect = natm_disconnect, | | 535 | .pr_disconnect = natm_disconnect, |
536 | .pr_shutdown = natm_shutdown, | | 536 | .pr_shutdown = natm_shutdown, |
537 | .pr_abort = natm_abort, | | 537 | .pr_abort = natm_abort, |
538 | .pr_ioctl = natm_ioctl, | | 538 | .pr_ioctl = natm_ioctl, |
539 | .pr_stat = natm_stat, | | 539 | .pr_stat = natm_stat, |
540 | .pr_peeraddr = natm_peeraddr, | | 540 | .pr_peeraddr = natm_peeraddr, |
541 | .pr_sockaddr = natm_sockaddr, | | 541 | .pr_sockaddr = natm_sockaddr, |
542 | .pr_rcvd = natm_rcvd, | | 542 | .pr_rcvd = natm_rcvd, |
543 | .pr_recvoob = natm_recvoob, | | 543 | .pr_recvoob = natm_recvoob, |
544 | .pr_send = natm_send, | | 544 | .pr_send = natm_send, |
545 | .pr_sendoob = natm_sendoob, | | 545 | .pr_sendoob = natm_sendoob, |
546 | .pr_purgeif = natm_purgeif, | | 546 | .pr_purgeif = natm_purgeif, |
547 | }; | | 547 | }; |