123202Smckusick /* 2*63231Sbostic * Copyright (c) 1984, 1985, 1986, 1987, 1993 3*63231Sbostic * The Regents of the University of California. All rights reserved. 423202Smckusick * 544498Sbostic * %sccs.include.redist.c% 633371Ssklower * 7*63231Sbostic * @(#)idp_usrreq.c 8.1 (Berkeley) 06/10/93 823202Smckusick */ 921479Ssklower 1056534Sbostic #include <sys/param.h> 1156534Sbostic #include <sys/malloc.h> 1256534Sbostic #include <sys/mbuf.h> 1356534Sbostic #include <sys/protosw.h> 1456534Sbostic #include <sys/socket.h> 1556534Sbostic #include <sys/socketvar.h> 1656534Sbostic #include <sys/errno.h> 1756534Sbostic #include <sys/stat.h> 1821479Ssklower 1956534Sbostic #include <net/if.h> 2056534Sbostic #include <net/route.h> 2121479Ssklower 2256534Sbostic #include <netns/ns.h> 2356534Sbostic #include <netns/ns_pcb.h> 2456534Sbostic #include <netns/ns_if.h> 2556534Sbostic #include <netns/idp.h> 2656534Sbostic #include <netns/idp_var.h> 2756534Sbostic #include <netns/ns_error.h> 2821479Ssklower 2921479Ssklower /* 3021479Ssklower * IDP protocol implementation. 3121479Ssklower */ 3221479Ssklower 3337473Ssklower struct sockaddr_ns idp_ns = { sizeof(idp_ns), AF_NS }; 3421479Ssklower 3523977Ssklower /* 3623977Ssklower * This may also be called for raw listeners. 3723977Ssklower */ 3835797Ssklower idp_input(m, nsp) 3921479Ssklower struct mbuf *m; 4021479Ssklower register struct nspcb *nsp; 4121479Ssklower { 4221479Ssklower register struct idp *idp = mtod(m, struct idp *); 4335797Ssklower struct ifnet *ifp = m->m_pkthdr.rcvif; 4421479Ssklower 4524611Ssklower if (nsp==0) 4624049Ssklower panic("No nspcb"); 4721479Ssklower /* 4821479Ssklower * Construct sockaddr format source address. 4921479Ssklower * Stuff source address and datagram in user buffer. 5021479Ssklower */ 5121479Ssklower idp_ns.sns_addr = idp->idp_sna; 5226055Ssklower if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) { 5337473Ssklower register struct ifaddr *ifa; 5424611Ssklower 5537473Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 5637473Ssklower if (ifa->ifa_addr->sa_family == AF_NS) { 5724611Ssklower idp_ns.sns_addr.x_net = 5837473Ssklower IA_SNS(ifa)->sns_addr.x_net; 5924611Ssklower break; 6024611Ssklower } 6124611Ssklower } 6224611Ssklower } 6321479Ssklower nsp->nsp_rpt = idp->idp_pt; 6421479Ssklower if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { 6521479Ssklower m->m_len -= sizeof (struct idp); 6635797Ssklower m->m_pkthdr.len -= sizeof (struct idp); 6735797Ssklower m->m_data += sizeof (struct idp); 6821479Ssklower } 6921479Ssklower if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns, 7021479Ssklower m, (struct mbuf *)0) == 0) 7121479Ssklower goto bad; 7221479Ssklower sorwakeup(nsp->nsp_socket); 7321479Ssklower return; 7421479Ssklower bad: 7521479Ssklower m_freem(m); 7621479Ssklower } 7721479Ssklower 7821479Ssklower idp_abort(nsp) 7921479Ssklower struct nspcb *nsp; 8021479Ssklower { 8121479Ssklower struct socket *so = nsp->nsp_socket; 8221479Ssklower 8321479Ssklower ns_pcbdisconnect(nsp); 8421479Ssklower soisdisconnected(so); 8521479Ssklower } 8623977Ssklower /* 8723977Ssklower * Drop connection, reporting 8823977Ssklower * the specified error. 8923977Ssklower */ 9023977Ssklower struct nspcb * 9123977Ssklower idp_drop(nsp, errno) 9223977Ssklower register struct nspcb *nsp; 9323977Ssklower int errno; 9423977Ssklower { 9523977Ssklower struct socket *so = nsp->nsp_socket; 9621479Ssklower 9723977Ssklower /* 9823977Ssklower * someday, in the xerox world 9923977Ssklower * we will generate error protocol packets 10023977Ssklower * announcing that the socket has gone away. 10123977Ssklower */ 10223977Ssklower /*if (TCPS_HAVERCVDSYN(tp->t_state)) { 10323977Ssklower tp->t_state = TCPS_CLOSED; 10423977Ssklower (void) tcp_output(tp); 10523977Ssklower }*/ 10623977Ssklower so->so_error = errno; 10723977Ssklower ns_pcbdisconnect(nsp); 10823977Ssklower soisdisconnected(so); 10923977Ssklower } 11023977Ssklower 11125042Ssklower int noIdpRoute; 11221479Ssklower idp_output(nsp, m0) 11321479Ssklower struct nspcb *nsp; 11421479Ssklower struct mbuf *m0; 11521479Ssklower { 11621479Ssklower register struct mbuf *m; 11721479Ssklower register struct idp *idp; 11821479Ssklower register struct socket *so; 11921479Ssklower register int len = 0; 12021479Ssklower register struct route *ro; 12121479Ssklower struct mbuf *mprev; 12221479Ssklower extern int idpcksum; 12321479Ssklower 12421479Ssklower /* 12521479Ssklower * Calculate data length. 12621479Ssklower */ 12721479Ssklower for (m = m0; m; m = m->m_next) { 12821479Ssklower mprev = m; 12921479Ssklower len += m->m_len; 13021479Ssklower } 13121479Ssklower /* 13221479Ssklower * Make sure packet is actually of even length. 13321479Ssklower */ 13421479Ssklower 13521479Ssklower if (len & 1) { 13621479Ssklower m = mprev; 13735797Ssklower if ((m->m_flags & M_EXT) == 0 && 13835797Ssklower (m->m_len + m->m_data < &m->m_dat[MLEN])) { 13921479Ssklower m->m_len++; 14021479Ssklower } else { 14121479Ssklower struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 14221479Ssklower 14321699Ssklower if (m1 == 0) { 14421699Ssklower m_freem(m0); 14521699Ssklower return (ENOBUFS); 14621699Ssklower } 14721479Ssklower m1->m_len = 1; 14821479Ssklower * mtod(m1, char *) = 0; 14921479Ssklower m->m_next = m1; 15021479Ssklower } 15135797Ssklower m0->m_pkthdr.len++; 15221479Ssklower } 15321479Ssklower 15421479Ssklower /* 15521479Ssklower * Fill in mbuf with extended IDP header 15621479Ssklower * and addresses and length put into network format. 15721479Ssklower */ 15835797Ssklower m = m0; 15921479Ssklower if (nsp->nsp_flags & NSP_RAWOUT) { 16021479Ssklower idp = mtod(m, struct idp *); 16121479Ssklower } else { 16235797Ssklower M_PREPEND(m, sizeof (struct idp), M_DONTWAIT); 16335797Ssklower if (m == 0) 16421479Ssklower return (ENOBUFS); 16521479Ssklower idp = mtod(m, struct idp *); 16621479Ssklower idp->idp_tc = 0; 16721479Ssklower idp->idp_pt = nsp->nsp_dpt; 16821479Ssklower idp->idp_sna = nsp->nsp_laddr; 16921479Ssklower idp->idp_dna = nsp->nsp_faddr; 17021479Ssklower len += sizeof (struct idp); 17121479Ssklower } 17221479Ssklower 17321479Ssklower idp->idp_len = htons((u_short)len); 17421479Ssklower 17521479Ssklower if (idpcksum) { 17621479Ssklower idp->idp_sum = 0; 17721479Ssklower len = ((len - 1) | 1) + 1; 17821479Ssklower idp->idp_sum = ns_cksum(m, len); 17921479Ssklower } else 18021479Ssklower idp->idp_sum = 0xffff; 18121479Ssklower 18221479Ssklower /* 18321479Ssklower * Output datagram. 18421479Ssklower */ 18521479Ssklower so = nsp->nsp_socket; 18621479Ssklower if (so->so_options & SO_DONTROUTE) 18721479Ssklower return (ns_output(m, (struct route *)0, 18821479Ssklower (so->so_options & SO_BROADCAST) | NS_ROUTETOIF)); 18921479Ssklower /* 19021479Ssklower * Use cached route for previous datagram if 19125042Ssklower * possible. If the previous net was the same 19225042Ssklower * and the interface was a broadcast medium, or 19325042Ssklower * if the previous destination was identical, 19425042Ssklower * then we are ok. 19521479Ssklower * 19621479Ssklower * NB: We don't handle broadcasts because that 19721479Ssklower * would require 3 subroutine calls. 19821479Ssklower */ 19921479Ssklower ro = &nsp->nsp_route; 20025042Ssklower #ifdef ancient_history 20125042Ssklower /* 20225042Ssklower * I think that this will all be handled in ns_pcbconnect! 20325042Ssklower */ 20425042Ssklower if (ro->ro_rt) { 20525042Ssklower if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) { 20625042Ssklower /* 20725042Ssklower * This assumes we have no GH type routes 20825042Ssklower */ 20925042Ssklower if (ro->ro_rt->rt_flags & RTF_HOST) { 21025042Ssklower if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna)) 21125042Ssklower goto re_route; 21225042Ssklower 21325042Ssklower } 21425042Ssklower if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) { 21525042Ssklower register struct ns_addr *dst = 21625042Ssklower &satons_addr(ro->ro_dst); 21725042Ssklower dst->x_host = idp->idp_dna.x_host; 21825042Ssklower } 21925042Ssklower /* 22025042Ssklower * Otherwise, we go through the same gateway 22125042Ssklower * and dst is already set up. 22225042Ssklower */ 22325042Ssklower } else { 22425042Ssklower re_route: 22525042Ssklower RTFREE(ro->ro_rt); 22625042Ssklower ro->ro_rt = (struct rtentry *)0; 22725042Ssklower } 22821479Ssklower } 22925042Ssklower nsp->nsp_lastdst = idp->idp_dna; 23060358Sbostic #endif /* ancient_history */ 23125042Ssklower if (noIdpRoute) ro = 0; 23221479Ssklower return (ns_output(m, ro, so->so_options & SO_BROADCAST)); 23321479Ssklower } 23424225Ssklower /* ARGSUSED */ 23521479Ssklower idp_ctloutput(req, so, level, name, value) 23621479Ssklower int req, level; 23721479Ssklower struct socket *so; 23821479Ssklower int name; 23921479Ssklower struct mbuf **value; 24021479Ssklower { 24121479Ssklower register struct mbuf *m; 24221479Ssklower struct nspcb *nsp = sotonspcb(so); 24321479Ssklower int mask, error = 0; 24423977Ssklower extern long ns_pexseq; 24521479Ssklower 24623500Ssklower if (nsp == NULL) 24723500Ssklower return (EINVAL); 24821479Ssklower 24921479Ssklower switch (req) { 25023500Ssklower 25121479Ssklower case PRCO_GETOPT: 25223500Ssklower if (value==NULL) 25323500Ssklower return (EINVAL); 25421479Ssklower m = m_get(M_DONTWAIT, MT_DATA); 25523500Ssklower if (m==NULL) 25623500Ssklower return (ENOBUFS); 25721479Ssklower switch (name) { 25823500Ssklower 25924049Ssklower case SO_ALL_PACKETS: 26024049Ssklower mask = NSP_ALL_PACKETS; 26124049Ssklower goto get_flags; 26224049Ssklower 26321479Ssklower case SO_HEADERS_ON_INPUT: 26421479Ssklower mask = NSP_RAWIN; 26521479Ssklower goto get_flags; 26623500Ssklower 26721479Ssklower case SO_HEADERS_ON_OUTPUT: 26821479Ssklower mask = NSP_RAWOUT; 26921479Ssklower get_flags: 27021479Ssklower m->m_len = sizeof(short); 27121479Ssklower *mtod(m, short *) = nsp->nsp_flags & mask; 27221479Ssklower break; 27323500Ssklower 27421479Ssklower case SO_DEFAULT_HEADERS: 27521479Ssklower m->m_len = sizeof(struct idp); 27621479Ssklower { 27721479Ssklower register struct idp *idp = mtod(m, struct idp *); 27821479Ssklower idp->idp_len = 0; 27921479Ssklower idp->idp_sum = 0; 28021479Ssklower idp->idp_tc = 0; 28121479Ssklower idp->idp_pt = nsp->nsp_dpt; 28221479Ssklower idp->idp_dna = nsp->nsp_faddr; 28321479Ssklower idp->idp_sna = nsp->nsp_laddr; 28421479Ssklower } 28523977Ssklower break; 28623977Ssklower 28723977Ssklower case SO_SEQNO: 28823977Ssklower m->m_len = sizeof(long); 28923977Ssklower *mtod(m, long *) = ns_pexseq++; 29025335Ssklower break; 29125335Ssklower 29225335Ssklower default: 29325335Ssklower error = EINVAL; 29421479Ssklower } 29521479Ssklower *value = m; 29621479Ssklower break; 29723500Ssklower 29821479Ssklower case PRCO_SETOPT: 29921479Ssklower switch (name) { 30024225Ssklower int *ok; 30121479Ssklower 30224049Ssklower case SO_ALL_PACKETS: 30324049Ssklower mask = NSP_ALL_PACKETS; 30424049Ssklower goto set_head; 30524049Ssklower 30621479Ssklower case SO_HEADERS_ON_INPUT: 30721479Ssklower mask = NSP_RAWIN; 30821479Ssklower goto set_head; 30923500Ssklower 31021479Ssklower case SO_HEADERS_ON_OUTPUT: 31121479Ssklower mask = NSP_RAWOUT; 31221479Ssklower set_head: 31321479Ssklower if (value && *value) { 31421479Ssklower ok = mtod(*value, int *); 31521479Ssklower if (*ok) 31621479Ssklower nsp->nsp_flags |= mask; 31721479Ssklower else 31821479Ssklower nsp->nsp_flags &= ~mask; 31921479Ssklower } else error = EINVAL; 32021479Ssklower break; 32123500Ssklower 32221479Ssklower case SO_DEFAULT_HEADERS: 32321479Ssklower { 32421479Ssklower register struct idp *idp 32521479Ssklower = mtod(*value, struct idp *); 32621479Ssklower nsp->nsp_dpt = idp->idp_pt; 32721479Ssklower } 32825335Ssklower break; 32921479Ssklower #ifdef NSIP 33023500Ssklower 33121479Ssklower case SO_NSIP_ROUTE: 33221479Ssklower error = nsip_route(*value); 33325335Ssklower break; 33460358Sbostic #endif /* NSIP */ 33525335Ssklower default: 33625335Ssklower error = EINVAL; 33721479Ssklower } 33821479Ssklower if (value && *value) 33921479Ssklower m_freem(*value); 34021479Ssklower break; 34121479Ssklower } 34223500Ssklower return (error); 34321479Ssklower } 34421479Ssklower 34521479Ssklower /*ARGSUSED*/ 34641921Ssklower idp_usrreq(so, req, m, nam, control) 34721479Ssklower struct socket *so; 34821479Ssklower int req; 34941921Ssklower struct mbuf *m, *nam, *control; 35021479Ssklower { 35121479Ssklower struct nspcb *nsp = sotonspcb(so); 35221479Ssklower int error = 0; 35321479Ssklower 35421479Ssklower if (req == PRU_CONTROL) 35521479Ssklower return (ns_control(so, (int)m, (caddr_t)nam, 35641921Ssklower (struct ifnet *)control)); 35741921Ssklower if (control && control->m_len) { 35821479Ssklower error = EINVAL; 35921479Ssklower goto release; 36021479Ssklower } 36121479Ssklower if (nsp == NULL && req != PRU_ATTACH) { 36221479Ssklower error = EINVAL; 36321479Ssklower goto release; 36421479Ssklower } 36521479Ssklower switch (req) { 36621479Ssklower 36721479Ssklower case PRU_ATTACH: 36821479Ssklower if (nsp != NULL) { 36921479Ssklower error = EINVAL; 37021479Ssklower break; 37121479Ssklower } 37221479Ssklower error = ns_pcballoc(so, &nspcb); 37321479Ssklower if (error) 37421479Ssklower break; 37534500Skarels error = soreserve(so, (u_long) 2048, (u_long) 2048); 37621479Ssklower if (error) 37721479Ssklower break; 37821479Ssklower break; 37921479Ssklower 38021479Ssklower case PRU_DETACH: 38121479Ssklower if (nsp == NULL) { 38221479Ssklower error = ENOTCONN; 38321479Ssklower break; 38421479Ssklower } 38521479Ssklower ns_pcbdetach(nsp); 38621479Ssklower break; 38721479Ssklower 38821479Ssklower case PRU_BIND: 38921479Ssklower error = ns_pcbbind(nsp, nam); 39021479Ssklower break; 39121479Ssklower 39221479Ssklower case PRU_LISTEN: 39321479Ssklower error = EOPNOTSUPP; 39421479Ssklower break; 39521479Ssklower 39621479Ssklower case PRU_CONNECT: 39721479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) { 39821479Ssklower error = EISCONN; 39921479Ssklower break; 40021479Ssklower } 40121479Ssklower error = ns_pcbconnect(nsp, nam); 40221479Ssklower if (error == 0) 40321479Ssklower soisconnected(so); 40421479Ssklower break; 40521479Ssklower 40621479Ssklower case PRU_CONNECT2: 40721479Ssklower error = EOPNOTSUPP; 40821479Ssklower break; 40921479Ssklower 41021479Ssklower case PRU_ACCEPT: 41121479Ssklower error = EOPNOTSUPP; 41221479Ssklower break; 41321479Ssklower 41421479Ssklower case PRU_DISCONNECT: 41521479Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 41621479Ssklower error = ENOTCONN; 41721479Ssklower break; 41821479Ssklower } 41921479Ssklower ns_pcbdisconnect(nsp); 42021479Ssklower soisdisconnected(so); 42121479Ssklower break; 42221479Ssklower 42321479Ssklower case PRU_SHUTDOWN: 42421479Ssklower socantsendmore(so); 42521479Ssklower break; 42621479Ssklower 42721479Ssklower case PRU_SEND: 42821479Ssklower { 42921479Ssklower struct ns_addr laddr; 43021479Ssklower int s; 43121479Ssklower 43221479Ssklower if (nam) { 43321479Ssklower laddr = nsp->nsp_laddr; 43421479Ssklower if (!ns_nullhost(nsp->nsp_faddr)) { 43521479Ssklower error = EISCONN; 43621479Ssklower break; 43721479Ssklower } 43821479Ssklower /* 43921479Ssklower * Must block input while temporarily connected. 44021479Ssklower */ 44121479Ssklower s = splnet(); 44221479Ssklower error = ns_pcbconnect(nsp, nam); 44321479Ssklower if (error) { 44421479Ssklower splx(s); 44521479Ssklower break; 44621479Ssklower } 44721479Ssklower } else { 44821479Ssklower if (ns_nullhost(nsp->nsp_faddr)) { 44921479Ssklower error = ENOTCONN; 45021479Ssklower break; 45121479Ssklower } 45221479Ssklower } 45321479Ssklower error = idp_output(nsp, m); 45421479Ssklower m = NULL; 45521479Ssklower if (nam) { 45621479Ssklower ns_pcbdisconnect(nsp); 45721479Ssklower splx(s); 45821479Ssklower nsp->nsp_laddr.x_host = laddr.x_host; 45921479Ssklower nsp->nsp_laddr.x_port = laddr.x_port; 46021479Ssklower } 46121479Ssklower } 46221479Ssklower break; 46321479Ssklower 46421479Ssklower case PRU_ABORT: 46521479Ssklower ns_pcbdetach(nsp); 46621479Ssklower sofree(so); 46721479Ssklower soisdisconnected(so); 46821479Ssklower break; 46921479Ssklower 47021479Ssklower case PRU_SOCKADDR: 47121479Ssklower ns_setsockaddr(nsp, nam); 47221479Ssklower break; 47321479Ssklower 47421479Ssklower case PRU_PEERADDR: 47521479Ssklower ns_setpeeraddr(nsp, nam); 47621479Ssklower break; 47721479Ssklower 47821479Ssklower case PRU_SENSE: 47921479Ssklower /* 48021479Ssklower * stat: don't bother with a blocksize. 48121479Ssklower */ 48221479Ssklower return (0); 48321479Ssklower 48421479Ssklower case PRU_SENDOOB: 48521479Ssklower case PRU_FASTTIMO: 48621479Ssklower case PRU_SLOWTIMO: 48721479Ssklower case PRU_PROTORCV: 48821479Ssklower case PRU_PROTOSEND: 48921479Ssklower error = EOPNOTSUPP; 49021479Ssklower break; 49121479Ssklower 49221479Ssklower case PRU_CONTROL: 49321479Ssklower case PRU_RCVD: 49421479Ssklower case PRU_RCVOOB: 49521479Ssklower return (EOPNOTSUPP); /* do not free mbuf's */ 49621479Ssklower 49721479Ssklower default: 49821479Ssklower panic("idp_usrreq"); 49921479Ssklower } 50021479Ssklower release: 50141921Ssklower if (control != NULL) 50241921Ssklower m_freem(control); 50321479Ssklower if (m != NULL) 50421479Ssklower m_freem(m); 50521479Ssklower return (error); 50621479Ssklower } 50721479Ssklower /*ARGSUSED*/ 50841921Ssklower idp_raw_usrreq(so, req, m, nam, control) 50921479Ssklower struct socket *so; 51021479Ssklower int req; 51141921Ssklower struct mbuf *m, *nam, *control; 51221479Ssklower { 51321479Ssklower int error = 0; 51421479Ssklower struct nspcb *nsp = sotonspcb(so); 51521479Ssklower extern struct nspcb nsrawpcb; 51621479Ssklower 51721479Ssklower switch (req) { 51821479Ssklower 51921479Ssklower case PRU_ATTACH: 52021479Ssklower 52150238Ssklower if (!(so->so_state & SS_PRIV) || (nsp != NULL)) { 52221479Ssklower error = EINVAL; 52321479Ssklower break; 52421479Ssklower } 52521479Ssklower error = ns_pcballoc(so, &nsrawpcb); 52621479Ssklower if (error) 52721479Ssklower break; 52834500Skarels error = soreserve(so, (u_long) 2048, (u_long) 2048); 52921479Ssklower if (error) 53021479Ssklower break; 53121479Ssklower nsp = sotonspcb(so); 53221479Ssklower nsp->nsp_faddr.x_host = ns_broadhost; 53321479Ssklower nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT; 53421479Ssklower break; 53521479Ssklower default: 53641921Ssklower error = idp_usrreq(so, req, m, nam, control); 53721479Ssklower } 53823500Ssklower return (error); 53921479Ssklower } 54021479Ssklower 541