Annotation of sys/netnatm/natm.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: natm.c,v 1.7 2006/03/04 22:40:16 brad 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: #include <sys/ioctl.h>
44: #include <sys/proc.h>
45: #include <sys/protosw.h>
46: #include <sys/mbuf.h>
47: #include <sys/socket.h>
48: #include <sys/socketvar.h>
49:
50: #include <net/if.h>
51: #include <net/if_atm.h>
52: #include <net/netisr.h>
53: #include <net/radix.h>
54: #include <net/route.h>
55:
56: #include <netinet/in.h>
57:
58: #include <netnatm/natm.h>
59:
60: u_long natm5_sendspace = 16*1024;
61: u_long natm5_recvspace = 16*1024;
62:
63: u_long natm0_sendspace = 16*1024;
64: u_long natm0_recvspace = 16*1024;
65:
66: /*
67: * user requests
68: */
69:
70: #if defined(__NetBSD__)
71: int natm_usrreq(so, req, m, nam, control)
72: #elif defined(__OpenBSD__) || defined(__FreeBSD__)
73: int natm_usrreq(so, req, m, nam, control)
74: #endif
75: struct socket *so;
76: int req;
77: struct mbuf *m, *nam, *control;
78: #if defined(__NetBSD__)
79: struct proc *p;
80: #endif
81: {
82: int error = 0, s, s2;
83: struct natmpcb *npcb;
84: struct sockaddr_natm *snatm;
85: struct atm_pseudoioctl api;
86: struct atm_pseudohdr *aph;
87: struct atm_rawioctl ario;
88: struct ifnet *ifp;
89: int proto = so->so_proto->pr_protocol;
90:
91: s = SPLSOFTNET();
92:
93: npcb = (struct natmpcb *) so->so_pcb;
94:
95: if (npcb == NULL && req != PRU_ATTACH) {
96: error = EINVAL;
97: goto done;
98: }
99:
100:
101: switch (req) {
102: case PRU_ATTACH: /* attach protocol to up */
103:
104: if (npcb) {
105: error = EISCONN;
106: break;
107: }
108:
109: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
110: if (proto == PROTO_NATMAAL5)
111: error = soreserve(so, natm5_sendspace, natm5_recvspace);
112: else
113: error = soreserve(so, natm0_sendspace, natm0_recvspace);
114: if (error)
115: break;
116: }
117:
118: so->so_pcb = (caddr_t) (npcb = npcb_alloc(M_WAITOK));
119: npcb->npcb_socket = so;
120:
121: break;
122:
123: case PRU_DETACH: /* detach protocol from up */
124:
125: /*
126: * we turn on 'drain' *before* we sofree.
127: */
128:
129: npcb_free(npcb, NPCB_DESTROY); /* drain */
130: so->so_pcb = NULL;
131: sofree(so);
132:
133: break;
134:
135: case PRU_CONNECT: /* establish connection to peer */
136:
137: /*
138: * validate nam and npcb
139: */
140:
141: if (nam->m_len != sizeof(*snatm)) {
142: error = EINVAL;
143: break;
144: }
145: snatm = mtod(nam, struct sockaddr_natm *);
146: if (snatm->snatm_len != sizeof(*snatm) ||
147: (npcb->npcb_flags & NPCB_FREE) == 0) {
148: error = EINVAL;
149: break;
150: }
151: if (snatm->snatm_family != AF_NATM) {
152: error = EAFNOSUPPORT;
153: break;
154: }
155:
156: snatm->snatm_if[IFNAMSIZ-1] = '\0'; /* XXX ensure null termination
157: since ifunit() uses strcmp */
158:
159: /*
160: * convert interface string to ifp, validate.
161: */
162:
163: ifp = ifunit(snatm->snatm_if);
164: if (ifp == NULL || (ifp->if_flags & IFF_RUNNING) == 0) {
165: error = ENXIO;
166: break;
167: }
168: if (ifp->if_output != atm_output) {
169: error = EAFNOSUPPORT;
170: break;
171: }
172:
173:
174: /*
175: * register us with the NATM PCB layer
176: */
177:
178: if (npcb_add(npcb, ifp, snatm->snatm_vci, snatm->snatm_vpi) != npcb) {
179: error = EADDRINUSE;
180: break;
181: }
182:
183: /*
184: * enable rx
185: */
186:
187: ATM_PH_FLAGS(&api.aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
188: ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
189: ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
190: api.rxhand = npcb;
191: s2 = splnet();
192: if (ifp->if_ioctl == NULL ||
193: ifp->if_ioctl(ifp, SIOCATMENA, (caddr_t) &api) != 0) {
194: splx(s2);
195: npcb_free(npcb, NPCB_REMOVE);
196: error = EIO;
197: break;
198: }
199: splx(s2);
200:
201: soisconnected(so);
202:
203: break;
204:
205: case PRU_DISCONNECT: /* disconnect from peer */
206:
207: if ((npcb->npcb_flags & NPCB_CONNECTED) == 0) {
208: printf("natm: disconnected check\n");
209: error = EIO;
210: break;
211: }
212: ifp = npcb->npcb_ifp;
213:
214: /*
215: * disable rx
216: */
217:
218: ATM_PH_FLAGS(&api.aph) = ATM_PH_AAL5;
219: ATM_PH_VPI(&api.aph) = npcb->npcb_vpi;
220: ATM_PH_SETVCI(&api.aph, npcb->npcb_vci);
221: api.rxhand = npcb;
222: s2 = splnet();
223: if (ifp->if_ioctl != NULL)
224: ifp->if_ioctl(ifp, SIOCATMDIS, (caddr_t) &api);
225: splx(s);
226:
227: npcb_free(npcb, NPCB_REMOVE);
228: soisdisconnected(so);
229:
230: break;
231:
232: case PRU_SHUTDOWN: /* won't send any more data */
233: socantsendmore(so);
234: break;
235:
236: case PRU_SEND: /* send this data */
237: if (control && control->m_len) {
238: m_freem(control);
239: m_freem(m);
240: error = EINVAL;
241: break;
242: }
243:
244: /*
245: * send the data. we must put an atm_pseudohdr on first
246: */
247:
248: M_PREPEND(m, sizeof(*aph), M_WAITOK);
249: aph = mtod(m, struct atm_pseudohdr *);
250: ATM_PH_VPI(aph) = npcb->npcb_vpi;
251: ATM_PH_SETVCI(aph, npcb->npcb_vci);
252: ATM_PH_FLAGS(aph) = (proto == PROTO_NATMAAL5) ? ATM_PH_AAL5 : 0;
253:
254: error = atm_output(npcb->npcb_ifp, m, NULL, NULL);
255:
256: break;
257:
258: case PRU_SENSE: /* return status into m */
259: /* return zero? */
260: break;
261:
262: case PRU_PEERADDR: /* fetch peer's address */
263: snatm = mtod(nam, struct sockaddr_natm *);
264: bzero(snatm, sizeof(*snatm));
265: nam->m_len = snatm->snatm_len = sizeof(*snatm);
266: snatm->snatm_family = AF_NATM;
267: #if defined(__NetBSD__) || defined(__OpenBSD__)
268: bcopy(npcb->npcb_ifp->if_xname, snatm->snatm_if, sizeof(snatm->snatm_if));
269: #elif defined(__FreeBSD__)
270: sprintf(snatm->snatm_if, "%s%d", npcb->npcb_ifp->if_name,
271: npcb->npcb_ifp->if_unit);
272: #endif
273: snatm->snatm_vci = npcb->npcb_vci;
274: snatm->snatm_vpi = npcb->npcb_vpi;
275: break;
276:
277: case PRU_CONTROL: /* control operations on protocol */
278: /*
279: * raw atm ioctl. comes in as a SIOCRAWATM. we convert it to
280: * SIOCXRAWATM and pass it to the driver.
281: */
282: if ((u_long)m == SIOCRAWATM) {
283: if (npcb->npcb_ifp == NULL) {
284: error = ENOTCONN;
285: break;
286: }
287: ario.npcb = npcb;
288: ario.rawvalue = *((int *)nam);
289: error = npcb->npcb_ifp->if_ioctl(npcb->npcb_ifp,
290: SIOCXRAWATM, (caddr_t) &ario);
291: if (!error) {
292: if (ario.rawvalue)
293: npcb->npcb_flags |= NPCB_RAW;
294: else
295: npcb->npcb_flags &= ~(NPCB_RAW);
296: }
297:
298: break;
299: }
300:
301: error = EOPNOTSUPP;
302: break;
303:
304: case PRU_BIND: /* bind socket to address */
305: case PRU_LISTEN: /* listen for connection */
306: case PRU_ACCEPT: /* accept connection from peer */
307: case PRU_CONNECT2: /* connect two sockets */
308: case PRU_ABORT: /* abort (fast DISCONNECT, DETATCH) */
309: /* (only happens if LISTEN socket) */
310: case PRU_RCVD: /* have taken data; more room now */
311: case PRU_FASTTIMO: /* 200ms timeout */
312: case PRU_SLOWTIMO: /* 500ms timeout */
313: case PRU_RCVOOB: /* retrieve out of band data */
314: case PRU_SENDOOB: /* send out of band data */
315: case PRU_PROTORCV: /* receive from below */
316: case PRU_PROTOSEND: /* send to below */
317: case PRU_SOCKADDR: /* fetch socket's address */
318: #ifdef DIAGNOSTIC
319: printf("natm: PRU #%d unsupported\n", req);
320: #endif
321: error = EOPNOTSUPP;
322: break;
323:
324: default: panic("natm usrreq");
325: }
326:
327: done:
328: splx(s);
329: return(error);
330: }
331:
332: /*
333: * natmintr: splsoftnet interrupt
334: *
335: * note: we expect a socket pointer in rcvif rather than an interface
336: * pointer. we can get the interface pointer from the so's PCB if
337: * we really need it.
338: */
339:
340: void
341: natmintr()
342:
343: {
344: int s;
345: struct mbuf *m;
346: struct socket *so;
347: struct natmpcb *npcb;
348:
349: next:
350: s = splnet();
351: IF_DEQUEUE(&natmintrq, m);
352: splx(s);
353: if (m == NULL)
354: return;
355:
356: #ifdef DIAGNOSTIC
357: if ((m->m_flags & M_PKTHDR) == 0)
358: panic("natmintr no HDR");
359: #endif
360:
361: npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
362: so = npcb->npcb_socket;
363:
364: s = splnet(); /* could have atm devs @ different levels */
365: npcb->npcb_inq--;
366: splx(s);
367:
368: if (npcb->npcb_flags & NPCB_DRAIN) {
369: m_freem(m);
370: if (npcb->npcb_inq == 0)
371: FREE(npcb, M_PCB); /* done! */
372: goto next;
373: }
374:
375: if (npcb->npcb_flags & NPCB_FREE) {
376: m_freem(m); /* drop */
377: goto next;
378: }
379:
380: #ifdef NEED_TO_RESTORE_IFP
381: m->m_pkthdr.rcvif = npcb->npcb_ifp;
382: #else
383: #ifdef DIAGNOSTIC
384: m->m_pkthdr.rcvif = NULL; /* null it out to be safe */
385: #endif
386: #endif
387:
388: if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
389: ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
390: #ifdef NATM_STAT
391: natm_sookcnt++;
392: natm_sookbytes += m->m_pkthdr.len;
393: #endif
394: sbappendrecord(&so->so_rcv, m);
395: sorwakeup(so);
396: } else {
397: #ifdef NATM_STAT
398: natm_sodropcnt++;
399: natm_sodropbytes += m->m_pkthdr.len;
400: #endif
401: m_freem(m);
402: }
403:
404: goto next;
405: }
406:
407: #if defined(__FreeBSD__)
408: NETISR_SET(NETISR_NATM, natmintr);
409: #endif
410:
411:
412: /*
413: * natm0_sysctl: not used, but here in case we want to add something
414: * later...
415: */
416:
417: int natm0_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
418:
419: int *name;
420: u_int namelen;
421: void *oldp;
422: size_t *oldlenp;
423: void *newp;
424: size_t newlen;
425:
426: {
427: /* All sysctl names at this level are terminal. */
428: if (namelen != 1)
429: return (ENOTDIR);
430: return (ENOPROTOOPT);
431: }
432:
433: /*
434: * natm5_sysctl: not used, but here in case we want to add something
435: * later...
436: */
437:
438: int natm5_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
439:
440: int *name;
441: u_int namelen;
442: void *oldp;
443: size_t *oldlenp;
444: void *newp;
445: size_t newlen;
446:
447: {
448: /* All sysctl names at this level are terminal. */
449: if (namelen != 1)
450: return (ENOTDIR);
451: return (ENOPROTOOPT);
452: }
CVSweb