home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netns / spp_usrreq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  42.1 KB  |  1,805 lines

  1. /*
  2.  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)spp_usrreq.c    7.15 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "malloc.h"
  39. #include "mbuf.h"
  40. #include "protosw.h"
  41. #include "socket.h"
  42. #include "socketvar.h"
  43. #include "errno.h"
  44.  
  45. #include "../net/if.h"
  46. #include "../net/route.h"
  47. #include "../netinet/tcp_fsm.h"
  48.  
  49. #include "ns.h"
  50. #include "ns_pcb.h"
  51. #include "idp.h"
  52. #include "idp_var.h"
  53. #include "ns_error.h"
  54. #include "sp.h"
  55. #include "spidp.h"
  56. #include "spp_timer.h"
  57. #include "spp_var.h"
  58. #include "spp_debug.h"
  59.  
  60. /*
  61.  * SP protocol implementation.
  62.  */
  63. spp_init()
  64. {
  65.  
  66.     spp_iss = 1; /* WRONG !! should fish it out of TODR */
  67. }
  68. struct spidp spp_savesi;
  69. int traceallspps = 0;
  70. extern int sppconsdebug;
  71. int spp_hardnosed;
  72. int spp_use_delack = 0;
  73. u_short spp_newchecks[50];
  74.  
  75. /*ARGSUSED*/
  76. spp_input(m, nsp)
  77.     register struct mbuf *m;
  78.     register struct nspcb *nsp;
  79. {
  80.     register struct sppcb *cb;
  81.     register struct spidp *si = mtod(m, struct spidp *);
  82.     register struct socket *so;
  83.     short ostate;
  84.     int dropsocket = 0;
  85.  
  86.  
  87.     sppstat.spps_rcvtotal++;
  88.     if (nsp == 0) {
  89.         panic("No nspcb in spp_input\n");
  90.         return;
  91.     }
  92.  
  93.     cb = nstosppcb(nsp);
  94.     if (cb == 0) goto bad;
  95.  
  96.     if (m->m_len < sizeof(*si)) {
  97.         if ((m = m_pullup(m, sizeof(*si))) == 0) {
  98.             sppstat.spps_rcvshort++;
  99.             return;
  100.         }
  101.         si = mtod(m, struct spidp *);
  102.     }
  103.     si->si_seq = ntohs(si->si_seq);
  104.     si->si_ack = ntohs(si->si_ack);
  105.     si->si_alo = ntohs(si->si_alo);
  106.  
  107.     so = nsp->nsp_socket;
  108.     if (so->so_options & SO_DEBUG || traceallspps) {
  109.         ostate = cb->s_state;
  110.         spp_savesi = *si;
  111.     }
  112.     if (so->so_options & SO_ACCEPTCONN) {
  113.         struct sppcb *ocb = cb;
  114.  
  115.         so = sonewconn(so, 0);
  116.         if (so == 0) {
  117.             goto drop;
  118.         }
  119.         /*
  120.          * This is ugly, but ....
  121.          *
  122.          * Mark socket as temporary until we're
  123.          * committed to keeping it.  The code at
  124.          * ``drop'' and ``dropwithreset'' check the
  125.          * flag dropsocket to see if the temporary
  126.          * socket created here should be discarded.
  127.          * We mark the socket as discardable until
  128.          * we're committed to it below in TCPS_LISTEN.
  129.          */
  130.         dropsocket++;
  131.         nsp = (struct nspcb *)so->so_pcb;
  132.         nsp->nsp_laddr = si->si_dna;
  133.         cb = nstosppcb(nsp);
  134.         cb->s_mtu = ocb->s_mtu;        /* preserve sockopts */
  135.         cb->s_flags = ocb->s_flags;    /* preserve sockopts */
  136.         cb->s_flags2 = ocb->s_flags2;    /* preserve sockopts */
  137.         cb->s_state = TCPS_LISTEN;
  138.     }
  139.  
  140.     /*
  141.      * Packet received on connection.
  142.      * reset idle time and keep-alive timer;
  143.      */
  144.     cb->s_idle = 0;
  145.     cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
  146.  
  147.     switch (cb->s_state) {
  148.  
  149.     case TCPS_LISTEN:{
  150.         struct mbuf *am;
  151.         register struct sockaddr_ns *sns;
  152.         struct ns_addr laddr;
  153.  
  154.         /*
  155.          * If somebody here was carying on a conversation
  156.          * and went away, and his pen pal thinks he can
  157.          * still talk, we get the misdirected packet.
  158.          */
  159.         if (spp_hardnosed && (si->si_did != 0 || si->si_seq != 0)) {
  160.             spp_istat.gonawy++;
  161.             goto dropwithreset;
  162.         }
  163.         am = m_get(M_DONTWAIT, MT_SONAME);
  164.         if (am == NULL)
  165.             goto drop;
  166.         am->m_len = sizeof (struct sockaddr_ns);
  167.         sns = mtod(am, struct sockaddr_ns *);
  168.         sns->sns_len = sizeof(*sns);
  169.         sns->sns_family = AF_NS;
  170.         sns->sns_addr = si->si_sna;
  171.         laddr = nsp->nsp_laddr;
  172.         if (ns_nullhost(laddr))
  173.             nsp->nsp_laddr = si->si_dna;
  174.         if (ns_pcbconnect(nsp, am)) {
  175.             nsp->nsp_laddr = laddr;
  176.             (void) m_free(am);
  177.             spp_istat.noconn++;
  178.             goto drop;
  179.         }
  180.         (void) m_free(am);
  181.         spp_template(cb);
  182.         dropsocket = 0;        /* committed to socket */
  183.         cb->s_did = si->si_sid;
  184.         cb->s_rack = si->si_ack;
  185.         cb->s_ralo = si->si_alo;
  186. #define THREEWAYSHAKE
  187. #ifdef THREEWAYSHAKE
  188.         cb->s_state = TCPS_SYN_RECEIVED;
  189.         cb->s_force = 1 + SPPT_KEEP;
  190.         sppstat.spps_accepts++;
  191.         cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
  192.         }
  193.         break;
  194.     /*
  195.      * This state means that we have heard a response
  196.      * to our acceptance of their connection
  197.      * It is probably logically unnecessary in this
  198.      * implementation.
  199.      */
  200.      case TCPS_SYN_RECEIVED: {
  201.         if (si->si_did!=cb->s_sid) {
  202.             spp_istat.wrncon++;
  203.             goto drop;
  204.         }
  205. #endif
  206.         nsp->nsp_fport =  si->si_sport;
  207.         cb->s_timer[SPPT_REXMT] = 0;
  208.         cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
  209.         soisconnected(so);
  210.         cb->s_state = TCPS_ESTABLISHED;
  211.         sppstat.spps_accepts++;
  212.         }
  213.         break;
  214.  
  215.     /*
  216.      * This state means that we have gotten a response
  217.      * to our attempt to establish a connection.
  218.      * We fill in the data from the other side,
  219.      * telling us which port to respond to, instead of the well-
  220.      * known one we might have sent to in the first place.
  221.      * We also require that this is a response to our
  222.      * connection id.
  223.      */
  224.     case TCPS_SYN_SENT:
  225.         if (si->si_did!=cb->s_sid) {
  226.             spp_istat.notme++;
  227.             goto drop;
  228.         }
  229.         sppstat.spps_connects++;
  230.         cb->s_did = si->si_sid;
  231.         cb->s_rack = si->si_ack;
  232.         cb->s_ralo = si->si_alo;
  233.         cb->s_dport = nsp->nsp_fport =  si->si_sport;
  234.         cb->s_timer[SPPT_REXMT] = 0;
  235.         cb->s_flags |= SF_ACKNOW;
  236.         soisconnected(so);
  237.         cb->s_state = TCPS_ESTABLISHED;
  238.         /* Use roundtrip time of connection request for initial rtt */
  239.         if (cb->s_rtt) {
  240.             cb->s_srtt = cb->s_rtt << 3;
  241.             cb->s_rttvar = cb->s_rtt << 1;
  242.             SPPT_RANGESET(cb->s_rxtcur,
  243.                 ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1,
  244.                 SPPTV_MIN, SPPTV_REXMTMAX);
  245.                 cb->s_rtt = 0;
  246.         }
  247.     }
  248.     if (so->so_options & SO_DEBUG || traceallspps)
  249.         spp_trace(SA_INPUT, (u_char)ostate, cb, &spp_savesi, 0);
  250.  
  251.     m->m_len -= sizeof (struct idp);
  252.     m->m_pkthdr.len -= sizeof (struct idp);
  253.     m->m_data += sizeof (struct idp);
  254.  
  255.     if (spp_reass(cb, si)) {
  256.         (void) m_freem(m);
  257.     }
  258.     if (cb->s_force || (cb->s_flags & (SF_ACKNOW|SF_WIN|SF_RXT)))
  259.         (void) spp_output(cb, (struct mbuf *)0);
  260.     cb->s_flags &= ~(SF_WIN|SF_RXT);
  261.     return;
  262.  
  263. dropwithreset:
  264.     if (dropsocket)
  265.         (void) soabort(so);
  266.     si->si_seq = ntohs(si->si_seq);
  267.     si->si_ack = ntohs(si->si_ack);
  268.     si->si_alo = ntohs(si->si_alo);
  269.     ns_error(dtom(si), NS_ERR_NOSOCK, 0);
  270.     if (cb->s_nspcb->nsp_socket->so_options & SO_DEBUG || traceallspps)
  271.         spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0);
  272.     return;
  273.  
  274. drop:
  275. bad:
  276.     if (cb == 0 || cb->s_nspcb->nsp_socket->so_options & SO_DEBUG ||
  277.             traceallspps)
  278.         spp_trace(SA_DROP, (u_char)ostate, cb, &spp_savesi, 0);
  279.     m_freem(m);
  280. }
  281.  
  282. int spprexmtthresh = 3;
  283.  
  284. /*
  285.  * This is structurally similar to the tcp reassembly routine
  286.  * but its function is somewhat different:  It merely queues
  287.  * packets up, and suppresses duplicates.
  288.  */
  289. spp_reass(cb, si)
  290. register struct sppcb *cb;
  291. register struct spidp *si;
  292. {
  293.     register struct spidp_q *q;
  294.     register struct mbuf *m;
  295.     register struct socket *so = cb->s_nspcb->nsp_socket;
  296.     char packetp = cb->s_flags & SF_HI;
  297.     int incr;
  298.     char wakeup = 0;
  299.  
  300.     if (si == SI(0))
  301.         goto present;
  302.     /*
  303.      * Update our news from them.
  304.      */
  305.     if (si->si_cc & SP_SA)
  306.         cb->s_flags |= (spp_use_delack ? SF_DELACK : SF_ACKNOW);
  307.     if (SSEQ_GT(si->si_alo, cb->s_ralo))
  308.         cb->s_flags |= SF_WIN;
  309.     if (SSEQ_LEQ(si->si_ack, cb->s_rack)) {
  310.         if ((si->si_cc & SP_SP) && cb->s_rack != (cb->s_smax + 1)) {
  311.             sppstat.spps_rcvdupack++;
  312.             /*
  313.              * If this is a completely duplicate ack
  314.              * and other conditions hold, we assume
  315.              * a packet has been dropped and retransmit
  316.              * it exactly as in tcp_input().
  317.              */
  318.             if (si->si_ack != cb->s_rack ||
  319.                 si->si_alo != cb->s_ralo)
  320.                 cb->s_dupacks = 0;
  321.             else if (++cb->s_dupacks == spprexmtthresh) {
  322.                 u_short onxt = cb->s_snxt;
  323.                 int cwnd = cb->s_cwnd;
  324.  
  325.                 cb->s_snxt = si->si_ack;
  326.                 cb->s_cwnd = CUNIT;
  327.                 cb->s_force = 1 + SPPT_REXMT;
  328.                 (void) spp_output(cb, (struct mbuf *)0);
  329.                 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur;
  330.                 cb->s_rtt = 0;
  331.                 if (cwnd >= 4 * CUNIT)
  332.                     cb->s_cwnd = cwnd / 2;
  333.                 if (SSEQ_GT(onxt, cb->s_snxt))
  334.                     cb->s_snxt = onxt;
  335.                 return (1);
  336.             }
  337.         } else
  338.             cb->s_dupacks = 0;
  339.         goto update_window;
  340.     }
  341.     cb->s_dupacks = 0;
  342.     /*
  343.      * If our correspondent acknowledges data we haven't sent
  344.      * TCP would drop the packet after acking.  We'll be a little
  345.      * more permissive
  346.      */
  347.     if (SSEQ_GT(si->si_ack, (cb->s_smax + 1))) {
  348.         sppstat.spps_rcvacktoomuch++;
  349.         si->si_ack = cb->s_smax + 1;
  350.     }
  351.     sppstat.spps_rcvackpack++;
  352.     /*
  353.      * If transmit timer is running and timed sequence
  354.      * number was acked, update smoothed round trip time.
  355.      * See discussion of algorithm in tcp_input.c
  356.      */
  357.     if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) {
  358.         sppstat.spps_rttupdated++;
  359.         if (cb->s_srtt != 0) {
  360.             register short delta;
  361.             delta = cb->s_rtt - (cb->s_srtt >> 3);
  362.             if ((cb->s_srtt += delta) <= 0)
  363.                 cb->s_srtt = 1;
  364.             if (delta < 0)
  365.                 delta = -delta;
  366.             delta -= (cb->s_rttvar >> 2);
  367.             if ((cb->s_rttvar += delta) <= 0)
  368.                 cb->s_rttvar = 1;
  369.         } else {
  370.             /*
  371.              * No rtt measurement yet
  372.              */
  373.             cb->s_srtt = cb->s_rtt << 3;
  374.             cb->s_rttvar = cb->s_rtt << 1;
  375.         }
  376.         cb->s_rtt = 0;
  377.         cb->s_rxtshift = 0;
  378.         SPPT_RANGESET(cb->s_rxtcur,
  379.             ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1,
  380.             SPPTV_MIN, SPPTV_REXMTMAX);
  381.     }
  382.     /*
  383.      * If all outstanding data is acked, stop retransmit
  384.      * timer and remember to restart (more output or persist).
  385.      * If there is more data to be acked, restart retransmit
  386.      * timer, using current (possibly backed-off) value;
  387.      */
  388.     if (si->si_ack == cb->s_smax + 1) {
  389.         cb->s_timer[SPPT_REXMT] = 0;
  390.         cb->s_flags |= SF_RXT;
  391.     } else if (cb->s_timer[SPPT_PERSIST] == 0)
  392.         cb->s_timer[SPPT_REXMT] = cb->s_rxtcur;
  393.     /*
  394.      * When new data is acked, open the congestion window.
  395.      * If the window gives us less than ssthresh packets
  396.      * in flight, open exponentially (maxseg at a time).
  397.      * Otherwise open linearly (maxseg^2 / cwnd at a time).
  398.      */
  399.     incr = CUNIT;
  400.     if (cb->s_cwnd > cb->s_ssthresh)
  401.         incr = max(incr * incr / cb->s_cwnd, 1);
  402.     cb->s_cwnd = min(cb->s_cwnd + incr, cb->s_cwmx);
  403.     /*
  404.      * Trim Acked data from output queue.
  405.      */
  406.     while ((m = so->so_snd.sb_mb) != NULL) {
  407.         if (SSEQ_LT((mtod(m, struct spidp *))->si_seq, si->si_ack))
  408.             sbdroprecord(&so->so_snd);
  409.         else
  410.             break;
  411.     }
  412.     sowwakeup(so);
  413.     cb->s_rack = si->si_ack;
  414. update_window:
  415.     if (SSEQ_LT(cb->s_snxt, cb->s_rack))
  416.         cb->s_snxt = cb->s_rack;
  417.     if (SSEQ_LT(cb->s_swl1, si->si_seq) || cb->s_swl1 == si->si_seq &&
  418.         (SSEQ_LT(cb->s_swl2, si->si_ack) ||
  419.          cb->s_swl2 == si->si_ack && SSEQ_LT(cb->s_ralo, si->si_alo))) {
  420.         /* keep track of pure window updates */
  421.         if ((si->si_cc & SP_SP) && cb->s_swl2 == si->si_ack
  422.             && SSEQ_LT(cb->s_ralo, si->si_alo)) {
  423.             sppstat.spps_rcvwinupd++;
  424.             sppstat.spps_rcvdupack--;
  425.         }
  426.         cb->s_ralo = si->si_alo;
  427.         cb->s_swl1 = si->si_seq;
  428.         cb->s_swl2 = si->si_ack;
  429.         cb->s_swnd = (1 + si->si_alo - si->si_ack);
  430.         if (cb->s_swnd > cb->s_smxw)
  431.             cb->s_smxw = cb->s_swnd;
  432.         cb->s_flags |= SF_WIN;
  433.     }
  434.     /*
  435.      * If this packet number is higher than that which
  436.      * we have allocated refuse it, unless urgent
  437.      */
  438.     if (SSEQ_GT(si->si_seq, cb->s_alo)) {
  439.         if (si->si_cc & SP_SP) {
  440.             sppstat.spps_rcvwinprobe++;
  441.             return (1);
  442.         } else
  443.             sppstat.spps_rcvpackafterwin++;
  444.         if (si->si_cc & SP_OB) {
  445.             if (SSEQ_GT(si->si_seq, cb->s_alo + 60)) {
  446.                 ns_error(dtom(si), NS_ERR_FULLUP, 0);
  447.                 return (0);
  448.             } /* else queue this packet; */
  449.         } else {
  450.             /*register struct socket *so = cb->s_nspcb->nsp_socket;
  451.             if (so->so_state && SS_NOFDREF) {
  452.                 ns_error(dtom(si), NS_ERR_NOSOCK, 0);
  453.                 (void)spp_close(cb);
  454.             } else
  455.                        would crash system*/
  456.             spp_istat.notyet++;
  457.             ns_error(dtom(si), NS_ERR_FULLUP, 0);
  458.             return (0);
  459.         }
  460.     }
  461.     /*
  462.      * If this is a system packet, we don't need to
  463.      * queue it up, and won't update acknowledge #
  464.      */
  465.     if (si->si_cc & SP_SP) {
  466.         return (1);
  467.     }
  468.     /*
  469.      * We have already seen this packet, so drop.
  470.      */
  471.     if (SSEQ_LT(si->si_seq, cb->s_ack)) {
  472.         spp_istat.bdreas++;
  473.         sppstat.spps_rcvduppack++;
  474.         if (si->si_seq == cb->s_ack - 1)
  475.             spp_istat.lstdup++;
  476.         return (1);
  477.     }
  478.     /*
  479.      * Loop through all packets queued up to insert in
  480.      * appropriate sequence.
  481.      */
  482.     for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) {
  483.         if (si->si_seq == SI(q)->si_seq) {
  484.             sppstat.spps_rcvduppack++;
  485.             return (1);
  486.         }
  487.         if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) {
  488.             sppstat.spps_rcvoopack++;
  489.             break;
  490.         }
  491.     }
  492.     insque(si, q->si_prev);
  493.     /*
  494.      * If this packet is urgent, inform process
  495.      */
  496.     if (si->si_cc & SP_OB) {
  497.         cb->s_iobc = ((char *)si)[1 + sizeof(*si)];
  498.         sohasoutofband(so);
  499.         cb->s_oobflags |= SF_IOOB;
  500.     }
  501. present:
  502. #define SPINC sizeof(struct sphdr)
  503.     /*
  504.      * Loop through all packets queued up to update acknowledge
  505.      * number, and present all acknowledged data to user;
  506.      * If in packet interface mode, show packet headers.
  507.      */
  508.     for (q = cb->s_q.si_next; q!=&cb->s_q; q = q->si_next) {
  509.           if (SI(q)->si_seq == cb->s_ack) {
  510.             cb->s_ack++;
  511.             m = dtom(q);
  512.             if (SI(q)->si_cc & SP_OB) {
  513.                 cb->s_oobflags &= ~SF_IOOB;
  514.                 if (so->so_rcv.sb_cc)
  515.                     so->so_oobmark = so->so_rcv.sb_cc;
  516.                 else
  517.                     so->so_state |= SS_RCVATMARK;
  518.             }
  519.             q = q->si_prev;
  520.             remque(q->si_next);
  521.             wakeup = 1;
  522.             sppstat.spps_rcvpack++;
  523. #ifdef SF_NEWCALL
  524.             if (cb->s_flags2 & SF_NEWCALL) {
  525.                 struct sphdr *sp = mtod(m, struct sphdr *);
  526.                 u_char dt = sp->sp_dt;
  527.                 spp_newchecks[4]++;
  528.                 if (dt != cb->s_rhdr.sp_dt) {
  529.                     struct mbuf *mm =
  530.                        m_getclr(M_DONTWAIT, MT_CONTROL);
  531.                     spp_newchecks[0]++;
  532.                     if (mm != NULL) {
  533.                         u_short *s =
  534.                             mtod(mm, u_short *);
  535.                         cb->s_rhdr.sp_dt = dt;
  536.                         mm->m_len = 5; /*XXX*/
  537.                         s[0] = 5;
  538.                         s[1] = 1;
  539.                         *(u_char *)(&s[2]) = dt;
  540.                         sbappend(&so->so_rcv, mm);
  541.                     }
  542.                 }
  543.                 if (sp->sp_cc & SP_OB) {
  544.                     MCHTYPE(m, MT_OOBDATA);
  545.                     spp_newchecks[1]++;
  546.                     so->so_oobmark = 0;
  547.                     so->so_state &= ~SS_RCVATMARK;
  548.                 }
  549.                 if (packetp == 0) {
  550.                     m->m_data += SPINC;
  551.                     m->m_len -= SPINC;
  552.                     m->m_pkthdr.len -= SPINC;
  553.                 }
  554.                 if ((sp->sp_cc & SP_EM) || packetp) {
  555.                     sbappendrecord(&so->so_rcv, m);
  556.                     spp_newchecks[9]++;
  557.                 } else
  558.                     sbappend(&so->so_rcv, m);
  559.             } else
  560. #endif
  561.             if (packetp) {
  562.                 sbappendrecord(&so->so_rcv, m);
  563.             } else {
  564.                 cb->s_rhdr = *mtod(m, struct sphdr *);
  565.                 m->m_data += SPINC;
  566.                 m->m_len -= SPINC;
  567.                 m->m_pkthdr.len -= SPINC;
  568.                 sbappend(&so->so_rcv, m);
  569.             }
  570.           } else
  571.             break;
  572.     }
  573.     if (wakeup) sorwakeup(so);
  574.     return (0);
  575. }
  576.  
  577. spp_ctlinput(cmd, arg)
  578.     int cmd;
  579.     caddr_t arg;
  580. {
  581.     struct ns_addr *na;
  582.     extern u_char nsctlerrmap[];
  583.     extern spp_abort(), spp_quench();
  584.     extern struct nspcb *idp_drop();
  585.     struct ns_errp *errp;
  586.     struct nspcb *nsp;
  587.     struct sockaddr_ns *sns;
  588.     int type;
  589.  
  590.     if (cmd < 0 || cmd > PRC_NCMDS)
  591.         return;
  592.     type = NS_ERR_UNREACH_HOST;
  593.  
  594.     switch (cmd) {
  595.  
  596.     case PRC_ROUTEDEAD:
  597.         return;
  598.  
  599.     case PRC_IFDOWN:
  600.     case PRC_HOSTDEAD:
  601.     case PRC_HOSTUNREACH:
  602.         sns = (struct sockaddr_ns *)arg;
  603.         if (sns->sns_family != AF_NS)
  604.             return;
  605.         na = &sns->sns_addr;
  606.         break;
  607.  
  608.     default:
  609.         errp = (struct ns_errp *)arg;
  610.         na = &errp->ns_err_idp.idp_dna;
  611.         type = errp->ns_err_num;
  612.         type = ntohs((u_short)type);
  613.     }
  614.     switch (type) {
  615.  
  616.     case NS_ERR_UNREACH_HOST:
  617.         ns_pcbnotify(na, (int)nsctlerrmap[cmd], spp_abort, (long) 0);
  618.         break;
  619.  
  620.     case NS_ERR_TOO_BIG:
  621.     case NS_ERR_NOSOCK:
  622.         nsp = ns_pcblookup(na, errp->ns_err_idp.idp_sna.x_port,
  623.             NS_WILDCARD);
  624.         if (nsp) {
  625.             if(nsp->nsp_pcb)
  626.                 (void) spp_drop((struct sppcb *)nsp->nsp_pcb,
  627.                         (int)nsctlerrmap[cmd]);
  628.             else
  629.                 (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
  630.         }
  631.         break;
  632.  
  633.     case NS_ERR_FULLUP:
  634.         ns_pcbnotify(na, 0, spp_quench, (long) 0);
  635.     }
  636. }
  637. /*
  638.  * When a source quench is received, close congestion window
  639.  * to one packet.  We will gradually open it again as we proceed.
  640.  */
  641. spp_quench(nsp)
  642.     struct nspcb *nsp;
  643. {
  644.     struct sppcb *cb = nstosppcb(nsp);
  645.  
  646.     if (cb)
  647.         cb->s_cwnd = CUNIT;
  648. }
  649.  
  650. #ifdef notdef
  651. int
  652. spp_fixmtu(nsp)
  653. register struct nspcb *nsp;
  654. {
  655.     register struct sppcb *cb = (struct sppcb *)(nsp->nsp_pcb);
  656.     register struct mbuf *m;
  657.     register struct spidp *si;
  658.     struct ns_errp *ep;
  659.     struct sockbuf *sb;
  660.     int badseq, len;
  661.     struct mbuf *firstbad, *m0;
  662.  
  663.     if (cb) {
  664.         /* 
  665.          * The notification that we have sent
  666.          * too much is bad news -- we will
  667.          * have to go through queued up so far
  668.          * splitting ones which are too big and
  669.          * reassigning sequence numbers and checksums.
  670.          * we should then retransmit all packets from
  671.          * one above the offending packet to the last one
  672.          * we had sent (or our allocation)
  673.          * then the offending one so that the any queued
  674.          * data at our destination will be discarded.
  675.          */
  676.          ep = (struct ns_errp *)nsp->nsp_notify_param;
  677.          sb = &nsp->nsp_socket->so_snd;
  678.          cb->s_mtu = ep->ns_err_param;
  679.          badseq = SI(&ep->ns_err_idp)->si_seq;
  680.          for (m = sb->sb_mb; m; m = m->m_act) {
  681.             si = mtod(m, struct spidp *);
  682.             if (si->si_seq == badseq)
  683.                 break;
  684.          }
  685.          if (m == 0) return;
  686.          firstbad = m;
  687.          /*for (;;) {*/
  688.             /* calculate length */
  689.             for (m0 = m, len = 0; m ; m = m->m_next)
  690.                 len += m->m_len;
  691.             if (len > cb->s_mtu) {
  692.             }
  693.         /* FINISH THIS
  694.         } */
  695.     }
  696. }
  697. #endif
  698.  
  699. spp_output(cb, m0)
  700.     register struct sppcb *cb;
  701.     struct mbuf *m0;
  702. {
  703.     struct socket *so = cb->s_nspcb->nsp_socket;
  704.     register struct mbuf *m;
  705.     register struct spidp *si = (struct spidp *) 0;
  706.     register struct sockbuf *sb = &so->so_snd;
  707.     int len = 0, win, rcv_win;
  708.     short span, off, recordp = 0;
  709.     u_short alo;
  710.     int error = 0, sendalot;
  711. #ifdef notdef
  712.     int idle;
  713. #endif
  714.     struct mbuf *mprev;
  715.     extern int idpcksum;
  716.  
  717.     if (m0) {
  718.         int mtu = cb->s_mtu;
  719.         int datalen;
  720.         /*
  721.          * Make sure that packet isn't too big.
  722.          */
  723.         for (m = m0; m ; m = m->m_next) {
  724.             mprev = m;
  725.             len += m->m_len;
  726.             if (m->m_flags & M_EOR)
  727.                 recordp = 1;
  728.         }
  729.         datalen = (cb->s_flags & SF_HO) ?
  730.                 len - sizeof (struct sphdr) : len;
  731.         if (datalen > mtu) {
  732.             if (cb->s_flags & SF_PI) {
  733.                 m_freem(m0);
  734.                 return (EMSGSIZE);
  735.             } else {
  736.                 int oldEM = cb->s_cc & SP_EM;
  737.  
  738.                 cb->s_cc &= ~SP_EM;
  739.                 while (len > mtu) {
  740.                     /*
  741.                      * Here we are only being called
  742.                      * from usrreq(), so it is OK to
  743.                      * block.
  744.                      */
  745.                     m = m_copym(m0, 0, mtu, M_WAIT);
  746.                     if (cb->s_flags & SF_NEWCALL) {
  747.                         struct mbuf *mm = m;
  748.                         spp_newchecks[7]++;
  749.                         while (mm) {
  750.                         mm->m_flags &= ~M_EOR;
  751.                         mm = mm->m_next;
  752.                         }
  753.                     }
  754.                     error = spp_output(cb, m);
  755.                     if (error) {
  756.                         cb->s_cc |= oldEM;
  757.                         m_freem(m0);
  758.                         return(error);
  759.                     }
  760.                     m_adj(m0, mtu);
  761.                     len -= mtu;
  762.                 }
  763.                 cb->s_cc |= oldEM;
  764.             }
  765.         }
  766.         /*
  767.          * Force length even, by adding a "garbage byte" if
  768.          * necessary.
  769.          */
  770.         if (len & 1) {
  771.             m = mprev;
  772.             if (M_TRAILINGSPACE(m) >= 1)
  773.                 m->m_len++;
  774.             else {
  775.                 struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
  776.  
  777.                 if (m1 == 0) {
  778.                     m_freem(m0);
  779.                     return (ENOBUFS);
  780.                 }
  781.                 m1->m_len = 1;
  782.                 *(mtod(m1, u_char *)) = 0;
  783.                 m->m_next = m1;
  784.             }
  785.         }
  786.         m = m_gethdr(M_DONTWAIT, MT_HEADER);
  787.         if (m == 0) {
  788.             m_freem(m0);
  789.             return (ENOBUFS);
  790.         }
  791.         /*
  792.          * Fill in mbuf with extended SP header
  793.          * and addresses and length put into network format.
  794.          */
  795.         MH_ALIGN(m, sizeof (struct spidp));
  796.         m->m_len = sizeof (struct spidp);
  797.         m->m_next = m0;
  798.         si = mtod(m, struct spidp *);
  799.         si->si_i = *cb->s_idp;
  800.         si->si_s = cb->s_shdr;
  801.         if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) {
  802.             register struct sphdr *sh;
  803.             if (m0->m_len < sizeof (*sh)) {
  804.                 if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) {
  805.                     (void) m_free(m);
  806.                     m_freem(m0);
  807.                     return (EINVAL);
  808.                 }
  809.                 m->m_next = m0;
  810.             }
  811.             sh = mtod(m0, struct sphdr *);
  812.             si->si_dt = sh->sp_dt;
  813.             si->si_cc |= sh->sp_cc & SP_EM;
  814.             m0->m_len -= sizeof (*sh);
  815.             m0->m_data += sizeof (*sh);
  816.             len -= sizeof (*sh);
  817.         }
  818.         len += sizeof(*si);
  819.         if ((cb->s_flags2 & SF_NEWCALL) && recordp) {
  820.             si->si_cc  |= SP_EM;
  821.             spp_newchecks[8]++;
  822.         }
  823.         if (cb->s_oobflags & SF_SOOB) {
  824.             /*
  825.              * Per jqj@cornell:
  826.              * make sure OB packets convey exactly 1 byte.
  827.              * If the packet is 1 byte or larger, we
  828.              * have already guaranted there to be at least
  829.              * one garbage byte for the checksum, and
  830.              * extra bytes shouldn't hurt!
  831.              */
  832.             if (len > sizeof(*si)) {
  833.                 si->si_cc |= SP_OB;
  834.                 len = (1 + sizeof(*si));
  835.             }
  836.         }
  837.         si->si_len = htons((u_short)len);
  838.         m->m_pkthdr.len = ((len - 1) | 1) + 1;
  839.         /*
  840.          * queue stuff up for output
  841.          */
  842.         sbappendrecord(sb, m);
  843.         cb->s_seq++;
  844.     }
  845. #ifdef notdef
  846.     idle = (cb->s_smax == (cb->s_rack - 1));
  847. #endif
  848. again:
  849.     sendalot = 0;
  850.     off = cb->s_snxt - cb->s_rack;
  851.     win = min(cb->s_swnd, (cb->s_cwnd/CUNIT));
  852.  
  853.     /*
  854.      * If in persist timeout with window of 0, send a probe.
  855.      * Otherwise, if window is small but nonzero
  856.      * and timer expired, send what we can and go into
  857.      * transmit state.
  858.      */
  859.     if (cb->s_force == 1 + SPPT_PERSIST) {
  860.         if (win != 0) {
  861.             cb->s_timer[SPPT_PERSIST] = 0;
  862.             cb->s_rxtshift = 0;
  863.         }
  864.     }
  865.     span = cb->s_seq - cb->s_rack;
  866.     len = min(span, win) - off;
  867.  
  868.     if (len < 0) {
  869.         /*
  870.          * Window shrank after we went into it.
  871.          * If window shrank to 0, cancel pending
  872.          * restransmission and pull s_snxt back
  873.          * to (closed) window.  We will enter persist
  874.          * state below.  If the widndow didn't close completely,
  875.          * just wait for an ACK.
  876.          */
  877.         len = 0;
  878.         if (win == 0) {
  879.             cb->s_timer[SPPT_REXMT] = 0;
  880.             cb->s_snxt = cb->s_rack;
  881.         }
  882.     }
  883.     if (len > 1)
  884.         sendalot = 1;
  885.     rcv_win = sbspace(&so->so_rcv);
  886.  
  887.     /*
  888.      * Send if we owe peer an ACK.
  889.      */
  890.     if (cb->s_oobflags & SF_SOOB) {
  891.         /*
  892.          * must transmit this out of band packet
  893.          */
  894.         cb->s_oobflags &= ~ SF_SOOB;
  895.         sendalot = 1;
  896.         sppstat.spps_sndurg++;
  897.         goto found;
  898.     }
  899.     if (cb->s_flags & SF_ACKNOW)
  900.         goto send;
  901.     if (cb->s_state < TCPS_ESTABLISHED)
  902.         goto send;
  903.     /*
  904.      * Silly window can't happen in spp.
  905.      * Code from tcp deleted.
  906.      */
  907.     if (len)
  908.         goto send;
  909.     /*
  910.      * Compare available window to amount of window
  911.      * known to peer (as advertised window less
  912.      * next expected input.)  If the difference is at least two
  913.      * packets or at least 35% of the mximum possible window,
  914.      * then want to send a window update to peer.
  915.      */
  916.     if (rcv_win > 0) {
  917.         u_short delta =  1 + cb->s_alo - cb->s_ack;
  918.         int adv = rcv_win - (delta * cb->s_mtu);
  919.         
  920.         if ((so->so_rcv.sb_cc == 0 && adv >= (2 * cb->s_mtu)) ||
  921.             (100 * adv / so->so_rcv.sb_hiwat >= 35)) {
  922.             sppstat.spps_sndwinup++;
  923.             cb->s_flags |= SF_ACKNOW;
  924.             goto send;
  925.         }
  926.  
  927.     }
  928.     /*
  929.      * Many comments from tcp_output.c are appropriate here
  930.      * including . . .
  931.      * If send window is too small, there is data to transmit, and no
  932.      * retransmit or persist is pending, then go to persist state.
  933.      * If nothing happens soon, send when timer expires:
  934.      * if window is nonzero, transmit what we can,
  935.      * otherwise send a probe.
  936.      */
  937.     if (so->so_snd.sb_cc && cb->s_timer[SPPT_REXMT] == 0 &&
  938.         cb->s_timer[SPPT_PERSIST] == 0) {
  939.             cb->s_rxtshift = 0;
  940.             spp_setpersist(cb);
  941.     }
  942.     /*
  943.      * No reason to send a packet, just return.
  944.      */
  945.     cb->s_outx = 1;
  946.     return (0);
  947.  
  948. send:
  949.     /*
  950.      * Find requested packet.
  951.      */
  952.     si = 0;
  953.     if (len > 0) {
  954.         cb->s_want = cb->s_snxt;
  955.         for (m = sb->sb_mb; m; m = m->m_act) {
  956.             si = mtod(m, struct spidp *);
  957.             if (SSEQ_LEQ(cb->s_snxt, si->si_seq))
  958.                 break;
  959.         }
  960.     found:
  961.         if (si) {
  962.             if (si->si_seq == cb->s_snxt)
  963.                     cb->s_snxt++;
  964.                 else
  965.                     sppstat.spps_sndvoid++, si = 0;
  966.         }
  967.     }
  968.     /*
  969.      * update window
  970.      */
  971.     if (rcv_win < 0)
  972.         rcv_win = 0;
  973.     alo = cb->s_ack - 1 + (rcv_win / ((short)cb->s_mtu));
  974.     if (SSEQ_LT(alo, cb->s_alo)) 
  975.         alo = cb->s_alo;
  976.  
  977.     if (si) {
  978.         /*
  979.          * must make a copy of this packet for
  980.          * idp_output to monkey with
  981.          */
  982.         m = m_copy(dtom(si), 0, (int)M_COPYALL);
  983.         if (m == NULL) {
  984.             return (ENOBUFS);
  985.         }
  986.         si = mtod(m, struct spidp *);
  987.         if (SSEQ_LT(si->si_seq, cb->s_smax))
  988.             sppstat.spps_sndrexmitpack++;
  989.         else
  990.             sppstat.spps_sndpack++;
  991.     } else if (cb->s_force || cb->s_flags & SF_ACKNOW) {
  992.         /*
  993.          * Must send an acknowledgement or a probe
  994.          */
  995.         if (cb->s_force)
  996.             sppstat.spps_sndprobe++;
  997.         if (cb->s_flags & SF_ACKNOW)
  998.             sppstat.spps_sndacks++;
  999.         m = m_gethdr(M_DONTWAIT, MT_HEADER);
  1000.         if (m == 0)
  1001.             return (ENOBUFS);
  1002.         /*
  1003.          * Fill in mbuf with extended SP header
  1004.          * and addresses and length put into network format.
  1005.          */
  1006.         MH_ALIGN(m, sizeof (struct spidp));
  1007.         m->m_len = sizeof (*si);
  1008.         m->m_pkthdr.len = sizeof (*si);
  1009.         si = mtod(m, struct spidp *);
  1010.         si->si_i = *cb->s_idp;
  1011.         si->si_s = cb->s_shdr;
  1012.         si->si_seq = cb->s_smax + 1;
  1013.         si->si_len = htons(sizeof (*si));
  1014.         si->si_cc |= SP_SP;
  1015.     } else {
  1016.         cb->s_outx = 3;
  1017.         if (so->so_options & SO_DEBUG || traceallspps)
  1018.             spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
  1019.         return (0);
  1020.     }
  1021.     /*
  1022.      * Stuff checksum and output datagram.
  1023.      */
  1024.     if ((si->si_cc & SP_SP) == 0) {
  1025.         if (cb->s_force != (1 + SPPT_PERSIST) ||
  1026.             cb->s_timer[SPPT_PERSIST] == 0) {
  1027.             /*
  1028.              * If this is a new packet and we are not currently 
  1029.              * timing anything, time this one.
  1030.              */
  1031.             if (SSEQ_LT(cb->s_smax, si->si_seq)) {
  1032.                 cb->s_smax = si->si_seq;
  1033.                 if (cb->s_rtt == 0) {
  1034.                     sppstat.spps_segstimed++;
  1035.                     cb->s_rtseq = si->si_seq;
  1036.                     cb->s_rtt = 1;
  1037.                 }
  1038.             }
  1039.             /*
  1040.              * Set rexmt timer if not currently set,
  1041.              * Initial value for retransmit timer is smoothed
  1042.              * round-trip time + 2 * round-trip time variance.
  1043.              * Initialize shift counter which is used for backoff
  1044.              * of retransmit time.
  1045.              */
  1046.             if (cb->s_timer[SPPT_REXMT] == 0 &&
  1047.                 cb->s_snxt != cb->s_rack) {
  1048.                 cb->s_timer[SPPT_REXMT] = cb->s_rxtcur;
  1049.                 if (cb->s_timer[SPPT_PERSIST]) {
  1050.                     cb->s_timer[SPPT_PERSIST] = 0;
  1051.                     cb->s_rxtshift = 0;
  1052.                 }
  1053.             }
  1054.         } else if (SSEQ_LT(cb->s_smax, si->si_seq)) {
  1055.             cb->s_smax = si->si_seq;
  1056.         }
  1057.     } else if (cb->s_state < TCPS_ESTABLISHED) {
  1058.         if (cb->s_rtt == 0)
  1059.             cb->s_rtt = 1; /* Time initial handshake */
  1060.         if (cb->s_timer[SPPT_REXMT] == 0)
  1061.             cb->s_timer[SPPT_REXMT] = cb->s_rxtcur;
  1062.     }
  1063.     {
  1064.         /*
  1065.          * Do not request acks when we ack their data packets or
  1066.          * when we do a gratuitous window update.
  1067.          */
  1068.         if (((si->si_cc & SP_SP) == 0) || cb->s_force)
  1069.                 si->si_cc |= SP_SA;
  1070.         si->si_seq = htons(si->si_seq);
  1071.         si->si_alo = htons(alo);
  1072.         si->si_ack = htons(cb->s_ack);
  1073.  
  1074.         if (idpcksum) {
  1075.             si->si_sum = 0;
  1076.             len = ntohs(si->si_len);
  1077.             if (len & 1)
  1078.                 len++;
  1079.             si->si_sum = ns_cksum(m, len);
  1080.         } else
  1081.             si->si_sum = 0xffff;
  1082.  
  1083.         cb->s_outx = 4;
  1084.         if (so->so_options & SO_DEBUG || traceallspps)
  1085.             spp_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
  1086.  
  1087.         if (so->so_options & SO_DONTROUTE)
  1088.             error = ns_output(m, (struct route *)0, NS_ROUTETOIF);
  1089.         else
  1090.             error = ns_output(m, &cb->s_nspcb->nsp_route, 0);
  1091.     }
  1092.     if (error) {
  1093.         return (error);
  1094.     }
  1095.     sppstat.spps_sndtotal++;
  1096.     /*
  1097.      * Data sent (as far as we can tell).
  1098.      * If this advertises a larger window than any other segment,
  1099.      * then remember the size of the advertized window.
  1100.      * Any pending ACK has now been sent.
  1101.      */
  1102.     cb->s_force = 0;
  1103.     cb->s_flags &= ~(SF_ACKNOW|SF_DELACK);
  1104.     if (SSEQ_GT(alo, cb->s_alo))
  1105.         cb->s_alo = alo;
  1106.     if (sendalot)
  1107.         goto again;
  1108.     cb->s_outx = 5;
  1109.     return (0);
  1110. }
  1111.  
  1112. int spp_do_persist_panics = 0;
  1113.  
  1114. spp_setpersist(cb)
  1115.     register struct sppcb *cb;
  1116. {
  1117.     register t = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1;
  1118.     extern int spp_backoff[];
  1119.  
  1120.     if (cb->s_timer[SPPT_REXMT] && spp_do_persist_panics)
  1121.         panic("spp_output REXMT");
  1122.     /*
  1123.      * Start/restart persistance timer.
  1124.      */
  1125.     SPPT_RANGESET(cb->s_timer[SPPT_PERSIST],
  1126.         t*spp_backoff[cb->s_rxtshift],
  1127.         SPPTV_PERSMIN, SPPTV_PERSMAX);
  1128.     if (cb->s_rxtshift < SPP_MAXRXTSHIFT)
  1129.         cb->s_rxtshift++;
  1130. }
  1131. /*ARGSUSED*/
  1132. spp_ctloutput(req, so, level, name, value)
  1133.     int req;
  1134.     struct socket *so;
  1135.     int name;
  1136.     struct mbuf **value;
  1137. {
  1138.     register struct mbuf *m;
  1139.     struct nspcb *nsp = sotonspcb(so);
  1140.     register struct sppcb *cb;
  1141.     int mask, error = 0;
  1142.  
  1143.     if (level != NSPROTO_SPP) {
  1144.         /* This will have to be changed when we do more general
  1145.            stacking of protocols */
  1146.         return (idp_ctloutput(req, so, level, name, value));
  1147.     }
  1148.     if (nsp == NULL) {
  1149.         error = EINVAL;
  1150.         goto release;
  1151.     } else
  1152.         cb = nstosppcb(nsp);
  1153.  
  1154.     switch (req) {
  1155.  
  1156.     case PRCO_GETOPT:
  1157.         if (value == NULL)
  1158.             return (EINVAL);
  1159.         m = m_get(M_DONTWAIT, MT_DATA);
  1160.         if (m == NULL)
  1161.             return (ENOBUFS);
  1162.         switch (name) {
  1163.  
  1164.         case SO_HEADERS_ON_INPUT:
  1165.             mask = SF_HI;
  1166.             goto get_flags;
  1167.  
  1168.         case SO_HEADERS_ON_OUTPUT:
  1169.             mask = SF_HO;
  1170.         get_flags:
  1171.             m->m_len = sizeof(short);
  1172.             *mtod(m, short *) = cb->s_flags & mask;
  1173.             break;
  1174.  
  1175.         case SO_MTU:
  1176.             m->m_len = sizeof(u_short);
  1177.             *mtod(m, short *) = cb->s_mtu;
  1178.             break;
  1179.  
  1180.         case SO_LAST_HEADER:
  1181.             m->m_len = sizeof(struct sphdr);
  1182.             *mtod(m, struct sphdr *) = cb->s_rhdr;
  1183.             break;
  1184.  
  1185.         case SO_DEFAULT_HEADERS:
  1186.             m->m_len = sizeof(struct spidp);
  1187.             *mtod(m, struct sphdr *) = cb->s_shdr;
  1188.             break;
  1189.  
  1190.         default:
  1191.             error = EINVAL;
  1192.         }
  1193.         *value = m;
  1194.         break;
  1195.  
  1196.     case PRCO_SETOPT:
  1197.         if (value == 0 || *value == 0) {
  1198.             error = EINVAL;
  1199.             break;
  1200.         }
  1201.         switch (name) {
  1202.             int *ok;
  1203.  
  1204.         case SO_HEADERS_ON_INPUT:
  1205.             mask = SF_HI;
  1206.             goto set_head;
  1207.  
  1208.         case SO_HEADERS_ON_OUTPUT:
  1209.             mask = SF_HO;
  1210.         set_head:
  1211.             if (cb->s_flags & SF_PI) {
  1212.                 ok = mtod(*value, int *);
  1213.                 if (*ok)
  1214.                     cb->s_flags |= mask;
  1215.                 else
  1216.                     cb->s_flags &= ~mask;
  1217.             } else error = EINVAL;
  1218.             break;
  1219.  
  1220.         case SO_MTU:
  1221.             cb->s_mtu = *(mtod(*value, u_short *));
  1222.             break;
  1223.  
  1224. #ifdef SF_NEWCALL
  1225.         case SO_NEWCALL:
  1226.             ok = mtod(*value, int *);
  1227.             if (*ok) {
  1228.                 cb->s_flags2 |= SF_NEWCALL;
  1229.                 spp_newchecks[5]++;
  1230.             } else {
  1231.                 cb->s_flags2 &= ~SF_NEWCALL;
  1232.                 spp_newchecks[6]++;
  1233.             }
  1234.             break;
  1235. #endif
  1236.  
  1237.         case SO_DEFAULT_HEADERS:
  1238.             {
  1239.                 register struct sphdr *sp
  1240.                         = mtod(*value, struct sphdr *);
  1241.                 cb->s_dt = sp->sp_dt;
  1242.                 cb->s_cc = sp->sp_cc & SP_EM;
  1243.             }
  1244.             break;
  1245.  
  1246.         default:
  1247.             error = EINVAL;
  1248.         }
  1249.         m_freem(*value);
  1250.         break;
  1251.     }
  1252.     release:
  1253.         return (error);
  1254. }
  1255.  
  1256. /*ARGSUSED*/
  1257. spp_usrreq(so, req, m, nam, controlp)
  1258.     struct socket *so;
  1259.     int req;
  1260.     struct mbuf *m, *nam, *controlp;
  1261. {
  1262.     struct nspcb *nsp = sotonspcb(so);
  1263.     register struct sppcb *cb;
  1264.     int s = splnet();
  1265.     int error = 0, ostate;
  1266.     struct mbuf *mm;
  1267.     register struct sockbuf *sb;
  1268.  
  1269.     if (req == PRU_CONTROL)
  1270.                 return (ns_control(so, (int)m, (caddr_t)nam,
  1271.             (struct ifnet *)controlp));
  1272.     if (nsp == NULL) {
  1273.         if (req != PRU_ATTACH) {
  1274.             error = EINVAL;
  1275.             goto release;
  1276.         }
  1277.     } else
  1278.         cb = nstosppcb(nsp);
  1279.  
  1280.     ostate = cb ? cb->s_state : 0;
  1281.  
  1282.     switch (req) {
  1283.  
  1284.     case PRU_ATTACH:
  1285.         if (nsp != NULL) {
  1286.             error = EISCONN;
  1287.             break;
  1288.         }
  1289.         error = ns_pcballoc(so, &nspcb);
  1290.         if (error)
  1291.             break;
  1292.         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  1293.             error = soreserve(so, (u_long) 3072, (u_long) 3072);
  1294.             if (error)
  1295.                 break;
  1296.         }
  1297.         nsp = sotonspcb(so);
  1298.  
  1299.         mm = m_getclr(M_DONTWAIT, MT_PCB);
  1300.         sb = &so->so_snd;
  1301.  
  1302.         if (mm == NULL) {
  1303.             error = ENOBUFS;
  1304.             break;
  1305.         }
  1306.         cb = mtod(mm, struct sppcb *);
  1307.         mm = m_getclr(M_DONTWAIT, MT_HEADER);
  1308.         if (mm == NULL) {
  1309.             (void) m_free(dtom(m));
  1310.             error = ENOBUFS;
  1311.             break;
  1312.         }
  1313.         cb->s_idp = mtod(mm, struct idp *);
  1314.         cb->s_state = TCPS_LISTEN;
  1315.         cb->s_smax = -1;
  1316.         cb->s_swl1 = -1;
  1317.         cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q;
  1318.         cb->s_nspcb = nsp;
  1319.         cb->s_mtu = 576 - sizeof (struct spidp);
  1320.         cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu;
  1321.         cb->s_ssthresh = cb->s_cwnd;
  1322.         cb->s_cwmx = sbspace(sb) * CUNIT /
  1323.                 (2 * sizeof (struct spidp));
  1324.         /* Above is recomputed when connecting to account
  1325.            for changed buffering or mtu's */
  1326.         cb->s_rtt = SPPTV_SRTTBASE;
  1327.         cb->s_rttvar = SPPTV_SRTTDFLT << 2;
  1328.         SPPT_RANGESET(cb->s_rxtcur,
  1329.             ((SPPTV_SRTTBASE >> 2) + (SPPTV_SRTTDFLT << 2)) >> 1,
  1330.             SPPTV_MIN, SPPTV_REXMTMAX);
  1331.         nsp->nsp_pcb = (caddr_t) cb; 
  1332.         break;
  1333.  
  1334.     case PRU_DETACH:
  1335.         if (nsp == NULL) {
  1336.             error = ENOTCONN;
  1337.             break;
  1338.         }
  1339.         if (cb->s_state > TCPS_LISTEN)
  1340.             cb = spp_disconnect(cb);
  1341.         else
  1342.             cb = spp_close(cb);
  1343.         break;
  1344.  
  1345.     case PRU_BIND:
  1346.         error = ns_pcbbind(nsp, nam);
  1347.         break;
  1348.  
  1349.     case PRU_LISTEN:
  1350.         if (nsp->nsp_lport == 0)
  1351.             error = ns_pcbbind(nsp, (struct mbuf *)0);
  1352.         if (error == 0)
  1353.             cb->s_state = TCPS_LISTEN;
  1354.         break;
  1355.  
  1356.     /*
  1357.      * Initiate connection to peer.
  1358.      * Enter SYN_SENT state, and mark socket as connecting.
  1359.      * Start keep-alive timer, setup prototype header,
  1360.      * Send initial system packet requesting connection.
  1361.      */
  1362.     case PRU_CONNECT:
  1363.         if (nsp->nsp_lport == 0) {
  1364.             error = ns_pcbbind(nsp, (struct mbuf *)0);
  1365.             if (error)
  1366.                 break;
  1367.         }
  1368.         error = ns_pcbconnect(nsp, nam);
  1369.         if (error)
  1370.             break;
  1371.         soisconnecting(so);
  1372.         sppstat.spps_connattempt++;
  1373.         cb->s_state = TCPS_SYN_SENT;
  1374.         cb->s_did = 0;
  1375.         spp_template(cb);
  1376.         cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
  1377.         cb->s_force = 1 + SPPTV_KEEP;
  1378.         /*
  1379.          * Other party is required to respond to
  1380.          * the port I send from, but he is not
  1381.          * required to answer from where I am sending to,
  1382.          * so allow wildcarding.
  1383.          * original port I am sending to is still saved in
  1384.          * cb->s_dport.
  1385.          */
  1386.         nsp->nsp_fport = 0;
  1387.         error = spp_output(cb, (struct mbuf *) 0);
  1388.         break;
  1389.  
  1390.     case PRU_CONNECT2:
  1391.         error = EOPNOTSUPP;
  1392.         break;
  1393.  
  1394.     /*
  1395.      * We may decide later to implement connection closing
  1396.      * handshaking at the spp level optionally.
  1397.      * here is the hook to do it:
  1398.      */
  1399.     case PRU_DISCONNECT:
  1400.         cb = spp_disconnect(cb);
  1401.         break;
  1402.  
  1403.     /*
  1404.      * Accept a connection.  Essentially all the work is
  1405.      * done at higher levels; just return the address
  1406.      * of the peer, storing through addr.
  1407.      */
  1408.     case PRU_ACCEPT: {
  1409.         struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
  1410.  
  1411.         nam->m_len = sizeof (struct sockaddr_ns);
  1412.         sns->sns_family = AF_NS;
  1413.         sns->sns_addr = nsp->nsp_faddr;
  1414.         break;
  1415.         }
  1416.  
  1417.     case PRU_SHUTDOWN:
  1418.         socantsendmore(so);
  1419.         cb = spp_usrclosed(cb);
  1420.         if (cb)
  1421.             error = spp_output(cb, (struct mbuf *) 0);
  1422.         break;
  1423.  
  1424.     /*
  1425.      * After a receive, possibly send acknowledgment
  1426.      * updating allocation.
  1427.      */
  1428.     case PRU_RCVD:
  1429.         cb->s_flags |= SF_RVD;
  1430.         (void) spp_output(cb, (struct mbuf *) 0);
  1431.         cb->s_flags &= ~SF_RVD;
  1432.         break;
  1433.  
  1434.     case PRU_ABORT:
  1435.         (void) spp_drop(cb, ECONNABORTED);
  1436.         break;
  1437.  
  1438.     case PRU_SENSE:
  1439.     case PRU_CONTROL:
  1440.         m = NULL;
  1441.         error = EOPNOTSUPP;
  1442.         break;
  1443.  
  1444.     case PRU_RCVOOB:
  1445.         if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
  1446.             (so->so_state & SS_RCVATMARK)) {
  1447.             m->m_len = 1;
  1448.             *mtod(m, caddr_t) = cb->s_iobc;
  1449.             break;
  1450.         }
  1451.         error = EINVAL;
  1452.         break;
  1453.  
  1454.     case PRU_SENDOOB:
  1455.         if (sbspace(&so->so_snd) < -512) {
  1456.             error = ENOBUFS;
  1457.             break;
  1458.         }
  1459.         cb->s_oobflags |= SF_SOOB;
  1460.         /* fall into */
  1461.     case PRU_SEND:
  1462.         if (controlp) {
  1463.             u_short *p = mtod(controlp, u_short *);
  1464.             spp_newchecks[2]++;
  1465.             if ((p[0] == 5) && p[1] == 1) { /* XXXX, for testing */
  1466.                 cb->s_shdr.sp_dt = *(u_char *)(&p[2]);
  1467.                 spp_newchecks[3]++;
  1468.             }
  1469.             m_freem(controlp);
  1470.         }
  1471.         controlp = NULL;
  1472.         error = spp_output(cb, m);
  1473.         m = NULL;
  1474.         break;
  1475.  
  1476.     case PRU_SOCKADDR:
  1477.         ns_setsockaddr(nsp, nam);
  1478.         break;
  1479.  
  1480.     case PRU_PEERADDR:
  1481.         ns_setpeeraddr(nsp, nam);
  1482.         break;
  1483.  
  1484.     case PRU_SLOWTIMO:
  1485.         cb = spp_timers(cb, (int)nam);
  1486.         req |= ((int)nam) << 8;
  1487.         break;
  1488.  
  1489.     case PRU_FASTTIMO:
  1490.     case PRU_PROTORCV:
  1491.     case PRU_PROTOSEND:
  1492.         error =  EOPNOTSUPP;
  1493.         break;
  1494.  
  1495.     default:
  1496.         panic("sp_usrreq");
  1497.     }
  1498.     if (cb && (so->so_options & SO_DEBUG || traceallspps))
  1499.         spp_trace(SA_USER, (u_char)ostate, cb, (struct spidp *)0, req);
  1500. release:
  1501.     if (controlp != NULL)
  1502.         m_freem(controlp);
  1503.     if (m != NULL)
  1504.         m_freem(m);
  1505.     splx(s);
  1506.     return (error);
  1507. }
  1508.  
  1509. spp_usrreq_sp(so, req, m, nam, controlp)
  1510.     struct socket *so;
  1511.     int req;
  1512.     struct mbuf *m, *nam, *controlp;
  1513. {
  1514.     int error = spp_usrreq(so, req, m, nam, controlp);
  1515.  
  1516.     if (req == PRU_ATTACH && error == 0) {
  1517.         struct nspcb *nsp = sotonspcb(so);
  1518.         ((struct sppcb *)nsp->nsp_pcb)->s_flags |=
  1519.                     (SF_HI | SF_HO | SF_PI);
  1520.     }
  1521.     return (error);
  1522. }
  1523.  
  1524. /*
  1525.  * Create template to be used to send spp packets on a connection.
  1526.  * Called after host entry created, fills
  1527.  * in a skeletal spp header (choosing connection id),
  1528.  * minimizing the amount of work necessary when the connection is used.
  1529.  */
  1530. spp_template(cb)
  1531.     register struct sppcb *cb;
  1532. {
  1533.     register struct nspcb *nsp = cb->s_nspcb;
  1534.     register struct idp *idp = cb->s_idp;
  1535.     register struct sockbuf *sb = &(nsp->nsp_socket->so_snd);
  1536.  
  1537.     idp->idp_pt = NSPROTO_SPP;
  1538.     idp->idp_sna = nsp->nsp_laddr;
  1539.     idp->idp_dna = nsp->nsp_faddr;
  1540.     cb->s_sid = htons(spp_iss);
  1541.     spp_iss += SPP_ISSINCR/2;
  1542.     cb->s_alo = 1;
  1543.     cb->s_cwnd = (sbspace(sb) * CUNIT) / cb->s_mtu;
  1544.     cb->s_ssthresh = cb->s_cwnd; /* Try to expand fast to full complement
  1545.                     of large packets */
  1546.     cb->s_cwmx = (sbspace(sb) * CUNIT) / (2 * sizeof(struct spidp));
  1547.     cb->s_cwmx = max(cb->s_cwmx, cb->s_cwnd);
  1548.         /* But allow for lots of little packets as well */
  1549. }
  1550.  
  1551. /*
  1552.  * Close a SPIP control block:
  1553.  *    discard spp control block itself
  1554.  *    discard ns protocol control block
  1555.  *    wake up any sleepers
  1556.  */
  1557. struct sppcb *
  1558. spp_close(cb)
  1559.     register struct sppcb *cb;
  1560. {
  1561.     register struct spidp_q *s;
  1562.     struct nspcb *nsp = cb->s_nspcb;
  1563.     struct socket *so = nsp->nsp_socket;
  1564.     register struct mbuf *m;
  1565.  
  1566.     s = cb->s_q.si_next;
  1567.     while (s != &(cb->s_q)) {
  1568.         s = s->si_next;
  1569.         m = dtom(s->si_prev);
  1570.         remque(s->si_prev);
  1571.         m_freem(m);
  1572.     }
  1573.     (void) m_free(dtom(cb->s_idp));
  1574.     (void) m_free(dtom(cb));
  1575.     nsp->nsp_pcb = 0;
  1576.     soisdisconnected(so);
  1577.     ns_pcbdetach(nsp);
  1578.     sppstat.spps_closed++;
  1579.     return ((struct sppcb *)0);
  1580. }
  1581. /*
  1582.  *    Someday we may do level 3 handshaking
  1583.  *    to close a connection or send a xerox style error.
  1584.  *    For now, just close.
  1585.  */
  1586. struct sppcb *
  1587. spp_usrclosed(cb)
  1588.     register struct sppcb *cb;
  1589. {
  1590.     return (spp_close(cb));
  1591. }
  1592. struct sppcb *
  1593. spp_disconnect(cb)
  1594.     register struct sppcb *cb;
  1595. {
  1596.     return (spp_close(cb));
  1597. }
  1598. /*
  1599.  * Drop connection, reporting
  1600.  * the specified error.
  1601.  */
  1602. struct sppcb *
  1603. spp_drop(cb, errno)
  1604.     register struct sppcb *cb;
  1605.     int errno;
  1606. {
  1607.     struct socket *so = cb->s_nspcb->nsp_socket;
  1608.  
  1609.     /*
  1610.      * someday, in the xerox world
  1611.      * we will generate error protocol packets
  1612.      * announcing that the socket has gone away.
  1613.      */
  1614.     if (TCPS_HAVERCVDSYN(cb->s_state)) {
  1615.         sppstat.spps_drops++;
  1616.         cb->s_state = TCPS_CLOSED;
  1617.         /*(void) tcp_output(cb);*/
  1618.     } else
  1619.         sppstat.spps_conndrops++;
  1620.     so->so_error = errno;
  1621.     return (spp_close(cb));
  1622. }
  1623.  
  1624. spp_abort(nsp)
  1625.     struct nspcb *nsp;
  1626. {
  1627.  
  1628.     (void) spp_close((struct sppcb *)nsp->nsp_pcb);
  1629. }
  1630.  
  1631. int    spp_backoff[SPP_MAXRXTSHIFT+1] =
  1632.     { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
  1633. /*
  1634.  * Fast timeout routine for processing delayed acks
  1635.  */
  1636. spp_fasttimo()
  1637. {
  1638.     register struct nspcb *nsp;
  1639.     register struct sppcb *cb;
  1640.     int s = splnet();
  1641.  
  1642.     nsp = nspcb.nsp_next;
  1643.     if (nsp)
  1644.     for (; nsp != &nspcb; nsp = nsp->nsp_next)
  1645.         if ((cb = (struct sppcb *)nsp->nsp_pcb) &&
  1646.             (cb->s_flags & SF_DELACK)) {
  1647.             cb->s_flags &= ~SF_DELACK;
  1648.             cb->s_flags |= SF_ACKNOW;
  1649.             sppstat.spps_delack++;
  1650.             (void) spp_output(cb, (struct mbuf *) 0);
  1651.         }
  1652.     splx(s);
  1653. }
  1654.  
  1655. /*
  1656.  * spp protocol timeout routine called every 500 ms.
  1657.  * Updates the timers in all active pcb's and
  1658.  * causes finite state machine actions if timers expire.
  1659.  */
  1660. spp_slowtimo()
  1661. {
  1662.     register struct nspcb *ip, *ipnxt;
  1663.     register struct sppcb *cb;
  1664.     int s = splnet();
  1665.     register int i;
  1666.  
  1667.     /*
  1668.      * Search through tcb's and update active timers.
  1669.      */
  1670.     ip = nspcb.nsp_next;
  1671.     if (ip == 0) {
  1672.         splx(s);
  1673.         return;
  1674.     }
  1675.     while (ip != &nspcb) {
  1676.         cb = nstosppcb(ip);
  1677.         ipnxt = ip->nsp_next;
  1678.         if (cb == 0)
  1679.             goto tpgone;
  1680.         for (i = 0; i < SPPT_NTIMERS; i++) {
  1681.             if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
  1682.                 (void) spp_usrreq(cb->s_nspcb->nsp_socket,
  1683.                     PRU_SLOWTIMO, (struct mbuf *)0,
  1684.                     (struct mbuf *)i, (struct mbuf *)0,
  1685.                     (struct mbuf *)0);
  1686.                 if (ipnxt->nsp_prev != ip)
  1687.                     goto tpgone;
  1688.             }
  1689.         }
  1690.         cb->s_idle++;
  1691.         if (cb->s_rtt)
  1692.             cb->s_rtt++;
  1693. tpgone:
  1694.         ip = ipnxt;
  1695.     }
  1696.     spp_iss += SPP_ISSINCR/PR_SLOWHZ;        /* increment iss */
  1697.     splx(s);
  1698. }
  1699. /*
  1700.  * SPP timer processing.
  1701.  */
  1702. struct sppcb *
  1703. spp_timers(cb, timer)
  1704.     register struct sppcb *cb;
  1705.     int timer;
  1706. {
  1707.     long rexmt;
  1708.     int win;
  1709.  
  1710.     cb->s_force = 1 + timer;
  1711.     switch (timer) {
  1712.  
  1713.     /*
  1714.      * 2 MSL timeout in shutdown went off.  TCP deletes connection
  1715.      * control block.
  1716.      */
  1717.     case SPPT_2MSL:
  1718.         printf("spp: SPPT_2MSL went off for no reason\n");
  1719.         cb->s_timer[timer] = 0;
  1720.         break;
  1721.  
  1722.     /*
  1723.      * Retransmission timer went off.  Message has not
  1724.      * been acked within retransmit interval.  Back off
  1725.      * to a longer retransmit interval and retransmit one packet.
  1726.      */
  1727.     case SPPT_REXMT:
  1728.         if (++cb->s_rxtshift > SPP_MAXRXTSHIFT) {
  1729.             cb->s_rxtshift = SPP_MAXRXTSHIFT;
  1730.             sppstat.spps_timeoutdrop++;
  1731.             cb = spp_drop(cb, ETIMEDOUT);
  1732.             break;
  1733.         }
  1734.         sppstat.spps_rexmttimeo++;
  1735.         rexmt = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1;
  1736.         rexmt *= spp_backoff[cb->s_rxtshift];
  1737.         SPPT_RANGESET(cb->s_rxtcur, rexmt, SPPTV_MIN, SPPTV_REXMTMAX);
  1738.         cb->s_timer[SPPT_REXMT] = cb->s_rxtcur;
  1739.         /*
  1740.          * If we have backed off fairly far, our srtt
  1741.          * estimate is probably bogus.  Clobber it
  1742.          * so we'll take the next rtt measurement as our srtt;
  1743.          * move the current srtt into rttvar to keep the current
  1744.          * retransmit times until then.
  1745.          */
  1746.         if (cb->s_rxtshift > SPP_MAXRXTSHIFT / 4 ) {
  1747.             cb->s_rttvar += (cb->s_srtt >> 2);
  1748.             cb->s_srtt = 0;
  1749.         }
  1750.         cb->s_snxt = cb->s_rack;
  1751.         /*
  1752.          * If timing a packet, stop the timer.
  1753.          */
  1754.         cb->s_rtt = 0;
  1755.         /*
  1756.          * See very long discussion in tcp_timer.c about congestion
  1757.          * window and sstrhesh
  1758.          */
  1759.         win = min(cb->s_swnd, (cb->s_cwnd/CUNIT)) / 2;
  1760.         if (win < 2)
  1761.             win = 2;
  1762.         cb->s_cwnd = CUNIT;
  1763.         cb->s_ssthresh = win * CUNIT;
  1764.         (void) spp_output(cb, (struct mbuf *) 0);
  1765.         break;
  1766.  
  1767.     /*
  1768.      * Persistance timer into zero window.
  1769.      * Force a probe to be sent.
  1770.      */
  1771.     case SPPT_PERSIST:
  1772.         sppstat.spps_persisttimeo++;
  1773.         spp_setpersist(cb);
  1774.         (void) spp_output(cb, (struct mbuf *) 0);
  1775.         break;
  1776.  
  1777.     /*
  1778.      * Keep-alive timer went off; send something
  1779.      * or drop connection if idle for too long.
  1780.      */
  1781.     case SPPT_KEEP:
  1782.         sppstat.spps_keeptimeo++;
  1783.         if (cb->s_state < TCPS_ESTABLISHED)
  1784.             goto dropit;
  1785.         if (cb->s_nspcb->nsp_socket->so_options & SO_KEEPALIVE) {
  1786.                 if (cb->s_idle >= SPPTV_MAXIDLE)
  1787.                 goto dropit;
  1788.             sppstat.spps_keepprobe++;
  1789.             (void) spp_output(cb, (struct mbuf *) 0);
  1790.         } else
  1791.             cb->s_idle = 0;
  1792.         cb->s_timer[SPPT_KEEP] = SPPTV_KEEP;
  1793.         break;
  1794.     dropit:
  1795.         sppstat.spps_keepdrops++;
  1796.         cb = spp_drop(cb, ETIMEDOUT);
  1797.         break;
  1798.     }
  1799.     return (cb);
  1800. }
  1801. #ifndef lint
  1802. int SppcbSize = sizeof (struct sppcb);
  1803. int NspcbSize = sizeof (struct nspcb);
  1804. #endif lint
  1805.