|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1997, 1998 Apple Computer, Inc. All Rights Reserved */
26: /*
27: * @(#)ndrv.c 1.1 (Rhapsody) 6/10/97
28: * Justin Walker, 970604
29: * AF_NDRV support
30: * 980130 - Cleanup, reorg, performance improvemements
31: */
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/kernel.h>
36: #include <sys/malloc.h>
37: #include <sys/mbuf.h>
38: #include <sys/protosw.h>
39: #include <sys/domain.h>
40: #include <sys/socket.h>
41: #include <sys/socketvar.h>
42: #include <sys/ioctl.h>
43: #include <sys/errno.h>
44: #include <sys/syslog.h>
45: #include <sys/proc.h>
46:
47: #include <net/if.h>
48: #include <net/netisr.h>
49: #include <net/route.h>
50: #include <net/if_llc.h>
51: #include <net/if_dl.h>
52: #include <net/if_types.h>
53: #include "if_blue.h"
54: #include "ndrv.h"
55:
56: #if INET
57: #include <netinet/in.h>
58: #include <netinet/in_var.h>
59: #endif
60: #include <netinet/if_ether.h>
61:
62: #if NS
63: #include <netns/ns.h>
64: #include <netns/ns_if.h>
65: #endif
66:
67: #if ISO
68: #include <netiso/argo_debug.h>
69: #include <netiso/iso.h>
70: #include <netiso/iso_var.h>
71: #include <netiso/iso_snpac.h>
72: #endif
73:
74: #if LLC
75: #include <netccitt/dll.h>
76: #include <netccitt/llc_var.h>
77: #endif
78:
79: #include <machine/spl.h>
80:
81: extern void ndrv_ctlinput(), ndrv_init(), ndrv_drain();
82: extern int ndrv_ctloutput(), ndrv_usrreq(), ndrv_output(), ndrv_sysctl();
83:
84: int ndrv_attach(struct socket *, int);
85: int ndrv_detach(struct ndrv_cb *);
86: int ndrv_bind(struct socket *, struct mbuf *);
87: int ndrv_disconnect(struct ndrv_cb *);
88:
89: extern struct domain ndrvdomain; /* That silly forward reference stuff */
90:
91: struct protosw ndrvsw[] =
92: { { SOCK_RAW, &ndrvdomain, 0, PR_ATOMIC|PR_ADDR,
93: 0, ndrv_output, ndrv_ctlinput, ndrv_ctloutput,
94: ndrv_usrreq, ndrv_init, NULL, NULL,
95: ndrv_drain, ndrv_sysctl
96: }
97: };
98:
99: void ndrv_dinit(void);
100:
101: struct domain ndrvdomain =
102: { AF_NDRV, "NetDriver", NULL, NULL, NULL,
103: ndrvsw, &ndrvsw[sizeof(ndrvsw)/sizeof(ndrvsw[0])],
104: NULL, NULL, 0, 0
105: };
106:
107: unsigned long ndrv_sendspace = NDRVSNDQ;
108: unsigned long ndrv_recvspace = NDRVRCVQ;
109: struct ndrv_cb ndrvl; /* Head of controlblock list */
110:
111: #define BLUEQMAXLEN 50
112: int blueqmaxlen = BLUEQMAXLEN; /* Default */
113:
114: /* Domain init function for AF_NDRV - noop */
115: void
116: ndrv_dinit(void)
117: {
118: }
119:
120: /*
121: * Protocol init function for NDRV protocol
122: * Init the control block list.
123: */
124: void
125: ndrv_init()
126: { ndrvl.nd_next = ndrvl.nd_prev = &ndrvl;
127: blueq.ifq_maxlen = blueqmaxlen;
128: }
129:
130: /*
131: * Protocol output - Called from, e.g., the Blue Box
132: * Just use the driver. If we're splitting, loop it back.
133: */
134: int
135: ndrv_output(register struct mbuf *m,
136: register struct socket *so)
137: { register struct ndrv_cb *np = sotondrvcb(so);
138: register struct ifnet *ifp = np->nd_if;
139: int s, error;
140: extern struct ifnet_blue *blue_if;
141: extern void kprintf(const char *, ...);
142: extern int Filter_check(struct mbuf **);
143: #define senderr(e) { error = (e); goto bad;}
144:
145: #if 0
146: kprintf("NDRV output: %x, %x, %x\n", m, so, np);
147: #endif
148:
149: /*
150: * No header is a format error
151: */
152: if ((m->m_flags&M_PKTHDR) == 0)
153: return(ENOBUFS); /* EINVAL??? */
154:
155: /* If we're splitting, */
156: if (ifp->if_flags&IFF_SPLITTER) /* Splitter is turned on */
157: { register struct mbuf *m0;
158: struct mbuf *m1;
159: register int rv;
160: extern struct mbuf *m_dup(struct mbuf *, int);
161: #if 0
162: kprintf("NDRV_OUTPUT: m0 = %x\n", m0);
163: #endif
164:
165: m1 = m;
166: rv = Filter_check(&m1);
167: m = m1;
168: /*
169: * -1 => Not For Rhapsody
170: * 0 => For Both
171: * 1 => For Rhapsody
172: */
173: if (rv >= 0)
174: { register struct ether_header *eh;
175:
176: if (rv == 0)
177: { if ((m0 = m_dup(m, M_WAIT)) == NULL)
178: ((struct ifnet_blue *)ifp->if_Y)->no_bufs2++;
179: } else
180: { m0 = m;
181: m = NULL;
182: }
183: /* Hack alert! */
184: eh = mtod(m0, struct ether_header *);
185: m0->m_data += sizeof(struct ether_header);
186: m0->m_len -= sizeof (struct ether_header);
187: m0->m_pkthdr.len -= sizeof(struct ether_header);
188: m0->m_flags |= 0x80;
189: ether_input((struct ifnet *)blue_if, eh, m0);
190: if (!m)
191: return(0);
192: }
193: }
194:
195: /*
196: * Output to real device. Here if rv==0.
197: * Cribbed from ether_output() XXX
198: *
199: * Can't do multicast accounting because we don't know
200: * (a) if our interface does multicast; and
201: * (b) what a multicast address looks like
202: */
203: s = splimp();
204: /*
205: * Queue message on interface, and start output
206: * Can't check for already active, since that's a race.
207: */
208: if (IF_QFULL(&ifp->if_snd)) {
209: IF_DROP(&ifp->if_snd);
210: splx(s);
211: senderr(ENOBUFS);
212: }
213: IF_ENQUEUE(&ifp->if_snd, m);
214: (*ifp->if_start)(ifp);
215: splx(s);
216: ifp->if_obytes += m->m_len; /* MP alert! */
217: blue_if->pkts_out++;
218: return (0);
219: bad:
220: if (m)
221: m_freem(m);
222: return (error);
223: }
224:
225: /* The meat of the protocol handler */
226: int
227: ndrv_usrreq(register struct socket *so,
228: register int req,
229: register struct mbuf *m,
230: register struct mbuf *nam,
231: register struct mbuf *control)
232: { register struct ndrv_cb *np = sotondrvcb(so);
233: register int error = 0;
234: int len;
235: extern int splitter_ctl(struct socket *, int, caddr_t, struct ifnet *);
236:
237: #if 0
238: kprintf("NDRV usrreq: %x, %x, %x\n", so, req, np);
239: #endif
240: if (req == PRU_CONTROL)
241: return (splitter_ctl(so, (int)m, (caddr_t)nam,
242: (struct ifnet *)control));
243: if (control && control->m_len) {
244: error = EOPNOTSUPP;
245: goto release;
246: }
247: if (req != PRU_ATTACH && np == 0) {
248: error = EINVAL;
249: goto release;
250: }
251:
252: switch (req) {
253:
254: /*
255: * Allocate a control block and fill in the
256: * necessary info to allow packets to be routed to
257: * the appropriate device driver routine.
258: */
259: case PRU_ATTACH:
260: error = ndrv_attach(so, (int)nam);
261: break;
262:
263: /*
264: * Destroy state just before socket deallocation.
265: * Flush data or not depending on the options.
266: */
267: case PRU_DETACH:
268: ndrv_detach((struct ndrv_cb *)np);
269: break;
270:
271: /*
272: * If a socket isn't bound to a single address,
273: * the ndrv input routine will hand it anything
274: * within that protocol family (assuming there's
275: * nothing else around it should go to).
276: *
277: * Don't expect this to be used.
278: */
279: case PRU_CONNECT:
280: if (np->nd_faddr) {
281: error = EISCONN;
282: break;
283: }
284: nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
285: np->nd_faddr = mtod(nam, struct sockaddr_ndrv *);
286: soisconnected(so);
287: break;
288:
289: /*
290: * This is the "driver open" hook - we 'bind' to the
291: * named driver.
292: */
293: case PRU_BIND:
294: if (np->nd_laddr) {
295: error = EINVAL; /* XXX */
296: break;
297: }
298: error = ndrv_bind(so, nam);
299: break;
300:
301: case PRU_CONNECT2:
302: error = EOPNOTSUPP;
303: goto release;
304:
305: case PRU_DISCONNECT:
306: if (np->nd_faddr == 0) {
307: error = ENOTCONN;
308: break;
309: }
310: ndrv_disconnect((struct ndrv_cb *)np);
311: soisdisconnected(so);
312: break;
313:
314: /*
315: * Mark the connection as being incapable of further input.
316: */
317: case PRU_SHUTDOWN:
318: socantsendmore(so);
319: break;
320:
321: /*
322: * Ship a packet out. The ndrv output will pass it
323: * to the appropriate driver. The really tricky part
324: * is the destination address...
325: */
326: case PRU_SEND:
327: error = ndrv_output(m, so);
328: m = NULL;
329: break;
330:
331: case PRU_ABORT:
332: ndrv_disconnect((struct ndrv_cb *)np);
333: sofree(so);
334: soisdisconnected(so);
335: break;
336:
337: case PRU_SENSE:
338: /*
339: * stat: don't bother with a blocksize.
340: */
341: return (0);
342:
343: /*
344: * Not supported.
345: */
346: case PRU_RCVOOB:
347: case PRU_RCVD:
348: return(EOPNOTSUPP);
349:
350: case PRU_LISTEN:
351: case PRU_ACCEPT:
352: case PRU_SENDOOB:
353: case PRU_SLOWTIMO:
354: case PRU_FASTTIMO:
355: case PRU_PROTORCV:
356: case PRU_PROTOSEND:
357: error = EOPNOTSUPP;
358: break;
359:
360: case PRU_SOCKADDR:
361: if (np->nd_laddr == 0) {
362: error = EINVAL;
363: break;
364: }
365: len = np->nd_laddr->snd_len;
366: bcopy((caddr_t)np->nd_laddr, mtod(nam, caddr_t),
367: (unsigned)len);
368: nam->m_len = len;
369: break;
370:
371: case PRU_PEERADDR:
372: if (np->nd_faddr == 0) {
373: error = ENOTCONN;
374: break;
375: }
376: len = np->nd_faddr->snd_len;
377: bcopy((caddr_t)np->nd_faddr, mtod(nam, caddr_t),
378: (unsigned)len);
379: nam->m_len = len;
380: break;
381:
382: default:
383: panic("ndrv_usrreq");
384: }
385: release:
386: if (m != NULL)
387: m_freem(m);
388: return (error);
389: }
390:
391: /* Control input */
392: void
393: ndrv_ctlinput()
394: {}
395:
396: /* Control output */
397: int
398: ndrv_ctloutput()
399: {
400: return(0);
401: }
402:
403: /* Drain the queues */
404: void
405: ndrv_drain()
406: {}
407:
408: /* Sysctl hook for NDRV */
409: int
410: ndrv_sysctl()
411: {
412: return(0);
413: }
414:
415: /*
416: * Allocate an ndrv control block and some buffer space for the socket
417: */
418: int
419: ndrv_attach(register struct socket *so,
420: register int proto)
421: { int error;
422: register struct ndrv_cb *np = sotondrvcb(so);
423:
424: #if 0
425: kprintf("NDRV attach: %x, %x, %x\n", so, proto, np);
426: #endif
427: MALLOC(np, struct ndrv_cb *, sizeof(*np), M_PCB, M_WAITOK);
428: #if 0
429: kprintf("NDRV attach: %x, %x, %x\n", so, proto, np);
430: #endif
431: if ((so->so_pcb = (caddr_t)np))
432: bzero(np, sizeof(*np));
433: else
434: return(ENOBUFS);
435: if ((error = soreserve(so, ndrv_sendspace, ndrv_recvspace)))
436: return(error);
437: np->nd_signature = NDRV_SIGNATURE;
438: np->nd_socket = so;
439: np->nd_proto.sp_family = so->so_proto->pr_domain->dom_family;
440: np->nd_proto.sp_protocol = proto;
441: insque((queue_t)np, (queue_t)&ndrvl);
442: return(0);
443: }
444:
445: int
446: ndrv_detach(register struct ndrv_cb *np)
447: { register struct socket *so = np->nd_socket;
448: extern struct ifnet_blue *blue_if;
449: extern void splitter_close(struct ndrv_cb *);
450:
451: #if 0
452: kprintf("NDRV detach: %x, %x\n", so, np);
453: #endif
454: if (blue_if)
455: splitter_close(np); /* 'np' is freed within */
456: so->so_pcb = 0;
457: sofree(so);
458: return(0);
459: }
460:
461: int
462: ndrv_disconnect(register struct ndrv_cb *np)
463: {
464: #if 0
465: kprintf("NDRV disconnect: %x\n", np);
466: #endif
467: if (np->nd_faddr)
468: { m_freem(dtom(np->nd_faddr));
469: np->nd_faddr = 0;
470: }
471: if (np->nd_socket->so_state & SS_NOFDREF)
472: ndrv_detach(np);
473: return(0);
474: }
475:
476: /*
477: * Here's where we latch onto the driver and make it ours.
478: */
479: int
480: ndrv_bind(register struct socket *so,
481: register struct mbuf *nam)
482: { register char *dname;
483: register struct sockaddr_ndrv *sa;
484: register struct ndrv_cb *np;
485: register struct ifnet *ifp;
486: extern int name_cmp(struct ifnet *, char *);
487:
488: if (ifnet == 0)
489: return(EADDRNOTAVAIL); /* Quick sanity check */
490: np = sotondrvcb(so);
491: /* I think we just latch onto a copy here; the caller frees */
492: nam = m_copym(nam, 0, M_COPYALL, M_WAITOK);
493: sa = mtod(nam, struct sockaddr_ndrv *);
494: np->nd_laddr = sa;
495: dname = sa->snd_name;
496: if (dname == NULL)
497: return(EINVAL);
498: #if 0
499: kprintf("NDRV bind: %x, %x, %s\n", so, np, dname);
500: #endif
501: /* Track down the driver and its ifnet structure.
502: * There's no internal call for this so we have to dup the code
503: * in if.c/ifconf()
504: */
505: for (ifp = ifnet; ifp; ifp = ifp->if_next)
506: if (name_cmp(ifp, dname) == 0)
507: break;
508: if (ifp == NULL)
509: return(EADDRNOTAVAIL);
510: /*
511: * Now, at this point, we should force open the driver and somehow
512: * register ourselves to receive packets (a la the bpf).
513: * However, we have this groaty hack in place that makes it
514: * not necessary for blue box purposes (the 'splitter' trick).
515: * If we want this to be a full-fledged AF, we have to force the
516: * open and implement a filter mechanism.
517: */
518: np->nd_if = ifp;
519: return(0);
520: }
521:
522: /*
523: * Try to compare a device name (q) with one of the funky ifnet
524: * device names (ifp).
525: */
526: int name_cmp(register struct ifnet *ifp, register char *q)
527: { register char *r;
528: register int len;
529: char buf[IFNAMSIZ];
530: static char *sprint_d();
531:
532: r = buf;
533: len = strlen(ifp->if_name);
534: strncpy(r, ifp->if_name, IFNAMSIZ);
535: r += len;
536: (void)sprint_d(ifp->if_unit, r, r-buf);
537: #if 0
538: kprintf("Comparing %s, %s\n", buf, q);
539: #endif
540: return(strncmp(buf, q, IFNAMSIZ));
541: }
542:
543: /* Hackery - return a string version of a decimal number */
544: static char *
545: sprint_d(n, buf, buflen)
546: u_int n;
547: char *buf;
548: int buflen;
549: {
550: register char *cp = buf + buflen - 1;
551:
552: *cp = 0;
553: do {
554: cp--;
555: *cp = "0123456789"[n % 10];
556: n /= 10;
557: } while (n != 0);
558: return (cp);
559: }
560:
561: /*
562: * When closing, dump any enqueued mbufs.
563: */
564: void
565: ndrv_flushq(register struct ifqueue *q)
566: { register struct mbuf *m;
567: register int s;
568: for (;;)
569: { s = splimp();
570: IF_DEQUEUE(q, m);
571: if (m == NULL)
572: break;
573: IF_DROP(q);
574: splx(s);
575: if (m)
576: m_freem(m);
577: }
578: splx(s);
579: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.