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