ipx_usrreq.c revision 83366
111819Sjulian/* 211819Sjulian * Copyright (c) 1995, Mike Mitchell 311819Sjulian * Copyright (c) 1984, 1985, 1986, 1987, 1993 411819Sjulian * The Regents of the University of California. All rights reserved. 511819Sjulian * 611819Sjulian * Redistribution and use in source and binary forms, with or without 711819Sjulian * modification, are permitted provided that the following conditions 811819Sjulian * are met: 911819Sjulian * 1. Redistributions of source code must retain the above copyright 1011819Sjulian * notice, this list of conditions and the following disclaimer. 1111819Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1211819Sjulian * notice, this list of conditions and the following disclaimer in the 1311819Sjulian * documentation and/or other materials provided with the distribution. 1411819Sjulian * 3. All advertising materials mentioning features or use of this software 1511819Sjulian * must display the following acknowledgement: 1611819Sjulian * This product includes software developed by the University of 1711819Sjulian * California, Berkeley and its contributors. 1811819Sjulian * 4. Neither the name of the University nor the names of its contributors 1911819Sjulian * may be used to endorse or promote products derived from this software 2011819Sjulian * without specific prior written permission. 2111819Sjulian * 2211819Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2311819Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2411819Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2511819Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2611819Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2711819Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2811819Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2911819Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3011819Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3111819Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3211819Sjulian * SUCH DAMAGE. 3311819Sjulian * 3412057Sjulian * @(#)ipx_usrreq.c 3512057Sjulian * 3650477Speter * $FreeBSD: head/sys/netipx/ipx_usrreq.c 83366 2001-09-12 08:38:13Z julian $ 3711819Sjulian */ 3811819Sjulian 3931742Seivind#include "opt_ipx.h" 4031742Seivind 4111819Sjulian#include <sys/param.h> 4211819Sjulian#include <sys/systm.h> 4319947Sjhay#include <sys/kernel.h> 4411819Sjulian#include <sys/mbuf.h> 4511819Sjulian#include <sys/protosw.h> 4611819Sjulian#include <sys/socket.h> 4711819Sjulian#include <sys/socketvar.h> 4819947Sjhay#include <sys/sysctl.h> 4911819Sjulian 5011819Sjulian#include <net/if.h> 5111819Sjulian#include <net/route.h> 5211819Sjulian 5311947Sjulian#include <netinet/in.h> 5411947Sjulian 5511819Sjulian#include <netipx/ipx.h> 5611819Sjulian#include <netipx/ipx_pcb.h> 5711819Sjulian#include <netipx/ipx_if.h> 5811819Sjulian#include <netipx/ipx_var.h> 5911947Sjulian#include <netipx/ipx_ip.h> 6011819Sjulian 6111819Sjulian/* 6211819Sjulian * IPX protocol implementation. 6311819Sjulian */ 6411819Sjulian 6533181Seivindstatic int ipxsendspace = IPXSNDQ; 6619947SjhaySYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxsendspace, CTLFLAG_RW, 6719947Sjhay &ipxsendspace, 0, ""); 6833181Seivindstatic int ipxrecvspace = IPXRCVQ; 6919947SjhaySYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW, 7019947Sjhay &ipxrecvspace, 0, ""); 7119947Sjhay 7224659Sjhaystatic int ipx_usr_abort(struct socket *so); 7383366Sjulianstatic int ipx_attach(struct socket *so, int proto, struct thread *td); 7483366Sjulianstatic int ipx_bind(struct socket *so, struct sockaddr *nam, struct thread *td); 7528270Swollmanstatic int ipx_connect(struct socket *so, struct sockaddr *nam, 7683366Sjulian struct thread *td); 7724659Sjhaystatic int ipx_detach(struct socket *so); 7824659Sjhaystatic int ipx_disconnect(struct socket *so); 7924659Sjhaystatic int ipx_send(struct socket *so, int flags, struct mbuf *m, 8028270Swollman struct sockaddr *addr, struct mbuf *control, 8183366Sjulian struct thread *td); 8224659Sjhaystatic int ipx_shutdown(struct socket *so); 8383366Sjulianstatic int ripx_attach(struct socket *so, int proto, struct thread *td); 8425652Sjhaystatic int ipx_output(struct ipxpcb *ipxp, struct mbuf *m0); 8524659Sjhay 8625652Sjhaystruct pr_usrreqs ipx_usrreqs = { 8724659Sjhay ipx_usr_abort, pru_accept_notsupp, ipx_attach, ipx_bind, 8824659Sjhay ipx_connect, pru_connect2_notsupp, ipx_control, ipx_detach, 8924659Sjhay ipx_disconnect, pru_listen_notsupp, ipx_peeraddr, pru_rcvd_notsupp, 9024659Sjhay pru_rcvoob_notsupp, ipx_send, pru_sense_null, ipx_shutdown, 9129366Speter ipx_sockaddr, sosend, soreceive, sopoll 9224659Sjhay}; 9324659Sjhay 9425652Sjhaystruct pr_usrreqs ripx_usrreqs = { 9524659Sjhay ipx_usr_abort, pru_accept_notsupp, ripx_attach, ipx_bind, 9624659Sjhay ipx_connect, pru_connect2_notsupp, ipx_control, ipx_detach, 9724659Sjhay ipx_disconnect, pru_listen_notsupp, ipx_peeraddr, pru_rcvd_notsupp, 9824659Sjhay pru_rcvoob_notsupp, ipx_send, pru_sense_null, ipx_shutdown, 9929366Speter ipx_sockaddr, sosend, soreceive, sopoll 10024659Sjhay}; 10124659Sjhay 10211819Sjulian/* 10311819Sjulian * This may also be called for raw listeners. 10411819Sjulian */ 10511819Sjulianvoid 10611819Sjulianipx_input(m, ipxp) 10711819Sjulian struct mbuf *m; 10811819Sjulian register struct ipxpcb *ipxp; 10911819Sjulian{ 11011819Sjulian register struct ipx *ipx = mtod(m, struct ipx *); 11111819Sjulian struct ifnet *ifp = m->m_pkthdr.rcvif; 11215245Sjhay struct sockaddr_ipx ipx_ipx; 11311819Sjulian 11425652Sjhay if (ipxp == NULL) 11511819Sjulian panic("No ipxpcb"); 11611819Sjulian /* 11711819Sjulian * Construct sockaddr format source address. 11811819Sjulian * Stuff source address and datagram in user buffer. 11911819Sjulian */ 12015245Sjhay ipx_ipx.sipx_len = sizeof(ipx_ipx); 12115245Sjhay ipx_ipx.sipx_family = AF_IPX; 12211819Sjulian ipx_ipx.sipx_addr = ipx->ipx_sna; 12315245Sjhay ipx_ipx.sipx_zero[0] = '\0'; 12415245Sjhay ipx_ipx.sipx_zero[1] = '\0'; 12525652Sjhay if (ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet) && ifp != NULL) { 12611819Sjulian register struct ifaddr *ifa; 12711819Sjulian 12871999Sphk for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL; 12971999Sphk ifa = TAILQ_NEXT(ifa, ifa_link)) { 13011819Sjulian if (ifa->ifa_addr->sa_family == AF_IPX) { 13111819Sjulian ipx_ipx.sipx_addr.x_net = 13211819Sjulian IA_SIPX(ifa)->sipx_addr.x_net; 13311819Sjulian break; 13411819Sjulian } 13511819Sjulian } 13611819Sjulian } 13711819Sjulian ipxp->ipxp_rpt = ipx->ipx_pt; 13825652Sjhay if (!(ipxp->ipxp_flags & IPXP_RAWIN) ) { 13925652Sjhay m->m_len -= sizeof(struct ipx); 14025652Sjhay m->m_pkthdr.len -= sizeof(struct ipx); 14125652Sjhay m->m_data += sizeof(struct ipx); 14211819Sjulian } 14311819Sjulian if (sbappendaddr(&ipxp->ipxp_socket->so_rcv, (struct sockaddr *)&ipx_ipx, 14425652Sjhay m, (struct mbuf *)NULL) == 0) 14511819Sjulian goto bad; 14611819Sjulian sorwakeup(ipxp->ipxp_socket); 14711819Sjulian return; 14811819Sjulianbad: 14911819Sjulian m_freem(m); 15011819Sjulian} 15111819Sjulian 15211819Sjulianvoid 15311819Sjulianipx_abort(ipxp) 15411819Sjulian struct ipxpcb *ipxp; 15511819Sjulian{ 15611819Sjulian struct socket *so = ipxp->ipxp_socket; 15711819Sjulian 15811819Sjulian ipx_pcbdisconnect(ipxp); 15911819Sjulian soisdisconnected(so); 16011819Sjulian} 16125652Sjhay 16211819Sjulian/* 16311819Sjulian * Drop connection, reporting 16411819Sjulian * the specified error. 16511819Sjulian */ 16611819Sjulianvoid 16711819Sjulianipx_drop(ipxp, errno) 16811819Sjulian register struct ipxpcb *ipxp; 16911819Sjulian int errno; 17011819Sjulian{ 17111819Sjulian struct socket *so = ipxp->ipxp_socket; 17211819Sjulian 17311819Sjulian /* 17425652Sjhay * someday, in the IPX world 17511819Sjulian * we will generate error protocol packets 17611819Sjulian * announcing that the socket has gone away. 17725652Sjhay * 17825652Sjhay * XXX Probably never. IPX does not have error packets. 17911819Sjulian */ 18011819Sjulian /*if (TCPS_HAVERCVDSYN(tp->t_state)) { 18111819Sjulian tp->t_state = TCPS_CLOSED; 18225652Sjhay tcp_output(tp); 18311819Sjulian }*/ 18411819Sjulian so->so_error = errno; 18511819Sjulian ipx_pcbdisconnect(ipxp); 18611819Sjulian soisdisconnected(so); 18711819Sjulian} 18811819Sjulian 18925652Sjhaystatic int 19011819Sjulianipx_output(ipxp, m0) 19111819Sjulian struct ipxpcb *ipxp; 19211819Sjulian struct mbuf *m0; 19311819Sjulian{ 19411819Sjulian register struct ipx *ipx; 19511819Sjulian register struct socket *so; 19611819Sjulian register int len = 0; 19711819Sjulian register struct route *ro; 19854799Sgreen struct mbuf *m; 19911819Sjulian struct mbuf *mprev = NULL; 20011819Sjulian 20111819Sjulian /* 20211819Sjulian * Calculate data length. 20311819Sjulian */ 20425652Sjhay for (m = m0; m != NULL; m = m->m_next) { 20511819Sjulian mprev = m; 20611819Sjulian len += m->m_len; 20711819Sjulian } 20811819Sjulian /* 20911819Sjulian * Make sure packet is actually of even length. 21011819Sjulian */ 21111819Sjulian 21211819Sjulian if (len & 1) { 21311819Sjulian m = mprev; 21411819Sjulian if ((m->m_flags & M_EXT) == 0 && 21511819Sjulian (m->m_len + m->m_data < &m->m_dat[MLEN])) { 21650519Sjhay mtod(m, char*)[m->m_len++] = 0; 21711819Sjulian } else { 21811819Sjulian struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA); 21911819Sjulian 22025652Sjhay if (m1 == NULL) { 22111819Sjulian m_freem(m0); 22211819Sjulian return (ENOBUFS); 22311819Sjulian } 22411819Sjulian m1->m_len = 1; 22511819Sjulian * mtod(m1, char *) = 0; 22611819Sjulian m->m_next = m1; 22711819Sjulian } 22811819Sjulian m0->m_pkthdr.len++; 22911819Sjulian } 23011819Sjulian 23111819Sjulian /* 23211819Sjulian * Fill in mbuf with extended IPX header 23311819Sjulian * and addresses and length put into network format. 23411819Sjulian */ 23511819Sjulian m = m0; 23611819Sjulian if (ipxp->ipxp_flags & IPXP_RAWOUT) { 23711819Sjulian ipx = mtod(m, struct ipx *); 23811819Sjulian } else { 23925652Sjhay M_PREPEND(m, sizeof(struct ipx), M_DONTWAIT); 24025652Sjhay if (m == NULL) 24111819Sjulian return (ENOBUFS); 24211819Sjulian ipx = mtod(m, struct ipx *); 24311819Sjulian ipx->ipx_tc = 0; 24411819Sjulian ipx->ipx_pt = ipxp->ipxp_dpt; 24511819Sjulian ipx->ipx_sna = ipxp->ipxp_laddr; 24611819Sjulian ipx->ipx_dna = ipxp->ipxp_faddr; 24725652Sjhay len += sizeof(struct ipx); 24811819Sjulian } 24911819Sjulian 25011819Sjulian ipx->ipx_len = htons((u_short)len); 25111819Sjulian 25250519Sjhay if (ipxp->ipxp_flags & IPXP_CHECKSUM) { 25311819Sjulian ipx->ipx_sum = ipx_cksum(m, len); 25411819Sjulian } else 25511819Sjulian ipx->ipx_sum = 0xffff; 25611819Sjulian 25711819Sjulian /* 25811819Sjulian * Output datagram. 25911819Sjulian */ 26011819Sjulian so = ipxp->ipxp_socket; 26111819Sjulian if (so->so_options & SO_DONTROUTE) 26225652Sjhay return (ipx_outputfl(m, (struct route *)NULL, 26311819Sjulian (so->so_options & SO_BROADCAST) | IPX_ROUTETOIF)); 26411819Sjulian /* 26511819Sjulian * Use cached route for previous datagram if 26611819Sjulian * possible. If the previous net was the same 26711819Sjulian * and the interface was a broadcast medium, or 26811819Sjulian * if the previous destination was identical, 26911819Sjulian * then we are ok. 27011819Sjulian * 27111819Sjulian * NB: We don't handle broadcasts because that 27211819Sjulian * would require 3 subroutine calls. 27311819Sjulian */ 27411819Sjulian ro = &ipxp->ipxp_route; 27511819Sjulian#ifdef ancient_history 27611819Sjulian /* 27711819Sjulian * I think that this will all be handled in ipx_pcbconnect! 27811819Sjulian */ 27925652Sjhay if (ro->ro_rt != NULL) { 28011819Sjulian if(ipx_neteq(ipxp->ipxp_lastdst, ipx->ipx_dna)) { 28111819Sjulian /* 28211819Sjulian * This assumes we have no GH type routes 28311819Sjulian */ 28411819Sjulian if (ro->ro_rt->rt_flags & RTF_HOST) { 28511819Sjulian if (!ipx_hosteq(ipxp->ipxp_lastdst, ipx->ipx_dna)) 28611819Sjulian goto re_route; 28711819Sjulian 28811819Sjulian } 28911819Sjulian if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) { 29011819Sjulian register struct ipx_addr *dst = 29111819Sjulian &satoipx_addr(ro->ro_dst); 29211819Sjulian dst->x_host = ipx->ipx_dna.x_host; 29311819Sjulian } 29411819Sjulian /* 29511819Sjulian * Otherwise, we go through the same gateway 29611819Sjulian * and dst is already set up. 29711819Sjulian */ 29811819Sjulian } else { 29911819Sjulian re_route: 30011819Sjulian RTFREE(ro->ro_rt); 30125652Sjhay ro->ro_rt = NULL; 30211819Sjulian } 30311819Sjulian } 30411819Sjulian ipxp->ipxp_lastdst = ipx->ipx_dna; 30511819Sjulian#endif /* ancient_history */ 30611819Sjulian return (ipx_outputfl(m, ro, so->so_options & SO_BROADCAST)); 30711819Sjulian} 30819947Sjhay 30911819Sjulianint 31038482Swollmanipx_ctloutput(so, sopt) 31111819Sjulian struct socket *so; 31238482Swollman struct sockopt *sopt; 31311819Sjulian{ 31411819Sjulian struct ipxpcb *ipxp = sotoipxpcb(so); 31538482Swollman int mask, error, optval; 31638482Swollman short soptval; 31738482Swollman struct ipx ioptval; 31811819Sjulian 31938482Swollman error = 0; 32011819Sjulian if (ipxp == NULL) 32111819Sjulian return (EINVAL); 32211819Sjulian 32338482Swollman switch (sopt->sopt_dir) { 32438482Swollman case SOPT_GET: 32538482Swollman switch (sopt->sopt_name) { 32611819Sjulian case SO_ALL_PACKETS: 32711819Sjulian mask = IPXP_ALL_PACKETS; 32811819Sjulian goto get_flags; 32911819Sjulian 33011819Sjulian case SO_HEADERS_ON_INPUT: 33111819Sjulian mask = IPXP_RAWIN; 33211819Sjulian goto get_flags; 33350519Sjhay 33450519Sjhay case SO_IPX_CHECKSUM: 33550519Sjhay mask = IPXP_CHECKSUM; 33650519Sjhay goto get_flags; 33711819Sjulian 33811819Sjulian case SO_HEADERS_ON_OUTPUT: 33911819Sjulian mask = IPXP_RAWOUT; 34011819Sjulian get_flags: 34138482Swollman soptval = ipxp->ipxp_flags & mask; 34238482Swollman error = sooptcopyout(sopt, &soptval, sizeof soptval); 34311819Sjulian break; 34411819Sjulian 34511819Sjulian case SO_DEFAULT_HEADERS: 34638482Swollman ioptval.ipx_len = 0; 34738482Swollman ioptval.ipx_sum = 0; 34838482Swollman ioptval.ipx_tc = 0; 34938482Swollman ioptval.ipx_pt = ipxp->ipxp_dpt; 35038482Swollman ioptval.ipx_dna = ipxp->ipxp_faddr; 35138482Swollman ioptval.ipx_sna = ipxp->ipxp_laddr; 35238482Swollman error = sooptcopyout(sopt, &soptval, sizeof soptval); 35311819Sjulian break; 35411819Sjulian 35511819Sjulian case SO_SEQNO: 35638482Swollman error = sooptcopyout(sopt, &ipx_pexseq, 35738482Swollman sizeof ipx_pexseq); 35838482Swollman ipx_pexseq++; 35911819Sjulian break; 36011819Sjulian 36111819Sjulian default: 36211819Sjulian error = EINVAL; 36311819Sjulian } 36411819Sjulian break; 36511819Sjulian 36638482Swollman case SOPT_SET: 36738482Swollman switch (sopt->sopt_name) { 36811819Sjulian case SO_ALL_PACKETS: 36911819Sjulian mask = IPXP_ALL_PACKETS; 37011819Sjulian goto set_head; 37111819Sjulian 37211819Sjulian case SO_HEADERS_ON_INPUT: 37311819Sjulian mask = IPXP_RAWIN; 37411819Sjulian goto set_head; 37511819Sjulian 37650519Sjhay case SO_IPX_CHECKSUM: 37750519Sjhay mask = IPXP_CHECKSUM; 37850519Sjhay 37911819Sjulian case SO_HEADERS_ON_OUTPUT: 38011819Sjulian mask = IPXP_RAWOUT; 38111819Sjulian set_head: 38238482Swollman error = sooptcopyin(sopt, &optval, sizeof optval, 38338482Swollman sizeof optval); 38438482Swollman if (error) 38538482Swollman break; 38638482Swollman if (optval) 38738482Swollman ipxp->ipxp_flags |= mask; 38838482Swollman else 38938482Swollman ipxp->ipxp_flags &= ~mask; 39011819Sjulian break; 39111819Sjulian 39211819Sjulian case SO_DEFAULT_HEADERS: 39338482Swollman error = sooptcopyin(sopt, &ioptval, sizeof ioptval, 39438482Swollman sizeof ioptval); 39538482Swollman if (error) 39638482Swollman break; 39738482Swollman ipxp->ipxp_dpt = ioptval.ipx_pt; 39811819Sjulian break; 39911819Sjulian#ifdef IPXIP 40011819Sjulian case SO_IPXIP_ROUTE: 40138482Swollman error = ipxip_route(so, sopt); 40211819Sjulian break; 40311819Sjulian#endif /* IPXIP */ 40431742Seivind#ifdef IPTUNNEL 40531742Seivind#if 0 40631742Seivind case SO_IPXTUNNEL_ROUTE: 40738482Swollman error = ipxtun_route(so, sopt); 40811819Sjulian break; 40911819Sjulian#endif 41031742Seivind#endif 41111819Sjulian default: 41211819Sjulian error = EINVAL; 41311819Sjulian } 41411819Sjulian break; 41511819Sjulian } 41611819Sjulian return (error); 41711819Sjulian} 41811819Sjulian 41924659Sjhaystatic int 42024659Sjhayipx_usr_abort(so) 42111819Sjulian struct socket *so; 42211819Sjulian{ 42324659Sjhay int s; 42411819Sjulian struct ipxpcb *ipxp = sotoipxpcb(so); 42511819Sjulian 42624659Sjhay s = splnet(); 42724659Sjhay ipx_pcbdetach(ipxp); 42824659Sjhay splx(s); 42924659Sjhay sofree(so); 43024659Sjhay soisdisconnected(so); 43124659Sjhay return (0); 43224659Sjhay} 43311819Sjulian 43424659Sjhaystatic int 43583366Sjulianipx_attach(so, proto, td) 43624659Sjhay struct socket *so; 43724659Sjhay int proto; 43883366Sjulian struct thread *td; 43924659Sjhay{ 44024659Sjhay int error; 44124659Sjhay int s; 44224659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 44324659Sjhay 44424659Sjhay if (ipxp != NULL) 44524659Sjhay return (EINVAL); 44624659Sjhay s = splnet(); 44783366Sjulian error = ipx_pcballoc(so, &ipxpcb, td); 44824659Sjhay splx(s); 44924659Sjhay if (error == 0) 45019947Sjhay error = soreserve(so, ipxsendspace, ipxrecvspace); 45124659Sjhay return (error); 45224659Sjhay} 45311819Sjulian 45424659Sjhaystatic int 45583366Sjulianipx_bind(so, nam, td) 45624659Sjhay struct socket *so; 45728270Swollman struct sockaddr *nam; 45883366Sjulian struct thread *td; 45924659Sjhay{ 46024659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 46111819Sjulian 46283366Sjulian return (ipx_pcbbind(ipxp, nam, td)); 46324659Sjhay} 46411819Sjulian 46524659Sjhaystatic int 46683366Sjulianipx_connect(so, nam, td) 46724659Sjhay struct socket *so; 46828270Swollman struct sockaddr *nam; 46983366Sjulian struct thread *td; 47024659Sjhay{ 47124659Sjhay int error; 47224659Sjhay int s; 47324659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 47411819Sjulian 47524659Sjhay if (!ipx_nullhost(ipxp->ipxp_faddr)) 47624659Sjhay return (EISCONN); 47724659Sjhay s = splnet(); 47883366Sjulian error = ipx_pcbconnect(ipxp, nam, td); 47924659Sjhay splx(s); 48024659Sjhay if (error == 0) 48124659Sjhay soisconnected(so); 48224659Sjhay return (error); 48324659Sjhay} 48411819Sjulian 48524659Sjhaystatic int 48624659Sjhayipx_detach(so) 48724659Sjhay struct socket *so; 48824659Sjhay{ 48924659Sjhay int s; 49024659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 49111819Sjulian 49224659Sjhay if (ipxp == NULL) 49324659Sjhay return (ENOTCONN); 49424659Sjhay s = splnet(); 49524659Sjhay ipx_pcbdetach(ipxp); 49624659Sjhay splx(s); 49724659Sjhay return (0); 49824659Sjhay} 49911819Sjulian 50024659Sjhaystatic int 50124659Sjhayipx_disconnect(so) 50224659Sjhay struct socket *so; 50324659Sjhay{ 50424659Sjhay int s; 50524659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 50611819Sjulian 50724659Sjhay if (ipx_nullhost(ipxp->ipxp_faddr)) 50824659Sjhay return (ENOTCONN); 50924659Sjhay s = splnet(); 51024659Sjhay ipx_pcbdisconnect(ipxp); 51124659Sjhay splx(s); 51224659Sjhay soisdisconnected(so); 51324659Sjhay return (0); 51424659Sjhay} 51511819Sjulian 51624659Sjhayint 51724659Sjhayipx_peeraddr(so, nam) 51824659Sjhay struct socket *so; 51928270Swollman struct sockaddr **nam; 52024659Sjhay{ 52124659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 52211819Sjulian 52328270Swollman ipx_setpeeraddr(ipxp, nam); /* XXX what if alloc fails? */ 52424659Sjhay return (0); 52524659Sjhay} 52624659Sjhay 52724659Sjhaystatic int 52883366Sjulianipx_send(so, flags, m, nam, control, td) 52924659Sjhay struct socket *so; 53024659Sjhay int flags; 53124659Sjhay struct mbuf *m; 53228270Swollman struct sockaddr *nam; 53324659Sjhay struct mbuf *control; 53483366Sjulian struct thread *td; 53524659Sjhay{ 53624659Sjhay int error; 53724659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 53824659Sjhay struct ipx_addr laddr; 53924659Sjhay int s = 0; 54024659Sjhay 54125652Sjhay if (nam != NULL) { 54224659Sjhay laddr = ipxp->ipxp_laddr; 54324659Sjhay if (!ipx_nullhost(ipxp->ipxp_faddr)) { 54424659Sjhay error = EISCONN; 54524659Sjhay goto send_release; 54611819Sjulian } 54724659Sjhay /* 54824659Sjhay * Must block input while temporarily connected. 54924659Sjhay */ 55024659Sjhay s = splnet(); 55183366Sjulian error = ipx_pcbconnect(ipxp, nam, td); 55224659Sjhay if (error) { 55311819Sjulian splx(s); 55424659Sjhay goto send_release; 55511819Sjulian } 55624659Sjhay } else { 55724659Sjhay if (ipx_nullhost(ipxp->ipxp_faddr)) { 55824659Sjhay error = ENOTCONN; 55924659Sjhay goto send_release; 56024659Sjhay } 56111819Sjulian } 56224659Sjhay error = ipx_output(ipxp, m); 56324659Sjhay m = NULL; 56425652Sjhay if (nam != NULL) { 56524659Sjhay ipx_pcbdisconnect(ipxp); 56624659Sjhay splx(s); 56743712Sjhay ipxp->ipxp_laddr = laddr; 56824659Sjhay } 56911819Sjulian 57024659Sjhaysend_release: 57111819Sjulian if (m != NULL) 57211819Sjulian m_freem(m); 57311819Sjulian return (error); 57411819Sjulian} 57519947Sjhay 57624659Sjhaystatic int 57724659Sjhayipx_shutdown(so) 57824659Sjhay struct socket *so; 57924659Sjhay{ 58024659Sjhay socantsendmore(so); 58124659Sjhay return (0); 58224659Sjhay} 58324659Sjhay 58411819Sjulianint 58524659Sjhayipx_sockaddr(so, nam) 58611819Sjulian struct socket *so; 58728270Swollman struct sockaddr **nam; 58811819Sjulian{ 58911819Sjulian struct ipxpcb *ipxp = sotoipxpcb(so); 59011819Sjulian 59128270Swollman ipx_setsockaddr(ipxp, nam); /* XXX what if alloc fails? */ 59224659Sjhay return (0); 59324659Sjhay} 59411819Sjulian 59524659Sjhaystatic int 59683366Sjulianripx_attach(so, proto, td) 59724659Sjhay struct socket *so; 59824659Sjhay int proto; 59983366Sjulian struct thread *td; 60024659Sjhay{ 60124659Sjhay int error = 0; 60224659Sjhay int s; 60324659Sjhay struct ipxpcb *ipxp = sotoipxpcb(so); 60411819Sjulian 60583366Sjulian if (td != NULL && (error = suser_td(td)) != 0) 60625345Sjhay return (error); 60724659Sjhay s = splnet(); 60883366Sjulian error = ipx_pcballoc(so, &ipxrawpcb, td); 60924659Sjhay splx(s); 61024659Sjhay if (error) 61124659Sjhay return (error); 61224659Sjhay error = soreserve(so, ipxsendspace, ipxrecvspace); 61324659Sjhay if (error) 61424659Sjhay return (error); 61524659Sjhay ipxp = sotoipxpcb(so); 61624659Sjhay ipxp->ipxp_faddr.x_host = ipx_broadhost; 61724659Sjhay ipxp->ipxp_flags = IPXP_RAWIN | IPXP_RAWOUT; 61811819Sjulian return (error); 61911819Sjulian} 620