123202Smckusick /* 233371Ssklower * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. 333371Ssklower * All rights reserved. 423202Smckusick * 5*44498Sbostic * %sccs.include.redist.c% 633371Ssklower * 7*44498Sbostic * @(#)idp_usrreq.c 7.10 (Berkeley) 06/28/90 823202Smckusick */ 921479Ssklower 1021479Ssklower #include "param.h" 1121479Ssklower #include "user.h" 1235797Ssklower #include "malloc.h" 1321479Ssklower #include "mbuf.h" 1421479Ssklower #include "protosw.h" 1521479Ssklower #include "socket.h" 1621479Ssklower #include "socketvar.h" 1721479Ssklower #include "errno.h" 1821479Ssklower #include "stat.h" 1921479Ssklower 2021479Ssklower #include "../net/if.h" 2121479Ssklower #include "../net/route.h" 2221479Ssklower 2321479Ssklower #include "ns.h" 2421479Ssklower #include "ns_pcb.h" 2524611Ssklower #include "ns_if.h" 2621479Ssklower #include "idp.h" 2721479Ssklower #include "idp_var.h" 2821479Ssklower #include "ns_error.h" 2921479Ssklower 3021479Ssklower /* 3121479Ssklower * IDP protocol implementation. 3221479Ssklower */ 3321479Ssklower 3437473Ssklower struct sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS }; 3521479Ssklower 3623977Ssklower /* 3723977Ssklower * This may also be called for raw listeners. 3823977Ssklower */ 3935797Ssklower idp_input(m, nsp) 4021479Ssklower struct mbuf *m; 4121479Ssklower register struct nspcb *nsp; 4221479Ssklower { 4321479Ssklower register struct idp *idp = mtod(m, struct idp *); 4435797Ssklower struct ifnet *ifp = m->m_pkthdr.rcvif; 4521479Ssklower 4624611Ssklower if (nsp==0) 4724049Ssklower panic("No nspcb"); 4821479Ssklower /* 4921479Ssklower * Construct sockaddr format source address. 5021479Ssklower * Stuff source address and datagram in user buffer. 5121479Ssklower */ 5221479Ssklower idp_ns.sns_addr = idp->idp_sna; 5326055Ssklower if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) { 5437473Ssklower register struct ifaddr *ifa; 5524611Ssklower 5637473Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 5737473Ssklower if (ifa->ifa_addr->sa_family == AF_NS) { 5824611Ssklower idp_ns.sns_addr.x_net = 5937473Ssklower IA_SNS(ifa)->sns_addr.x_net; 6024611Ssklower break; 6124611Ssklower } 6224611Ssklower } 6324611Ssklower } 6421479Ssklower nsp->nsp_rpt = idp->idp_pt; 6521479Ssklower if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { 6621479Ssklower m->m_len -= sizeof (struct idp); 6735797Ssklower m->m_pkthdr.len -= sizeof (struct idp); 6835797Ssklower m->m_data += sizeof (struct idp); 6921479Ssklower } 7021479Ssklower if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns, 7121479Ssklower m, (struct mbuf *)0) == 0) 7221479Ssklower goto bad; 7321479Ssklower sorwakeup(nsp->nsp_socket); 7421479Ssklower return; 7521479Ssklower bad: 7621479Ssklower m_freem(m); 7721479Ssklower } 7821479Ssklower 7921479Ssklower idp_abort(nsp) 8021479Ssklower struct nspcb *nsp; 8121479Ssklower { 8221479Ssklower struct socket *so = nsp->nsp_socket; 8321479Ssklower 8421479Ssklower ns_pcbdisconnect(nsp); 8521479Ssklower soisdisconnected(so); 8621479Ssklower } 8723977Ssklower /* 8823977Ssklower * Drop connection, reporting 8923977Ssklower * the specified error. 9023977Ssklower */ 9123977Ssklower struct nspcb * 9223977Ssklower idp_drop(nsp, errno) 9323977Ssklower register struct nspcb *nsp; 9423977Ssklower int errno; 9523977Ssklower { 9623977Ssklower struct socket *so = nsp->nsp_socket; 9721479Ssklower 9823977Ssklower /* 9923977Ssklower * someday, in the xerox world 10023977Ssklower * we will generate error protocol packets 10123977Ssklower * announcing that the socket has gone away. 10223977Ssklower */ 10323977Ssklower /*if (TCPS_HAVERCVDSYN(tp->t_state)) { 10423977Ssklower tp->t_state = TCPS_CLOSED; 10523977Ssklower (void) tcp_output(tp); 10623977Ssklower }*/ 10723977Ssklower so->so_error = errno; 10823977Ssklower ns_pcbdisconnect(nsp); 10923977Ssklower soisdisconnected(so); 11023977Ssklower } 11123977Ssklower 11225042Ssklower int noIdpRoute; 11321479Ssklower idp_output(nsp, m0) 11421479Ssklower struct nspcb *nsp; 11521479Ssklower struct mbuf *m0; 11621479Ssklower { 11721479Ssklower register struct mbuf *m; 11821479Ssklower register struct idp *idp; 11921479Ssklower register struct socket *so; 12021479Ssklower register int len = 0; 12121479Ssklower register struct route *ro; 12221479Ssklower struct mbuf *mprev; 12321479Ssklower extern int idpcksum; 12421479Ssklower 12521479Ssklower /* 12621479Ssklower * Calculate data length. 12721479Ssklower */ 12821479Ssklower for (m = m0; m; m = m->m_next) { 12921479Ssklower mprev = m; 13021479Ssklower len += m->m_len; 13121479Ssklower } 13221479Ssklower /* 13321479Ssklower * Make sure packet is actually of even length. 13421479Ssklower */ 13521479Ssklower 13621479Ssklower if (len & 1) { 13721479Ssklower m = mprev; 13835797Ssklower if ((m->m_flags & M_EXT) == 0 && 13935797Ssklower (m->m_len + m->m_data < &m->m_dat[MLEN])) { 14021479Ssklower m->m_len++; 14121479Ssklower } else { 14221479Ssklower struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 14321479Ssklower 14421699Ssklower if (m1 == 0) { 14521699Ssklower m_freem(m0); 14621699Ssklower return (ENOBUFS); 14721699Ssklower } 14821479Ssklower m1->m_len = 1; 14921479Ssklower * mtod(m1, char *) = 0; 15021479Ssklower m->m_next = m1; 15121479Ssklower } 15235797Ssklower m0->m_pkthdr.len++; 15321479Ssklower } 15421479Ssklower 15521479Ssklower /* 15621479Ssklower * Fill in mbuf with extended IDP header 15721479Ssklower * and addresses and length put into network format. 15821479Ssklower */ 15935797Ssklower m = m0; 16021479Ssklower if (nsp->nsp_flags & NSP_RAWOUT) { 16121479Ssklower idp = mtod(m, struct idp *); 16221479Ssklower } else { 16335797Ssklower M_PREPEND(m, sizeof (struct idp), M_DONTWAIT); 16435797Ssklower if (m == 0) 16521479Ssklower return (ENOBUFS); 16621479Ssklower idp = mtod(m, struct idp *); 16721479Ssklower idp->idp_tc = 0; 16821479Ssklower idp->idp_pt = nsp->nsp_dpt; 16921479Ssklower idp->idp_sna = nsp->nsp_laddr; 17021479Ssklower idp->idp_dna = nsp->nsp_faddr; 17121479Ssklower len += sizeof (struct idp); 17221479Ssklower } 17321479Ssklower 17421479Ssklower idp->idp_len = htons((u_short)len); 17521479Ssklower 17621479Ssklower if (idpcksum) { 17721479Ssklower idp->idp_sum = 0; 17821479Ssklower len = ((len - 1) | 1) + 1; 17921479Ssklower idp->idp_sum = ns_cksum(m, len); 18021479Ssklower } else 18121479Ssklower idp->idp_sum = 0xffff; 18221479Ssklower 18321479Ssklower /* 18421479Ssklower * Output datagram. 18521479Ssklower */ 18621479Ssklower so = nsp->nsp_socket; 18721479Ssklower if (so->so_options & SO_DONTROUTE) 18821479Ssklower return (ns_output(m, (struct route *)0, 18921479Ssklower (so->so_options & SO_BROADCAST) | NS_ROUTETOIF)); 19021479Ssklower /* 19121479Ssklower * Use cached route for previous datagram if 19225042Ssklower * possible. If the previous net was the same 19325042Ssklower * and the interface was a broadcast medium, or 19425042Ssklower * if the previous destination was identical, 19525042Ssklower * then we are ok. 19621479Ssklower * 19721479Ssklower * NB: We don't handle broadcasts because that 19821479Ssklower * would require 3 subroutine calls. 19921479Ssklower */ 20021479Ssklower ro = &nsp->nsp_route; 20125042Ssklower #ifdef ancient_history 20225042Ssklower /* 20325042Ssklower * I think that this will all be handled in ns_pcbconnect! 20425042Ssklower */ 20525042Ssklower if (ro->ro_rt) { 20625042Ssklower if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) { 20725042Ssklower /* 20825042Ssklower * This assumes we have no GH type routes 20925042Ssklower */ 21025042Ssklower if (ro->ro_rt->rt_flags & RTF_HOST) { 21125042Ssklower if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna)) 21225042Ssklower goto re_route; 21325042Ssklower 21425042Ssklower } 21525042Ssklower if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) { 21625042Ssklower register struct ns_addr *dst = 21725042Ssklower &satons_addr(ro->ro_dst); 21825042Ssklower dst->x_host = idp->idp_dna.x_host; 21925042Ssklower } 22025042Ssklower /* 22125042Ssklower * Otherwise, we go through the same gateway 22225042Ssklower * and dst is already set up. 22325042Ssklower */ 22425042Ssklower } else { 22525042Ssklower re_route: 22625042Ssklower RTFREE(ro->ro_rt); 22725042Ssklower ro->ro_rt = (struct rtentry *)0; 22825042Ssklower } 22921479Ssklower } 23025042Ssklower nsp->nsp_lastdst = idp->idp_dna; 23125042Ssklower #endif ancient_history 23225042Ssklower if (noIdpRoute) ro = 0; 23321479Ssklower return (ns_output(m, ro, so->so_options & SO_BROADCAST)); 23421479Ssklower } 23524225Ssklower /* ARGSUSED */ 23621479Ssklower idp_ctloutput(req, so, level, name, value) 23721479Ssklower int req, level; 23821479Ssklower struct socket *so; 23921479Ssklower int name; 24021479Ssklower struct mbuf **value; 24121479Ssklower { 24221479Ssklower register struct mbuf *m; 24321479Ssklower struct nspcb *nsp = sotonspcb(so); 24421479Ssklower int mask, error = 0; 24523977Ssklower extern long ns_pexseq; 24621479Ssklower 24723500Ssklower if (nsp == NULL) 24823500Ssklower return (EINVAL); 24921479Ssklower 25021479Ssklower switch (req) { 25123500Ssklower 25221479Ssklower case PRCO_GETOPT: 25323500Ssklower if (value==NULL) 25423500Ssklower return (EINVAL); 25521479Ssklower m = m_get(M_DONTWAIT, MT_DATA); 25623500Ssklower if (m==NULL) 25723500Ssklower return (ENOBUFS); 25821479Ssklower switch (name) { 25923500Ssklower 26024049Ssklower case SO_ALL_PACKETS: 26124049Ssklower mask = NSP_ALL_PACKETS; 26224049Ssklower goto get_flags; 26324049Ssklower 26421479Ssklower case SO_HEADERS_ON_INPUT: 26521479Ssklower mask = NSP_RAWIN; 26621479Ssklower goto get_flags; 26723500Ssklower 26821479Ssklower case SO_HEADERS_ON_OUTPUT: 26921479Ssklower mask = NSP_RAWOUT; 27021479Ssklower get_flags: 27121479Ssklower m->m_len = sizeof(short); 27221479Ssklower *mtod(m, short *) = nsp->nsp_flags & mask; 27321479Ssklower break; 27423500Ssklower 27521479Ssklower case SO_DEFAULT_HEADERS: 27621479Ssklower m->m_len = sizeof(struct idp); 27721479Ssklower { 27821479Ssklower register struct idp *idp = mtod(m, struct idp *); 27921479Ssklower idp->idp_len = 0; 28021479Ssklower idp->idp_sum = 0; 28121479Ssklower idp->idp_tc = 0; 28221479Ssklower idp->idp_pt = nsp->nsp_dpt; 28321479Ssklower idp->idp_dna = nsp->nsp_faddr; 28421479Ssklower idp->idp_sna = nsp->nsp_laddr; 28521479Ssklower } 28623977Ssklower break; 28723977Ssklower 28823977Ssklower case SO_SEQNO: 28923977Ssklower m->m_len = sizeof(long); 29023977Ssklower *mtod(m, long *) = ns_pexseq++; 29125335Ssklower break; 29225335Ssklower 29325335Ssklower default: 29425335Ssklower error = EINVAL; 29521479Ssklower } 29621479Ssklower *value = m; 29721479Ssklower break; 29823500Ssklower 29921479Ssklower case PRCO_SETOPT: 30021479Ssklower switch (name) { 30124225Ssklower int *ok; 30221479Ssklower 30324049Ssklower case SO_ALL_PACKETS: 30424049Ssklower mask = NSP_ALL_PACKETS; 30524049Ssklower goto set_head; 30624049Ssklower 30721479Ssklower case SO_HEADERS_ON_INPUT: 30821479Ssklower mask = NSP_RAWIN; 30921479Ssklower goto set_head; 31023500Ssklower 31121479Ssklower case SO_HEADERS_ON_OUTPUT: 31221479Ssklower mask = NSP_RAWOUT; 31321479Ssklower set_head: 31421479Ssklower if (value && *value) { 31521479Ssklower ok = mtod(*value, int *); 31621479Ssklower if (*ok) 31721479Ssklower nsp->nsp_flags |= mask; 31821479Ssklower else 31921479Ssklower nsp->nsp_flags &= ~mask; 32021479Ssklower } else error = EINVAL; 32121479Ssklower break; 32223500Ssklower 32321479Ssklower case SO_DEFAULT_HEADERS: 32421479Ssklower { 32521479Ssklower register struct idp *idp 32621479Ssklower = mtod(*value, struct idp *); 32721479Ssklower nsp->nsp_dpt = idp->idp_pt; 32821479Ssklower } 32925335Ssklower break; 33021479Ssklower #ifdef NSIP 33123500Ssklower 33221479Ssklower case SO_NSIP_ROUTE: 33321479Ssklower error = nsip_route(*value); 33425335Ssklower break; 33521479Ssklower #endif NSIP 33625335Ssklower default: 33725335Ssklower error = EINVAL; 33821479Ssklower } 33921479Ssklower if (value && *value) 34021479Ssklower m_freem(*value); 34121479Ssklower break; 34221479Ssklower } 34323500Ssklower return (error); 34421479Ssklower } 34521479Ssklower 34621479Ssklower /*ARGSUSED*/ 34741921Ssklower idp_usrreq(so, req, m, nam, control) 34821479Ssklower struct socket *so; 34921479Ssklower int req; 35041921Ssklower struct mbuf *m, *nam, *control; 35121479Ssklower { 35221479Ssklower struct nspcb *nsp = sotonspcb(so); 35321479Ssklower int error = 0; 35421479Ssklower 35521479Ssklower if (req == PRU_CONTROL) 35621479Ssklower return (ns_control(so, (int)m, (caddr_t)nam, 35741921Ssklower (struct ifnet *)control)); 35841921Ssklower if (control && control->m_len) { 35921479Ssklower error = EINVAL; 36021479Ssklower goto release; 36121479Ssklower } 36221479Ssklower if (nsp == NULL && req != PRU_ATTACH) { 36321479Ssklower error = EINVAL; 36421479Ssklower goto release; 36521479Ssklower } 36621479Ssklower switch (req) { 36721479Ssklower 36821479Ssklower case PRU_ATTACH: 36921479Ssklower if (nsp != NULL) { 37021479Ssklower error = EINVAL; 37121479Ssklower break; 37221479Ssklower } 37321479Ssklower error = ns_pcballoc(so, &nspcb); 37421479Ssklower if (error) 37521479Ssklower break; 37634500Skarels error = soreserve(so, (u_long) 2048, (u_long) 2048); 37721479Ssklower if (error) 37821479Ssklower break; 37921479Ssklower break; 38021479Ssklower 38121479Ssklower case PRU_DETACH: 38221479Ssklower if (nsp == NULL) { 38321479Ssklower error = ENOTCONN; 38421479Ssklower break; 38521479Ssklower } 38621479Ssklower ns_pcbdetach(nsp); 38721479Ssklower break; 38821479Ssklower 38921479Ssklower case PRU_BIND: 39021479Ssklower error = ns_pcbbind(nsp, nam); 39121479Ssklower break; 39221479Ssklower 39321479Ssklower case PRU_LISTEN: 39421479Ssklower error = EOPNOTSUPP; 39521479Ssklower break; 39621479Ssklower 39721479Ssklower case PRU_CONNECT: 39821479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) { 39921479Ssklower error = EISCONN; 40021479Ssklower break; 40121479Ssklower } 40221479Ssklower error = ns_pcbconnect(nsp, nam); 40321479Ssklower if (error == 0) 40421479Ssklower soisconnected(so); 40521479Ssklower break; 40621479Ssklower 40721479Ssklower case PRU_CONNECT2: 40821479Ssklower error = EOPNOTSUPP; 40921479Ssklower break; 41021479Ssklower 41121479Ssklower case PRU_ACCEPT: 41221479Ssklower error = EOPNOTSUPP; 41321479Ssklower break; 41421479Ssklower 41521479Ssklower case PRU_DISCONNECT: 41621479Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 41721479Ssklower error = ENOTCONN; 41821479Ssklower break; 41921479Ssklower } 42021479Ssklower ns_pcbdisconnect(nsp); 42121479Ssklower soisdisconnected(so); 42221479Ssklower break; 42321479Ssklower 42421479Ssklower case PRU_SHUTDOWN: 42521479Ssklower socantsendmore(so); 42621479Ssklower break; 42721479Ssklower 42821479Ssklower case PRU_SEND: 42921479Ssklower { 43021479Ssklower struct ns_addr laddr; 43121479Ssklower int s; 43221479Ssklower 43321479Ssklower if (nam) { 43421479Ssklower laddr = nsp->nsp_laddr; 43521479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) { 43621479Ssklower error = EISCONN; 43721479Ssklower break; 43821479Ssklower } 43921479Ssklower /* 44021479Ssklower * Must block input while temporarily connected. 44121479Ssklower */ 44221479Ssklower s = splnet(); 44321479Ssklower error = ns_pcbconnect(nsp, nam); 44421479Ssklower if (error) { 44521479Ssklower splx(s); 44621479Ssklower break; 44721479Ssklower } 44821479Ssklower } else { 44921479Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 45021479Ssklower error = ENOTCONN; 45121479Ssklower break; 45221479Ssklower } 45321479Ssklower } 45421479Ssklower error = idp_output(nsp, m); 45521479Ssklower m = NULL; 45621479Ssklower if (nam) { 45721479Ssklower ns_pcbdisconnect(nsp); 45821479Ssklower splx(s); 45921479Ssklower nsp->nsp_laddr.x_host = laddr.x_host; 46021479Ssklower nsp->nsp_laddr.x_port = laddr.x_port; 46121479Ssklower } 46221479Ssklower } 46321479Ssklower break; 46421479Ssklower 46521479Ssklower case PRU_ABORT: 46621479Ssklower ns_pcbdetach(nsp); 46721479Ssklower sofree(so); 46821479Ssklower soisdisconnected(so); 46921479Ssklower break; 47021479Ssklower 47121479Ssklower case PRU_SOCKADDR: 47221479Ssklower ns_setsockaddr(nsp, nam); 47321479Ssklower break; 47421479Ssklower 47521479Ssklower case PRU_PEERADDR: 47621479Ssklower ns_setpeeraddr(nsp, nam); 47721479Ssklower break; 47821479Ssklower 47921479Ssklower case PRU_SENSE: 48021479Ssklower /* 48121479Ssklower * stat: don't bother with a blocksize. 48221479Ssklower */ 48321479Ssklower return (0); 48421479Ssklower 48521479Ssklower case PRU_SENDOOB: 48621479Ssklower case PRU_FASTTIMO: 48721479Ssklower case PRU_SLOWTIMO: 48821479Ssklower case PRU_PROTORCV: 48921479Ssklower case PRU_PROTOSEND: 49021479Ssklower error = EOPNOTSUPP; 49121479Ssklower break; 49221479Ssklower 49321479Ssklower case PRU_CONTROL: 49421479Ssklower case PRU_RCVD: 49521479Ssklower case PRU_RCVOOB: 49621479Ssklower return (EOPNOTSUPP); /* do not free mbuf's */ 49721479Ssklower 49821479Ssklower default: 49921479Ssklower panic("idp_usrreq"); 50021479Ssklower } 50121479Ssklower release: 50241921Ssklower if (control != NULL) 50341921Ssklower m_freem(control); 50421479Ssklower if (m != NULL) 50521479Ssklower m_freem(m); 50621479Ssklower return (error); 50721479Ssklower } 50821479Ssklower /*ARGSUSED*/ 50941921Ssklower idp_raw_usrreq(so, req, m, nam, control) 51021479Ssklower struct socket *so; 51121479Ssklower int req; 51241921Ssklower struct mbuf *m, *nam, *control; 51321479Ssklower { 51421479Ssklower int error = 0; 51521479Ssklower struct nspcb *nsp = sotonspcb(so); 51621479Ssklower extern struct nspcb nsrawpcb; 51721479Ssklower 51821479Ssklower switch (req) { 51921479Ssklower 52021479Ssklower case PRU_ATTACH: 52121479Ssklower 52237546Smckusick if (suser(u.u_cred, &u.u_acflag) || (nsp != NULL)) { 52321479Ssklower error = EINVAL; 52421479Ssklower break; 52521479Ssklower } 52621479Ssklower error = ns_pcballoc(so, &nsrawpcb); 52721479Ssklower if (error) 52821479Ssklower break; 52934500Skarels error = soreserve(so, (u_long) 2048, (u_long) 2048); 53021479Ssklower if (error) 53121479Ssklower break; 53221479Ssklower nsp = sotonspcb(so); 53321479Ssklower nsp->nsp_faddr.x_host = ns_broadhost; 53421479Ssklower nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT; 53521479Ssklower break; 53621479Ssklower default: 53741921Ssklower error = idp_usrreq(so, req, m, nam, control); 53821479Ssklower } 53923500Ssklower return (error); 54021479Ssklower } 54121479Ssklower 542