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