Annotation of src/sys/netnatm/natm.c, Revision 1.45
1.45 ! rtr 1: /* $NetBSD: natm.c,v 1.44 2014/08/08 03:05:45 rtr Exp $ */
1.1 chuck 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: *
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
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
25: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26: */
27:
28: /*
29: * natm.c: native mode ATM access (both aal0 and aal5).
30: */
1.7 lukem 31:
32: #include <sys/cdefs.h>
1.45 ! rtr 33: __KERNEL_RCSID(0, "$NetBSD: natm.c,v 1.44 2014/08/08 03:05:45 rtr Exp $");
1.1 chuck 34:
35: #include <sys/param.h>
1.32 rtr 36: #include <sys/kmem.h>
1.1 chuck 37: #include <sys/systm.h>
38: #include <sys/kernel.h>
39: #include <sys/domain.h>
40: #include <sys/ioctl.h>
41: #include <sys/protosw.h>
42: #include <sys/mbuf.h>
43: #include <sys/socket.h>
44: #include <sys/socketvar.h>
45:
46: #include <net/if.h>
47: #include <net/if_atm.h>
48: #include <net/netisr.h>
49: #include <net/route.h>
50:
51: #include <netinet/in.h>
52:
53: #include <netnatm/natm.h>
54:
55: u_long natm5_sendspace = 16*1024;
56: u_long natm5_recvspace = 16*1024;
57:
58: u_long natm0_sendspace = 16*1024;
59: u_long natm0_recvspace = 16*1024;
60:
1.26 rmind 61: static int
62: natm_attach(struct socket *so, int proto)
63: {
1.32 rtr 64: int error = 0;
1.26 rmind 65: struct natmpcb *npcb;
66:
67: KASSERT(so->so_pcb == NULL);
68: sosetlock(so);
69:
70: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
71: if (proto == PROTO_NATMAAL5)
72: error = soreserve(so, natm5_sendspace, natm5_recvspace);
73: else
74: error = soreserve(so, natm0_sendspace, natm0_recvspace);
75: if (error)
76: return error;
77: }
78: npcb = npcb_alloc(true);
79: npcb->npcb_socket = so;
80: so->so_pcb = npcb;
1.32 rtr 81: return error;
1.26 rmind 82: }
83:
84: static void
85: natm_detach(struct socket *so)
86: {
87: struct natmpcb *npcb = (struct natmpcb *)so->so_pcb;
88:
89: /*
90: * we turn on 'drain' *before* we sofree.
91: */
92:
93: npcb_free(npcb, NPCB_DESTROY); /* drain */
94: so->so_pcb = NULL;
95: /* sofree drops the lock */
96: sofree(so);
97: mutex_enter(softnet_lock);
98: }
99:
1.28 rtr 100: static int
1.37 rtr 101: natm_accept(struct socket *so, struct mbuf *nam)
102: {
1.40 rtr 103: KASSERT(solocked(so));
1.37 rtr 104:
105: return EOPNOTSUPP;
106: }
107:
108: static int
1.42 rtr 109: natm_bind(struct socket *so, struct mbuf *nam, struct lwp *l)
1.39 rtr 110: {
1.40 rtr 111: KASSERT(solocked(so));
1.39 rtr 112:
113: return EOPNOTSUPP;
114: }
115:
116: static int
1.42 rtr 117: natm_listen(struct socket *so, struct lwp *l)
1.39 rtr 118: {
1.40 rtr 119: KASSERT(solocked(so));
1.39 rtr 120:
121: return EOPNOTSUPP;
122: }
123:
124: static int
1.42 rtr 125: natm_connect(struct socket *so, struct mbuf *nam, struct lwp *l)
1.40 rtr 126: {
127: int error = 0, s2;
128: struct natmpcb *npcb;
129: struct sockaddr_natm *snatm;
130: struct atm_pseudoioctl api;
131: struct atm_pseudohdr *aph;
132: struct ifnet *ifp;
133: int proto = so->so_proto->pr_protocol;
134:
135: KASSERT(solocked(so));
136:
137: /*
138: * validate nam and npcb
139: */
140:
141: if (nam->m_len != sizeof(*snatm))
142: return EINVAL;
143: snatm = mtod(nam, struct sockaddr_natm *);
144: if (snatm->snatm_len != sizeof(*snatm) ||
145: (npcb->npcb_flags & NPCB_FREE) == 0)
146: return EINVAL;
147: if (snatm->snatm_family != AF_NATM)
148: return EAFNOSUPPORT;
149:
150: snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
151: since ifunit() uses strcmp */
152:
153: /*
154: * convert interface string to ifp, validate.
155: */
156:
157: ifp = ifunit(snatm->snatm_if);
158: if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
159: return ENXIO;
160: }
161: if (ifp->if_output != atm_output) {
162: return EAFNOSUPPORT;
163: }
164:
165: /*
166: * register us with the NATM PCB layer
167: */
168:
169: if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb)
170: return EADDRINUSE;
171:
172: /*
173: * enable rx
174: */
175:
176: ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
177: ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
178: ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
179: api.rxhand = npcb;
180: s2 = splnet();
181: if (ifp->if_ioctl(ifp, SIOCATMENA, &api) != 0) {
182: splx(s2);
183: npcb_free(npcb, NPCB_REMOVE);
184: return EIO;
185: }
186: splx(s2);
187:
188: soisconnected(so);
189: return error;
190: }
191:
1.41 rtr 192: static int
1.45 ! rtr 193: natm_connect2(struct socket *so, struct socket *so2)
! 194: {
! 195: KASSERT(solocked(so));
! 196:
! 197: return EOPNOTSUPP;
! 198: }
! 199:
! 200: static int
1.41 rtr 201: natm_disconnect(struct socket *so)
202: {
203: struct natmpcb *npcb = (struct natmpcb *)so->so_pcb;
204:
205: KASSERT(solocked(so));
206: KASSERT(npcb != NULL);
207:
208: if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
209: printf("natm: disconnected check\n");
210: return EIO;
211: }
212: ifp = npcb->npcb_ifp;
213:
214: /*
215: * disable rx
216: */
217: ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
218: ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
219: ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
220: api.rxhand = npcb;
221:
222: s2 = splnet();
223: ifp->if_ioctl(ifp, SIOCATMDIS, &api);
224: splx(s);
225:
226: npcb_free(npcb, NPCB_REMOVE);
227: soisdisconnected(so);
228: return 0;
229: }
230:
231: static int
232: natm_shutdown(struct socket *so)
233: {
234: int s;
235:
236: KASSERT(solocked(so));
237:
238: s = splsoftnet();
239: socantsendmore(so);
240: splx(s);
241:
242: return 0;
243: }
244:
245: static int
246: natm_abort(struct socket *so)
247: {
248: KASSERT(solocked(so));
249:
250: return EOPNOTSUPP;
251: }
1.40 rtr 252:
253: static int
1.29 rtr 254: natm_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
1.28 rtr 255: {
1.32 rtr 256: int error = 0, s;
257: struct natmpcb *npcb;
258: struct atm_rawioctl ario;
1.28 rtr 259:
260: s = SPLSOFTNET();
261:
1.32 rtr 262: npcb = (struct natmpcb *) so->so_pcb;
263:
1.28 rtr 264: /*
265: * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
266: * SIOCXRAWATM and pass it to the driver.
267: */
1.29 rtr 268: if (cmd == SIOCRAWATM) {
1.28 rtr 269: if (npcb->npcb_ifp == NULL) {
270: error = ENOTCONN;
271: goto done;
272: }
273: ario.npcb = npcb;
274: ario.rawvalue = *((int *)nam);
275: error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp, SIOCXRAWATM, &ario);
276: if (!error) {
277: if (ario.rawvalue)
278: npcb->npcb_flags |= NPCB_RAW;
279: else
280: npcb->npcb_flags &= ~(NPCB_RAW);
281: }
282:
283: goto done;
284: }
285:
286: error = EOPNOTSUPP;
287:
288: done:
289: splx(s);
290: return(error);
291: }
292:
1.30 rtr 293: static int
1.31 rtr 294: natm_stat(struct socket *so, struct stat *ub)
1.30 rtr 295: {
1.35 rtr 296: KASSERT(solocked(so));
297:
1.34 rtr 298: return 0;
1.30 rtr 299: }
300:
1.36 rtr 301: static int
302: natm_peeraddr(struct socket *so, struct mbuf *nam)
303: {
304: struct natmpcb *npcb = (struct natmpcb *) so->so_pcb;
305: struct sockaddr_natm *snatm;
306:
307: KASSERT(solocked(so));
308: KASSERT(pcb != NULL);
309: KASSERT(nam != NULL);
310:
311: snatm = mtod(nam, struct sockaddr_natm *);
312: memset(snatm, 0, sizeof(*snatm));
313: nam->m_len = snatm->snatm_len = sizeof(*snatm);
314: snatm->snatm_family = AF_NATM;
315: memcpy(snatm->snatm_if, npcb->npcb_ifp->if_xname, sizeof(snatm->snatm_if));
316: snatm->snatm_vci = npcb->npcb_vci;
317: snatm->snatm_vpi = npcb->npcb_vpi;
318: return 0;
319: }
320:
321: static int
322: natm_sockaddr(struct socket *so, struct mbuf *nam)
323: {
1.44 rtr 324: KASSERT(solocked(so));
325:
326: return EOPNOTSUPP;
327: }
328:
329: static int
330: natm_rcvd(struct socket *so, int flags, struct lwp *l)
331: {
332: KASSERT(solocked(so));
1.36 rtr 333:
1.44 rtr 334: return EOPNOTSUPP;
1.36 rtr 335: }
336:
1.38 rtr 337: static int
338: natm_recvoob(struct socket *so, struct mbuf *m, int flags)
339: {
1.44 rtr 340: KASSERT(solocked(so));
341:
342: return EOPNOTSUPP;
343: }
344:
345: static int
346: natm_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
347: struct mbuf *control)
348: {
349: struct natmpcb *npcb = (struct natmpcb *) so->so_pcb;
350: struct atm_pseudohdr *aph;
351:
352: KASSERT(solocked(so));
353: KASSERT(pcb != NULL);
354: KASSERT(m != NULL);
355:
356: if (control && control->m_len) {
357: m_freem(control);
358: m_freem(m);
359: return EINVAL;
360: }
361:
362: /*
363: * send the data. we must put an atm_pseudohdr on first
364: */
365: s = SPLSOFTNET();
366: M_PREPEND(m, sizeof(*aph), M_WAITOK);
367: if (m == NULL) {
368: error = ENOBUFS;
369: break;
370: }
371: aph = mtod(m, struct atm_pseudohdr *);
372: ATM_PH_VPI(aph) = npcb->npcb_vpi;
373: ATM_PH_SETVCI(aph, npcb->npcb_vci);
374: ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
375: error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
376: splx(s);
1.38 rtr 377:
1.44 rtr 378: return error;
1.38 rtr 379: }
380:
381: static int
1.43 rtr 382: natm_send(struct socket *so, struct mbuf *m, struct mbuf *nam,
383: struct mbuf *control, struct lwp *l)
384: {
385: struct natmpcb *npcb = (struct natmpcb *) so->so_pcb;
386: struct atm_pseudohdr *aph;
387:
388: KASSERT(solocked(so));
389: KASSERT(pcb != NULL);
390: KASSERT(m != NULL);
391:
392: if (control && control->m_len) {
393: m_freem(control);
394: m_freem(m);
395: return EINVAL;
396: }
397:
398: /*
399: * send the data. we must put an atm_pseudohdr on first
400: */
401: s = SPLSOFTNET();
402: M_PREPEND(m, sizeof(*aph), M_WAITOK);
403: if (m == NULL) {
404: error = ENOBUFS;
405: break;
406: }
407: aph = mtod(m, struct atm_pseudohdr *);
408: ATM_PH_VPI(aph) = npcb->npcb_vpi;
409: ATM_PH_SETVCI(aph, npcb->npcb_vci);
410: ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
411: error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
412: splx(s);
413:
414: return error;
415: }
416:
417: static int
1.38 rtr 418: natm_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
419: {
1.45 ! rtr 420: KASSERT(solocked(so));
! 421:
! 422: return EOPNOTSUPP;
! 423: }
! 424:
! 425: static int
! 426: natm_purgeif(struct socket *so, struct ifnet *ifp)
! 427: {
1.38 rtr 428:
1.45 ! rtr 429: return EOPNOTSUPP;
1.38 rtr 430: }
431:
1.1 chuck 432: /*
433: * user requests
434: */
435:
1.25 rmind 436: static int
437: natm_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
438: struct mbuf *control, struct lwp *l)
1.1 chuck 439: {
440: int error = 0, s, s2;
441: struct natmpcb *npcb;
442: struct sockaddr_natm *snatm;
443: struct atm_pseudoioctl api;
444: struct atm_pseudohdr *aph;
445: struct ifnet *ifp;
446: int proto = so->so_proto->pr_protocol;
447:
1.26 rmind 448: KASSERT(req != PRU_ATTACH);
449: KASSERT(req != PRU_DETACH);
1.37 rtr 450: KASSERT(req != PRU_ACCEPT);
1.39 rtr 451: KASSERT(req != PRU_BIND);
452: KASSERT(req != PRU_LISTEN);
1.40 rtr 453: KASSERT(req != PRU_CONNECT);
1.45 ! rtr 454: KASSERT(req != PRU_CONNECT2);
1.41 rtr 455: KASSERT(req != PRU_DISCONNECT);
456: KASSERT(req != PRU_SHUTDOWN);
457: KASSERT(req != PRU_ABORT);
1.28 rtr 458: KASSERT(req != PRU_CONTROL);
1.30 rtr 459: KASSERT(req != PRU_SENSE);
1.36 rtr 460: KASSERT(req != PRU_PEERADDR);
461: KASSERT(req != PRU_SOCKADDR);
1.44 rtr 462: KASSERT(req != PRU_RCVD);
1.38 rtr 463: KASSERT(req != PRU_RCVOOB);
1.43 rtr 464: KASSERT(req != PRU_SEND);
1.38 rtr 465: KASSERT(req != PRU_SENDOOB);
1.45 ! rtr 466: KASSERT(req != PRU_PURGEIF);
1.26 rmind 467:
1.45 ! rtr 468: if (so->so_pcb == NULL)
! 469: return EINVAL;
1.11 perry 470:
1.1 chuck 471: switch (req) {
472: case PRU_FASTTIMO: /* 200ms timeout */
473: case PRU_SLOWTIMO: /* 500ms timeout */
474: case PRU_PROTORCV: /* receive from below */
475: case PRU_PROTOSEND: /* send to below */
476: #ifdef DIAGNOSTIC
1.4 christos 477: printf("natm: PRU #%d unsupported\n", req);
1.1 chuck 478: #endif
479: error = EOPNOTSUPP;
480: break;
1.11 perry 481:
1.1 chuck 482: default: panic("natm usrreq");
483: }
484:
485: done:
1.45 ! rtr 486: return error;
1.1 chuck 487: }
488:
489: /*
490: * natmintr: splsoftnet interrupt
491: *
492: * note: we expect a socket pointer in rcvif rather than an interface
493: * pointer. we can get the interface pointer from the so's PCB if
494: * we really need it.
495: */
496:
497: void
1.19 cegger 498: natmintr(void)
1.1 chuck 499:
500: {
501: int s;
502: struct mbuf *m;
503: struct socket *so;
504: struct natmpcb *npcb;
505:
1.15 ad 506: mutex_enter(softnet_lock);
1.1 chuck 507: next:
1.6 thorpej 508: s = splnet();
1.1 chuck 509: IF_DEQUEUE(&natmintrq, m);
510: splx(s);
1.15 ad 511: if (m == NULL) {
512: mutex_exit(softnet_lock);
1.1 chuck 513: return;
1.15 ad 514: }
1.1 chuck 515:
516: #ifdef DIAGNOSTIC
517: if ((m->m_flags & M_PKTHDR) == 0)
1.5 chuck 518: panic("natmintr no HDR");
1.1 chuck 519: #endif
520:
521: npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
522: so = npcb->npcb_socket;
523:
1.6 thorpej 524: s = splnet(); /* could have atm devs @ different levels */
1.1 chuck 525: npcb->npcb_inq--;
526: splx(s);
527:
528: if (npcb->npcb_flags & NPCB_DRAIN) {
529: m_freem(m);
530: if (npcb->npcb_inq == 0)
1.26 rmind 531: kmem_intr_free(npcb, sizeof(*npcb));
1.1 chuck 532: goto next;
533: }
534:
535: if (npcb->npcb_flags & NPCB_FREE) {
536: m_freem(m); /* drop */
537: goto next;
538: }
539:
540: #ifdef NEED_TO_RESTORE_IFP
541: m->m_pkthdr.rcvif = npcb->npcb_ifp;
542: #else
543: #ifdef DIAGNOSTIC
544: m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
545: #endif
546: #endif
547:
548: if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
549: ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
550: #ifdef NATM_STAT
551: natm_sookcnt++;
552: natm_sookbytes += m->m_pkthdr.len;
553: #endif
1.2 thorpej 554: sbappendrecord(&so->so_rcv, m);
1.1 chuck 555: sorwakeup(so);
556: } else {
557: #ifdef NATM_STAT
558: natm_sodropcnt++;
559: natm_sodropbytes += m->m_pkthdr.len;
560: #endif
561: m_freem(m);
562: }
563:
564: goto next;
565: }
1.25 rmind 566:
1.27 rmind 567: PR_WRAP_USRREQS(natm)
568: #define natm_attach natm_attach_wrapper
569: #define natm_detach natm_detach_wrapper
1.37 rtr 570: #define natm_accept natm_accept_wrapper
1.39 rtr 571: #define natm_bind natm_bind_wrapper
572: #define natm_listen natm_listen_wrapper
1.40 rtr 573: #define natm_connect natm_connect_wrapper
1.45 ! rtr 574: #define natm_connect2 natm_connect2_wrapper
1.41 rtr 575: #define natm_disconnect natm_disconnect_wrapper
576: #define natm_shutdown natm_shutdown_wrapper
577: #define natm_abort natm_abort_wrapper
1.28 rtr 578: #define natm_ioctl natm_ioctl_wrapper
1.30 rtr 579: #define natm_stat natm_stat_wrapper
1.36 rtr 580: #define natm_peeraddr natm_peeraddr_wrapper
581: #define natm_sockaddr natm_sockaddr_wrapper
1.44 rtr 582: #define natm_rcvd natm_rcvd_wrapper
1.38 rtr 583: #define natm_recvoob natm_recvoob_wrapper
1.43 rtr 584: #define natm_send natm_send_wrapper
1.38 rtr 585: #define natm_sendoob natm_sendoob_wrapper
1.45 ! rtr 586: #define natm_purgeif natm_purgeif_wrapper
1.25 rmind 587: #define natm_usrreq natm_usrreq_wrapper
588:
589: const struct pr_usrreqs natm_usrreqs = {
1.26 rmind 590: .pr_attach = natm_attach,
591: .pr_detach = natm_detach,
1.37 rtr 592: .pr_accept = natm_accept,
1.39 rtr 593: .pr_bind = natm_bind,
594: .pr_listen = natm_listen,
1.40 rtr 595: .pr_connect = natm_connect,
1.45 ! rtr 596: .pr_connect2 = natm_connect2,
1.41 rtr 597: .pr_disconnect = natm_disconnect,
598: .pr_shutdown = natm_shutdown,
599: .pr_abort = natm_abort,
1.28 rtr 600: .pr_ioctl = natm_ioctl,
1.30 rtr 601: .pr_stat = natm_stat,
1.36 rtr 602: .pr_peeraddr = natm_peeraddr,
603: .pr_sockaddr = natm_sockaddr,
1.44 rtr 604: .pr_rcvd = natm_rcvd,
1.38 rtr 605: .pr_recvoob = natm_recvoob,
1.43 rtr 606: .pr_send = natm_send,
1.38 rtr 607: .pr_sendoob = natm_sendoob,
1.45 ! rtr 608: .pr_purgeif = natm_purgeif,
1.25 rmind 609: .pr_generic = natm_usrreq,
610: };
CVSweb <webmaster@jp.NetBSD.org>