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