Deleted Added
full compact
natm.c (25606) natm.c (28270)
1/* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $ */
2
3/*
4 *
5 * Copyright (c) 1996 Charles D. Cranor and Washington University.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor and
19 * Washington University.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * natm.c: native mode ATM access (both aal0 and aal5).
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/domain.h>
43#if defined(__FreeBSD__)
44#include <sys/sockio.h>
45#else
46#include <sys/ioctl.h>
47#endif
48#include <sys/proc.h>
49#include <sys/protosw.h>
50#include <sys/mbuf.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
53
54#include <net/if.h>
55#include <net/if_atm.h>
56#include <net/netisr.h>
57#include <net/radix.h>
58#include <net/route.h>
59
60#include <netinet/in.h>
61
62#include <netnatm/natm.h>
63
64u_long natm5_sendspace = 16*1024;
65u_long natm5_recvspace = 16*1024;
66
67u_long natm0_sendspace = 16*1024;
68u_long natm0_recvspace = 16*1024;
69
70/*
71 * user requests
72 */
73#ifdef FREEBSD_USRREQS
74/*
75 * FreeBSD new usrreqs supersedes pr_usrreq.
76 */
77static int natm_usr_attach __P((struct socket *, int, struct proc *));
78static int natm_usr_detach __P((struct socket *));
1/* $NetBSD: natm.c,v 1.5 1996/11/09 03:26:26 chuck Exp $ */
2
3/*
4 *
5 * Copyright (c) 1996 Charles D. Cranor and Washington University.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles D. Cranor and
19 * Washington University.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/*
36 * natm.c: native mode ATM access (both aal0 and aal5).
37 */
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/domain.h>
43#if defined(__FreeBSD__)
44#include <sys/sockio.h>
45#else
46#include <sys/ioctl.h>
47#endif
48#include <sys/proc.h>
49#include <sys/protosw.h>
50#include <sys/mbuf.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
53
54#include <net/if.h>
55#include <net/if_atm.h>
56#include <net/netisr.h>
57#include <net/radix.h>
58#include <net/route.h>
59
60#include <netinet/in.h>
61
62#include <netnatm/natm.h>
63
64u_long natm5_sendspace = 16*1024;
65u_long natm5_recvspace = 16*1024;
66
67u_long natm0_sendspace = 16*1024;
68u_long natm0_recvspace = 16*1024;
69
70/*
71 * user requests
72 */
73#ifdef FREEBSD_USRREQS
74/*
75 * FreeBSD new usrreqs supersedes pr_usrreq.
76 */
77static int natm_usr_attach __P((struct socket *, int, struct proc *));
78static int natm_usr_detach __P((struct socket *));
79static int natm_usr_connect __P((struct socket *, struct mbuf *,
79static int natm_usr_connect __P((struct socket *, struct sockaddr *,
80 struct proc *));
81static int natm_usr_disconnect __P((struct socket *));
82static int natm_usr_shutdown __P((struct socket *));
83static int natm_usr_send __P((struct socket *, int, struct mbuf *,
80 struct proc *));
81static int natm_usr_disconnect __P((struct socket *));
82static int natm_usr_shutdown __P((struct socket *));
83static int natm_usr_send __P((struct socket *, int, struct mbuf *,
84 struct mbuf *, struct mbuf *, struct proc *));
85static int natm_usr_peeraddr __P((struct socket *, struct mbuf *));
84 struct sockaddr *, struct mbuf *,
85 struct proc *));
86static int natm_usr_peeraddr __P((struct socket *, struct sockaddr **));
86static int natm_usr_control __P((struct socket *, int, caddr_t,
87 struct ifnet *, struct proc *));
88static int natm_usr_abort __P((struct socket *));
87static int natm_usr_control __P((struct socket *, int, caddr_t,
88 struct ifnet *, struct proc *));
89static int natm_usr_abort __P((struct socket *));
89static int natm_usr_bind __P((struct socket *, struct mbuf *, struct proc *));
90static int natm_usr_sockaddr __P((struct socket *, struct mbuf *));
90static int natm_usr_bind __P((struct socket *, struct sockaddr *,
91 struct proc *));
92static int natm_usr_sockaddr __P((struct socket *, struct sockaddr **));
91
92static int
93natm_usr_attach(struct socket *so, int proto, struct proc *p)
94{
95 struct natmpcb *npcb;
96 int error = 0;
97 int s = SPLSOFTNET();
98
99 npcb = (struct natmpcb *) so->so_pcb;
100
101 if (npcb) {
102 error = EISCONN;
103 goto out;
104 }
105
106 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
107 if (proto == PROTO_NATMAAL5)
108 error = soreserve(so, natm5_sendspace, natm5_recvspace);
109 else
110 error = soreserve(so, natm0_sendspace, natm0_recvspace);
111 if (error)
112 goto out;
113 }
114
115 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
116 npcb->npcb_socket = so;
117 out:
118 splx(s);
119 return (error);
120}
121
122static int
123natm_usr_detach(struct socket *so)
124{
125 struct natmpcb *npcb;
126 int error = 0;
127 int s = SPLSOFTNET();
128
129 npcb = (struct natmpcb *) so->so_pcb;
130 if (npcb == NULL) {
131 error = EINVAL;
132 goto out;
133 }
134
135 /*
136 * we turn on 'drain' *before* we sofree.
137 */
138 npcb_free(npcb, NPCB_DESTROY); /* drain */
139 so->so_pcb = NULL;
140 sofree(so);
141 out:
142 splx(s);
143 return (error);
144}
145
146static int
93
94static int
95natm_usr_attach(struct socket *so, int proto, struct proc *p)
96{
97 struct natmpcb *npcb;
98 int error = 0;
99 int s = SPLSOFTNET();
100
101 npcb = (struct natmpcb *) so->so_pcb;
102
103 if (npcb) {
104 error = EISCONN;
105 goto out;
106 }
107
108 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
109 if (proto == PROTO_NATMAAL5)
110 error = soreserve(so, natm5_sendspace, natm5_recvspace);
111 else
112 error = soreserve(so, natm0_sendspace, natm0_recvspace);
113 if (error)
114 goto out;
115 }
116
117 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
118 npcb->npcb_socket = so;
119 out:
120 splx(s);
121 return (error);
122}
123
124static int
125natm_usr_detach(struct socket *so)
126{
127 struct natmpcb *npcb;
128 int error = 0;
129 int s = SPLSOFTNET();
130
131 npcb = (struct natmpcb *) so->so_pcb;
132 if (npcb == NULL) {
133 error = EINVAL;
134 goto out;
135 }
136
137 /*
138 * we turn on 'drain' *before* we sofree.
139 */
140 npcb_free(npcb, NPCB_DESTROY); /* drain */
141 so->so_pcb = NULL;
142 sofree(so);
143 out:
144 splx(s);
145 return (error);
146}
147
148static int
147natm_usr_connect(struct socket *so, struct mbuf *nam, struct proc *p)
149natm_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
148{
149 struct natmpcb *npcb;
150 struct sockaddr_natm *snatm;
151 struct atm_pseudoioctl api;
152 struct atm_pseudohdr *aph;
153 struct ifnet *ifp;
154 int error = 0;
155 int s2, s = SPLSOFTNET();
156 int proto = so->so_proto->pr_protocol;
157
158 npcb = (struct natmpcb *) so->so_pcb;
159 if (npcb == NULL) {
160 error = EINVAL;
161 goto out;
162 }
163
164 /*
165 * validate nam and npcb
166 */
167
150{
151 struct natmpcb *npcb;
152 struct sockaddr_natm *snatm;
153 struct atm_pseudoioctl api;
154 struct atm_pseudohdr *aph;
155 struct ifnet *ifp;
156 int error = 0;
157 int s2, s = SPLSOFTNET();
158 int proto = so->so_proto->pr_protocol;
159
160 npcb = (struct natmpcb *) so->so_pcb;
161 if (npcb == NULL) {
162 error = EINVAL;
163 goto out;
164 }
165
166 /*
167 * validate nam and npcb
168 */
169
168 if (nam->m_len != sizeof(*snatm)) {
169 error = EINVAL;
170 goto out;
171 }
172 snatm = mtod(nam, struct sockaddr_natm *);
170 snatm = (struct sockaddr_natm *)nam;
173 if (snatm->snatm_len != sizeof(*snatm) ||
174 (npcb->npcb_flags & NPCB_FREE) == 0) {
175 error = EINVAL;
176 goto out;
177 }
178 if (snatm->snatm_family != AF_NATM) {
179 error = EAFNOSUPPORT;
180 goto out;
181 }
182
183 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
184 since ifunit() uses strcmp */
185
186 /*
187 * convert interface string to ifp, validate.
188 */
189
190 ifp = ifunit(snatm->snatm_if);
191 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
192 error = ENXIO;
193 goto out;
194 }
195 if (ifp->if_output != atm_output) {
196 error = EAFNOSUPPORT;
197 goto out;
198 }
199
200 /*
201 * register us with the NATM PCB layer
202 */
203
204 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
205 error = EADDRINUSE;
206 goto out;
207 }
208
209 /*
210 * enable rx
211 */
212
213 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
214 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
215 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
216 api.rxhand = npcb;
217 s2 = splimp();
218 if (ifp->if_ioctl == NULL ||
219 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
220 splx(s2);
221 npcb_free(npcb, NPCB_REMOVE);
222 error = EIO;
223 goto out;
224 }
225 splx(s2);
226
227 soisconnected(so);
228
229 out:
230 splx(s);
231 return (error);
232}
233
234static int
235natm_usr_disconnect(struct socket *so)
236{
237 struct natmpcb *npcb;
238 struct sockaddr_natm *snatm;
239 struct atm_pseudoioctl api;
240 struct atm_pseudohdr *aph;
241 struct ifnet *ifp;
242 int error = 0;
243 int s2, s = SPLSOFTNET();
244 int proto = so->so_proto->pr_protocol;
245
246 npcb = (struct natmpcb *) so->so_pcb;
247 if (npcb == NULL) {
248 error = EINVAL;
249 goto out;
250 }
251
252 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
253 printf("natm: disconnected check\n");
254 error = EIO;
255 goto out;
256 }
257 ifp = npcb->npcb_ifp;
258
259 /*
260 * disable rx
261 */
262
263 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
264 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
265 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
266 api.rxhand = npcb;
267 s2 = splimp();
268 if (ifp->if_ioctl != NULL)
269 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
270 splx(s2);
271
272 npcb_free(npcb, NPCB_REMOVE);
273 soisdisconnected(so);
274
275 out:
276 splx(s);
277 return (error);
278}
279
280static int
281natm_usr_shutdown(struct socket *so)
282{
283 socantsendmore(so);
284 return 0;
285}
286
287static int
171 if (snatm->snatm_len != sizeof(*snatm) ||
172 (npcb->npcb_flags & NPCB_FREE) == 0) {
173 error = EINVAL;
174 goto out;
175 }
176 if (snatm->snatm_family != AF_NATM) {
177 error = EAFNOSUPPORT;
178 goto out;
179 }
180
181 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
182 since ifunit() uses strcmp */
183
184 /*
185 * convert interface string to ifp, validate.
186 */
187
188 ifp = ifunit(snatm->snatm_if);
189 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
190 error = ENXIO;
191 goto out;
192 }
193 if (ifp->if_output != atm_output) {
194 error = EAFNOSUPPORT;
195 goto out;
196 }
197
198 /*
199 * register us with the NATM PCB layer
200 */
201
202 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
203 error = EADDRINUSE;
204 goto out;
205 }
206
207 /*
208 * enable rx
209 */
210
211 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
212 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
213 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
214 api.rxhand = npcb;
215 s2 = splimp();
216 if (ifp->if_ioctl == NULL ||
217 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
218 splx(s2);
219 npcb_free(npcb, NPCB_REMOVE);
220 error = EIO;
221 goto out;
222 }
223 splx(s2);
224
225 soisconnected(so);
226
227 out:
228 splx(s);
229 return (error);
230}
231
232static int
233natm_usr_disconnect(struct socket *so)
234{
235 struct natmpcb *npcb;
236 struct sockaddr_natm *snatm;
237 struct atm_pseudoioctl api;
238 struct atm_pseudohdr *aph;
239 struct ifnet *ifp;
240 int error = 0;
241 int s2, s = SPLSOFTNET();
242 int proto = so->so_proto->pr_protocol;
243
244 npcb = (struct natmpcb *) so->so_pcb;
245 if (npcb == NULL) {
246 error = EINVAL;
247 goto out;
248 }
249
250 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
251 printf("natm: disconnected check\n");
252 error = EIO;
253 goto out;
254 }
255 ifp = npcb->npcb_ifp;
256
257 /*
258 * disable rx
259 */
260
261 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
262 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
263 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
264 api.rxhand = npcb;
265 s2 = splimp();
266 if (ifp->if_ioctl != NULL)
267 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
268 splx(s2);
269
270 npcb_free(npcb, NPCB_REMOVE);
271 soisdisconnected(so);
272
273 out:
274 splx(s);
275 return (error);
276}
277
278static int
279natm_usr_shutdown(struct socket *so)
280{
281 socantsendmore(so);
282 return 0;
283}
284
285static int
288natm_usr_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
289 struct mbuf *control, struct proc *p)
286natm_usr_send(struct socket *so, int flags, struct mbuf *m,
287 struct sockaddr *nam, struct mbuf *control, struct proc *p)
290{
291 struct natmpcb *npcb;
292 struct atm_pseudohdr *aph;
293 int error = 0;
294 int s = SPLSOFTNET();
295 int proto = so->so_proto->pr_protocol;
296
297 npcb = (struct natmpcb *) so->so_pcb;
298 if (npcb == NULL) {
299 error = EINVAL;
300 goto out;
301 }
302
303 if (control && control->m_len) {
304 m_freem(control);
305 m_freem(m);
306 error = EINVAL;
307 goto out;
308 }
309
310 /*
311 * send the data. we must put an atm_pseudohdr on first
312 */
313
314 M_PREPEND(m, sizeof(*aph), M_WAITOK);
315 if (m == NULL) {
316 error = ENOBUFS;
317 goto out;
318 }
319 aph = mtod(m, struct atm_pseudohdr *);
320 ATM_PH_VPI(aph) = npcb->npcb_vpi;
321 ATM_PH_SETVCI(aph, npcb->npcb_vci);
322 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
323
324 error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
325
326 out:
327 splx(s);
328 return (error);
329}
330
331static int
288{
289 struct natmpcb *npcb;
290 struct atm_pseudohdr *aph;
291 int error = 0;
292 int s = SPLSOFTNET();
293 int proto = so->so_proto->pr_protocol;
294
295 npcb = (struct natmpcb *) so->so_pcb;
296 if (npcb == NULL) {
297 error = EINVAL;
298 goto out;
299 }
300
301 if (control && control->m_len) {
302 m_freem(control);
303 m_freem(m);
304 error = EINVAL;
305 goto out;
306 }
307
308 /*
309 * send the data. we must put an atm_pseudohdr on first
310 */
311
312 M_PREPEND(m, sizeof(*aph), M_WAITOK);
313 if (m == NULL) {
314 error = ENOBUFS;
315 goto out;
316 }
317 aph = mtod(m, struct atm_pseudohdr *);
318 ATM_PH_VPI(aph) = npcb->npcb_vpi;
319 ATM_PH_SETVCI(aph, npcb->npcb_vci);
320 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
321
322 error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
323
324 out:
325 splx(s);
326 return (error);
327}
328
329static int
332natm_usr_peeraddr(struct socket *so, struct mbuf *nam)
330natm_usr_peeraddr(struct socket *so, struct sockaddr **nam)
333{
334 struct natmpcb *npcb;
331{
332 struct natmpcb *npcb;
335 struct sockaddr_natm *snatm;
333 struct sockaddr_natm *snatm, ssnatm;
336 int error = 0;
337 int s = SPLSOFTNET();
338
339 npcb = (struct natmpcb *) so->so_pcb;
340 if (npcb == NULL) {
341 error = EINVAL;
342 goto out;
343 }
344
334 int error = 0;
335 int s = SPLSOFTNET();
336
337 npcb = (struct natmpcb *) so->so_pcb;
338 if (npcb == NULL) {
339 error = EINVAL;
340 goto out;
341 }
342
345 snatm = mtod(nam, struct sockaddr_natm *);
343 snatm = &ssnatm;
346 bzero(snatm, sizeof(*snatm));
344 bzero(snatm, sizeof(*snatm));
347 nam->m_len = snatm->snatm_len = sizeof(*snatm);
345 snatm->snatm_len = sizeof(*snatm);
348 snatm->snatm_family = AF_NATM;
349 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
350 npcb->npcb_ifp->if_unit);
351 snatm->snatm_vci = npcb->npcb_vci;
352 snatm->snatm_vpi = npcb->npcb_vpi;
346 snatm->snatm_family = AF_NATM;
347 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
348 npcb->npcb_ifp->if_unit);
349 snatm->snatm_vci = npcb->npcb_vci;
350 snatm->snatm_vpi = npcb->npcb_vpi;
351 *nam = dup_sockaddr((struct sockaddr *)snatm, 0);
353
354 out:
355 splx(s);
356 return (error);
357}
358
359static int
360natm_usr_control(struct socket *so, int cmd, caddr_t arg,
361 struct ifnet *ifp, struct proc *p)
362{
363 struct natmpcb *npcb;
364 struct atm_rawioctl ario;
365 int error = 0;
366 int s = SPLSOFTNET();
367
368 npcb = (struct natmpcb *) so->so_pcb;
369 if (npcb == NULL) {
370 error = EINVAL;
371 goto out;
372 }
373
374 /*
375 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
376 * SIOCXRAWATM and pass it to the driver.
377 */
378 if (cmd == SIOCRAWATM) {
379 if (npcb->npcb_ifp == NULL) {
380 error = ENOTCONN;
381 goto out;
382 }
383 ario.npcb = npcb;
384 ario.rawvalue = *((int *)arg);
385 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
386 SIOCXRAWATM, (caddr_t) &ario);
387 if (!error) {
388 if (ario.rawvalue)
389 npcb->npcb_flags |= NPCB_RAW;
390 else
391 npcb->npcb_flags &= ~(NPCB_RAW);
392 }
393 }
394 else
395 error = EOPNOTSUPP;
396
397 out:
398 splx(s);
399 return (error);
400}
401
402static int
403natm_usr_abort(struct socket *so)
404{
405 return natm_usr_shutdown(so);
406}
407
408static int
352
353 out:
354 splx(s);
355 return (error);
356}
357
358static int
359natm_usr_control(struct socket *so, int cmd, caddr_t arg,
360 struct ifnet *ifp, struct proc *p)
361{
362 struct natmpcb *npcb;
363 struct atm_rawioctl ario;
364 int error = 0;
365 int s = SPLSOFTNET();
366
367 npcb = (struct natmpcb *) so->so_pcb;
368 if (npcb == NULL) {
369 error = EINVAL;
370 goto out;
371 }
372
373 /*
374 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
375 * SIOCXRAWATM and pass it to the driver.
376 */
377 if (cmd == SIOCRAWATM) {
378 if (npcb->npcb_ifp == NULL) {
379 error = ENOTCONN;
380 goto out;
381 }
382 ario.npcb = npcb;
383 ario.rawvalue = *((int *)arg);
384 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
385 SIOCXRAWATM, (caddr_t) &ario);
386 if (!error) {
387 if (ario.rawvalue)
388 npcb->npcb_flags |= NPCB_RAW;
389 else
390 npcb->npcb_flags &= ~(NPCB_RAW);
391 }
392 }
393 else
394 error = EOPNOTSUPP;
395
396 out:
397 splx(s);
398 return (error);
399}
400
401static int
402natm_usr_abort(struct socket *so)
403{
404 return natm_usr_shutdown(so);
405}
406
407static int
409natm_usr_bind(struct socket *so, struct mbuf *nam, struct proc *p)
408natm_usr_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
410{
411 return EOPNOTSUPP;
412}
413
414static int
409{
410 return EOPNOTSUPP;
411}
412
413static int
415natm_usr_sockaddr(struct socket *so, struct mbuf *nam)
414natm_usr_sockaddr(struct socket *so, struct sockaddr **nam)
416{
417 return EOPNOTSUPP;
418}
419
420/* xxx - should be const */
421struct pr_usrreqs natm_usrreqs = {
422 natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind,
423 natm_usr_connect, pru_connect2_notsupp, natm_usr_control,
424 natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp,
425 natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
426 natm_usr_send, pru_sense_null, natm_usr_shutdown,
427 natm_usr_sockaddr, sosend, soreceive, soselect
428};
429
430#else /* !FREEBSD_USRREQS */
431
432#if defined(__NetBSD__) || defined(__OpenBSD__)
433int natm_usrreq(so, req, m, nam, control, p)
434#elif defined(__FreeBSD__)
435int natm_usrreq(so, req, m, nam, control)
436#endif
437
438struct socket *so;
439int req;
440struct mbuf *m, *nam, *control;
441#if defined(__NetBSD__) || defined(__OpenBSD__)
442struct proc *p;
443#endif
444
445{
446 int error = 0, s, s2;
447 struct natmpcb *npcb;
448 struct sockaddr_natm *snatm;
449 struct atm_pseudoioctl api;
450 struct atm_pseudohdr *aph;
451 struct atm_rawioctl ario;
452 struct ifnet *ifp;
453 int proto = so->so_proto->pr_protocol;
454
455 s = SPLSOFTNET();
456
457 npcb = (struct natmpcb *) so->so_pcb;
458
459 if (npcb == NULL && req != PRU_ATTACH) {
460 error = EINVAL;
461 goto done;
462 }
463
464
465 switch (req) {
466 case PRU_ATTACH: /* attach protocol to up */
467
468 if (npcb) {
469 error = EISCONN;
470 break;
471 }
472
473 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
474 if (proto == PROTO_NATMAAL5)
475 error = soreserve(so, natm5_sendspace, natm5_recvspace);
476 else
477 error = soreserve(so, natm0_sendspace, natm0_recvspace);
478 if (error)
479 break;
480 }
481
482 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
483 npcb->npcb_socket = so;
484
485 break;
486
487 case PRU_DETACH: /* detach protocol from up */
488
489 /*
490 * we turn on 'drain' *before* we sofree.
491 */
492
493 npcb_free(npcb, NPCB_DESTROY); /* drain */
494 so->so_pcb = NULL;
495 sofree(so);
496
497 break;
498
499 case PRU_CONNECT: /* establish connection to peer */
500
501 /*
502 * validate nam and npcb
503 */
504
505 if (nam->m_len != sizeof(*snatm)) {
506 error = EINVAL;
507 break;
508 }
509 snatm = mtod(nam, struct sockaddr_natm *);
510 if (snatm->snatm_len != sizeof(*snatm) ||
511 (npcb->npcb_flags & NPCB_FREE) == 0) {
512 error = EINVAL;
513 break;
514 }
515 if (snatm->snatm_family != AF_NATM) {
516 error = EAFNOSUPPORT;
517 break;
518 }
519
520 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
521 since ifunit() uses strcmp */
522
523 /*
524 * convert interface string to ifp, validate.
525 */
526
527 ifp = ifunit(snatm->snatm_if);
528 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
529 error = ENXIO;
530 break;
531 }
532 if (ifp->if_output != atm_output) {
533 error = EAFNOSUPPORT;
534 break;
535 }
536
537
538 /*
539 * register us with the NATM PCB layer
540 */
541
542 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
543 error = EADDRINUSE;
544 break;
545 }
546
547 /*
548 * enable rx
549 */
550
551 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
552 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
553 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
554 api.rxhand = npcb;
555 s2 = splimp();
556 if (ifp->if_ioctl == NULL ||
557 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
558 splx(s2);
559 npcb_free(npcb, NPCB_REMOVE);
560 error = EIO;
561 break;
562 }
563 splx(s2);
564
565 soisconnected(so);
566
567 break;
568
569 case PRU_DISCONNECT: /* disconnect from peer */
570
571 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
572 printf("natm: disconnected check\n");
573 error = EIO;
574 break;
575 }
576 ifp = npcb->npcb_ifp;
577
578 /*
579 * disable rx
580 */
581
582 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
583 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
584 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
585 api.rxhand = npcb;
586 s2 = splimp();
587 if (ifp->if_ioctl != NULL)
588 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
589 splx(s2);
590
591 npcb_free(npcb, NPCB_REMOVE);
592 soisdisconnected(so);
593
594 break;
595
596 case PRU_SHUTDOWN: /* won't send any more data */
597 socantsendmore(so);
598 break;
599
600 case PRU_SEND: /* send this data */
601 if (control && control->m_len) {
602 m_freem(control);
603 m_freem(m);
604 error = EINVAL;
605 break;
606 }
607
608 /*
609 * send the data. we must put an atm_pseudohdr on first
610 */
611
612 M_PREPEND(m, sizeof(*aph), M_WAITOK);
613 if (m == NULL) {
614 error = ENOBUFS;
615 break;
616 }
617 aph = mtod(m, struct atm_pseudohdr *);
618 ATM_PH_VPI(aph) = npcb->npcb_vpi;
619 ATM_PH_SETVCI(aph, npcb->npcb_vci);
620 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
621
622 error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
623
624 break;
625
626 case PRU_SENSE: /* return status into m */
627 /* return zero? */
628 break;
629
630 case PRU_PEERADDR: /* fetch peer's address */
631 snatm = mtod(nam, struct sockaddr_natm *);
632 bzero(snatm, sizeof(*snatm));
633 nam->m_len = snatm->snatm_len = sizeof(*snatm);
634 snatm->snatm_family = AF_NATM;
635#if defined(__NetBSD__) || defined(__OpenBSD__)
636 bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
637#elif defined(__FreeBSD__)
638 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
639 npcb->npcb_ifp->if_unit);
640#endif
641 snatm->snatm_vci = npcb->npcb_vci;
642 snatm->snatm_vpi = npcb->npcb_vpi;
643 break;
644
645 case PRU_CONTROL: /* control operations on protocol */
646 /*
647 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
648 * SIOCXRAWATM and pass it to the driver.
649 */
650 if ((u_long)m == SIOCRAWATM) {
651 if (npcb->npcb_ifp == NULL) {
652 error = ENOTCONN;
653 break;
654 }
655 ario.npcb = npcb;
656 ario.rawvalue = *((int *)nam);
657 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
658 SIOCXRAWATM, (caddr_t) &ario);
659 if (!error) {
660 if (ario.rawvalue)
661 npcb->npcb_flags |= NPCB_RAW;
662 else
663 npcb->npcb_flags &= ~(NPCB_RAW);
664 }
665
666 break;
667 }
668
669 error = EOPNOTSUPP;
670 break;
671
672 case PRU_BIND: /* bind socket to address */
673 case PRU_LISTEN: /* listen for connection */
674 case PRU_ACCEPT: /* accept connection from peer */
675 case PRU_CONNECT2: /* connect two sockets */
676 case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */
677 /* (only happens if LISTEN socket) */
678 case PRU_RCVD: /* have taken data; more room now */
679 case PRU_FASTTIMO: /* 200ms timeout */
680 case PRU_SLOWTIMO: /* 500ms timeout */
681 case PRU_RCVOOB: /* retrieve out of band data */
682 case PRU_SENDOOB: /* send out of band data */
683 case PRU_PROTORCV: /* receive from below */
684 case PRU_PROTOSEND: /* send to below */
685 case PRU_SOCKADDR: /* fetch socket's address */
686#ifdef DIAGNOSTIC
687 printf("natm: PRU #%d unsupported\n", req);
688#endif
689 error = EOPNOTSUPP;
690 break;
691
692 default: panic("natm usrreq");
693 }
694
695done:
696 splx(s);
697 return(error);
698}
699
700#endif /* !FREEBSD_USRREQS */
701
702/*
703 * natmintr: splsoftnet interrupt
704 *
705 * note: we expect a socket pointer in rcvif rather than an interface
706 * pointer. we can get the interface pointer from the so's PCB if
707 * we really need it.
708 */
709
710void
711natmintr()
712
713{
714 int s;
715 struct mbuf *m;
716 struct socket *so;
717 struct natmpcb *npcb;
718
719next:
720 s = splimp();
721 IF_DEQUEUE(&natmintrq, m);
722 splx(s);
723 if (m == NULL)
724 return;
725
726#ifdef DIAGNOSTIC
727 if ((m->m_flags & M_PKTHDR) == 0)
728 panic("natmintr no HDR");
729#endif
730
731 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
732 so = npcb->npcb_socket;
733
734 s = splimp(); /* could have atm devs @ different levels */
735 npcb->npcb_inq--;
736 splx(s);
737
738 if (npcb->npcb_flags & NPCB_DRAIN) {
739 m_freem(m);
740 if (npcb->npcb_inq == 0)
741 FREE(npcb, M_PCB); /* done! */
742 goto next;
743 }
744
745 if (npcb->npcb_flags & NPCB_FREE) {
746 m_freem(m); /* drop */
747 goto next;
748 }
749
750#ifdef NEED_TO_RESTORE_IFP
751 m->m_pkthdr.rcvif = npcb->npcb_ifp;
752#else
753#ifdef DIAGNOSTIC
754m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
755#endif
756#endif
757
758 if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
759 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
760#ifdef NATM_STAT
761 natm_sookcnt++;
762 natm_sookbytes += m->m_pkthdr.len;
763#endif
764 sbappendrecord(&so->so_rcv, m);
765 sorwakeup(so);
766 } else {
767#ifdef NATM_STAT
768 natm_sodropcnt++;
769 natm_sodropbytes += m->m_pkthdr.len;
770#endif
771 m_freem(m);
772 }
773
774 goto next;
775}
776
777#if defined(__FreeBSD__)
778NETISR_SET(NETISR_NATM, natmintr);
779#endif
780
781
782/*
783 * natm0_sysctl: not used, but here in case we want to add something
784 * later...
785 */
786
787int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
788
789int *name;
790u_int namelen;
791void *oldp;
792size_t *oldlenp;
793void *newp;
794size_t newlen;
795
796{
797 /* All sysctl names at this level are terminal. */
798 if (namelen != 1)
799 return (ENOTDIR);
800 return (ENOPROTOOPT);
801}
802
803/*
804 * natm5_sysctl: not used, but here in case we want to add something
805 * later...
806 */
807
808int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
809
810int *name;
811u_int namelen;
812void *oldp;
813size_t *oldlenp;
814void *newp;
815size_t newlen;
816
817{
818 /* All sysctl names at this level are terminal. */
819 if (namelen != 1)
820 return (ENOTDIR);
821 return (ENOPROTOOPT);
822}
415{
416 return EOPNOTSUPP;
417}
418
419/* xxx - should be const */
420struct pr_usrreqs natm_usrreqs = {
421 natm_usr_abort, pru_accept_notsupp, natm_usr_attach, natm_usr_bind,
422 natm_usr_connect, pru_connect2_notsupp, natm_usr_control,
423 natm_usr_detach, natm_usr_disconnect, pru_listen_notsupp,
424 natm_usr_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
425 natm_usr_send, pru_sense_null, natm_usr_shutdown,
426 natm_usr_sockaddr, sosend, soreceive, soselect
427};
428
429#else /* !FREEBSD_USRREQS */
430
431#if defined(__NetBSD__) || defined(__OpenBSD__)
432int natm_usrreq(so, req, m, nam, control, p)
433#elif defined(__FreeBSD__)
434int natm_usrreq(so, req, m, nam, control)
435#endif
436
437struct socket *so;
438int req;
439struct mbuf *m, *nam, *control;
440#if defined(__NetBSD__) || defined(__OpenBSD__)
441struct proc *p;
442#endif
443
444{
445 int error = 0, s, s2;
446 struct natmpcb *npcb;
447 struct sockaddr_natm *snatm;
448 struct atm_pseudoioctl api;
449 struct atm_pseudohdr *aph;
450 struct atm_rawioctl ario;
451 struct ifnet *ifp;
452 int proto = so->so_proto->pr_protocol;
453
454 s = SPLSOFTNET();
455
456 npcb = (struct natmpcb *) so->so_pcb;
457
458 if (npcb == NULL && req != PRU_ATTACH) {
459 error = EINVAL;
460 goto done;
461 }
462
463
464 switch (req) {
465 case PRU_ATTACH: /* attach protocol to up */
466
467 if (npcb) {
468 error = EISCONN;
469 break;
470 }
471
472 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
473 if (proto == PROTO_NATMAAL5)
474 error = soreserve(so, natm5_sendspace, natm5_recvspace);
475 else
476 error = soreserve(so, natm0_sendspace, natm0_recvspace);
477 if (error)
478 break;
479 }
480
481 so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
482 npcb->npcb_socket = so;
483
484 break;
485
486 case PRU_DETACH: /* detach protocol from up */
487
488 /*
489 * we turn on 'drain' *before* we sofree.
490 */
491
492 npcb_free(npcb, NPCB_DESTROY); /* drain */
493 so->so_pcb = NULL;
494 sofree(so);
495
496 break;
497
498 case PRU_CONNECT: /* establish connection to peer */
499
500 /*
501 * validate nam and npcb
502 */
503
504 if (nam->m_len != sizeof(*snatm)) {
505 error = EINVAL;
506 break;
507 }
508 snatm = mtod(nam, struct sockaddr_natm *);
509 if (snatm->snatm_len != sizeof(*snatm) ||
510 (npcb->npcb_flags & NPCB_FREE) == 0) {
511 error = EINVAL;
512 break;
513 }
514 if (snatm->snatm_family != AF_NATM) {
515 error = EAFNOSUPPORT;
516 break;
517 }
518
519 snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
520 since ifunit() uses strcmp */
521
522 /*
523 * convert interface string to ifp, validate.
524 */
525
526 ifp = ifunit(snatm->snatm_if);
527 if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
528 error = ENXIO;
529 break;
530 }
531 if (ifp->if_output != atm_output) {
532 error = EAFNOSUPPORT;
533 break;
534 }
535
536
537 /*
538 * register us with the NATM PCB layer
539 */
540
541 if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
542 error = EADDRINUSE;
543 break;
544 }
545
546 /*
547 * enable rx
548 */
549
550 ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
551 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
552 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
553 api.rxhand = npcb;
554 s2 = splimp();
555 if (ifp->if_ioctl == NULL ||
556 ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
557 splx(s2);
558 npcb_free(npcb, NPCB_REMOVE);
559 error = EIO;
560 break;
561 }
562 splx(s2);
563
564 soisconnected(so);
565
566 break;
567
568 case PRU_DISCONNECT: /* disconnect from peer */
569
570 if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
571 printf("natm: disconnected check\n");
572 error = EIO;
573 break;
574 }
575 ifp = npcb->npcb_ifp;
576
577 /*
578 * disable rx
579 */
580
581 ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
582 ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
583 ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
584 api.rxhand = npcb;
585 s2 = splimp();
586 if (ifp->if_ioctl != NULL)
587 ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
588 splx(s2);
589
590 npcb_free(npcb, NPCB_REMOVE);
591 soisdisconnected(so);
592
593 break;
594
595 case PRU_SHUTDOWN: /* won't send any more data */
596 socantsendmore(so);
597 break;
598
599 case PRU_SEND: /* send this data */
600 if (control && control->m_len) {
601 m_freem(control);
602 m_freem(m);
603 error = EINVAL;
604 break;
605 }
606
607 /*
608 * send the data. we must put an atm_pseudohdr on first
609 */
610
611 M_PREPEND(m, sizeof(*aph), M_WAITOK);
612 if (m == NULL) {
613 error = ENOBUFS;
614 break;
615 }
616 aph = mtod(m, struct atm_pseudohdr *);
617 ATM_PH_VPI(aph) = npcb->npcb_vpi;
618 ATM_PH_SETVCI(aph, npcb->npcb_vci);
619 ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
620
621 error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
622
623 break;
624
625 case PRU_SENSE: /* return status into m */
626 /* return zero? */
627 break;
628
629 case PRU_PEERADDR: /* fetch peer's address */
630 snatm = mtod(nam, struct sockaddr_natm *);
631 bzero(snatm, sizeof(*snatm));
632 nam->m_len = snatm->snatm_len = sizeof(*snatm);
633 snatm->snatm_family = AF_NATM;
634#if defined(__NetBSD__) || defined(__OpenBSD__)
635 bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
636#elif defined(__FreeBSD__)
637 sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
638 npcb->npcb_ifp->if_unit);
639#endif
640 snatm->snatm_vci = npcb->npcb_vci;
641 snatm->snatm_vpi = npcb->npcb_vpi;
642 break;
643
644 case PRU_CONTROL: /* control operations on protocol */
645 /*
646 * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
647 * SIOCXRAWATM and pass it to the driver.
648 */
649 if ((u_long)m == SIOCRAWATM) {
650 if (npcb->npcb_ifp == NULL) {
651 error = ENOTCONN;
652 break;
653 }
654 ario.npcb = npcb;
655 ario.rawvalue = *((int *)nam);
656 error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
657 SIOCXRAWATM, (caddr_t) &ario);
658 if (!error) {
659 if (ario.rawvalue)
660 npcb->npcb_flags |= NPCB_RAW;
661 else
662 npcb->npcb_flags &= ~(NPCB_RAW);
663 }
664
665 break;
666 }
667
668 error = EOPNOTSUPP;
669 break;
670
671 case PRU_BIND: /* bind socket to address */
672 case PRU_LISTEN: /* listen for connection */
673 case PRU_ACCEPT: /* accept connection from peer */
674 case PRU_CONNECT2: /* connect two sockets */
675 case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */
676 /* (only happens if LISTEN socket) */
677 case PRU_RCVD: /* have taken data; more room now */
678 case PRU_FASTTIMO: /* 200ms timeout */
679 case PRU_SLOWTIMO: /* 500ms timeout */
680 case PRU_RCVOOB: /* retrieve out of band data */
681 case PRU_SENDOOB: /* send out of band data */
682 case PRU_PROTORCV: /* receive from below */
683 case PRU_PROTOSEND: /* send to below */
684 case PRU_SOCKADDR: /* fetch socket's address */
685#ifdef DIAGNOSTIC
686 printf("natm: PRU #%d unsupported\n", req);
687#endif
688 error = EOPNOTSUPP;
689 break;
690
691 default: panic("natm usrreq");
692 }
693
694done:
695 splx(s);
696 return(error);
697}
698
699#endif /* !FREEBSD_USRREQS */
700
701/*
702 * natmintr: splsoftnet interrupt
703 *
704 * note: we expect a socket pointer in rcvif rather than an interface
705 * pointer. we can get the interface pointer from the so's PCB if
706 * we really need it.
707 */
708
709void
710natmintr()
711
712{
713 int s;
714 struct mbuf *m;
715 struct socket *so;
716 struct natmpcb *npcb;
717
718next:
719 s = splimp();
720 IF_DEQUEUE(&natmintrq, m);
721 splx(s);
722 if (m == NULL)
723 return;
724
725#ifdef DIAGNOSTIC
726 if ((m->m_flags & M_PKTHDR) == 0)
727 panic("natmintr no HDR");
728#endif
729
730 npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
731 so = npcb->npcb_socket;
732
733 s = splimp(); /* could have atm devs @ different levels */
734 npcb->npcb_inq--;
735 splx(s);
736
737 if (npcb->npcb_flags & NPCB_DRAIN) {
738 m_freem(m);
739 if (npcb->npcb_inq == 0)
740 FREE(npcb, M_PCB); /* done! */
741 goto next;
742 }
743
744 if (npcb->npcb_flags & NPCB_FREE) {
745 m_freem(m); /* drop */
746 goto next;
747 }
748
749#ifdef NEED_TO_RESTORE_IFP
750 m->m_pkthdr.rcvif = npcb->npcb_ifp;
751#else
752#ifdef DIAGNOSTIC
753m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
754#endif
755#endif
756
757 if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
758 ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
759#ifdef NATM_STAT
760 natm_sookcnt++;
761 natm_sookbytes += m->m_pkthdr.len;
762#endif
763 sbappendrecord(&so->so_rcv, m);
764 sorwakeup(so);
765 } else {
766#ifdef NATM_STAT
767 natm_sodropcnt++;
768 natm_sodropbytes += m->m_pkthdr.len;
769#endif
770 m_freem(m);
771 }
772
773 goto next;
774}
775
776#if defined(__FreeBSD__)
777NETISR_SET(NETISR_NATM, natmintr);
778#endif
779
780
781/*
782 * natm0_sysctl: not used, but here in case we want to add something
783 * later...
784 */
785
786int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
787
788int *name;
789u_int namelen;
790void *oldp;
791size_t *oldlenp;
792void *newp;
793size_t newlen;
794
795{
796 /* All sysctl names at this level are terminal. */
797 if (namelen != 1)
798 return (ENOTDIR);
799 return (ENOPROTOOPT);
800}
801
802/*
803 * natm5_sysctl: not used, but here in case we want to add something
804 * later...
805 */
806
807int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
808
809int *name;
810u_int namelen;
811void *oldp;
812size_t *oldlenp;
813void *newp;
814size_t newlen;
815
816{
817 /* All sysctl names at this level are terminal. */
818 if (namelen != 1)
819 return (ENOTDIR);
820 return (ENOPROTOOPT);
821}