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