BSD 4_4_Lite2 release
[unix-history] / usr / src / sys / netns / spp_usrreq.c
index dcfc563..7ce6723 100644 (file)
@@ -1,46 +1,61 @@
 /*
 /*
- * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1984, 1985, 1986, 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)spp_usrreq.c        7.9 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)spp_usrreq.c        8.2 (Berkeley) 1/9/95
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "dir.h"
-#include "user.h"
-#include "mbuf.h"
-#include "protosw.h"
-#include "socket.h"
-#include "socketvar.h"
-#include "errno.h"
-
-#include "../net/if.h"
-#include "../net/route.h"
-#include "../netinet/tcp_fsm.h"
-
-#include "ns.h"
-#include "ns_pcb.h"
-#include "idp.h"
-#include "idp_var.h"
-#include "ns_error.h"
-#include "sp.h"
-#include "spidp.h"
-#include "spp_timer.h"
-#include "spp_var.h"
-#include "spp_debug.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/tcp_fsm.h>
+
+#include <netns/ns.h>
+#include <netns/ns_pcb.h>
+#include <netns/idp.h>
+#include <netns/idp_var.h>
+#include <netns/ns_error.h>
+#include <netns/sp.h>
+#include <netns/spidp.h>
+#include <netns/spp_timer.h>
+#include <netns/spp_var.h>
+#include <netns/spp_debug.h>
 
 /*
  * SP protocol implementation.
 
 /*
  * SP protocol implementation.
@@ -55,12 +70,12 @@ int traceallspps = 0;
 extern int sppconsdebug;
 int spp_hardnosed;
 int spp_use_delack = 0;
 extern int sppconsdebug;
 int spp_hardnosed;
 int spp_use_delack = 0;
+u_short spp_newchecks[50];
 
 /*ARGSUSED*/
 
 /*ARGSUSED*/
-spp_input(m, nsp, ifp)
+spp_input(m, nsp)
        register struct mbuf *m;
        register struct nspcb *nsp;
        register struct mbuf *m;
        register struct nspcb *nsp;
-       struct ifnet *ifp;
 {
        register struct sppcb *cb;
        register struct spidp *si = mtod(m, struct spidp *);
 {
        register struct sppcb *cb;
        register struct spidp *si = mtod(m, struct spidp *);
@@ -97,7 +112,7 @@ spp_input(m, nsp, ifp)
        if (so->so_options & SO_ACCEPTCONN) {
                struct sppcb *ocb = cb;
 
        if (so->so_options & SO_ACCEPTCONN) {
                struct sppcb *ocb = cb;
 
-               so = sonewconn(so);
+               so = sonewconn(so, 0);
                if (so == 0) {
                        goto drop;
                }
                if (so == 0) {
                        goto drop;
                }
@@ -118,6 +133,7 @@ spp_input(m, nsp, ifp)
                cb = nstosppcb(nsp);
                cb->s_mtu = ocb->s_mtu;         /* preserve sockopts */
                cb->s_flags = ocb->s_flags;     /* preserve sockopts */
                cb = nstosppcb(nsp);
                cb->s_mtu = ocb->s_mtu;         /* preserve sockopts */
                cb->s_flags = ocb->s_flags;     /* preserve sockopts */
+               cb->s_flags2 = ocb->s_flags2;   /* preserve sockopts */
                cb->s_state = TCPS_LISTEN;
        }
 
                cb->s_state = TCPS_LISTEN;
        }
 
@@ -149,6 +165,7 @@ spp_input(m, nsp, ifp)
                        goto drop;
                am->m_len = sizeof (struct sockaddr_ns);
                sns = mtod(am, struct sockaddr_ns *);
                        goto drop;
                am->m_len = sizeof (struct sockaddr_ns);
                sns = mtod(am, struct sockaddr_ns *);
+               sns->sns_len = sizeof(*sns);
                sns->sns_family = AF_NS;
                sns->sns_addr = si->si_sna;
                laddr = nsp->nsp_laddr;
                sns->sns_family = AF_NS;
                sns->sns_addr = si->si_sna;
                laddr = nsp->nsp_laddr;
@@ -232,7 +249,8 @@ spp_input(m, nsp, ifp)
                spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0);
 
        m->m_len -= sizeof (struct idp);
                spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0);
 
        m->m_len -= sizeof (struct idp);
-       m->m_off += sizeof (struct idp);
+       m->m_pkthdr.len -= sizeof (struct idp);
+       m->m_data += sizeof (struct idp);
 
        if (spp_reass(cb, si)) {
                (void) m_freem(m);
 
        if (spp_reass(cb, si)) {
                (void) m_freem(m);
@@ -380,8 +398,8 @@ register struct spidp *si;
         */
        incr = CUNIT;
        if (cb->s_cwnd > cb->s_ssthresh)
         */
        incr = CUNIT;
        if (cb->s_cwnd > cb->s_ssthresh)
-               incr = MAX(incr * incr / cb->s_cwnd, 1);
-       cb->s_cwnd = MIN(cb->s_cwnd + incr, cb->s_cwmx);
+               incr = max(incr * incr / cb->s_cwnd, 1);
+       cb->s_cwnd = min(cb->s_cwnd + incr, cb->s_cwmx);
        /*
         * Trim Acked data from output queue.
         */
        /*
         * Trim Acked data from output queue.
         */
@@ -391,8 +409,7 @@ register struct spidp *si;
                else
                        break;
        }
                else
                        break;
        }
-       if ((so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel)
-                sowwakeup(so);
+       sowwakeup(so);
        cb->s_rack = si->si_ack;
 update_window:
        if (SSEQ_LT(cb->s_snxt, cb->s_rack))
        cb->s_rack = si->si_ack;
 update_window:
        if (SSEQ_LT(cb->s_snxt, cb->s_rack))
@@ -503,12 +520,51 @@ present:
                        remque(q->si_next);
                        wakeup = 1;
                        sppstat.spps_rcvpack++;
                        remque(q->si_next);
                        wakeup = 1;
                        sppstat.spps_rcvpack++;
+#ifdef SF_NEWCALL
+                       if (cb->s_flags2 & SF_NEWCALL) {
+                               struct sphdr *sp = mtod(m, struct sphdr *);
+                               u_char dt = sp->sp_dt;
+                               spp_newchecks[4]++;
+                               if (dt != cb->s_rhdr.sp_dt) {
+                                       struct mbuf *mm =
+                                          m_getclr(M_DONTWAIT, MT_CONTROL);
+                                       spp_newchecks[0]++;
+                                       if (mm != NULL) {
+                                               u_short *s =
+                                                       mtod(mm, u_short *);
+                                               cb->s_rhdr.sp_dt = dt;
+                                               mm->m_len = 5; /*XXX*/
+                                               s[0] = 5;
+                                               s[1] = 1;
+                                               *(u_char *)(&s[2]) = dt;
+                                               sbappend(&so->so_rcv, mm);
+                                       }
+                               }
+                               if (sp->sp_cc & SP_OB) {
+                                       MCHTYPE(m, MT_OOBDATA);
+                                       spp_newchecks[1]++;
+                                       so->so_oobmark = 0;
+                                       so->so_state &= ~SS_RCVATMARK;
+                               }
+                               if (packetp == 0) {
+                                       m->m_data += SPINC;
+                                       m->m_len -= SPINC;
+                                       m->m_pkthdr.len -= SPINC;
+                               }
+                               if ((sp->sp_cc & SP_EM) || packetp) {
+                                       sbappendrecord(&so->so_rcv, m);
+                                       spp_newchecks[9]++;
+                               } else
+                                       sbappend(&so->so_rcv, m);
+                       } else
+#endif
                        if (packetp) {
                                sbappendrecord(&so->so_rcv, m);
                        } else {
                                cb->s_rhdr = *mtod(m, struct sphdr *);
                        if (packetp) {
                                sbappendrecord(&so->so_rcv, m);
                        } else {
                                cb->s_rhdr = *mtod(m, struct sphdr *);
-                               m->m_off += SPINC;
+                               m->m_data += SPINC;
                                m->m_len -= SPINC;
                                m->m_len -= SPINC;
+                               m->m_pkthdr.len -= SPINC;
                                sbappend(&so->so_rcv, m);
                        }
                  } else
                                sbappend(&so->so_rcv, m);
                        }
                  } else
@@ -649,7 +705,7 @@ spp_output(cb, m0)
        register struct spidp *si = (struct spidp *) 0;
        register struct sockbuf *sb = &so->so_snd;
        int len = 0, win, rcv_win;
        register struct spidp *si = (struct spidp *) 0;
        register struct sockbuf *sb = &so->so_snd;
        int len = 0, win, rcv_win;
-       short span, off;
+       short span, off, recordp = 0;
        u_short alo;
        int error = 0, sendalot;
 #ifdef notdef
        u_short alo;
        int error = 0, sendalot;
 #ifdef notdef
@@ -667,6 +723,8 @@ spp_output(cb, m0)
                for (m = m0; m ; m = m->m_next) {
                        mprev = m;
                        len += m->m_len;
                for (m = m0; m ; m = m->m_next) {
                        mprev = m;
                        len += m->m_len;
+                       if (m->m_flags & M_EOR)
+                               recordp = 1;
                }
                datalen = (cb->s_flags & SF_HO) ?
                                len - sizeof (struct sphdr) : len;
                }
                datalen = (cb->s_flags & SF_HO) ?
                                len - sizeof (struct sphdr) : len;
@@ -679,14 +737,22 @@ spp_output(cb, m0)
 
                                cb->s_cc &= ~SP_EM;
                                while (len > mtu) {
 
                                cb->s_cc &= ~SP_EM;
                                while (len > mtu) {
-                                       m = m_copy(m0, 0, mtu);
-                                       if (m == NULL) {
-                                               error = ENOBUFS;
-                                               goto bad_copy;
+                                       /*
+                                        * Here we are only being called
+                                        * from usrreq(), so it is OK to
+                                        * block.
+                                        */
+                                       m = m_copym(m0, 0, mtu, M_WAIT);
+                                       if (cb->s_flags & SF_NEWCALL) {
+                                           struct mbuf *mm = m;
+                                           spp_newchecks[7]++;
+                                           while (mm) {
+                                               mm->m_flags &= ~M_EOR;
+                                               mm = mm->m_next;
+                                           }
                                        }
                                        error = spp_output(cb, m);
                                        if (error) {
                                        }
                                        error = spp_output(cb, m);
                                        if (error) {
-                                       bad_copy:
                                                cb->s_cc |= oldEM;
                                                m_freem(m0);
                                                return(error);
                                                cb->s_cc |= oldEM;
                                                m_freem(m0);
                                                return(error);
@@ -703,7 +769,7 @@ spp_output(cb, m0)
                 */
                if (len & 1) {
                        m = mprev;
                 */
                if (len & 1) {
                        m = mprev;
-                       if (m->m_len + m->m_off < MMAXOFF)
+                       if (M_TRAILINGSPACE(m) >= 1)
                                m->m_len++;
                        else {
                                struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
                                m->m_len++;
                        else {
                                struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
@@ -713,11 +779,11 @@ spp_output(cb, m0)
                                        return (ENOBUFS);
                                }
                                m1->m_len = 1;
                                        return (ENOBUFS);
                                }
                                m1->m_len = 1;
-                               m1->m_off = MMAXOFF - 1;
+                               *(mtod(m1, u_char *)) = 0;
                                m->m_next = m1;
                        }
                }
                                m->m_next = m1;
                        }
                }
-               m = m_get(M_DONTWAIT, MT_HEADER);
+               m = m_gethdr(M_DONTWAIT, MT_HEADER);
                if (m == 0) {
                        m_freem(m0);
                        return (ENOBUFS);
                if (m == 0) {
                        m_freem(m0);
                        return (ENOBUFS);
@@ -725,9 +791,8 @@ spp_output(cb, m0)
                /*
                 * Fill in mbuf with extended SP header
                 * and addresses and length put into network format.
                /*
                 * Fill in mbuf with extended SP header
                 * and addresses and length put into network format.
-                * Long align so prepended ip headers will work on Gould.
                 */
                 */
-               m->m_off = MMAXOFF - sizeof (struct spidp) - 2;
+               MH_ALIGN(m, sizeof (struct spidp));
                m->m_len = sizeof (struct spidp);
                m->m_next = m0;
                si = mtod(m, struct spidp *);
                m->m_len = sizeof (struct spidp);
                m->m_next = m0;
                si = mtod(m, struct spidp *);
@@ -747,10 +812,14 @@ spp_output(cb, m0)
                        si->si_dt = sh->sp_dt;
                        si->si_cc |= sh->sp_cc & SP_EM;
                        m0->m_len -= sizeof (*sh);
                        si->si_dt = sh->sp_dt;
                        si->si_cc |= sh->sp_cc & SP_EM;
                        m0->m_len -= sizeof (*sh);
-                       m0->m_off += sizeof (*sh);
+                       m0->m_data += sizeof (*sh);
                        len -= sizeof (*sh);
                }
                len += sizeof(*si);
                        len -= sizeof (*sh);
                }
                len += sizeof(*si);
+               if ((cb->s_flags2 & SF_NEWCALL) && recordp) {
+                       si->si_cc  |= SP_EM;
+                       spp_newchecks[8]++;
+               }
                if (cb->s_oobflags & SF_SOOB) {
                        /*
                         * Per jqj@cornell:
                if (cb->s_oobflags & SF_SOOB) {
                        /*
                         * Per jqj@cornell:
@@ -766,6 +835,7 @@ spp_output(cb, m0)
                        }
                }
                si->si_len = htons((u_short)len);
                        }
                }
                si->si_len = htons((u_short)len);
+               m->m_pkthdr.len = ((len - 1) | 1) + 1;
                /*
                 * queue stuff up for output
                 */
                /*
                 * queue stuff up for output
                 */
@@ -778,7 +848,7 @@ spp_output(cb, m0)
 again:
        sendalot = 0;
        off = cb->s_snxt - cb->s_rack;
 again:
        sendalot = 0;
        off = cb->s_snxt - cb->s_rack;
-       win = MIN(cb->s_swnd, (cb->s_cwnd/CUNIT));
+       win = min(cb->s_swnd, (cb->s_cwnd/CUNIT));
 
        /*
         * If in persist timeout with window of 0, send a probe.
 
        /*
         * If in persist timeout with window of 0, send a probe.
@@ -793,7 +863,7 @@ again:
                }
        }
        span = cb->s_seq - cb->s_rack;
                }
        }
        span = cb->s_seq - cb->s_rack;
-       len = MIN(span, win) - off;
+       len = min(span, win) - off;
 
        if (len < 0) {
                /*
 
        if (len < 0) {
                /*
@@ -913,7 +983,6 @@ send:
                if (m == NULL) {
                        return (ENOBUFS);
                }
                if (m == NULL) {
                        return (ENOBUFS);
                }
-               m0 = m;
                si = mtod(m, struct spidp *);
                if (SSEQ_LT(si->si_seq, cb->s_smax))
                        sppstat.spps_sndrexmitpack++;
                si = mtod(m, struct spidp *);
                if (SSEQ_LT(si->si_seq, cb->s_smax))
                        sppstat.spps_sndrexmitpack++;
@@ -927,19 +996,16 @@ send:
                        sppstat.spps_sndprobe++;
                if (cb->s_flags & SF_ACKNOW)
                        sppstat.spps_sndacks++;
                        sppstat.spps_sndprobe++;
                if (cb->s_flags & SF_ACKNOW)
                        sppstat.spps_sndacks++;
-               m = m_get(M_DONTWAIT, MT_HEADER);
-               if (m == 0) {
+               m = m_gethdr(M_DONTWAIT, MT_HEADER);
+               if (m == 0)
                        return (ENOBUFS);
                        return (ENOBUFS);
-               }
                /*
                 * Fill in mbuf with extended SP header
                 * and addresses and length put into network format.
                /*
                 * Fill in mbuf with extended SP header
                 * and addresses and length put into network format.
-                * Allign beginning of packet to long to prepend
-                * ifp's on loopback, or NSIP encaspulation for fussy cpu's.
                 */
                 */
-               m->m_off = MMAXOFF - sizeof (struct spidp) - 2;
+               MH_ALIGN(m, sizeof (struct spidp));
                m->m_len = sizeof (*si);
                m->m_len = sizeof (*si);
-               m->m_next = 0;
+               m->m_pkthdr.len = sizeof (*si);
                si = mtod(m, struct spidp *);
                si->si_i = *cb->s_idp;
                si->si_s = cb->s_shdr;
                si = mtod(m, struct spidp *);
                si->si_i = *cb->s_idp;
                si->si_s = cb->s_shdr;
@@ -1010,7 +1076,7 @@ send:
                        len = ntohs(si->si_len);
                        if (len & 1)
                                len++;
                        len = ntohs(si->si_len);
                        if (len & 1)
                                len++;
-                       si->si_sum = ns_cksum(dtom(si), len);
+                       si->si_sum = ns_cksum(m, len);
                } else
                        si->si_sum = 0xffff;
 
                } else
                        si->si_sum = 0xffff;
 
@@ -1103,25 +1169,21 @@ spp_ctloutput(req, so, level, name, value)
                        mask = SF_HO;
                get_flags:
                        m->m_len = sizeof(short);
                        mask = SF_HO;
                get_flags:
                        m->m_len = sizeof(short);
-                       m->m_off = MMAXOFF - sizeof(short);
                        *mtod(m, short *) = cb->s_flags & mask;
                        break;
 
                case SO_MTU:
                        m->m_len = sizeof(u_short);
                        *mtod(m, short *) = cb->s_flags & mask;
                        break;
 
                case SO_MTU:
                        m->m_len = sizeof(u_short);
-                       m->m_off = MMAXOFF - sizeof(short);
                        *mtod(m, short *) = cb->s_mtu;
                        break;
 
                case SO_LAST_HEADER:
                        m->m_len = sizeof(struct sphdr);
                        *mtod(m, short *) = cb->s_mtu;
                        break;
 
                case SO_LAST_HEADER:
                        m->m_len = sizeof(struct sphdr);
-                       m->m_off = MMAXOFF - sizeof(struct sphdr);
                        *mtod(m, struct sphdr *) = cb->s_rhdr;
                        break;
 
                case SO_DEFAULT_HEADERS:
                        m->m_len = sizeof(struct spidp);
                        *mtod(m, struct sphdr *) = cb->s_rhdr;
                        break;
 
                case SO_DEFAULT_HEADERS:
                        m->m_len = sizeof(struct spidp);
-                       m->m_off = MMAXOFF - sizeof(struct sphdr);
                        *mtod(m, struct sphdr *) = cb->s_shdr;
                        break;
 
                        *mtod(m, struct sphdr *) = cb->s_shdr;
                        break;
 
@@ -1159,6 +1221,19 @@ spp_ctloutput(req, so, level, name, value)
                        cb->s_mtu = *(mtod(*value, u_short *));
                        break;
 
                        cb->s_mtu = *(mtod(*value, u_short *));
                        break;
 
+#ifdef SF_NEWCALL
+               case SO_NEWCALL:
+                       ok = mtod(*value, int *);
+                       if (*ok) {
+                               cb->s_flags2 |= SF_NEWCALL;
+                               spp_newchecks[5]++;
+                       } else {
+                               cb->s_flags2 &= ~SF_NEWCALL;
+                               spp_newchecks[6]++;
+                       }
+                       break;
+#endif
+
                case SO_DEFAULT_HEADERS:
                        {
                                register struct sphdr *sp
                case SO_DEFAULT_HEADERS:
                        {
                                register struct sphdr *sp
@@ -1179,10 +1254,10 @@ spp_ctloutput(req, so, level, name, value)
 }
 
 /*ARGSUSED*/
 }
 
 /*ARGSUSED*/
-spp_usrreq(so, req, m, nam, rights)
+spp_usrreq(so, req, m, nam, controlp)
        struct socket *so;
        int req;
        struct socket *so;
        int req;
-       struct mbuf *m, *nam, *rights;
+       struct mbuf *m, *nam, *controlp;
 {
        struct nspcb *nsp = sotonspcb(so);
        register struct sppcb *cb;
 {
        struct nspcb *nsp = sotonspcb(so);
        register struct sppcb *cb;
@@ -1192,12 +1267,8 @@ spp_usrreq(so, req, m, nam, rights)
        register struct sockbuf *sb;
 
        if (req == PRU_CONTROL)
        register struct sockbuf *sb;
 
        if (req == PRU_CONTROL)
-                return (ns_control(so, (int)m, (caddr_t)nam,
-                       (struct ifnet *)rights));
-       if (rights && rights->m_len) {
-               error = EINVAL;
-               goto release;
-       }
+                return (ns_control(so, m, (caddr_t)nam,
+                       (struct ifnet *)controlp));
        if (nsp == NULL) {
                if (req != PRU_ATTACH) {
                        error = EINVAL;
        if (nsp == NULL) {
                if (req != PRU_ATTACH) {
                        error = EINVAL;
@@ -1248,7 +1319,7 @@ spp_usrreq(so, req, m, nam, rights)
                cb->s_mtu = 576 - sizeof (struct spidp);
                cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu;
                cb->s_ssthresh = cb->s_cwnd;
                cb->s_mtu = 576 - sizeof (struct spidp);
                cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu;
                cb->s_ssthresh = cb->s_cwnd;
-               cb->s_cwmx = sb->sb_mbmax * CUNIT /
+               cb->s_cwmx = sbspace(sb) * CUNIT /
                                (2 * sizeof (struct spidp));
                /* Above is recomputed when connecting to account
                   for changed buffering or mtu's */
                                (2 * sizeof (struct spidp));
                /* Above is recomputed when connecting to account
                   for changed buffering or mtu's */
@@ -1388,6 +1459,16 @@ spp_usrreq(so, req, m, nam, rights)
                cb->s_oobflags |= SF_SOOB;
                /* fall into */
        case PRU_SEND:
                cb->s_oobflags |= SF_SOOB;
                /* fall into */
        case PRU_SEND:
+               if (controlp) {
+                       u_short *p = mtod(controlp, u_short *);
+                       spp_newchecks[2]++;
+                       if ((p[0] == 5) && p[1] == 1) { /* XXXX, for testing */
+                               cb->s_shdr.sp_dt = *(u_char *)(&p[2]);
+                               spp_newchecks[3]++;
+                       }
+                       m_freem(controlp);
+               }
+               controlp = NULL;
                error = spp_output(cb, m);
                m = NULL;
                break;
                error = spp_output(cb, m);
                m = NULL;
                break;
@@ -1417,18 +1498,20 @@ spp_usrreq(so, req, m, nam, rights)
        if (cb && (so->so_options & SO_DEBUG || traceallspps))
                spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req);
 release:
        if (cb && (so->so_options & SO_DEBUG || traceallspps))
                spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req);
 release:
+       if (controlp != NULL)
+               m_freem(controlp);
        if (m != NULL)
                m_freem(m);
        splx(s);
        return (error);
 }
 
        if (m != NULL)
                m_freem(m);
        splx(s);
        return (error);
 }
 
-spp_usrreq_sp(so, req, m, nam, rights)
+spp_usrreq_sp(so, req, m, nam, controlp)
        struct socket *so;
        int req;
        struct socket *so;
        int req;
-       struct mbuf *m, *nam, *rights;
+       struct mbuf *m, *nam, *controlp;
 {
 {
-       int error = spp_usrreq(so, req, m, nam, rights);
+       int error = spp_usrreq(so, req, m, nam, controlp);
 
        if (req == PRU_ATTACH && error == 0) {
                struct nspcb *nsp = sotonspcb(so);
 
        if (req == PRU_ATTACH && error == 0) {
                struct nspcb *nsp = sotonspcb(so);
@@ -1460,8 +1543,8 @@ spp_template(cb)
        cb->s_cwnd = (sbspace(sb) * CUNIT) / cb->s_mtu;
        cb->s_ssthresh = cb->s_cwnd; /* Try to expand fast to full complement
                                        of large packets */
        cb->s_cwnd = (sbspace(sb) * CUNIT) / cb->s_mtu;
        cb->s_ssthresh = cb->s_cwnd; /* Try to expand fast to full complement
                                        of large packets */
-       cb->s_cwmx = (sb->sb_mbmax * CUNIT) / (2 * sizeof(struct spidp));
-       cb->s_cwmx = MAX(cb->s_cwmx, cb->s_cwnd);
+       cb->s_cwmx = (sbspace(sb) * CUNIT) / (2 * sizeof(struct spidp));
+       cb->s_cwmx = max(cb->s_cwmx, cb->s_cwnd);
                /* But allow for lots of little packets as well */
 }
 
                /* But allow for lots of little packets as well */
 }
 
@@ -1598,7 +1681,8 @@ spp_slowtimo()
                        if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
                                (void) spp_usrreq(cb->s_nspcb->nsp_socket,
                                    PRU_SLOWTIMO, (struct mbuf *)0,
                        if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
                                (void) spp_usrreq(cb->s_nspcb->nsp_socket,
                                    PRU_SLOWTIMO, (struct mbuf *)0,
-                                   (struct mbuf *)i, (struct mbuf *)0);
+                                   (struct mbuf *)i, (struct mbuf *)0,
+                                   (struct mbuf *)0);
                                if (ipnxt->nsp_prev != ip)
                                        goto tpgone;
                        }
                                if (ipnxt->nsp_prev != ip)
                                        goto tpgone;
                        }
@@ -1672,7 +1756,7 @@ spp_timers(cb, timer)
                 * See very long discussion in tcp_timer.c about congestion
                 * window and sstrhesh
                 */
                 * See very long discussion in tcp_timer.c about congestion
                 * window and sstrhesh
                 */
-               win = MIN(cb->s_swnd, (cb->s_cwnd/CUNIT)) / 2;
+               win = min(cb->s_swnd, (cb->s_cwnd/CUNIT)) / 2;
                if (win < 2)
                        win = 2;
                cb->s_cwnd = CUNIT;
                if (win < 2)
                        win = 2;
                cb->s_cwnd = CUNIT;
@@ -1717,4 +1801,4 @@ spp_timers(cb, timer)
 #ifndef lint
 int SppcbSize = sizeof (struct sppcb);
 int NspcbSize = sizeof (struct nspcb);
 #ifndef lint
 int SppcbSize = sizeof (struct sppcb);
 int NspcbSize = sizeof (struct nspcb);
-#endif lint
+#endif /* lint */