|
|
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: /* ! 23: * Copyright (c) 1984, 1985, 1986, 1987, 1993 ! 24: * The Regents of the University of California. All rights reserved. ! 25: * ! 26: * Redistribution and use in source and binary forms, with or without ! 27: * modification, are permitted provided that the following conditions ! 28: * are met: ! 29: * 1. Redistributions of source code must retain the above copyright ! 30: * notice, this list of conditions and the following disclaimer. ! 31: * 2. Redistributions in binary form must reproduce the above copyright ! 32: * notice, this list of conditions and the following disclaimer in the ! 33: * documentation and/or other materials provided with the distribution. ! 34: * 3. All advertising materials mentioning features or use of this software ! 35: * must display the following acknowledgement: ! 36: * This product includes software developed by the University of ! 37: * California, Berkeley and its contributors. ! 38: * 4. Neither the name of the University nor the names of its contributors ! 39: * may be used to endorse or promote products derived from this software ! 40: * without specific prior written permission. ! 41: * ! 42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 52: * SUCH DAMAGE. ! 53: * ! 54: * @(#)idp_usrreq.c 8.1 (Berkeley) 6/10/93 ! 55: */ ! 56: ! 57: #include <sys/param.h> ! 58: #include <sys/malloc.h> ! 59: #include <sys/mbuf.h> ! 60: #include <sys/protosw.h> ! 61: #include <sys/socket.h> ! 62: #include <sys/socketvar.h> ! 63: #include <sys/errno.h> ! 64: #include <sys/stat.h> ! 65: ! 66: #include <net/if.h> ! 67: #include <net/route.h> ! 68: ! 69: #include <netns/ns.h> ! 70: #include <netns/ns_pcb.h> ! 71: #include <netns/ns_if.h> ! 72: #include <netns/idp.h> ! 73: #include <netns/idp_var.h> ! 74: #include <netns/ns_error.h> ! 75: ! 76: /* ! 77: * IDP protocol implementation. ! 78: */ ! 79: ! 80: struct sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS }; ! 81: ! 82: /* ! 83: * This may also be called for raw listeners. ! 84: */ ! 85: idp_input(m, nsp) ! 86: struct mbuf *m; ! 87: register struct nspcb *nsp; ! 88: { ! 89: register struct idp *idp = mtod(m, struct idp *); ! 90: struct ifnet *ifp = m->m_pkthdr.rcvif; ! 91: ! 92: if (nsp==0) ! 93: panic("No nspcb"); ! 94: /* ! 95: * Construct sockaddr format source address. ! 96: * Stuff source address and datagram in user buffer. ! 97: */ ! 98: idp_ns.sns_addr = idp->idp_sna; ! 99: if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) { ! 100: register struct ifaddr *ifa; ! 101: ! 102: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 103: if (ifa->ifa_addr->sa_family == AF_NS) { ! 104: idp_ns.sns_addr.x_net = ! 105: IA_SNS(ifa)->sns_addr.x_net; ! 106: break; ! 107: } ! 108: } ! 109: } ! 110: nsp->nsp_rpt = idp->idp_pt; ! 111: if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { ! 112: m->m_len -= sizeof (struct idp); ! 113: m->m_pkthdr.len -= sizeof (struct idp); ! 114: m->m_data += sizeof (struct idp); ! 115: } ! 116: if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns, ! 117: m, (struct mbuf *)0) == 0) ! 118: goto bad; ! 119: sorwakeup(nsp->nsp_socket); ! 120: return; ! 121: bad: ! 122: m_freem(m); ! 123: } ! 124: ! 125: idp_abort(nsp) ! 126: struct nspcb *nsp; ! 127: { ! 128: struct socket *so = nsp->nsp_socket; ! 129: ! 130: ns_pcbdisconnect(nsp); ! 131: soisdisconnected(so); ! 132: } ! 133: /* ! 134: * Drop connection, reporting ! 135: * the specified error. ! 136: */ ! 137: struct nspcb * ! 138: idp_drop(nsp, errno) ! 139: register struct nspcb *nsp; ! 140: int errno; ! 141: { ! 142: struct socket *so = nsp->nsp_socket; ! 143: ! 144: /* ! 145: * someday, in the xerox world ! 146: * we will generate error protocol packets ! 147: * announcing that the socket has gone away. ! 148: */ ! 149: /*if (TCPS_HAVERCVDSYN(tp->t_state)) { ! 150: tp->t_state = TCPS_CLOSED; ! 151: (void) tcp_output(tp); ! 152: }*/ ! 153: so->so_error = errno; ! 154: ns_pcbdisconnect(nsp); ! 155: soisdisconnected(so); ! 156: } ! 157: ! 158: int noIdpRoute; ! 159: idp_output(nsp, m0) ! 160: struct nspcb *nsp; ! 161: struct mbuf *m0; ! 162: { ! 163: register struct mbuf *m; ! 164: register struct idp *idp; ! 165: register struct socket *so; ! 166: register int len = 0; ! 167: register struct route *ro; ! 168: struct mbuf *mprev; ! 169: extern int idpcksum; ! 170: ! 171: /* ! 172: * Calculate data length. ! 173: */ ! 174: for (m = m0; m; m = m->m_next) { ! 175: mprev = m; ! 176: len += m->m_len; ! 177: } ! 178: /* ! 179: * Make sure packet is actually of even length. ! 180: */ ! 181: ! 182: if (len & 1) { ! 183: m = mprev; ! 184: if ((m->m_flags & M_EXT) == 0 && ! 185: (m->m_len + m->m_data < &m->m_dat[MLEN])) { ! 186: m->m_len++; ! 187: } else { ! 188: struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); ! 189: ! 190: if (m1 == 0) { ! 191: m_freem(m0); ! 192: return (ENOBUFS); ! 193: } ! 194: m1->m_len = 1; ! 195: * mtod(m1, char *) = 0; ! 196: m->m_next = m1; ! 197: } ! 198: m0->m_pkthdr.len++; ! 199: } ! 200: ! 201: /* ! 202: * Fill in mbuf with extended IDP header ! 203: * and addresses and length put into network format. ! 204: */ ! 205: m = m0; ! 206: if (nsp->nsp_flags & NSP_RAWOUT) { ! 207: idp = mtod(m, struct idp *); ! 208: } else { ! 209: M_PREPEND(m, sizeof (struct idp), M_DONTWAIT); ! 210: if (m == 0) ! 211: return (ENOBUFS); ! 212: idp = mtod(m, struct idp *); ! 213: idp->idp_tc = 0; ! 214: idp->idp_pt = nsp->nsp_dpt; ! 215: idp->idp_sna = nsp->nsp_laddr; ! 216: idp->idp_dna = nsp->nsp_faddr; ! 217: len += sizeof (struct idp); ! 218: } ! 219: ! 220: idp->idp_len = htons((u_short)len); ! 221: ! 222: if (idpcksum) { ! 223: idp->idp_sum = 0; ! 224: len = ((len - 1) | 1) + 1; ! 225: idp->idp_sum = ns_cksum(m, len); ! 226: } else ! 227: idp->idp_sum = 0xffff; ! 228: ! 229: /* ! 230: * Output datagram. ! 231: */ ! 232: so = nsp->nsp_socket; ! 233: if (so->so_options & SO_DONTROUTE) ! 234: return (ns_output(m, (struct route *)0, ! 235: (so->so_options & SO_BROADCAST) | NS_ROUTETOIF)); ! 236: /* ! 237: * Use cached route for previous datagram if ! 238: * possible. If the previous net was the same ! 239: * and the interface was a broadcast medium, or ! 240: * if the previous destination was identical, ! 241: * then we are ok. ! 242: * ! 243: * NB: We don't handle broadcasts because that ! 244: * would require 3 subroutine calls. ! 245: */ ! 246: ro = &nsp->nsp_route; ! 247: #ifdef ancient_history ! 248: /* ! 249: * I think that this will all be handled in ns_pcbconnect! ! 250: */ ! 251: if (ro->ro_rt) { ! 252: if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) { ! 253: /* ! 254: * This assumes we have no GH type routes ! 255: */ ! 256: if (ro->ro_rt->rt_flags & RTF_HOST) { ! 257: if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna)) ! 258: goto re_route; ! 259: ! 260: } ! 261: if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) { ! 262: register struct ns_addr *dst = ! 263: &satons_addr(ro->ro_dst); ! 264: dst->x_host = idp->idp_dna.x_host; ! 265: } ! 266: /* ! 267: * Otherwise, we go through the same gateway ! 268: * and dst is already set up. ! 269: */ ! 270: } else { ! 271: re_route: ! 272: RTFREE(ro->ro_rt); ! 273: ro->ro_rt = (struct rtentry *)0; ! 274: } ! 275: } ! 276: nsp->nsp_lastdst = idp->idp_dna; ! 277: #endif /* ancient_history */ ! 278: if (noIdpRoute) ro = 0; ! 279: return (ns_output(m, ro, so->so_options & SO_BROADCAST)); ! 280: } ! 281: /* ARGSUSED */ ! 282: idp_ctloutput(req, so, level, name, value) ! 283: int req, level; ! 284: struct socket *so; ! 285: int name; ! 286: struct mbuf **value; ! 287: { ! 288: register struct mbuf *m; ! 289: struct nspcb *nsp = sotonspcb(so); ! 290: int mask, error = 0; ! 291: extern long ns_pexseq; ! 292: ! 293: if (nsp == NULL) ! 294: return (EINVAL); ! 295: ! 296: switch (req) { ! 297: ! 298: case PRCO_GETOPT: ! 299: if (value==NULL) ! 300: return (EINVAL); ! 301: m = m_get(M_DONTWAIT, MT_DATA); ! 302: if (m==NULL) ! 303: return (ENOBUFS); ! 304: switch (name) { ! 305: ! 306: case SO_ALL_PACKETS: ! 307: mask = NSP_ALL_PACKETS; ! 308: goto get_flags; ! 309: ! 310: case SO_HEADERS_ON_INPUT: ! 311: mask = NSP_RAWIN; ! 312: goto get_flags; ! 313: ! 314: case SO_HEADERS_ON_OUTPUT: ! 315: mask = NSP_RAWOUT; ! 316: get_flags: ! 317: m->m_len = sizeof(short); ! 318: *mtod(m, short *) = nsp->nsp_flags & mask; ! 319: break; ! 320: ! 321: case SO_DEFAULT_HEADERS: ! 322: m->m_len = sizeof(struct idp); ! 323: { ! 324: register struct idp *idp = mtod(m, struct idp *); ! 325: idp->idp_len = 0; ! 326: idp->idp_sum = 0; ! 327: idp->idp_tc = 0; ! 328: idp->idp_pt = nsp->nsp_dpt; ! 329: idp->idp_dna = nsp->nsp_faddr; ! 330: idp->idp_sna = nsp->nsp_laddr; ! 331: } ! 332: break; ! 333: ! 334: case SO_SEQNO: ! 335: m->m_len = sizeof(long); ! 336: *mtod(m, long *) = ns_pexseq++; ! 337: break; ! 338: ! 339: default: ! 340: error = EINVAL; ! 341: } ! 342: *value = m; ! 343: break; ! 344: ! 345: case PRCO_SETOPT: ! 346: switch (name) { ! 347: int *ok; ! 348: ! 349: case SO_ALL_PACKETS: ! 350: mask = NSP_ALL_PACKETS; ! 351: goto set_head; ! 352: ! 353: case SO_HEADERS_ON_INPUT: ! 354: mask = NSP_RAWIN; ! 355: goto set_head; ! 356: ! 357: case SO_HEADERS_ON_OUTPUT: ! 358: mask = NSP_RAWOUT; ! 359: set_head: ! 360: if (value && *value) { ! 361: ok = mtod(*value, int *); ! 362: if (*ok) ! 363: nsp->nsp_flags |= mask; ! 364: else ! 365: nsp->nsp_flags &= ~mask; ! 366: } else error = EINVAL; ! 367: break; ! 368: ! 369: case SO_DEFAULT_HEADERS: ! 370: { ! 371: register struct idp *idp ! 372: = mtod(*value, struct idp *); ! 373: nsp->nsp_dpt = idp->idp_pt; ! 374: } ! 375: break; ! 376: #ifdef NSIP ! 377: ! 378: case SO_NSIP_ROUTE: ! 379: error = nsip_route(*value); ! 380: break; ! 381: #endif /* NSIP */ ! 382: default: ! 383: error = EINVAL; ! 384: } ! 385: if (value && *value) ! 386: m_freem(*value); ! 387: break; ! 388: } ! 389: return (error); ! 390: } ! 391: ! 392: /*ARGSUSED*/ ! 393: idp_usrreq(so, req, m, nam, control) ! 394: struct socket *so; ! 395: int req; ! 396: struct mbuf *m, *nam, *control; ! 397: { ! 398: struct nspcb *nsp = sotonspcb(so); ! 399: int error = 0; ! 400: ! 401: if (req == PRU_CONTROL) ! 402: return (ns_control(so, (int)m, (caddr_t)nam, ! 403: (struct ifnet *)control)); ! 404: if (control && control->m_len) { ! 405: error = EINVAL; ! 406: goto release; ! 407: } ! 408: if (nsp == NULL && req != PRU_ATTACH) { ! 409: error = EINVAL; ! 410: goto release; ! 411: } ! 412: switch (req) { ! 413: ! 414: case PRU_ATTACH: ! 415: if (nsp != NULL) { ! 416: error = EINVAL; ! 417: break; ! 418: } ! 419: error = ns_pcballoc(so, &nspcb); ! 420: if (error) ! 421: break; ! 422: error = soreserve(so, (u_long) 2048, (u_long) 2048); ! 423: if (error) ! 424: break; ! 425: break; ! 426: ! 427: case PRU_DETACH: ! 428: if (nsp == NULL) { ! 429: error = ENOTCONN; ! 430: break; ! 431: } ! 432: ns_pcbdetach(nsp); ! 433: break; ! 434: ! 435: case PRU_BIND: ! 436: error = ns_pcbbind(nsp, nam); ! 437: break; ! 438: ! 439: case PRU_LISTEN: ! 440: error = EOPNOTSUPP; ! 441: break; ! 442: ! 443: case PRU_CONNECT: ! 444: if (!ns_nullhost(nsp->nsp_faddr)) { ! 445: error = EISCONN; ! 446: break; ! 447: } ! 448: error = ns_pcbconnect(nsp, nam); ! 449: if (error == 0) ! 450: soisconnected(so); ! 451: break; ! 452: ! 453: case PRU_CONNECT2: ! 454: error = EOPNOTSUPP; ! 455: break; ! 456: ! 457: case PRU_ACCEPT: ! 458: error = EOPNOTSUPP; ! 459: break; ! 460: ! 461: case PRU_DISCONNECT: ! 462: if (ns_nullhost(nsp->nsp_faddr)) { ! 463: error = ENOTCONN; ! 464: break; ! 465: } ! 466: ns_pcbdisconnect(nsp); ! 467: soisdisconnected(so); ! 468: break; ! 469: ! 470: case PRU_SHUTDOWN: ! 471: socantsendmore(so); ! 472: break; ! 473: ! 474: case PRU_SEND: ! 475: { ! 476: struct ns_addr laddr; ! 477: int s; ! 478: ! 479: if (nam) { ! 480: laddr = nsp->nsp_laddr; ! 481: if (!ns_nullhost(nsp->nsp_faddr)) { ! 482: error = EISCONN; ! 483: break; ! 484: } ! 485: /* ! 486: * Must block input while temporarily connected. ! 487: */ ! 488: s = splnet(); ! 489: error = ns_pcbconnect(nsp, nam); ! 490: if (error) { ! 491: splx(s); ! 492: break; ! 493: } ! 494: } else { ! 495: if (ns_nullhost(nsp->nsp_faddr)) { ! 496: error = ENOTCONN; ! 497: break; ! 498: } ! 499: } ! 500: error = idp_output(nsp, m); ! 501: m = NULL; ! 502: if (nam) { ! 503: ns_pcbdisconnect(nsp); ! 504: splx(s); ! 505: nsp->nsp_laddr.x_host = laddr.x_host; ! 506: nsp->nsp_laddr.x_port = laddr.x_port; ! 507: } ! 508: } ! 509: break; ! 510: ! 511: case PRU_ABORT: ! 512: ns_pcbdetach(nsp); ! 513: sofree(so); ! 514: soisdisconnected(so); ! 515: break; ! 516: ! 517: case PRU_SOCKADDR: ! 518: ns_setsockaddr(nsp, nam); ! 519: break; ! 520: ! 521: case PRU_PEERADDR: ! 522: ns_setpeeraddr(nsp, nam); ! 523: break; ! 524: ! 525: case PRU_SENSE: ! 526: /* ! 527: * stat: don't bother with a blocksize. ! 528: */ ! 529: return (0); ! 530: ! 531: case PRU_SENDOOB: ! 532: case PRU_FASTTIMO: ! 533: case PRU_SLOWTIMO: ! 534: case PRU_PROTORCV: ! 535: case PRU_PROTOSEND: ! 536: error = EOPNOTSUPP; ! 537: break; ! 538: ! 539: case PRU_CONTROL: ! 540: case PRU_RCVD: ! 541: case PRU_RCVOOB: ! 542: return (EOPNOTSUPP); /* do not free mbuf's */ ! 543: ! 544: default: ! 545: panic("idp_usrreq"); ! 546: } ! 547: release: ! 548: if (control != NULL) ! 549: m_freem(control); ! 550: if (m != NULL) ! 551: m_freem(m); ! 552: return (error); ! 553: } ! 554: /*ARGSUSED*/ ! 555: idp_raw_usrreq(so, req, m, nam, control) ! 556: struct socket *so; ! 557: int req; ! 558: struct mbuf *m, *nam, *control; ! 559: { ! 560: int error = 0; ! 561: struct nspcb *nsp = sotonspcb(so); ! 562: extern struct nspcb nsrawpcb; ! 563: ! 564: switch (req) { ! 565: ! 566: case PRU_ATTACH: ! 567: ! 568: if (!(so->so_state & SS_PRIV) || (nsp != NULL)) { ! 569: error = EINVAL; ! 570: break; ! 571: } ! 572: error = ns_pcballoc(so, &nsrawpcb); ! 573: if (error) ! 574: break; ! 575: error = soreserve(so, (u_long) 2048, (u_long) 2048); ! 576: if (error) ! 577: break; ! 578: nsp = sotonspcb(so); ! 579: nsp->nsp_faddr.x_host = ns_broadhost; ! 580: nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT; ! 581: break; ! 582: default: ! 583: error = idp_usrreq(so, req, m, nam, control); ! 584: } ! 585: return (error); ! 586: } ! 587:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.