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