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