Change IPX to use the pr_usrreqs structure.
This commit is contained in:
parent
8a34de70b7
commit
09aec948b9
@ -33,7 +33,7 @@
|
||||
*
|
||||
* @(#)ipx.h
|
||||
*
|
||||
* $Id$
|
||||
* $Id: ipx.h,v 1.9 1997/02/22 09:41:52 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETIPX_IPX_H_
|
||||
@ -158,6 +158,8 @@ struct ipx {
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
extern struct pr_usrreqs ipx_usrreqs;
|
||||
extern struct pr_usrreqs ripx_usrreqs;
|
||||
extern int ipxcksum;
|
||||
extern struct domain ipxdomain;
|
||||
extern struct sockaddr_ipx ipx_netmask;
|
||||
@ -191,13 +193,12 @@ void ipx_input __P((struct mbuf *m, struct ipxpcb *ipxp));
|
||||
void ipxintr __P((void));
|
||||
int ipx_output __P((struct ipxpcb *ipxp, struct mbuf *m0));
|
||||
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));
|
||||
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));
|
||||
|
||||
int ipx_peeraddr __P((struct socket *so, struct mbuf *nam));
|
||||
int ipx_sockaddr __P((struct socket *so, struct mbuf *nam));
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
* @(#)ipx_proto.c
|
||||
*
|
||||
* $Id$
|
||||
* $Id: ipx_proto.c,v 1.7 1997/02/22 09:41:56 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -57,39 +57,45 @@ struct protosw ipxsw[] = {
|
||||
{ 0, &ipxdomain, 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,
|
||||
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,
|
||||
0, 0, spx_ctlinput, spx_ctloutput,
|
||||
spx_usrreq,
|
||||
spx_init, spx_fasttimo, spx_slowtimo, 0
|
||||
0,
|
||||
spx_init, spx_fasttimo, spx_slowtimo, 0,
|
||||
&spx_usrreqs
|
||||
},
|
||||
{ SOCK_SEQPACKET,&ipxdomain, IPXPROTO_SPX, PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC,
|
||||
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,
|
||||
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,
|
||||
0, 0, 0, ipx_ctloutput,
|
||||
ipx_raw_usrreq,
|
||||
0, 0, 0, 0
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&ripx_usrreqs
|
||||
},
|
||||
#ifdef IPTUNNEL
|
||||
#if 0
|
||||
{ SOCK_RAW, &ipxdomain, IPPROTO_IPX, PR_ATOMIC|PR_ADDR,
|
||||
iptun_input, rip_output, iptun_ctlinput, 0,
|
||||
rip_usrreq,
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
&rip_usrreqs
|
||||
},
|
||||
#endif
|
||||
#endif
|
||||
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
* @(#)ipx_usrreq.c
|
||||
*
|
||||
* $Id$
|
||||
* $Id: ipx_usrreq.c,v 1.11 1997/02/22 09:41:57 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -74,6 +74,33 @@ int ipxrecvspace = IPXRCVQ;
|
||||
SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW,
|
||||
&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.
|
||||
*/
|
||||
@ -399,202 +426,200 @@ ipx_ctloutput(req, so, level, name, value)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
ipx_usrreq(so, req, m, nam, control)
|
||||
static int
|
||||
ipx_usr_abort(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);
|
||||
int error = 0;
|
||||
|
||||
if (req == PRU_CONTROL)
|
||||
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) {
|
||||
return (ipx_pcbbind(ipxp, nam));
|
||||
}
|
||||
|
||||
case PRU_ATTACH:
|
||||
if (ipxp != NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
error = ipx_pcballoc(so, &ipxpcb);
|
||||
if (error)
|
||||
break;
|
||||
error = soreserve(so, ipxsendspace, ipxrecvspace);
|
||||
if (error)
|
||||
break;
|
||||
break;
|
||||
static int
|
||||
ipx_connect(so, nam)
|
||||
struct socket *so;
|
||||
struct mbuf *nam;
|
||||
{
|
||||
int error;
|
||||
int s;
|
||||
struct ipxpcb *ipxp = sotoipxpcb(so);
|
||||
|
||||
case PRU_DETACH:
|
||||
if (ipxp == NULL) {
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
}
|
||||
ipx_pcbdetach(ipxp);
|
||||
break;
|
||||
if (!ipx_nullhost(ipxp->ipxp_faddr))
|
||||
return (EISCONN);
|
||||
s = splnet();
|
||||
error = ipx_pcbconnect(ipxp, nam);
|
||||
splx(s);
|
||||
if (error == 0)
|
||||
soisconnected(so);
|
||||
return (error);
|
||||
}
|
||||
|
||||
case PRU_BIND:
|
||||
error = ipx_pcbbind(ipxp, nam);
|
||||
break;
|
||||
static int
|
||||
ipx_detach(so)
|
||||
struct socket *so;
|
||||
{
|
||||
int s;
|
||||
struct ipxpcb *ipxp = sotoipxpcb(so);
|
||||
|
||||
case PRU_LISTEN:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
if (ipxp == NULL)
|
||||
return (ENOTCONN);
|
||||
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)) {
|
||||
error = EISCONN;
|
||||
break;
|
||||
goto send_release;
|
||||
}
|
||||
/*
|
||||
* Must block input while temporarily connected.
|
||||
*/
|
||||
s = splnet();
|
||||
error = ipx_pcbconnect(ipxp, nam);
|
||||
if (error == 0)
|
||||
soisconnected(so);
|
||||
break;
|
||||
|
||||
case PRU_CONNECT2:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case PRU_ACCEPT:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
|
||||
case PRU_DISCONNECT:
|
||||
if (error) {
|
||||
splx(s);
|
||||
goto send_release;
|
||||
}
|
||||
} else {
|
||||
if (ipx_nullhost(ipxp->ipxp_faddr)) {
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
goto send_release;
|
||||
}
|
||||
}
|
||||
error = ipx_output(ipxp, m);
|
||||
m = NULL;
|
||||
if (nam) {
|
||||
ipx_pcbdisconnect(ipxp);
|
||||
soisdisconnected(so);
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
splx(s);
|
||||
ipxp->ipxp_laddr.x_host = laddr.x_host;
|
||||
ipxp->ipxp_laddr.x_port = laddr.x_port;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRU_ABORT:
|
||||
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);
|
||||
send_release:
|
||||
if (m != NULL)
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
ipx_raw_usrreq(so, req, m, nam, control)
|
||||
static int
|
||||
ipx_shutdown(so)
|
||||
struct socket *so;
|
||||
int req;
|
||||
struct mbuf *m, *nam, *control;
|
||||
{
|
||||
int error = 0;
|
||||
struct ipxpcb *ipxp = sotoipxpcb(so);
|
||||
/*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);
|
||||
socantsendmore(so);
|
||||
return (0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
* @(#)spx.h
|
||||
*
|
||||
* $Id$
|
||||
* $Id: spx.h,v 1.9 1997/02/22 09:41:58 peter Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NETIPX_SPX_H_
|
||||
@ -169,6 +169,9 @@ struct spxpcb {
|
||||
|
||||
#ifdef KERNEL
|
||||
|
||||
extern struct pr_usrreqs spx_usrreqs;
|
||||
extern struct pr_usrreqs spx_usrreq_sps;
|
||||
|
||||
void spx_abort __P((struct ipxpcb *ipxp));
|
||||
struct spxpcb *
|
||||
spx_close __P((struct spxpcb *cb));
|
||||
@ -192,10 +195,6 @@ struct spxpcb *
|
||||
spx_timers __P((struct spxpcb *cb, int timer));
|
||||
struct spxpcb *
|
||||
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 */
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
*
|
||||
* @(#)spx_usrreq.h
|
||||
*
|
||||
* $Id$
|
||||
* $Id: spx_usrreq.c,v 1.10 1997/02/22 09:42:00 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -72,6 +72,37 @@ u_short spx_newchecks[50];
|
||||
struct spx_istat spx_istat;
|
||||
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
|
||||
spx_init()
|
||||
{
|
||||
@ -1266,252 +1297,319 @@ spx_ctloutput(req, so, level, name, value)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
spx_usrreq(so, req, m, nam, controlp)
|
||||
static int
|
||||
spx_usr_abort(so)
|
||||
struct socket *so;
|
||||
int req;
|
||||
struct mbuf *m, *nam, *controlp;
|
||||
{
|
||||
struct ipxpcb *ipxp = sotoipxpcb(so);
|
||||
register struct spxpcb *cb = NULL;
|
||||
int s = splnet();
|
||||
int error = 0, ostate;
|
||||
int s;
|
||||
struct ipxpcb *ipxp;
|
||||
struct spxpcb *cb;
|
||||
|
||||
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;
|
||||
register struct sockbuf *sb;
|
||||
struct sockbuf *sb;
|
||||
|
||||
if (req == PRU_CONTROL)
|
||||
return (ipx_control(so, (int)m, (caddr_t)nam,
|
||||
(struct ifnet *)controlp));
|
||||
if (ipxp == NULL) {
|
||||
if (req != PRU_ATTACH) {
|
||||
error = EINVAL;
|
||||
goto release;
|
||||
}
|
||||
} else
|
||||
cb = ipxtospxpcb(ipxp);
|
||||
ipxp = sotoipxpcb(so);
|
||||
cb = ipxtospxpcb(ipxp);
|
||||
|
||||
ostate = cb ? cb->s_state : 0;
|
||||
|
||||
switch (req) {
|
||||
|
||||
case PRU_ATTACH:
|
||||
if (ipxp != NULL) {
|
||||
error = EISCONN;
|
||||
break;
|
||||
}
|
||||
error = ipx_pcballoc(so, &ipxpcb);
|
||||
if (ipxp != NULL)
|
||||
return (EISCONN);
|
||||
s = splnet();
|
||||
error = ipx_pcballoc(so, &ipxpcb);
|
||||
if (error)
|
||||
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);
|
||||
if (error)
|
||||
break;
|
||||
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
|
||||
error = soreserve(so, (u_long) 3072, (u_long) 3072);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
ipxp = sotoipxpcb(so);
|
||||
goto spx_attach_end;
|
||||
}
|
||||
ipxp = sotoipxpcb(so);
|
||||
|
||||
mm = m_getclr(M_DONTWAIT, MT_PCB);
|
||||
sb = &so->so_snd;
|
||||
mm = m_getclr(M_DONTWAIT, MT_PCB);
|
||||
sb = &so->so_snd;
|
||||
|
||||
if (mm == NULL) {
|
||||
error = ENOBUFS;
|
||||
break;
|
||||
}
|
||||
cb = mtod(mm, struct spxpcb *);
|
||||
mm = m_getclr(M_DONTWAIT, MT_HEADER);
|
||||
if (mm == NULL) {
|
||||
(void) m_free(dtom(m));
|
||||
error = ENOBUFS;
|
||||
break;
|
||||
}
|
||||
cb->s_ipx = mtod(mm, struct ipx *);
|
||||
if (mm == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto spx_attach_end;
|
||||
}
|
||||
cb = mtod(mm, struct spxpcb *);
|
||||
mm = m_getclr(M_DONTWAIT, MT_HEADER);
|
||||
if (mm == NULL) {
|
||||
m_freem(dtom(cb));
|
||||
error = ENOBUFS;
|
||||
goto spx_attach_end;
|
||||
}
|
||||
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_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;
|
||||
break;
|
||||
return (error);
|
||||
}
|
||||
|
||||
case PRU_DETACH:
|
||||
if (ipxp == NULL) {
|
||||
error = ENOTCONN;
|
||||
break;
|
||||
}
|
||||
if (cb->s_state > TCPS_LISTEN)
|
||||
cb = spx_disconnect(cb);
|
||||
else
|
||||
cb = spx_close(cb);
|
||||
break;
|
||||
/*
|
||||
* After a receive, possibly send acknowledgment
|
||||
* updating allocation.
|
||||
*/
|
||||
static int
|
||||
spx_rcvd(so, flags)
|
||||
struct socket *so;
|
||||
int flags;
|
||||
{
|
||||
int s;
|
||||
struct ipxpcb *ipxp;
|
||||
struct spxpcb *cb;
|
||||
|
||||
case PRU_BIND:
|
||||
error = ipx_pcbbind(ipxp, nam);
|
||||
break;
|
||||
ipxp = sotoipxpcb(so);
|
||||
cb = ipxtospxpcb(ipxp);
|
||||
|
||||
case PRU_LISTEN:
|
||||
if (ipxp->ipxp_lport == 0)
|
||||
error = ipx_pcbbind(ipxp, (struct mbuf *)0);
|
||||
if (error == 0)
|
||||
cb->s_state = TCPS_LISTEN;
|
||||
break;
|
||||
s = splnet();
|
||||
cb->s_flags |= SF_RVD;
|
||||
spx_output(cb, (struct mbuf *) 0);
|
||||
cb->s_flags &= ~SF_RVD;
|
||||
splx(s);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
case PRU_CONNECT:
|
||||
if (ipxp->ipxp_lport == 0) {
|
||||
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;
|
||||
static int
|
||||
spx_rcvoob(so, m, flags)
|
||||
struct socket *so;
|
||||
struct mbuf *m;
|
||||
int flags;
|
||||
{
|
||||
struct ipxpcb *ipxp;
|
||||
struct spxpcb *cb;
|
||||
|
||||
case PRU_CONNECT2:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
ipxp = sotoipxpcb(so);
|
||||
cb = ipxtospxpcb(ipxp);
|
||||
|
||||
/*
|
||||
* We may decide later to implement connection closing
|
||||
* handshaking at the spx level optionally.
|
||||
* here is the hook to do it:
|
||||
*/
|
||||
case PRU_DISCONNECT:
|
||||
cb = spx_disconnect(cb);
|
||||
break;
|
||||
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;
|
||||
return (0);
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept a connection. Essentially all the work is
|
||||
* done at higher levels; just return the address
|
||||
* of the peer, storing through addr.
|
||||
*/
|
||||
case PRU_ACCEPT: {
|
||||
struct sockaddr_ipx *sipx = mtod(nam, struct sockaddr_ipx *);
|
||||
static int
|
||||
spx_send(so, flags, m, addr, controlp)
|
||||
struct socket *so;
|
||||
int flags;
|
||||
struct mbuf *m;
|
||||
struct mbuf *addr;
|
||||
struct mbuf *controlp;
|
||||
{
|
||||
int error;
|
||||
int s;
|
||||
struct ipxpcb *ipxp;
|
||||
struct spxpcb *cb;
|
||||
|
||||
nam->m_len = sizeof (struct sockaddr_ipx);
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_addr = ipxp->ipxp_faddr;
|
||||
break;
|
||||
}
|
||||
error = 0;
|
||||
ipxp = sotoipxpcb(so);
|
||||
cb = ipxtospxpcb(ipxp);
|
||||
|
||||
case PRU_SHUTDOWN:
|
||||
socantsendmore(so);
|
||||
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:
|
||||
s = splnet();
|
||||
if (flags & PRUS_OOB) {
|
||||
if (sbspace(&so->so_snd) < -512) {
|
||||
error = ENOBUFS;
|
||||
break;
|
||||
goto spx_send_end;
|
||||
}
|
||||
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))
|
||||
spx_trace(SA_USER, (u_char)ostate, cb, (struct spx *)0, req);
|
||||
release:
|
||||
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;
|
||||
spx_send_end:
|
||||
if (controlp != NULL)
|
||||
m_freem(controlp);
|
||||
if (m != NULL)
|
||||
@ -1520,16 +1618,40 @@ spx_usrreq(so, req, m, nam, controlp)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
spx_usrreq_sp(so, req, m, nam, controlp)
|
||||
struct socket *so;
|
||||
int req;
|
||||
struct mbuf *m, *nam, *controlp;
|
||||
static int
|
||||
spx_shutdown(so)
|
||||
struct socket *so;
|
||||
{
|
||||
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) {
|
||||
struct ipxpcb *ipxp = sotoipxpcb(so);
|
||||
error = 0;
|
||||
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 |=
|
||||
(SF_HI | SF_HO | SF_PI);
|
||||
}
|
||||
@ -1698,9 +1820,7 @@ spx_slowtimo()
|
||||
goto tpgone;
|
||||
for (i = 0; i < SPXT_NTIMERS; i++) {
|
||||
if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
|
||||
(void) spx_usrreq(cb->s_ipxpcb->ipxp_socket,
|
||||
PRU_SLOWTIMO, (struct mbuf *)0,
|
||||
(struct mbuf *)i, (struct mbuf *)0);
|
||||
spx_timers(cb, i);
|
||||
if (ipnxt->ipxp_prev != ip)
|
||||
goto tpgone;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user