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