diff --git a/sys/netipx/ipx.h b/sys/netipx/ipx.h index c309c54ced6a..db04b80e631d 100644 --- a/sys/netipx/ipx.h +++ b/sys/netipx/ipx.h @@ -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 diff --git a/sys/netipx/ipx_proto.c b/sys/netipx/ipx_proto.c index bb3a85004043..110135e6c00c 100644 --- a/sys/netipx/ipx_proto.c +++ b/sys/netipx/ipx_proto.c @@ -33,7 +33,7 @@ * * @(#)ipx_proto.c * - * $Id$ + * $Id: ipx_proto.c,v 1.7 1997/02/22 09:41:56 peter Exp $ */ #include @@ -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 diff --git a/sys/netipx/ipx_usrreq.c b/sys/netipx/ipx_usrreq.c index e0ff42a3eeef..f6fbaaa44ab2 100644 --- a/sys/netipx/ipx_usrreq.c +++ b/sys/netipx/ipx_usrreq.c @@ -33,7 +33,7 @@ * * @(#)ipx_usrreq.c * - * $Id$ + * $Id: ipx_usrreq.c,v 1.11 1997/02/22 09:41:57 peter Exp $ */ #include @@ -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); +} diff --git a/sys/netipx/spx.h b/sys/netipx/spx.h index b3e8e9b45a75..da3e70fe0b27 100644 --- a/sys/netipx/spx.h +++ b/sys/netipx/spx.h @@ -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 */ diff --git a/sys/netipx/spx_usrreq.c b/sys/netipx/spx_usrreq.c index 555d45dad666..bb62f5191ea5 100644 --- a/sys/netipx/spx_usrreq.c +++ b/sys/netipx/spx_usrreq.c @@ -33,7 +33,7 @@ * * @(#)spx_usrreq.h * - * $Id$ + * $Id: spx_usrreq.c,v 1.10 1997/02/22 09:42:00 peter Exp $ */ #include @@ -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; }