1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-06 13:09:50 +00:00

Change IPX to use the pr_usrreqs structure.

This commit is contained in:
John Hay 1997-04-05 20:05:11 +00:00
parent 5a55bb419e
commit 583f1729d1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=24659
5 changed files with 581 additions and 430 deletions

View File

@ -33,7 +33,7 @@
* *
* @(#)ipx.h * @(#)ipx.h
* *
* $Id$ * $Id: ipx.h,v 1.9 1997/02/22 09:41:52 peter Exp $
*/ */
#ifndef _NETIPX_IPX_H_ #ifndef _NETIPX_IPX_H_
@ -158,6 +158,8 @@ struct ipx {
#ifdef KERNEL #ifdef KERNEL
extern struct pr_usrreqs ipx_usrreqs;
extern struct pr_usrreqs ripx_usrreqs;
extern int ipxcksum; extern int ipxcksum;
extern struct domain ipxdomain; extern struct domain ipxdomain;
extern struct sockaddr_ipx ipx_netmask; extern struct sockaddr_ipx ipx_netmask;
@ -191,13 +193,12 @@ void ipx_input __P((struct mbuf *m, struct ipxpcb *ipxp));
void ipxintr __P((void)); void ipxintr __P((void));
int ipx_output __P((struct ipxpcb *ipxp, struct mbuf *m0)); int ipx_output __P((struct ipxpcb *ipxp, struct mbuf *m0));
int ipx_outputfl __P((struct mbuf *m0, struct route *ro, int flags)); int ipx_outputfl __P((struct mbuf *m0, struct route *ro, int flags));
int ipx_raw_usrreq __P((struct socket *so, int req, struct mbuf *m,
struct mbuf *nam, struct mbuf *control));
void ipx_undo_route __P((struct route *ro)); void ipx_undo_route __P((struct route *ro));
int ipx_usrreq __P((struct socket *so, int req, struct mbuf *m,
struct mbuf *nam, struct mbuf *control));
void ipx_watch_output __P((struct mbuf *m, struct ifnet *ifp)); void ipx_watch_output __P((struct mbuf *m, struct ifnet *ifp));
int ipx_peeraddr __P((struct socket *so, struct mbuf *nam));
int ipx_sockaddr __P((struct socket *so, struct mbuf *nam));
#else #else
#include <sys/cdefs.h> #include <sys/cdefs.h>

View File

@ -33,7 +33,7 @@
* *
* @(#)ipx_proto.c * @(#)ipx_proto.c
* *
* $Id$ * $Id: ipx_proto.c,v 1.7 1997/02/22 09:41:56 peter Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -57,39 +57,45 @@ struct protosw ipxsw[] = {
{ 0, &ipxdomain, 0, 0, { 0, &ipxdomain, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
ipx_init, 0, 0, 0 ipx_init, 0, 0, 0,
}, },
{ SOCK_DGRAM, &ipxdomain, 0, PR_ATOMIC|PR_ADDR, { SOCK_DGRAM, &ipxdomain, 0, PR_ATOMIC|PR_ADDR,
0, 0, ipx_ctlinput, ipx_ctloutput, 0, 0, ipx_ctlinput, ipx_ctloutput,
ipx_usrreq, 0,
0, 0, 0, 0 0, 0, 0, 0,
&ipx_usrreqs
}, },
{ SOCK_STREAM, &ipxdomain, IPXPROTO_SPX, PR_CONNREQUIRED|PR_WANTRCVD, { SOCK_STREAM, &ipxdomain, IPXPROTO_SPX, PR_CONNREQUIRED|PR_WANTRCVD,
0, 0, spx_ctlinput, spx_ctloutput, 0, 0, spx_ctlinput, spx_ctloutput,
spx_usrreq, 0,
spx_init, spx_fasttimo, spx_slowtimo, 0 spx_init, spx_fasttimo, spx_slowtimo, 0,
&spx_usrreqs
}, },
{ SOCK_SEQPACKET,&ipxdomain, IPXPROTO_SPX, PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC, { SOCK_SEQPACKET,&ipxdomain, IPXPROTO_SPX, PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC,
0, 0, spx_ctlinput, spx_ctloutput, 0, 0, spx_ctlinput, spx_ctloutput,
spx_usrreq_sp, 0,
0, 0, 0, 0 0, 0, 0, 0,
&spx_usrreq_sps
}, },
{ SOCK_RAW, &ipxdomain, IPXPROTO_RAW, PR_ATOMIC|PR_ADDR, { SOCK_RAW, &ipxdomain, IPXPROTO_RAW, PR_ATOMIC|PR_ADDR,
0, 0, 0, ipx_ctloutput, 0, 0, 0, ipx_ctloutput,
ipx_raw_usrreq, 0,
0, 0, 0, 0 0, 0, 0, 0,
&ripx_usrreqs
}, },
{ SOCK_RAW, &ipxdomain, IPXPROTO_ERROR, PR_ATOMIC|PR_ADDR, { SOCK_RAW, &ipxdomain, IPXPROTO_ERROR, PR_ATOMIC|PR_ADDR,
0, 0, 0, ipx_ctloutput, 0, 0, 0, ipx_ctloutput,
ipx_raw_usrreq, 0,
0, 0, 0, 0 0, 0, 0, 0,
&ripx_usrreqs
}, },
#ifdef IPTUNNEL #ifdef IPTUNNEL
#if 0 #if 0
{ SOCK_RAW, &ipxdomain, IPPROTO_IPX, PR_ATOMIC|PR_ADDR, { SOCK_RAW, &ipxdomain, IPPROTO_IPX, PR_ATOMIC|PR_ADDR,
iptun_input, rip_output, iptun_ctlinput, 0, iptun_input, rip_output, iptun_ctlinput, 0,
rip_usrreq, 0,
0, 0, 0, 0, 0, 0, 0, 0,
&rip_usrreqs
}, },
#endif #endif
#endif #endif

View File

@ -33,7 +33,7 @@
* *
* @(#)ipx_usrreq.c * @(#)ipx_usrreq.c
* *
* $Id$ * $Id: ipx_usrreq.c,v 1.11 1997/02/22 09:41:57 peter Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -74,6 +74,33 @@ int ipxrecvspace = IPXRCVQ;
SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW, SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW,
&ipxrecvspace, 0, ""); &ipxrecvspace, 0, "");
static int ipx_usr_abort(struct socket *so);
static int ipx_attach(struct socket *so, int proto);
static int ipx_bind(struct socket *so, struct mbuf *nam);
static int ipx_connect(struct socket *so, struct mbuf *nam);
static int ipx_detach(struct socket *so);
static int ipx_disconnect(struct socket *so);
static int ipx_send(struct socket *so, int flags, struct mbuf *m,
struct mbuf *addr, struct mbuf *control);
static int ipx_shutdown(struct socket *so);
static int ripx_attach(struct socket *so, int proto);
struct pr_usrreqs ipx_usrreqs = {
ipx_usr_abort, pru_accept_notsupp, ipx_attach, ipx_bind,
ipx_connect, pru_connect2_notsupp, ipx_control, ipx_detach,
ipx_disconnect, pru_listen_notsupp, ipx_peeraddr, pru_rcvd_notsupp,
pru_rcvoob_notsupp, ipx_send, pru_sense_null, ipx_shutdown,
ipx_sockaddr
};
struct pr_usrreqs ripx_usrreqs = {
ipx_usr_abort, pru_accept_notsupp, ripx_attach, ipx_bind,
ipx_connect, pru_connect2_notsupp, ipx_control, ipx_detach,
ipx_disconnect, pru_listen_notsupp, ipx_peeraddr, pru_rcvd_notsupp,
pru_rcvoob_notsupp, ipx_send, pru_sense_null, ipx_shutdown,
ipx_sockaddr
};
/* /*
* This may also be called for raw listeners. * This may also be called for raw listeners.
*/ */
@ -399,202 +426,200 @@ ipx_ctloutput(req, so, level, name, value)
return (error); return (error);
} }
/*ARGSUSED*/ static int
int ipx_usr_abort(so)
ipx_usrreq(so, req, m, nam, control)
struct socket *so; struct socket *so;
int req; {
struct mbuf *m, *nam, *control; int s;
struct ipxpcb *ipxp = sotoipxpcb(so);
s = splnet();
ipx_pcbdetach(ipxp);
splx(s);
sofree(so);
soisdisconnected(so);
return (0);
}
static int
ipx_attach(so, proto)
struct socket *so;
int proto;
{
int error;
int s;
struct ipxpcb *ipxp = sotoipxpcb(so);
if (ipxp != NULL)
return (EINVAL);
s = splnet();
error = ipx_pcballoc(so, &ipxpcb);
splx(s);
if (error == 0)
error = soreserve(so, ipxsendspace, ipxrecvspace);
return (error);
}
static int
ipx_bind(so, nam)
struct socket *so;
struct mbuf *nam;
{ {
struct ipxpcb *ipxp = sotoipxpcb(so); struct ipxpcb *ipxp = sotoipxpcb(so);
int error = 0;
if (req == PRU_CONTROL) return (ipx_pcbbind(ipxp, nam));
return (ipx_control(so, (int)m, (caddr_t)nam, }
(struct ifnet *)control));
if (control && control->m_len) {
error = EINVAL;
goto release;
}
if (ipxp == NULL && req != PRU_ATTACH) {
error = EINVAL;
goto release;
}
switch (req) {
case PRU_ATTACH: static int
if (ipxp != NULL) { ipx_connect(so, nam)
error = EINVAL; struct socket *so;
break; struct mbuf *nam;
} {
error = ipx_pcballoc(so, &ipxpcb); int error;
if (error) int s;
break; struct ipxpcb *ipxp = sotoipxpcb(so);
error = soreserve(so, ipxsendspace, ipxrecvspace);
if (error)
break;
break;
case PRU_DETACH: if (!ipx_nullhost(ipxp->ipxp_faddr))
if (ipxp == NULL) { return (EISCONN);
error = ENOTCONN; s = splnet();
break; error = ipx_pcbconnect(ipxp, nam);
} splx(s);
ipx_pcbdetach(ipxp); if (error == 0)
break; soisconnected(so);
return (error);
}
case PRU_BIND: static int
error = ipx_pcbbind(ipxp, nam); ipx_detach(so)
break; struct socket *so;
{
int s;
struct ipxpcb *ipxp = sotoipxpcb(so);
case PRU_LISTEN: if (ipxp == NULL)
error = EOPNOTSUPP; return (ENOTCONN);
break; s = splnet();
ipx_pcbdetach(ipxp);
splx(s);
return (0);
}
case PRU_CONNECT: static int
ipx_disconnect(so)
struct socket *so;
{
int s;
struct ipxpcb *ipxp = sotoipxpcb(so);
if (ipx_nullhost(ipxp->ipxp_faddr))
return (ENOTCONN);
s = splnet();
ipx_pcbdisconnect(ipxp);
splx(s);
soisdisconnected(so);
return (0);
}
int
ipx_peeraddr(so, nam)
struct socket *so;
struct mbuf *nam;
{
struct ipxpcb *ipxp = sotoipxpcb(so);
ipx_setpeeraddr(ipxp, nam);
return (0);
}
static int
ipx_send(so, flags, m, nam, control)
struct socket *so;
int flags;
struct mbuf *m;
struct mbuf *nam;
struct mbuf *control;
{
int error;
struct ipxpcb *ipxp = sotoipxpcb(so);
struct ipx_addr laddr;
int s = 0;
if (nam) {
laddr = ipxp->ipxp_laddr;
if (!ipx_nullhost(ipxp->ipxp_faddr)) { if (!ipx_nullhost(ipxp->ipxp_faddr)) {
error = EISCONN; error = EISCONN;
break; goto send_release;
} }
/*
* Must block input while temporarily connected.
*/
s = splnet();
error = ipx_pcbconnect(ipxp, nam); error = ipx_pcbconnect(ipxp, nam);
if (error == 0) if (error) {
soisconnected(so); splx(s);
break; goto send_release;
}
case PRU_CONNECT2: } else {
error = EOPNOTSUPP;
break;
case PRU_ACCEPT:
error = EOPNOTSUPP;
break;
case PRU_DISCONNECT:
if (ipx_nullhost(ipxp->ipxp_faddr)) { if (ipx_nullhost(ipxp->ipxp_faddr)) {
error = ENOTCONN; error = ENOTCONN;
break; goto send_release;
} }
}
error = ipx_output(ipxp, m);
m = NULL;
if (nam) {
ipx_pcbdisconnect(ipxp); ipx_pcbdisconnect(ipxp);
soisdisconnected(so); splx(s);
break; ipxp->ipxp_laddr.x_host = laddr.x_host;
ipxp->ipxp_laddr.x_port = laddr.x_port;
case PRU_SHUTDOWN:
socantsendmore(so);
break;
case PRU_SEND:
{
struct ipx_addr laddr;
int s = 0;
if (nam) {
laddr = ipxp->ipxp_laddr;
if (!ipx_nullhost(ipxp->ipxp_faddr)) {
error = EISCONN;
break;
}
/*
* Must block input while temporarily connected.
*/
s = splnet();
error = ipx_pcbconnect(ipxp, nam);
if (error) {
splx(s);
break;
}
} else {
if (ipx_nullhost(ipxp->ipxp_faddr)) {
error = ENOTCONN;
break;
}
}
error = ipx_output(ipxp, m);
m = NULL;
if (nam) {
ipx_pcbdisconnect(ipxp);
splx(s);
ipxp->ipxp_laddr.x_host = laddr.x_host;
ipxp->ipxp_laddr.x_port = laddr.x_port;
}
} }
break;
case PRU_ABORT: send_release:
ipx_pcbdetach(ipxp);
sofree(so);
soisdisconnected(so);
break;
case PRU_SOCKADDR:
ipx_setsockaddr(ipxp, nam);
break;
case PRU_PEERADDR:
ipx_setpeeraddr(ipxp, nam);
break;
case PRU_SENSE:
/*
* stat: don't bother with a blocksize.
*/
return (0);
case PRU_SENDOOB:
case PRU_FASTTIMO:
case PRU_SLOWTIMO:
case PRU_PROTORCV:
case PRU_PROTOSEND:
error = EOPNOTSUPP;
break;
case PRU_CONTROL:
case PRU_RCVD:
case PRU_RCVOOB:
return (EOPNOTSUPP); /* do not free mbuf's */
default:
panic("ipx_usrreq");
}
release:
if (control != NULL)
m_freem(control);
if (m != NULL) if (m != NULL)
m_freem(m); m_freem(m);
return (error); return (error);
} }
/*ARGSUSED*/ static int
int ipx_shutdown(so)
ipx_raw_usrreq(so, req, m, nam, control)
struct socket *so; struct socket *so;
int req;
struct mbuf *m, *nam, *control;
{ {
int error = 0; socantsendmore(so);
struct ipxpcb *ipxp = sotoipxpcb(so); return (0);
/*extern struct ipxpcb ipxrawpcb;*//*XXX*//*JRE*/
switch (req) {
case PRU_ATTACH:
if (!(so->so_state & SS_PRIV) || (ipxp != NULL)) {
error = EINVAL;
break;
}
error = ipx_pcballoc(so, &ipxrawpcb);
if (error)
break;
error = soreserve(so, ipxsendspace, ipxrecvspace);
if (error)
break;
ipxp = sotoipxpcb(so);
ipxp->ipxp_faddr.x_host = ipx_broadhost;
ipxp->ipxp_flags = IPXP_RAWIN | IPXP_RAWOUT;
break;
default:
error = ipx_usrreq(so, req, m, nam, control);
}
return (error);
} }
int
ipx_sockaddr(so, nam)
struct socket *so;
struct mbuf *nam;
{
struct ipxpcb *ipxp = sotoipxpcb(so);
ipx_setsockaddr(ipxp, nam);
return (0);
}
static int
ripx_attach(so, proto)
struct socket *so;
int proto;
{
int error = 0;
int s;
struct ipxpcb *ipxp = sotoipxpcb(so);
if (!(so->so_state & SS_PRIV) || (ipxp != NULL))
return (EINVAL);
s = splnet();
error = ipx_pcballoc(so, &ipxrawpcb);
splx(s);
if (error)
return (error);
error = soreserve(so, ipxsendspace, ipxrecvspace);
if (error)
return (error);
ipxp = sotoipxpcb(so);
ipxp->ipxp_faddr.x_host = ipx_broadhost;
ipxp->ipxp_flags = IPXP_RAWIN | IPXP_RAWOUT;
return (error);
}

View File

@ -33,7 +33,7 @@
* *
* @(#)spx.h * @(#)spx.h
* *
* $Id$ * $Id: spx.h,v 1.9 1997/02/22 09:41:58 peter Exp $
*/ */
#ifndef _NETIPX_SPX_H_ #ifndef _NETIPX_SPX_H_
@ -169,6 +169,9 @@ struct spxpcb {
#ifdef KERNEL #ifdef KERNEL
extern struct pr_usrreqs spx_usrreqs;
extern struct pr_usrreqs spx_usrreq_sps;
void spx_abort __P((struct ipxpcb *ipxp)); void spx_abort __P((struct ipxpcb *ipxp));
struct spxpcb * struct spxpcb *
spx_close __P((struct spxpcb *cb)); spx_close __P((struct spxpcb *cb));
@ -192,10 +195,6 @@ struct spxpcb *
spx_timers __P((struct spxpcb *cb, int timer)); spx_timers __P((struct spxpcb *cb, int timer));
struct spxpcb * struct spxpcb *
spx_usrclosed __P((struct spxpcb *cb)); spx_usrclosed __P((struct spxpcb *cb));
int spx_usrreq __P((struct socket *so, int req, struct mbuf *m,
struct mbuf *nam, struct mbuf *controlp));
int spx_usrreq_sp __P((struct socket *so, int req, struct mbuf *m,
struct mbuf *nam, struct mbuf *controlp));
#endif /* KERNEL */ #endif /* KERNEL */

View File

@ -33,7 +33,7 @@
* *
* @(#)spx_usrreq.h * @(#)spx_usrreq.h
* *
* $Id$ * $Id: spx_usrreq.c,v 1.10 1997/02/22 09:42:00 peter Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -72,6 +72,37 @@ u_short spx_newchecks[50];
struct spx_istat spx_istat; struct spx_istat spx_istat;
u_short spx_iss; u_short spx_iss;
static int spx_usr_abort(struct socket *so);
static int spx_accept(struct socket *so, struct mbuf *nam);
static int spx_attach(struct socket *so, int proto);
static int spx_bind(struct socket *so, struct mbuf *nam);
static int spx_connect(struct socket *so, struct mbuf *nam);
static int spx_detach(struct socket *so);
static int spx_usr_disconnect(struct socket *so);
static int spx_listen(struct socket *so);
static int spx_rcvd(struct socket *so, int flags);
static int spx_rcvoob(struct socket *so, struct mbuf *m, int flags);
static int spx_send(struct socket *so, int flags, struct mbuf *m,
struct mbuf *addr, struct mbuf *control);
static int spx_shutdown(struct socket *so);
static int spx_sp_attach(struct socket *so, int proto);
struct pr_usrreqs spx_usrreqs = {
spx_usr_abort, spx_accept, spx_attach, spx_bind,
spx_connect, pru_connect2_notsupp, ipx_control, spx_detach,
spx_usr_disconnect, spx_listen, ipx_peeraddr, spx_rcvd,
spx_rcvoob, spx_send, pru_sense_null, spx_shutdown,
ipx_sockaddr
};
struct pr_usrreqs spx_usrreq_sps = {
spx_usr_abort, spx_accept, spx_sp_attach, spx_bind,
spx_connect, pru_connect2_notsupp, ipx_control, spx_detach,
spx_usr_disconnect, spx_listen, ipx_peeraddr, spx_rcvd,
spx_rcvoob, spx_send, pru_sense_null, spx_shutdown,
ipx_sockaddr
};
void void
spx_init() spx_init()
{ {
@ -1266,252 +1297,319 @@ spx_ctloutput(req, so, level, name, value)
return (error); return (error);
} }
/*ARGSUSED*/ static int
int spx_usr_abort(so)
spx_usrreq(so, req, m, nam, controlp)
struct socket *so; struct socket *so;
int req;
struct mbuf *m, *nam, *controlp;
{ {
struct ipxpcb *ipxp = sotoipxpcb(so); int s;
register struct spxpcb *cb = NULL; struct ipxpcb *ipxp;
int s = splnet(); struct spxpcb *cb;
int error = 0, ostate;
ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
s = splnet();
spx_drop(cb, ECONNABORTED);
splx(s);
return (0);
}
/*
* Accept a connection. Essentially all the work is
* done at higher levels; just return the address
* of the peer, storing through addr.
*/
static int
spx_accept(so, nam)
struct socket *so;
struct mbuf *nam;
{
struct ipxpcb *ipxp;
struct sockaddr_ipx *sipx;
ipxp = sotoipxpcb(so);
sipx = mtod(nam, struct sockaddr_ipx *);
nam->m_len = sizeof (struct sockaddr_ipx);
sipx->sipx_family = AF_IPX;
sipx->sipx_addr = ipxp->ipxp_faddr;
return (0);
}
static int
spx_attach(so, proto)
struct socket *so;
int proto;
{
int error;
int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
struct mbuf *mm; struct mbuf *mm;
register struct sockbuf *sb; struct sockbuf *sb;
if (req == PRU_CONTROL) ipxp = sotoipxpcb(so);
return (ipx_control(so, (int)m, (caddr_t)nam, cb = ipxtospxpcb(ipxp);
(struct ifnet *)controlp));
if (ipxp == NULL) {
if (req != PRU_ATTACH) {
error = EINVAL;
goto release;
}
} else
cb = ipxtospxpcb(ipxp);
ostate = cb ? cb->s_state : 0; if (ipxp != NULL)
return (EISCONN);
switch (req) { s = splnet();
error = ipx_pcballoc(so, &ipxpcb);
case PRU_ATTACH: if (error)
if (ipxp != NULL) { goto spx_attach_end;
error = EISCONN; if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
break; error = soreserve(so, (u_long) 3072, (u_long) 3072);
}
error = ipx_pcballoc(so, &ipxpcb);
if (error) if (error)
break; goto spx_attach_end;
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { }
error = soreserve(so, (u_long) 3072, (u_long) 3072); ipxp = sotoipxpcb(so);
if (error)
break;
}
ipxp = sotoipxpcb(so);
mm = m_getclr(M_DONTWAIT, MT_PCB); mm = m_getclr(M_DONTWAIT, MT_PCB);
sb = &so->so_snd; sb = &so->so_snd;
if (mm == NULL) { if (mm == NULL) {
error = ENOBUFS; error = ENOBUFS;
break; goto spx_attach_end;
} }
cb = mtod(mm, struct spxpcb *); cb = mtod(mm, struct spxpcb *);
mm = m_getclr(M_DONTWAIT, MT_HEADER); mm = m_getclr(M_DONTWAIT, MT_HEADER);
if (mm == NULL) { if (mm == NULL) {
(void) m_free(dtom(m)); m_freem(dtom(cb));
error = ENOBUFS; error = ENOBUFS;
break; goto spx_attach_end;
} }
cb->s_ipx = mtod(mm, struct ipx *); cb->s_ipx = mtod(mm, struct ipx *);
cb->s_state = TCPS_LISTEN;
cb->s_smax = -1;
cb->s_swl1 = -1;
cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q;
cb->s_ipxpcb = ipxp;
cb->s_mtu = 576 - sizeof (struct spx);
cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu;
cb->s_ssthresh = cb->s_cwnd;
cb->s_cwmx = sbspace(sb) * CUNIT /
(2 * sizeof (struct spx));
/* Above is recomputed when connecting to account
for changed buffering or mtu's */
cb->s_rtt = SPXTV_SRTTBASE;
cb->s_rttvar = SPXTV_SRTTDFLT << 2;
SPXT_RANGESET(cb->s_rxtcur,
((SPXTV_SRTTBASE >> 2) + (SPXTV_SRTTDFLT << 2)) >> 1,
SPXTV_MIN, SPXTV_REXMTMAX);
ipxp->ipxp_pcb = (caddr_t) cb;
spx_attach_end:
splx(s);
return (error);
}
static int
spx_bind(so, nam)
struct socket *so;
struct mbuf *nam;
{
struct ipxpcb *ipxp;
ipxp = sotoipxpcb(so);
return (ipx_pcbbind(ipxp, nam));
}
/*
* Initiate connection to peer.
* Enter SYN_SENT state, and mark socket as connecting.
* Start keep-alive timer, setup prototype header,
* Send initial system packet requesting connection.
*/
static int
spx_connect(so, nam)
struct socket *so;
struct mbuf *nam;
{
int error;
int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
s = splnet();
if (ipxp->ipxp_lport == 0) {
error = ipx_pcbbind(ipxp, (struct mbuf *)0);
if (error)
goto spx_connect_end;
}
error = ipx_pcbconnect(ipxp, nam);
if (error)
goto spx_connect_end;
soisconnecting(so);
spxstat.spxs_connattempt++;
cb->s_state = TCPS_SYN_SENT;
cb->s_did = 0;
spx_template(cb);
cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
cb->s_force = 1 + SPXTV_KEEP;
/*
* Other party is required to respond to
* the port I send from, but he is not
* required to answer from where I am sending to,
* so allow wildcarding.
* original port I am sending to is still saved in
* cb->s_dport.
*/
ipxp->ipxp_fport = 0;
error = spx_output(cb, (struct mbuf *) 0);
spx_connect_end:
splx(s);
return (error);
}
static int
spx_detach(so)
struct socket *so;
{
int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
if (ipxp == NULL)
return (ENOTCONN);
s = splnet();
if (cb->s_state > TCPS_LISTEN)
spx_disconnect(cb);
else
spx_close(cb);
splx(s);
return (0);
}
/*
* We may decide later to implement connection closing
* handshaking at the spx level optionally.
* here is the hook to do it:
*/
static int
spx_usr_disconnect(so)
struct socket *so;
{
int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
s = splnet();
spx_disconnect(cb);
splx(s);
return (0);
}
static int
spx_listen(so)
struct socket *so;
{
int error;
struct ipxpcb *ipxp;
struct spxpcb *cb;
error = 0;
ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
if (ipxp->ipxp_lport == 0)
error = ipx_pcbbind(ipxp, (struct mbuf *)0);
if (error == 0)
cb->s_state = TCPS_LISTEN; cb->s_state = TCPS_LISTEN;
cb->s_smax = -1; return (error);
cb->s_swl1 = -1; }
cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q;
cb->s_ipxpcb = ipxp;
cb->s_mtu = 576 - sizeof (struct spx);
cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu;
cb->s_ssthresh = cb->s_cwnd;
cb->s_cwmx = sbspace(sb) * CUNIT /
(2 * sizeof (struct spx));
/* Above is recomputed when connecting to account
for changed buffering or mtu's */
cb->s_rtt = SPXTV_SRTTBASE;
cb->s_rttvar = SPXTV_SRTTDFLT << 2;
SPXT_RANGESET(cb->s_rxtcur,
((SPXTV_SRTTBASE >> 2) + (SPXTV_SRTTDFLT << 2)) >> 1,
SPXTV_MIN, SPXTV_REXMTMAX);
ipxp->ipxp_pcb = (caddr_t) cb;
break;
case PRU_DETACH: /*
if (ipxp == NULL) { * After a receive, possibly send acknowledgment
error = ENOTCONN; * updating allocation.
break; */
} static int
if (cb->s_state > TCPS_LISTEN) spx_rcvd(so, flags)
cb = spx_disconnect(cb); struct socket *so;
else int flags;
cb = spx_close(cb); {
break; int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
case PRU_BIND: ipxp = sotoipxpcb(so);
error = ipx_pcbbind(ipxp, nam); cb = ipxtospxpcb(ipxp);
break;
case PRU_LISTEN: s = splnet();
if (ipxp->ipxp_lport == 0) cb->s_flags |= SF_RVD;
error = ipx_pcbbind(ipxp, (struct mbuf *)0); spx_output(cb, (struct mbuf *) 0);
if (error == 0) cb->s_flags &= ~SF_RVD;
cb->s_state = TCPS_LISTEN; splx(s);
break; return (0);
}
/* static int
* Initiate connection to peer. spx_rcvoob(so, m, flags)
* Enter SYN_SENT state, and mark socket as connecting. struct socket *so;
* Start keep-alive timer, setup prototype header, struct mbuf *m;
* Send initial system packet requesting connection. int flags;
*/ {
case PRU_CONNECT: struct ipxpcb *ipxp;
if (ipxp->ipxp_lport == 0) { struct spxpcb *cb;
error = ipx_pcbbind(ipxp, (struct mbuf *)0);
if (error)
break;
}
error = ipx_pcbconnect(ipxp, nam);
if (error)
break;
soisconnecting(so);
spxstat.spxs_connattempt++;
cb->s_state = TCPS_SYN_SENT;
cb->s_did = 0;
spx_template(cb);
cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
cb->s_force = 1 + SPXTV_KEEP;
/*
* Other party is required to respond to
* the port I send from, but he is not
* required to answer from where I am sending to,
* so allow wildcarding.
* original port I am sending to is still saved in
* cb->s_dport.
*/
ipxp->ipxp_fport = 0;
error = spx_output(cb, (struct mbuf *) 0);
break;
case PRU_CONNECT2: ipxp = sotoipxpcb(so);
error = EOPNOTSUPP; cb = ipxtospxpcb(ipxp);
break;
/* if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
* We may decide later to implement connection closing (so->so_state & SS_RCVATMARK)) {
* handshaking at the spx level optionally. m->m_len = 1;
* here is the hook to do it: *mtod(m, caddr_t) = cb->s_iobc;
*/ return (0);
case PRU_DISCONNECT: }
cb = spx_disconnect(cb); return (EINVAL);
break; }
/* static int
* Accept a connection. Essentially all the work is spx_send(so, flags, m, addr, controlp)
* done at higher levels; just return the address struct socket *so;
* of the peer, storing through addr. int flags;
*/ struct mbuf *m;
case PRU_ACCEPT: { struct mbuf *addr;
struct sockaddr_ipx *sipx = mtod(nam, struct sockaddr_ipx *); struct mbuf *controlp;
{
int error;
int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
nam->m_len = sizeof (struct sockaddr_ipx); error = 0;
sipx->sipx_family = AF_IPX; ipxp = sotoipxpcb(so);
sipx->sipx_addr = ipxp->ipxp_faddr; cb = ipxtospxpcb(ipxp);
break;
}
case PRU_SHUTDOWN: s = splnet();
socantsendmore(so); if (flags & PRUS_OOB) {
cb = spx_usrclosed(cb);
if (cb)
error = spx_output(cb, (struct mbuf *) 0);
break;
/*
* After a receive, possibly send acknowledgment
* updating allocation.
*/
case PRU_RCVD:
cb->s_flags |= SF_RVD;
(void) spx_output(cb, (struct mbuf *) 0);
cb->s_flags &= ~SF_RVD;
break;
case PRU_ABORT:
(void) spx_drop(cb, ECONNABORTED);
break;
case PRU_SENSE:
case PRU_CONTROL:
m = NULL;
error = EOPNOTSUPP;
break;
case PRU_RCVOOB:
if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
(so->so_state & SS_RCVATMARK)) {
m->m_len = 1;
*mtod(m, caddr_t) = cb->s_iobc;
break;
}
error = EINVAL;
break;
case PRU_SENDOOB:
if (sbspace(&so->so_snd) < -512) { if (sbspace(&so->so_snd) < -512) {
error = ENOBUFS; error = ENOBUFS;
break; goto spx_send_end;
} }
cb->s_oobflags |= SF_SOOB; cb->s_oobflags |= SF_SOOB;
/* fall into */
case PRU_SEND:
if (controlp) {
u_short *p = mtod(controlp, u_short *);
spx_newchecks[2]++;
if ((p[0] == 5) && p[1] == 1) { /* XXXX, for testing */
cb->s_shdr.spx_dt = *(u_char *)(&p[2]);
spx_newchecks[3]++;
}
m_freem(controlp);
}
controlp = NULL;
error = spx_output(cb, m);
m = NULL;
break;
case PRU_SOCKADDR:
ipx_setsockaddr(ipxp, nam);
break;
case PRU_PEERADDR:
ipx_setpeeraddr(ipxp, nam);
break;
case PRU_SLOWTIMO:
cb = spx_timers(cb, (int)nam);
req |= ((int)nam) << 8;
break;
case PRU_FASTTIMO:
case PRU_PROTORCV:
case PRU_PROTOSEND:
error = EOPNOTSUPP;
break;
default:
panic("spx_usrreq");
} }
if (cb && (so->so_options & SO_DEBUG || traceallspxs)) if (controlp) {
spx_trace(SA_USER, (u_char)ostate, cb, (struct spx *)0, req); u_short *p = mtod(controlp, u_short *);
release: spx_newchecks[2]++;
if ((p[0] == 5) && p[1] == 1) { /* XXXX, for testing */
cb->s_shdr.spx_dt = *(u_char *)(&p[2]);
spx_newchecks[3]++;
}
m_freem(controlp);
}
controlp = NULL;
error = spx_output(cb, m);
m = NULL;
spx_send_end:
if (controlp != NULL) if (controlp != NULL)
m_freem(controlp); m_freem(controlp);
if (m != NULL) if (m != NULL)
@ -1520,16 +1618,40 @@ spx_usrreq(so, req, m, nam, controlp)
return (error); return (error);
} }
int static int
spx_usrreq_sp(so, req, m, nam, controlp) spx_shutdown(so)
struct socket *so; struct socket *so;
int req;
struct mbuf *m, *nam, *controlp;
{ {
int error = spx_usrreq(so, req, m, nam, controlp); int error;
int s;
struct ipxpcb *ipxp;
struct spxpcb *cb;
if (req == PRU_ATTACH && error == 0) { error = 0;
struct ipxpcb *ipxp = sotoipxpcb(so); ipxp = sotoipxpcb(so);
cb = ipxtospxpcb(ipxp);
s = splnet();
socantsendmore(so);
cb = spx_usrclosed(cb);
if (cb)
error = spx_output(cb, (struct mbuf *) 0);
splx(s);
return (error);
}
static int
spx_sp_attach(so, proto)
struct socket *so;
int proto;
{
int error;
struct ipxpcb *ipxp;
struct spxpcb *cb;
error = spx_attach(so, proto);
if (error == 0) {
ipxp = sotoipxpcb(so);
((struct spxpcb *)ipxp->ipxp_pcb)->s_flags |= ((struct spxpcb *)ipxp->ipxp_pcb)->s_flags |=
(SF_HI | SF_HO | SF_PI); (SF_HI | SF_HO | SF_PI);
} }
@ -1698,9 +1820,7 @@ spx_slowtimo()
goto tpgone; goto tpgone;
for (i = 0; i < SPXT_NTIMERS; i++) { for (i = 0; i < SPXT_NTIMERS; i++) {
if (cb->s_timer[i] && --cb->s_timer[i] == 0) { if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
(void) spx_usrreq(cb->s_ipxpcb->ipxp_socket, spx_timers(cb, i);
PRU_SLOWTIMO, (struct mbuf *)0,
(struct mbuf *)i, (struct mbuf *)0);
if (ipnxt->ipxp_prev != ip) if (ipnxt->ipxp_prev != ip)
goto tpgone; goto tpgone;
} }