|
|
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.