VirtualBox

Changeset 15472 in vbox for trunk/src


Ignore:
Timestamp:
Dec 14, 2008 8:57:47 PM (16 years ago)
Author:
vboxsync
Message:

NAT: readability

Location:
trunk/src/VBox/Devices/Network/slirp
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/if.c

    r14951 r15472  
    1313static void ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
    1414{
    15         ifm->ifs_next = ifmhead->ifs_next;
    16         ifmhead->ifs_next = ifm;
    17         ifm->ifs_prev = ifmhead;
    18         ifm->ifs_next->ifs_prev = ifm;
     15    ifm->ifs_next = ifmhead->ifs_next;
     16    ifmhead->ifs_next = ifm;
     17    ifm->ifs_prev = ifmhead;
     18    ifm->ifs_next->ifs_prev = ifm;
    1919}
    2020
    2121static void ifs_remque(struct mbuf *ifm)
    2222{
    23         ifm->ifs_prev->ifs_next = ifm->ifs_next;
    24         ifm->ifs_next->ifs_prev = ifm->ifs_prev;
     23    ifm->ifs_prev->ifs_next = ifm->ifs_next;
     24    ifm->ifs_next->ifs_prev = ifm->ifs_prev;
    2525}
    2626
     
    2828if_init(PNATState pData)
    2929{
    30         /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
    31         if_maxlinkhdr = 2 + 14 + 40;
    32         if_queued = 0;
    33         if_thresh = 10;
    34         if_mtu = 1500;
    35         if_mru = 1500;
    36         if_comp = IF_AUTOCOMP;
    37         if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
    38         if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
    39         /*      sl_compress_init(&comp_s); */
    40         next_m = &if_batchq;
     30    /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
     31    if_maxlinkhdr = 2 + 14 + 40;
     32    if_queued = 0;
     33    if_thresh = 10;
     34    if_mtu = 1500;
     35    if_mru = 1500;
     36    if_comp = IF_AUTOCOMP;
     37    if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
     38    if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
     39/*  sl_compress_init(&comp_s); */
     40    next_m = &if_batchq;
    4141}
    4242
     
    5757if_output(PNATState pData, struct socket *so, struct mbuf *ifm)
    5858{
    59         struct mbuf *ifq;
    60         int on_fastq = 1;
    61 
    62         DEBUG_CALL("if_output");
    63         DEBUG_ARG("so = %lx", (long)so);
    64         DEBUG_ARG("ifm = %lx", (long)ifm);
    65 
     59    struct mbuf *ifq;
     60    int on_fastq = 1;
     61
     62    DEBUG_CALL("if_output");
     63    DEBUG_ARG("so = %lx", (long)so);
     64    DEBUG_ARG("ifm = %lx", (long)ifm);
     65
     66    /*
     67     * First remove the mbuf from m_usedlist,
     68     * since we're gonna use m_next and m_prev ourselves
     69     * XXX Shouldn't need this, gotta change dtom() etc.
     70     */
     71    if (ifm->m_flags & M_USEDLIST)
     72    {
     73        remque(pData, ifm);
     74        ifm->m_flags &= ~M_USEDLIST;
     75    }
     76
     77    /*
     78     * See if there's already a batchq list for this session.
     79     * This can include an interactive session, which should go on fastq,
     80     * but gets too greedy... hence it'll be downgraded from fastq to batchq.
     81     * We mustn't put this packet back on the fastq (or we'll send it out of order)
     82     * XXX add cache here?
     83     */
     84    for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev)
     85    {
     86        if (so == ifq->ifq_so)
     87        {
     88            /* A match! */
     89            ifm->ifq_so = so;
     90            ifs_insque(ifm, ifq->ifs_prev);
     91            goto diddit;
     92        }
     93    }
     94
     95    /* No match, check which queue to put it on */
     96    if (so && (so->so_iptos & IPTOS_LOWDELAY))
     97    {
     98        ifq = if_fastq.ifq_prev;
     99        on_fastq = 1;
    66100        /*
    67          * First remove the mbuf from m_usedlist,
    68          * since we're gonna use m_next and m_prev ourselves
    69          * XXX Shouldn't need this, gotta change dtom() etc.
     101         * Check if this packet is a part of the last
     102         * packet's session
    70103         */
    71         if (ifm->m_flags & M_USEDLIST) {
    72                 remque(pData, ifm);
    73                 ifm->m_flags &= ~M_USEDLIST;
    74         }
    75 
     104        if (ifq->ifq_so == so)
     105        {
     106            ifm->ifq_so = so;
     107            ifs_insque(ifm, ifq->ifs_prev);
     108            goto diddit;
     109        }
     110    }
     111    else
     112        ifq = if_batchq.ifq_prev;
     113
     114    /* Create a new doubly linked list for this session */
     115    ifm->ifq_so = so;
     116    ifs_init(ifm);
     117    insque(pData, ifm, ifq);
     118
     119diddit:
     120    ++if_queued;
     121
     122    if (so)
     123    {
     124        /* Update *_queued */
     125        so->so_queued++;
     126        so->so_nqueued++;
    76127        /*
    77          * See if there's already a batchq list for this session.
    78          * This can include an interactive session, which should go on fastq,
    79          * but gets too greedy... hence it'll be downgraded from fastq to batchq.
    80          * We mustn't put this packet back on the fastq (or we'll send it out of order)
    81          * XXX add cache here?
     128         * Check if the interactive session should be downgraded to
     129         * the batchq.  A session is downgraded if it has queued 6
     130         * packets without pausing, and at least 3 of those packets
     131         * have been sent over the link
     132         * (XXX These are arbitrary numbers, probably not optimal..)
    82133         */
    83         for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) {
    84                 if (so == ifq->ifq_so) {
    85                         /* A match! */
    86                         ifm->ifq_so = so;
    87                         ifs_insque(ifm, ifq->ifs_prev);
    88                         goto diddit;
    89                 }
    90         }
    91 
    92         /* No match, check which queue to put it on */
    93         if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
    94                 ifq = if_fastq.ifq_prev;
    95                 on_fastq = 1;
    96                 /*
    97                  * Check if this packet is a part of the last
    98                  * packet's session
    99                  */
    100                 if (ifq->ifq_so == so) {
    101                         ifm->ifq_so = so;
    102                         ifs_insque(ifm, ifq->ifs_prev);
    103                         goto diddit;
    104                 }
    105         } else
    106                 ifq = if_batchq.ifq_prev;
    107 
    108         /* Create a new doubly linked list for this session */
    109         ifm->ifq_so = so;
    110         ifs_init(ifm);
    111         insque(pData, ifm, ifq);
    112 
    113 diddit:
    114         ++if_queued;
    115 
    116         if (so) {
    117                 /* Update *_queued */
    118                 so->so_queued++;
    119                 so->so_nqueued++;
    120                 /*
    121                  * Check if the interactive session should be downgraded to
    122                  * the batchq.  A session is downgraded if it has queued 6
    123                  * packets without pausing, and at least 3 of those packets
    124                  * have been sent over the link
    125                  * (XXX These are arbitrary numbers, probably not optimal..)
    126                  */
    127                 if (on_fastq && ((so->so_nqueued >= 6) &&
    128                                  (so->so_nqueued - so->so_queued) >= 3)) {
    129 
    130                         /* Remove from current queue... */
    131                         remque(pData, ifm->ifs_next);
    132 
    133                         /* ...And insert in the new.  That'll teach ya! */
    134                         insque(pData, ifm->ifs_next, &if_batchq);
    135                 }
    136         }
     134        if (on_fastq
     135            && so->so_nqueued >= 6
     136            && (so->so_nqueued - so->so_queued) >= 3)
     137        {
     138            /* Remove from current queue... */
     139            remque(pData, ifm->ifs_next);
     140
     141            /* ...And insert in the new.  That'll teach ya! */
     142            insque(pData, ifm->ifs_next, &if_batchq);
     143        }
     144    }
    137145
    138146#ifndef FULL_BOLT
    139         /*
    140          * This prevents us from malloc()ing too many mbufs
    141          */
    142         if (link_up) {
    143                 /* if_start will check towrite */
    144                 if_start(pData);
    145         }
     147    /*
     148     * This prevents us from malloc()ing too many mbufs
     149     */
     150    if (link_up)
     151    {
     152        /* if_start will check towrite */
     153        if_start(pData);
     154    }
    146155#endif
    147156}
     
    162171if_start(PNATState pData)
    163172{
    164         struct mbuf *ifm, *ifqt;
    165 
    166         DEBUG_CALL("if_start");
    167 
    168         if (if_queued == 0)
    169            return; /* Nothing to do */
    170 
    171  again:
     173    struct mbuf *ifm, *ifqt;
     174
     175    DEBUG_CALL("if_start");
     176
     177    if (!if_queued)
     178        return; /* Nothing to do */
     179
     180    for (;;)
     181    {
    172182        /* check if we can really output */
    173183        if (!slirp_can_output(pData->pvUser))
     
    178188         * If there's something in the fastq, select it immediately
    179189         */
    180         if (if_fastq.ifq_next != &if_fastq) {
    181                 ifm = if_fastq.ifq_next;
    182         } else {
    183                 /* Nothing on fastq, see if next_m is valid */
    184                 if (next_m != &if_batchq)
    185                    ifm = next_m;
    186                 else
    187                    ifm = if_batchq.ifq_next;
    188 
    189                 /* Set which packet to send on next iteration */
    190                 next_m = ifm->ifq_next;
     190        if (if_fastq.ifq_next != &if_fastq)
     191            ifm = if_fastq.ifq_next;
     192        else
     193        {
     194            /* Nothing on fastq, see if next_m is valid */
     195            if (next_m != &if_batchq)
     196                ifm = next_m;
     197            else
     198                ifm = if_batchq.ifq_next;
     199
     200            /* Set which packet to send on next iteration */
     201            next_m = ifm->ifq_next;
    191202        }
    192203        /* Remove it from the queue */
     
    196207
    197208        /* If there are more packets for this session, re-queue them */
    198         if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
    199                 insque(pData, ifm->ifs_next, ifqt);
    200                 ifs_remque(ifm);
     209        if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm)
     210        {
     211            insque(pData, ifm->ifs_next, ifqt);
     212            ifs_remque(ifm);
    201213        }
    202214
    203215        /* Update so_queued */
    204         if (ifm->ifq_so) {
    205                 if (--ifm->ifq_so->so_queued == 0)
    206                    /* If there's no more queued, reset nqueued */
    207                    ifm->ifq_so->so_nqueued = 0;
     216        if (ifm->ifq_so)
     217        {
     218            if (--ifm->ifq_so->so_queued == 0)
     219                /* If there's no more queued, reset nqueued */
     220                ifm->ifq_so->so_nqueued = 0;
    208221        }
    209222
     
    213226        m_free(pData, ifm);
    214227
    215         if (if_queued)
    216            goto again;
    217 }
     228        if (!if_queued)
     229            return;
     230    }
     231}
  • trunk/src/VBox/Devices/Network/slirp/tcp_input.c

    r15453 r15472  
    7373tcp_reass(PNATState pData, struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
    7474{
    75         struct tseg_qent *q;
    76         struct tseg_qent *p = NULL;
    77         struct tseg_qent *nq;
    78         struct tseg_qent *te = NULL;
    79         struct socket *so = tp->t_socket;
    80         int flags;
    81 
    82         /*
    83          * XXX: tcp_reass() is rather inefficient with its data structures
    84          * and should be rewritten (see NetBSD for optimizations).  While
    85          * doing that it should move to its own file tcp_reass.c.
    86          */
    87 
    88         /*
    89          * Call with th==NULL after become established to
    90          * force pre-ESTABLISHED data up to user socket.
    91          */
    92         if (th == NULL)
    93                 goto present;
    94 
    95         /*
    96          * Limit the number of segments in the reassembly queue to prevent
    97          * holding on to too many segments (and thus running out of mbufs).
    98          * Make sure to let the missing segment through which caused this
    99          * queue.  Always keep one global queue entry spare to be able to
    100          * process the missing segment.
    101          */
    102         if (th->th_seq != tp->rcv_nxt &&
    103             (tcp_reass_qsize + 1 >= tcp_reass_maxseg ||
    104              tp->t_segqlen >= tcp_reass_maxqlen)) {
    105                 tcp_reass_overflows++;
    106                 tcpstat.tcps_rcvmemdrop++;
     75    struct tseg_qent *q;
     76    struct tseg_qent *p = NULL;
     77    struct tseg_qent *nq;
     78    struct tseg_qent *te = NULL;
     79    struct socket *so = tp->t_socket;
     80    int flags;
     81
     82    /*
     83     * XXX: tcp_reass() is rather inefficient with its data structures
     84     * and should be rewritten (see NetBSD for optimizations).  While
     85     * doing that it should move to its own file tcp_reass.c.
     86     */
     87
     88    /*
     89     * Call with th==NULL after become established to
     90     * force pre-ESTABLISHED data up to user socket.
     91     */
     92    if (th == NULL)
     93        goto present;
     94
     95    /*
     96     * Limit the number of segments in the reassembly queue to prevent
     97     * holding on to too many segments (and thus running out of mbufs).
     98     * Make sure to let the missing segment through which caused this
     99     * queue.  Always keep one global queue entry spare to be able to
     100     * process the missing segment.
     101     */
     102    if (   th->th_seq != tp->rcv_nxt
     103        && (   tcp_reass_qsize + 1 >= tcp_reass_maxseg
     104            || tp->t_segqlen >= tcp_reass_maxqlen))
     105    {
     106        tcp_reass_overflows++;
     107        tcpstat.tcps_rcvmemdrop++;
     108        m_freem(pData, m);
     109        *tlenp = 0;
     110        return (0);
     111    }
     112
     113    /*
     114     * Allocate a new queue entry. If we can't, or hit the zone limit
     115     * just drop the pkt.
     116     */
     117    te = malloc(sizeof(struct tseg_qent));
     118    if (te == NULL)
     119    {
     120        tcpstat.tcps_rcvmemdrop++;
     121        m_freem(pData, m);
     122        *tlenp = 0;
     123        return (0);
     124    }
     125    tp->t_segqlen++;
     126    tcp_reass_qsize++;
     127
     128    /*
     129     * Find a segment which begins after this one does.
     130     */
     131    LIST_FOREACH(q, &tp->t_segq, tqe_q)
     132    {
     133        if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
     134            break;
     135        p = q;
     136    }
     137
     138    /*
     139     * If there is a preceding segment, it may provide some of
     140     * our data already.  If so, drop the data from the incoming
     141     * segment.  If it provides all of our data, drop us.
     142     */
     143    if (p != NULL)
     144    {
     145        int i;
     146        /* conversion to int (in i) handles seq wraparound */
     147        i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
     148        if (i > 0)
     149        {
     150            if (i >= *tlenp)
     151            {
     152                tcpstat.tcps_rcvduppack++;
     153                tcpstat.tcps_rcvdupbyte += *tlenp;
    107154                m_freem(pData, m);
    108                 *tlenp = 0;
    109                 return (0);
    110         }
    111 
    112         /*
    113          * Allocate a new queue entry. If we can't, or hit the zone limit
    114          * just drop the pkt.
    115          */
    116         te = malloc(sizeof(struct tseg_qent));
    117         if (te == NULL) {
    118                 tcpstat.tcps_rcvmemdrop++;
    119                 m_freem(pData, m);
    120                 *tlenp = 0;
    121                 return (0);
    122         }
    123         tp->t_segqlen++;
    124         tcp_reass_qsize++;
    125 
    126         /*
    127          * Find a segment which begins after this one does.
    128          */
    129         LIST_FOREACH(q, &tp->t_segq, tqe_q) {
    130                 if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
    131                         break;
    132                 p = q;
    133         }
    134 
    135         /*
    136          * If there is a preceding segment, it may provide some of
    137          * our data already.  If so, drop the data from the incoming
    138          * segment.  If it provides all of our data, drop us.
    139          */
    140         if (p != NULL) {
    141                 int i;
    142                 /* conversion to int (in i) handles seq wraparound */
    143                 i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
    144                 if (i > 0) {
    145                         if (i >= *tlenp) {
    146                                 tcpstat.tcps_rcvduppack++;
    147                                 tcpstat.tcps_rcvdupbyte += *tlenp;
    148                                 m_freem(pData, m);
    149                                 free(te);
    150                                 tp->t_segqlen--;
    151                                 tcp_reass_qsize--;
    152                                 /*
    153                                  * Try to present any queued data
    154                                  * at the left window edge to the user.
    155                                  * This is needed after the 3-WHS
    156                                  * completes.
    157                                  */
    158                                 goto present;   /* ??? */
    159                         }
    160                         m_adj(m, i);
    161                         *tlenp -= i;
    162                         th->th_seq += i;
    163                 }
    164         }
    165         tcpstat.tcps_rcvoopack++;
    166         tcpstat.tcps_rcvoobyte += *tlenp;
    167 
    168         /*
    169          * While we overlap succeeding segments trim them or,
    170          * if they are completely covered, dequeue them.
    171          */
    172         while (q) {
    173                 int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
    174                 if (i <= 0)
    175                         break;
    176                 if (i < q->tqe_len) {
    177                         q->tqe_th->th_seq += i;
    178                         q->tqe_len -= i;
    179                         m_adj(q->tqe_m, i);
    180                         break;
    181                 }
    182 
    183                 nq = LIST_NEXT(q, tqe_q);
    184                 LIST_REMOVE(q, tqe_q);
    185                 m_freem(pData, q->tqe_m);
    186                 free(q);
     155                free(te);
    187156                tp->t_segqlen--;
    188157                tcp_reass_qsize--;
    189                 q = nq;
    190         }
    191 
    192         /* Insert the new segment queue entry into place. */
    193         te->tqe_m = m;
    194         te->tqe_th = th;
    195         te->tqe_len = *tlenp;
    196 
    197         if (p == NULL) {
    198                 LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
    199         } else {
    200                 LIST_INSERT_AFTER(p, te, tqe_q);
    201         }
     158                /*
     159                 * Try to present any queued data
     160                 * at the left window edge to the user.
     161                 * This is needed after the 3-WHS
     162                 * completes.
     163                 */
     164                goto present;   /* ??? */
     165            }
     166            m_adj(m, i);
     167            *tlenp -= i;
     168            th->th_seq += i;
     169        }
     170    }
     171    tcpstat.tcps_rcvoopack++;
     172    tcpstat.tcps_rcvoobyte += *tlenp;
     173
     174    /*
     175     * While we overlap succeeding segments trim them or,
     176     * if they are completely covered, dequeue them.
     177     */
     178    while (q)
     179    {
     180        int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
     181        if (i <= 0)
     182            break;
     183        if (i < q->tqe_len)
     184        {
     185            q->tqe_th->th_seq += i;
     186            q->tqe_len -= i;
     187            m_adj(q->tqe_m, i);
     188            break;
     189        }
     190
     191        nq = LIST_NEXT(q, tqe_q);
     192        LIST_REMOVE(q, tqe_q);
     193        m_freem(pData, q->tqe_m);
     194        free(q);
     195        tp->t_segqlen--;
     196        tcp_reass_qsize--;
     197        q = nq;
     198    }
     199
     200    /* Insert the new segment queue entry into place. */
     201    te->tqe_m = m;
     202    te->tqe_th = th;
     203    te->tqe_len = *tlenp;
     204
     205    if (p == NULL)
     206    {
     207        LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
     208    }
     209    else
     210    {
     211        LIST_INSERT_AFTER(p, te, tqe_q);
     212    }
    202213
    203214present:
    204         /*
    205          * Present data to user, advancing rcv_nxt through
    206          * completed sequence space.
     215    /*
     216     * Present data to user, advancing rcv_nxt through
     217     * completed sequence space.
     218     */
     219    if (!TCPS_HAVEESTABLISHED(tp->t_state))
     220        return (0);
     221    q = LIST_FIRST(&tp->t_segq);
     222    if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
     223        return (0);
     224    do
     225    {
     226        tp->rcv_nxt += q->tqe_len;
     227        flags = q->tqe_th->th_flags & TH_FIN;
     228        nq = LIST_NEXT(q, tqe_q);
     229        LIST_REMOVE(q, tqe_q);
     230        /* XXX: This place should be checked for the same code in
     231         * original BSD code for Slirp and current BSD used SS_FCANTRCVMORE
    207232         */
    208         if (!TCPS_HAVEESTABLISHED(tp->t_state))
    209                 return (0);
    210         q = LIST_FIRST(&tp->t_segq);
    211         if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
    212                 return (0);
    213         do {
    214                 tp->rcv_nxt += q->tqe_len;
    215                 flags = q->tqe_th->th_flags & TH_FIN;
    216                 nq = LIST_NEXT(q, tqe_q);
    217                 LIST_REMOVE(q, tqe_q);
    218                 /* XXX: This place should be checked for the same code in
    219                  * original BSD code for Slirp and current BSD used SS_FCANTRCVMORE
    220                  */
    221                 if (so->so_state & SS_FCANTSENDMORE)
    222                         m_freem(pData, q->tqe_m);
    223                 else
    224                         sbappend(pData, so, q->tqe_m);
    225                 free(q);
    226                 tp->t_segqlen--;
    227                 tcp_reass_qsize--;
    228                 q = nq;
    229         } while (q && q->tqe_th->th_seq == tp->rcv_nxt);
    230         return (flags);
     233        if (so->so_state & SS_FCANTSENDMORE)
     234            m_freem(pData, q->tqe_m);
     235        else
     236            sbappend(pData, so, q->tqe_m);
     237        free(q);
     238        tp->t_segqlen--;
     239        tcp_reass_qsize--;
     240        q = nq;
     241    }
     242    while (q && q->tqe_th->th_seq == tp->rcv_nxt);
     243
     244    return flags;
    231245}
    232246
     
    238252tcp_input(PNATState pData, register struct mbuf *m, int iphlen, struct socket *inso)
    239253{
    240         struct ip save_ip, *ip;
    241         register struct tcpiphdr *ti;
    242         caddr_t optp = NULL;
    243         int optlen = 0;
    244         int len, tlen, off;
    245         register struct tcpcb *tp = 0;
    246         register int tiflags;
    247         struct socket *so = 0;
    248         int todrop, acked, ourfinisacked, needoutput = 0;
    249 /*      int dropsocket = 0; */
    250         int iss = 0;
    251         u_long tiwin;
    252 /*      int ts_present = 0; */
    253 
    254         DEBUG_CALL("tcp_input");
    255         DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
    256                     (long )m, iphlen, (long )inso ));
     254    struct ip save_ip, *ip;
     255    register struct tcpiphdr *ti;
     256    caddr_t optp = NULL;
     257    int optlen = 0;
     258    int len, tlen, off;
     259    register struct tcpcb *tp = 0;
     260    register int tiflags;
     261    struct socket *so = 0;
     262    int todrop, acked, ourfinisacked, needoutput = 0;
     263/*  int dropsocket = 0; */
     264    int iss = 0;
     265    u_long tiwin;
     266/*  int ts_present = 0; */
     267
     268    DEBUG_CALL("tcp_input");
     269    DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
     270                (long )m, iphlen, (long )inso ));
     271
     272    /*
     273     * If called with m == 0, then we're continuing the connect
     274     */
     275    if (m == NULL)
     276    {
     277        so = inso;
     278
     279        /* Re-set a few variables */
     280        tp = sototcpcb(so);
     281        m = so->so_m;
     282        so->so_m = 0;
     283        ti = so->so_ti;
     284        tiwin = ti->ti_win;
     285        tiflags = ti->ti_flags;
     286
     287        goto cont_conn;
     288    }
     289
     290    tcpstat.tcps_rcvtotal++;
     291    /*
     292     * Get IP and TCP header together in first mbuf.
     293     * Note: IP leaves IP header in first mbuf.
     294     */
     295    ti = mtod(m, struct tcpiphdr *);
     296    if (iphlen > sizeof(struct ip ))
     297    {
     298        ip_stripoptions(m, (struct mbuf *)0);
     299        iphlen = sizeof(struct ip );
     300    }
     301    /* XXX Check if too short */
     302
     303
     304    /*
     305     * Save a copy of the IP header in case we want restore it
     306     * for sending an ICMP error message in response.
     307     */
     308    ip = mtod(m, struct ip *);
     309    save_ip = *ip;
     310    save_ip.ip_len+= iphlen;
     311
     312    /*
     313     * Checksum extended TCP header and data.
     314     */
     315    tlen = ((struct ip *)ti)->ip_len;
     316    memset(ti->ti_x1, 0, 9);
     317    ti->ti_len = htons((u_int16_t)tlen);
     318    len = sizeof(struct ip ) + tlen;
     319    /* keep checksum for ICMP reply
     320     * ti->ti_sum = cksum(m, len);
     321     * if (ti->ti_sum) { */
     322    if (cksum(m, len))
     323    {
     324        tcpstat.tcps_rcvbadsum++;
     325        goto drop;
     326    }
     327
     328    /*
     329     * Check that TCP offset makes sense,
     330     * pull out TCP options and adjust length.              XXX
     331     */
     332    off = ti->ti_off << 2;
     333    if (   off < sizeof (struct tcphdr)
     334        || off > tlen)
     335    {
     336        tcpstat.tcps_rcvbadoff++;
     337        goto drop;
     338    }
     339    tlen -= off;
     340    ti->ti_len = tlen;
     341    if (off > sizeof (struct tcphdr))
     342    {
     343        optlen = off - sizeof (struct tcphdr);
     344        optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
    257345
    258346        /*
    259          * If called with m == 0, then we're continuing the connect
     347         * Do quick retrieval of timestamp options ("options
     348         * prediction?").  If timestamp is the only option and it's
     349         * formatted as recommended in RFC 1323 appendix A, we
     350         * quickly get the values now and not bother calling
     351         * tcp_dooptions(), etc.
    260352         */
    261         if (m == NULL) {
    262                 so = inso;
    263 
    264                 /* Re-set a few variables */
    265                 tp = sototcpcb(so);
    266                 m = so->so_m;
    267                 so->so_m = 0;
    268                 ti = so->so_ti;
    269                 tiwin = ti->ti_win;
    270                 tiflags = ti->ti_flags;
    271 
    272                 goto cont_conn;
    273         }
    274 
    275 
    276         tcpstat.tcps_rcvtotal++;
    277         /*
    278          * Get IP and TCP header together in first mbuf.
    279          * Note: IP leaves IP header in first mbuf.
    280          */
    281         ti = mtod(m, struct tcpiphdr *);
    282         if (iphlen > sizeof(struct ip )) {
    283           ip_stripoptions(m, (struct mbuf *)0);
    284           iphlen=sizeof(struct ip );
    285         }
    286         /* XXX Check if too short */
    287 
    288 
    289         /*
    290          * Save a copy of the IP header in case we want restore it
    291          * for sending an ICMP error message in response.
    292          */
    293         ip=mtod(m, struct ip *);
    294         save_ip = *ip;
    295         save_ip.ip_len+= iphlen;
    296 
    297         /*
    298          * Checksum extended TCP header and data.
    299          */
    300         tlen = ((struct ip *)ti)->ip_len;
    301         memset(ti->ti_x1, 0, 9);
    302         ti->ti_len = htons((u_int16_t)tlen);
    303         len = sizeof(struct ip ) + tlen;
    304         /* keep checksum for ICMP reply
    305          * ti->ti_sum = cksum(m, len);
    306          * if (ti->ti_sum) { */
    307         if(cksum(m, len)) {
    308           tcpstat.tcps_rcvbadsum++;
    309           goto drop;
    310         }
    311 
    312         /*
    313          * Check that TCP offset makes sense,
    314          * pull out TCP options and adjust length.              XXX
    315          */
    316         off = ti->ti_off << 2;
    317         if (off < sizeof (struct tcphdr) || off > tlen) {
    318           tcpstat.tcps_rcvbadoff++;
    319           goto drop;
    320         }
    321         tlen -= off;
    322         ti->ti_len = tlen;
    323         if (off > sizeof (struct tcphdr)) {
    324           optlen = off - sizeof (struct tcphdr);
    325           optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
    326 
    327                 /*
    328                  * Do quick retrieval of timestamp options ("options
    329                  * prediction?").  If timestamp is the only option and it's
    330                  * formatted as recommended in RFC 1323 appendix A, we
    331                  * quickly get the values now and not bother calling
    332                  * tcp_dooptions(), etc.
    333                  */
    334 /*              if ((optlen == TCPOLEN_TSTAMP_APPA ||
    335  *                   (optlen > TCPOLEN_TSTAMP_APPA &&
    336  *                      optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&
    337  *                   *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) &&
    338  *                   (ti->ti_flags & TH_SYN) == 0) {
    339  *                      ts_present = 1;
    340  *                      ts_val = ntohl(*(u_int32_t *)(optp + 4));
    341  *                      ts_ecr = ntohl(*(u_int32_t *)(optp + 8));
    342  *                      optp = NULL;   / * we've parsed the options * /
    343  *              }
    344  */
    345         }
    346         tiflags = ti->ti_flags;
    347 
    348         /*
    349          * Convert TCP protocol specific fields to host format.
    350          */
    351         NTOHL(ti->ti_seq);
    352         NTOHL(ti->ti_ack);
    353         NTOHS(ti->ti_win);
    354         NTOHS(ti->ti_urp);
    355 
    356         /*
    357          * Drop TCP, IP headers and TCP options.
    358          */
    359         m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
    360         m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
    361 
    362         /*
    363          * Locate pcb for segment.
    364          */
     353#if 0
     354        if ((   optlen == TCPOLEN_TSTAMP_APPA
     355             || (   optlen  > TCPOLEN_TSTAMP_APPA
     356                 && optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&
     357                *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) &&
     358                (ti->ti_flags & TH_SYN) == 0)
     359        {
     360            ts_present = 1;
     361            ts_val = ntohl(*(u_int32_t *)(optp + 4));
     362            ts_ecr = ntohl(*(u_int32_t *)(optp + 8));
     363            optp = NULL;   / * we have parsed the options * /
     364        }
     365#endif
     366    }
     367    tiflags = ti->ti_flags;
     368
     369    /*
     370     * Convert TCP protocol specific fields to host format.
     371     */
     372    NTOHL(ti->ti_seq);
     373    NTOHL(ti->ti_ack);
     374    NTOHS(ti->ti_win);
     375    NTOHS(ti->ti_urp);
     376
     377    /*
     378     * Drop TCP, IP headers and TCP options.
     379     */
     380    m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
     381    m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
     382
     383    /*
     384     * Locate pcb for segment.
     385     */
    365386findso:
    366         so = tcp_last_so;
    367         if (so->so_fport != ti->ti_dport ||
    368             so->so_lport != ti->ti_sport ||
    369             so->so_laddr.s_addr != ti->ti_src.s_addr ||
    370             so->so_faddr.s_addr != ti->ti_dst.s_addr) {
    371                 so = solookup(&tcb, ti->ti_src, ti->ti_sport,
    372                                ti->ti_dst, ti->ti_dport);
    373                 if (so)
    374                         tcp_last_so = so;
    375                 ++tcpstat.tcps_socachemiss;
    376         }
    377 
    378         /*
    379          * If the state is CLOSED (i.e., TCB does not exist) then
    380          * all data in the incoming segment is discarded.
    381          * If the TCB exists but is in CLOSED state, it is embryonic,
    382          * but should either do a listen or a connect soon.
    383          *
    384          * state == CLOSED means we've done socreate() but haven't
    385          * attached it to a protocol yet...
    386          *
    387          * XXX If a TCB does not exist, and the TH_SYN flag is
    388          * the only flag set, then create a session, mark it
    389          * as if it was LISTENING, and continue...
    390          */
    391         if (so == 0) {
    392           if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
     387    so = tcp_last_so;
     388    if (   so->so_fport        != ti->ti_dport
     389        || so->so_lport        != ti->ti_sport
     390        || so->so_laddr.s_addr != ti->ti_src.s_addr
     391        || so->so_faddr.s_addr != ti->ti_dst.s_addr)
     392    {
     393        so = solookup(&tcb, ti->ti_src, ti->ti_sport,
     394                      ti->ti_dst, ti->ti_dport);
     395        if (so)
     396            tcp_last_so = so;
     397        ++tcpstat.tcps_socachemiss;
     398    }
     399
     400    /*
     401     * If the state is CLOSED (i.e., TCB does not exist) then
     402     * all data in the incoming segment is discarded.
     403     * If the TCB exists but is in CLOSED state, it is embryonic,
     404     * but should either do a listen or a connect soon.
     405     *
     406     * state == CLOSED means we've done socreate() but haven't
     407     * attached it to a protocol yet...
     408     *
     409     * XXX If a TCB does not exist, and the TH_SYN flag is
     410     * the only flag set, then create a session, mark it
     411     * as if it was LISTENING, and continue...
     412     */
     413    if (so == 0)
     414    {
     415        if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
    393416            goto dropwithreset;
    394417
    395           if ((so = socreate()) == NULL)
     418        if ((so = socreate()) == NULL)
    396419            goto dropwithreset;
    397           if (tcp_attach(pData, so) < 0) {
     420        if (tcp_attach(pData, so) < 0)
     421        {
    398422            free(so); /* Not sofree (if it failed, it's not insqued) */
    399423            goto dropwithreset;
    400           }
    401 
    402           sbreserve(&so->so_snd, tcp_sndspace);
    403           sbreserve(&so->so_rcv, tcp_rcvspace);
    404 
    405           /*            tcp_last_so = so; */  /* XXX ? */
    406           /*            tp = sototcpcb(so);    */
    407 
    408           so->so_laddr = ti->ti_src;
    409           so->so_lport = ti->ti_sport;
    410           so->so_faddr = ti->ti_dst;
    411           so->so_fport = ti->ti_dport;
    412 
    413           if ((so->so_iptos = tcp_tos(so)) == 0)
     424        }
     425
     426        sbreserve(&so->so_snd, tcp_sndspace);
     427        sbreserve(&so->so_rcv, tcp_rcvspace);
     428
     429/*      tcp_last_so = so; */  /* XXX ? */
     430/*      tp = sototcpcb(so);    */
     431
     432        so->so_laddr = ti->ti_src;
     433        so->so_lport = ti->ti_sport;
     434        so->so_faddr = ti->ti_dst;
     435        so->so_fport = ti->ti_dport;
     436
     437        if ((so->so_iptos = tcp_tos(so)) == 0)
    414438            so->so_iptos = ((struct ip *)ti)->ip_tos;
    415439
    416           tp = sototcpcb(so);
    417           tp->t_state = TCPS_LISTEN;
    418         }
    419 
    420         /*
    421          * If this is a still-connecting socket, this probably
    422          * a retransmit of the SYN.  Whether it's a retransmit SYN
    423          * or something else, we nuke it.
    424          */
    425         if (so->so_state & SS_ISFCONNECTING)
    426                 goto drop;
    427 
    428440        tp = sototcpcb(so);
    429 
    430         /* XXX Should never fail */
    431         if (tp == 0)
    432                 goto dropwithreset;
    433         if (tp->t_state == TCPS_CLOSED)
    434                 goto drop;
    435 
    436         /* Unscale the window into a 32-bit value. */
    437 /*      if ((tiflags & TH_SYN) == 0)
    438  *              tiwin = ti->ti_win << tp->snd_scale;
    439  *      else
     441        tp->t_state = TCPS_LISTEN;
     442    }
     443
     444    /*
     445     * If this is a still-connecting socket, this probably
     446     * a retransmit of the SYN.  Whether it's a retransmit SYN
     447     * or something else, we nuke it.
     448     */
     449    if (so->so_state & SS_ISFCONNECTING)
     450        goto drop;
     451
     452    tp = sototcpcb(so);
     453
     454    /* XXX Should never fail */
     455    if (tp == 0)
     456        goto dropwithreset;
     457    if (tp->t_state == TCPS_CLOSED)
     458        goto drop;
     459
     460    /* Unscale the window into a 32-bit value. */
     461/*  if ((tiflags & TH_SYN) == 0)
     462 *      tiwin = ti->ti_win << tp->snd_scale;
     463 *  else
    440464 */
    441                 tiwin = ti->ti_win;
    442 
    443         /*
    444          * Segment received on connection.
    445          * Reset idle time and keep-alive timer.
    446          */
    447         tp->t_idle = 0;
    448         if (so_options)
    449            tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
    450         else
    451            tp->t_timer[TCPT_KEEP] = tcp_keepidle;
    452 
    453         /*
    454          * Process options if not in LISTEN state,
    455          * else do it below (after getting remote address).
    456          */
    457         if (optp && tp->t_state != TCPS_LISTEN)
    458                 tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti);
     465    tiwin = ti->ti_win;
     466
     467    /*
     468     * Segment received on connection.
     469     * Reset idle time and keep-alive timer.
     470     */
     471    tp->t_idle = 0;
     472    if (so_options)
     473        tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
     474    else
     475        tp->t_timer[TCPT_KEEP] = tcp_keepidle;
     476
     477    /*
     478     * Process options if not in LISTEN state,
     479     * else do it below (after getting remote address).
     480     */
     481    if (optp && tp->t_state != TCPS_LISTEN)
     482        tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti);
    459483/* , */
    460484/*                      &ts_present, &ts_val, &ts_ecr); */
    461485
     486    /*
     487     * Header prediction: check for the two common cases
     488     * of a uni-directional data xfer.  If the packet has
     489     * no control flags, is in-sequence, the window didn't
     490     * change and we're not retransmitting, it's a
     491     * candidate.  If the length is zero and the ack moved
     492     * forward, we're the sender side of the xfer.  Just
     493     * free the data acked & wake any higher level process
     494     * that was blocked waiting for space.  If the length
     495     * is non-zero and the ack didn't move, we're the
     496     * receiver side.  If we're getting packets in-order
     497     * (the reassembly queue is empty), add the data to
     498     * the socket buffer and note that we need a delayed ack.
     499     *
     500     * XXX Some of these tests are not needed
     501     * eg: the tiwin == tp->snd_wnd prevents many more
     502     * predictions.. with no *real* advantage..
     503     */
     504    if (    tp->t_state == TCPS_ESTABLISHED
     505         && (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK
     506/*       && (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) */
     507         &&  ti->ti_seq == tp->rcv_nxt
     508         &&  tiwin && tiwin == tp->snd_wnd
     509         &&  tp->snd_nxt == tp->snd_max)
     510    {
    462511        /*
    463          * Header prediction: check for the two common cases
    464          * of a uni-directional data xfer.  If the packet has
    465          * no control flags, is in-sequence, the window didn't
    466          * change and we're not retransmitting, it's a
    467          * candidate.  If the length is zero and the ack moved
    468          * forward, we're the sender side of the xfer.  Just
    469          * free the data acked & wake any higher level process
    470          * that was blocked waiting for space.  If the length
    471          * is non-zero and the ack didn't move, we're the
    472          * receiver side.  If we're getting packets in-order
    473          * (the reassembly queue is empty), add the data to
    474          * the socket buffer and note that we need a delayed ack.
    475          *
    476          * XXX Some of these tests are not needed
    477          * eg: the tiwin == tp->snd_wnd prevents many more
    478          * predictions.. with no *real* advantage..
     512         * If last ACK falls within this segment's sequence numbers,
     513         *  record the timestamp.
    479514         */
    480         if (tp->t_state == TCPS_ESTABLISHED &&
    481             (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
    482 /*          (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */
    483             ti->ti_seq == tp->rcv_nxt &&
    484             tiwin && tiwin == tp->snd_wnd &&
    485             tp->snd_nxt == tp->snd_max) {
     515#if 0
     516        if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
     517                SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {
     518            tp->ts_recent_age = tcp_now;
     519            tp->ts_recent = ts_val;
     520        }
     521#endif
     522
     523        if (ti->ti_len == 0)
     524        {
     525            if (   SEQ_GT(ti->ti_ack, tp->snd_una)
     526                && SEQ_LEQ(ti->ti_ack, tp->snd_max)
     527                && tp->snd_cwnd >= tp->snd_wnd)
     528            {
    486529                /*
    487                  * If last ACK falls within this segment's sequence numbers,
    488                  *  record the timestamp.
     530                 * this is a pure ack for outstanding data.
    489531                 */
    490 /*              if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
    491  *                 SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {
    492  *                      tp->ts_recent_age = tcp_now;
    493  *                      tp->ts_recent = ts_val;
    494  *              }
    495  */
    496                 if (ti->ti_len == 0) {
    497                         if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
    498                             SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
    499                             tp->snd_cwnd >= tp->snd_wnd) {
    500                                 /*
    501                                  * this is a pure ack for outstanding data.
    502                                  */
    503                                 ++tcpstat.tcps_predack;
    504 /*                              if (ts_present)
    505  *                                      tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
    506  *                              else
    507  */                                  if (tp->t_rtt &&
    508                                             SEQ_GT(ti->ti_ack, tp->t_rtseq))
    509                                         tcp_xmit_timer(pData, tp, tp->t_rtt);
    510                                 acked = ti->ti_ack - tp->snd_una;
    511                                 tcpstat.tcps_rcvackpack++;
    512                                 tcpstat.tcps_rcvackbyte += acked;
    513                                 sbdrop(&so->so_snd, acked);
    514                                 tp->snd_una = ti->ti_ack;
    515                                 m_freem(pData, m);
    516 
    517                                 /*
    518                                  * If all outstanding data are acked, stop
    519                                  * retransmit timer, otherwise restart timer
    520                                  * using current (possibly backed-off) value.
    521                                  * If process is waiting for space,
    522                                  * wakeup/selwakeup/signal.  If data
    523                                  * are ready to send, let tcp_output
    524                                  * decide between more output or persist.
    525                                  */
    526                                 if (tp->snd_una == tp->snd_max)
    527                                         tp->t_timer[TCPT_REXMT] = 0;
    528                                 else if (tp->t_timer[TCPT_PERSIST] == 0)
    529                                         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
    530 
    531                                 /*
    532                                  * There's room in so_snd, sowwakup will read()
    533                                  * from the socket if we can
    534                                  */
    535 /*                              if (so->so_snd.sb_flags & SB_NOTIFY)
    536  *                                      sowwakeup(so);
    537  */
    538                                 /*
    539                                  * This is called because sowwakeup might have
    540                                  * put data into so_snd.  Since we don't so sowwakeup,
    541                                  * we don't need this.. XXX???
    542                                  */
    543                                 if (so->so_snd.sb_cc)
    544                                         (void) tcp_output(pData, tp);
    545 
    546                                 return;
    547                         }
    548                 } else if (ti->ti_ack == tp->snd_una &&
    549                     LIST_FIRST(&tp->t_segq) &&
    550                     ti->ti_len <= sbspace(&so->so_rcv)) {
    551                         /*
    552                          * this is a pure, in-sequence data packet
    553                          * with nothing on the reassembly queue and
    554                          * we have enough buffer space to take it.
    555                          */
    556                         ++tcpstat.tcps_preddat;
    557                         tp->rcv_nxt += ti->ti_len;
    558                         tcpstat.tcps_rcvpack++;
    559                         tcpstat.tcps_rcvbyte += ti->ti_len;
    560                         /*
    561                          * Add data to socket buffer.
    562                          */
    563                         if (so->so_emu) {
    564                                 if (tcp_emu(pData, so,m)) sbappend(pData, so, m);
    565                         } else
    566                                 sbappend(pData, so, m);
    567 
    568                         /*
    569                          * XXX This is called when data arrives.  Later, check
    570                          * if we can actually write() to the socket
    571                          * XXX Need to check? It's be NON_BLOCKING
    572                          */
    573 /*                      sorwakeup(so); */
    574 
    575                         /*
    576                          * If this is a short packet, then ACK now - with Nagel
    577                          *      congestion avoidance sender won't send more until
    578                          *      he gets an ACK.
    579                          *
    580                          * It is better to not delay acks at all to maximize
    581                          * TCP throughput.  See RFC 2581.
    582                          */
    583                         tp->t_flags |= TF_ACKNOW;
    584                         tcp_output(pData, tp);
    585                         return;
    586                 }
    587         } /* header prediction */
    588         /*
    589          * Calculate amount of space in receive window,
    590          * and then do TCP input processing.
    591          * Receive window is amount of space in rcv queue,
    592          * but not less than advertised window.
    593          */
    594         { int win;
    595           win = sbspace(&so->so_rcv);
    596           if (win < 0)
     532                ++tcpstat.tcps_predack;
     533#if 0
     534              if (ts_present)
     535                  tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
     536              else
     537#endif
     538                  if (   tp->t_rtt
     539                      && SEQ_GT(ti->ti_ack, tp->t_rtseq))
     540                      tcp_xmit_timer(pData, tp, tp->t_rtt);
     541              acked = ti->ti_ack - tp->snd_una;
     542              tcpstat.tcps_rcvackpack++;
     543              tcpstat.tcps_rcvackbyte += acked;
     544              sbdrop(&so->so_snd, acked);
     545              tp->snd_una = ti->ti_ack;
     546              m_freem(pData, m);
     547
     548              /*
     549               * If all outstanding data are acked, stop
     550               * retransmit timer, otherwise restart timer
     551               * using current (possibly backed-off) value.
     552               * If process is waiting for space,
     553               * wakeup/selwakeup/signal.  If data
     554               * are ready to send, let tcp_output
     555               * decide between more output or persist.
     556               */
     557              if (tp->snd_una == tp->snd_max)
     558                  tp->t_timer[TCPT_REXMT] = 0;
     559              else if (tp->t_timer[TCPT_PERSIST] == 0)
     560                  tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
     561
     562              /*
     563               * There's room in so_snd, sowwakup will read()
     564               * from the socket if we can
     565               */
     566#if 0
     567              if (so->so_snd.sb_flags & SB_NOTIFY)
     568                  sowwakeup(so);
     569#endif
     570              /*
     571               * This is called because sowwakeup might have
     572               * put data into so_snd.  Since we don't so sowwakeup,
     573               * we don't need this.. XXX???
     574               */
     575              if (so->so_snd.sb_cc)
     576                  (void) tcp_output(pData, tp);
     577
     578              return;
     579            }
     580        }
     581        else if (   ti->ti_ack == tp->snd_una
     582                 && LIST_FIRST(&tp->t_segq)
     583                 && ti->ti_len <= sbspace(&so->so_rcv))
     584        {
     585            /*
     586             * this is a pure, in-sequence data packet
     587             * with nothing on the reassembly queue and
     588             * we have enough buffer space to take it.
     589             */
     590            ++tcpstat.tcps_preddat;
     591            tp->rcv_nxt += ti->ti_len;
     592            tcpstat.tcps_rcvpack++;
     593            tcpstat.tcps_rcvbyte += ti->ti_len;
     594            /*
     595             * Add data to socket buffer.
     596             */
     597            if (so->so_emu)
     598            {
     599                if (tcp_emu(pData, so,m)) sbappend(pData, so, m);
     600            }
     601            else
     602                sbappend(pData, so, m);
     603
     604            /*
     605             * XXX This is called when data arrives.  Later, check
     606             * if we can actually write() to the socket
     607             * XXX Need to check? It's be NON_BLOCKING
     608             */
     609/*          sorwakeup(so); */
     610
     611            /*
     612             * If this is a short packet, then ACK now - with Nagel
     613             *      congestion avoidance sender won't send more until
     614             *      he gets an ACK.
     615             *
     616             * It is better to not delay acks at all to maximize
     617             * TCP throughput.  See RFC 2581.
     618             */
     619            tp->t_flags |= TF_ACKNOW;
     620            tcp_output(pData, tp);
     621            return;
     622        }
     623    } /* header prediction */
     624    /*
     625     * Calculate amount of space in receive window,
     626     * and then do TCP input processing.
     627     * Receive window is amount of space in rcv queue,
     628     * but not less than advertised window.
     629     */
     630    {
     631        int win;
     632        win = sbspace(&so->so_rcv);
     633        if (win < 0)
    597634            win = 0;
    598           tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
    599         }
    600 
    601         switch (tp->t_state) {
    602 
     635        tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
     636    }
     637
     638    switch (tp->t_state)
     639    {
    603640        /*
    604641         * If the state is LISTEN then ignore segment if it contains an RST.
     
    614651         * segment in this state.
    615652         */
    616         case TCPS_LISTEN: {
    617 
    618           if (tiflags & TH_RST)
    619             goto drop;
    620           if (tiflags & TH_ACK)
    621             goto dropwithreset;
    622           if ((tiflags & TH_SYN) == 0)
    623             goto drop;
    624 
    625           /*
    626            * This has way too many gotos...
    627            * But a bit of spaghetti code never hurt anybody :)
    628            */
    629 
    630           if (so->so_emu & EMU_NOCONNECT) {
    631             so->so_emu &= ~EMU_NOCONNECT;
    632             goto cont_input;
    633           }
    634 
    635           if((tcp_fconnect(pData, so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
    636             u_char code=ICMP_UNREACH_NET;
    637             DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
    638                         errno,strerror(errno)));
    639             if(errno == ECONNREFUSED) {
    640               /* ACK the SYN, send RST to refuse the connection */
    641               tcp_respond(pData, tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
    642                           TH_RST|TH_ACK);
    643             } else {
    644               if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
    645               HTONL(ti->ti_seq);             /* restore tcp header */
    646               HTONL(ti->ti_ack);
    647               HTONS(ti->ti_win);
    648               HTONS(ti->ti_urp);
    649               m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
    650               m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
    651               *ip=save_ip;
    652               icmp_error(pData, m, ICMP_UNREACH,code, 0,strerror(errno));
    653             }
    654             tp = tcp_close(pData, tp);
    655             m_free(pData, m);
    656           } else {
    657             /*
    658              * Haven't connected yet, save the current mbuf
    659              * and ti, and return
    660              * XXX Some OS's don't tell us whether the connect()
    661              * succeeded or not.  So we must time it out.
    662              */
    663             so->so_m = m;
    664             so->so_ti = ti;
     653        case TCPS_LISTEN:
     654        {
     655            if (tiflags & TH_RST)
     656                goto drop;
     657            if (tiflags & TH_ACK)
     658                goto dropwithreset;
     659            if ((tiflags & TH_SYN) == 0)
     660                goto drop;
     661
     662            /*
     663             * This has way too many gotos...
     664             * But a bit of spaghetti code never hurt anybody :)
     665             */
     666
     667            if (so->so_emu & EMU_NOCONNECT)
     668            {
     669                so->so_emu &= ~EMU_NOCONNECT;
     670                goto cont_input;
     671            }
     672
     673            if (   (tcp_fconnect(pData, so) == -1)
     674                && errno != EINPROGRESS
     675                && errno != EWOULDBLOCK)
     676            {
     677                u_char code = ICMP_UNREACH_NET;
     678                DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
     679                            errno,strerror(errno)));
     680                if (errno == ECONNREFUSED)
     681                {
     682                    /* ACK the SYN, send RST to refuse the connection */
     683                    tcp_respond(pData, tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
     684                               TH_RST|TH_ACK);
     685                }
     686                else
     687                {
     688                    if (errno == EHOSTUNREACH)
     689                        code = ICMP_UNREACH_HOST;
     690                    HTONL(ti->ti_seq);             /* restore tcp header */
     691                    HTONL(ti->ti_ack);
     692                    HTONS(ti->ti_win);
     693                    HTONS(ti->ti_urp);
     694                    m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
     695                    m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
     696                    *ip = save_ip;
     697                    icmp_error(pData, m, ICMP_UNREACH,code, 0,strerror(errno));
     698                }
     699                tp = tcp_close(pData, tp);
     700                m_free(pData, m);
     701            }
     702            else
     703            {
     704                /*
     705                 * Haven't connected yet, save the current mbuf
     706                 * and ti, and return
     707                 * XXX Some OS's don't tell us whether the connect()
     708                 * succeeded or not.  So we must time it out.
     709                 */
     710                so->so_m = m;
     711                so->so_ti = ti;
     712                tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
     713                tp->t_state = TCPS_SYN_RECEIVED;
     714            }
     715            return;
     716
     717cont_conn:
     718            /* m==NULL
     719             * Check if the connect succeeded
     720             */
     721            if (so->so_state & SS_NOFDREF)
     722            {
     723                tp = tcp_close(pData, tp);
     724                goto dropwithreset;
     725            }
     726cont_input:
     727            tcp_template(tp);
     728
     729            if (optp)
     730                tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti);
     731
     732            if (iss)
     733                tp->iss = iss;
     734            else
     735                tp->iss = tcp_iss;
     736            tcp_iss += TCP_ISSINCR/2;
     737            tp->irs = ti->ti_seq;
     738            tcp_sendseqinit(tp);
     739            tcp_rcvseqinit(tp);
     740            tp->t_flags |= TF_ACKNOW;
     741            tp->t_state = TCPS_SYN_RECEIVED;
    665742            tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
    666             tp->t_state = TCPS_SYN_RECEIVED;
    667           }
    668           return;
    669 
    670         cont_conn:
    671           /* m==NULL
    672            * Check if the connect succeeded
    673            */
    674           if (so->so_state & SS_NOFDREF) {
    675             tp = tcp_close(pData, tp);
    676             goto dropwithreset;
    677           }
    678         cont_input:
    679           tcp_template(tp);
    680 
    681           if (optp)
    682             tcp_dooptions(pData, tp, (u_char *)optp, optlen, ti);
    683           /* , */
    684           /*                            &ts_present, &ts_val, &ts_ecr); */
    685 
    686           if (iss)
    687             tp->iss = iss;
    688           else
    689             tp->iss = tcp_iss;
    690           tcp_iss += TCP_ISSINCR/2;
    691           tp->irs = ti->ti_seq;
    692           tcp_sendseqinit(tp);
    693           tcp_rcvseqinit(tp);
    694           tp->t_flags |= TF_ACKNOW;
    695           tp->t_state = TCPS_SYN_RECEIVED;
    696           tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
    697           tcpstat.tcps_accepts++;
    698           goto trimthenstep6;
     743            tcpstat.tcps_accepts++;
     744            goto trimthenstep6;
    699745        } /* case TCPS_LISTEN */
    700746
     
    712758         */
    713759        case TCPS_SYN_SENT:
    714                 if ((tiflags & TH_ACK) &&
    715                     (SEQ_LEQ(ti->ti_ack, tp->iss) ||
    716                      SEQ_GT(ti->ti_ack, tp->snd_max)))
    717                         goto dropwithreset;
    718 
    719                 if (tiflags & TH_RST) {
    720                         if (tiflags & TH_ACK)
    721                                 tp = tcp_drop(pData, tp,0); /* XXX Check t_softerror! */
    722                         goto drop;
     760            if (   (tiflags & TH_ACK)
     761                && (   SEQ_LEQ(ti->ti_ack, tp->iss)
     762                    || SEQ_GT(ti->ti_ack, tp->snd_max)))
     763                goto dropwithreset;
     764
     765            if (tiflags & TH_RST)
     766            {
     767                if (tiflags & TH_ACK)
     768                    tp = tcp_drop(pData, tp,0); /* XXX Check t_softerror! */
     769                goto drop;
     770            }
     771
     772            if ((tiflags & TH_SYN) == 0)
     773                goto drop;
     774            if (tiflags & TH_ACK)
     775            {
     776                tp->snd_una = ti->ti_ack;
     777                if (SEQ_LT(tp->snd_nxt, tp->snd_una))
     778                    tp->snd_nxt = tp->snd_una;
     779            }
     780
     781            tp->t_timer[TCPT_REXMT] = 0;
     782            tp->irs = ti->ti_seq;
     783            tcp_rcvseqinit(tp);
     784            tp->t_flags |= TF_ACKNOW;
     785            if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss))
     786            {
     787                tcpstat.tcps_connects++;
     788                soisfconnected(so);
     789                tp->t_state = TCPS_ESTABLISHED;
     790
     791                /* Do window scaling on this connection? */
     792#if 0
     793                if ((  tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE))
     794                     == (TF_RCVD_SCALE|TF_REQ_SCALE))
     795                {
     796                    tp->snd_scale = tp->requested_s_scale;
     797                    tp->rcv_scale = tp->request_r_scale;
    723798                }
    724 
    725                 if ((tiflags & TH_SYN) == 0)
    726                         goto drop;
    727                 if (tiflags & TH_ACK) {
    728                         tp->snd_una = ti->ti_ack;
    729                         if (SEQ_LT(tp->snd_nxt, tp->snd_una))
    730                                 tp->snd_nxt = tp->snd_una;
    731                 }
    732 
    733                 tp->t_timer[TCPT_REXMT] = 0;
    734                 tp->irs = ti->ti_seq;
    735                 tcp_rcvseqinit(tp);
     799#endif
     800                (void) tcp_reass(pData, tp, (struct tcphdr *)0, NULL, (struct mbuf *)0);
     801                /*
     802                 * if we didn't have to retransmit the SYN,
     803                 * use its rtt as our initial srtt & rtt var.
     804                 */
     805                if (tp->t_rtt)
     806                    tcp_xmit_timer(pData, tp, tp->t_rtt);
     807            }
     808            else
     809                tp->t_state = TCPS_SYN_RECEIVED;
     810
     811trimthenstep6:
     812            /*
     813             * Advance ti->ti_seq to correspond to first data byte.
     814             * If data, trim to stay within window,
     815             * dropping FIN if necessary.
     816             */
     817            ti->ti_seq++;
     818            if (ti->ti_len > tp->rcv_wnd)
     819            {
     820                todrop = ti->ti_len - tp->rcv_wnd;
     821                m_adj(m, -todrop);
     822                ti->ti_len = tp->rcv_wnd;
     823                tiflags &= ~TH_FIN;
     824                tcpstat.tcps_rcvpackafterwin++;
     825                tcpstat.tcps_rcvbyteafterwin += todrop;
     826            }
     827            tp->snd_wl1 = ti->ti_seq - 1;
     828            tp->rcv_up = ti->ti_seq;
     829            goto step6;
     830    } /* switch tp->t_state */
     831    /*
     832     * States other than LISTEN or SYN_SENT.
     833     * First check timestamp, if present.
     834     * Then check that at least some bytes of segment are within
     835     * receive window.  If segment begins before rcv_nxt,
     836     * drop leading data (and SYN); if nothing left, just ack.
     837     *
     838     * RFC 1323 PAWS: If we have a timestamp reply on this segment
     839     * and it's less than ts_recent, drop it.
     840     */
     841#if 0
     842    if (   ts_present
     843        && (tiflags & TH_RST) == 0
     844        && tp->ts_recent
     845        && TSTMP_LT(ts_val, tp->ts_recent))
     846    {
     847        /* Check to see if ts_recent is over 24 days old.  */
     848        if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE)
     849        {
     850            /*
     851             * Invalidate ts_recent.  If this segment updates
     852             * ts_recent, the age will be reset later and ts_recent
     853             * will get a valid value.  If it does not, setting
     854             * ts_recent to zero will at least satisfy the
     855             * requirement that zero be placed in the timestamp
     856             * echo reply when ts_recent isn't valid.  The
     857             * age isn't reset until we get a valid ts_recent
     858             * because we don't want out-of-order segments to be
     859             * dropped when ts_recent is old.
     860             */
     861            tp->ts_recent = 0;
     862        }
     863        else
     864        {
     865            tcpstat.tcps_rcvduppack++;
     866            tcpstat.tcps_rcvdupbyte += ti->ti_len;
     867            tcpstat.tcps_pawsdrop++;
     868            goto dropafterack;
     869        }
     870     }
     871#endif
     872
     873    todrop = tp->rcv_nxt - ti->ti_seq;
     874    if (todrop > 0)
     875    {
     876        if (tiflags & TH_SYN)
     877        {
     878            tiflags &= ~TH_SYN;
     879            ti->ti_seq++;
     880            if (ti->ti_urp > 1)
     881                ti->ti_urp--;
     882            else
     883                tiflags &= ~TH_URG;
     884            todrop--;
     885        }
     886        /*
     887         * Following if statement from Stevens, vol. 2, p. 960.
     888         */
     889        if (   todrop > ti->ti_len
     890            || (   todrop == ti->ti_len
     891                && (tiflags & TH_FIN) == 0))
     892        {
     893            /*
     894             * Any valid FIN must be to the left of the window.
     895             * At this point the FIN must be a duplicate or out
     896             * of sequence; drop it.
     897             */
     898            tiflags &= ~TH_FIN;
     899
     900            /*
     901             * Send an ACK to resynchronize and drop any data.
     902             * But keep on processing for RST or ACK.
     903             */
     904            tp->t_flags |= TF_ACKNOW;
     905            todrop = ti->ti_len;
     906            tcpstat.tcps_rcvduppack++;
     907            tcpstat.tcps_rcvdupbyte += todrop;
     908        }
     909        else
     910        {
     911            tcpstat.tcps_rcvpartduppack++;
     912            tcpstat.tcps_rcvpartdupbyte += todrop;
     913        }
     914        m_adj(m, todrop);
     915        ti->ti_seq += todrop;
     916        ti->ti_len -= todrop;
     917        if (ti->ti_urp > todrop)
     918            ti->ti_urp -= todrop;
     919        else
     920        {
     921            tiflags &= ~TH_URG;
     922            ti->ti_urp = 0;
     923        }
     924    }
     925    /*
     926     * If new data are received on a connection after the
     927     * user processes are gone, then RST the other end.
     928     */
     929    if (   (so->so_state & SS_NOFDREF)
     930        && tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len)
     931    {
     932        tp = tcp_close(pData, tp);
     933        tcpstat.tcps_rcvafterclose++;
     934        goto dropwithreset;
     935    }
     936
     937    /*
     938     * If segment ends after window, drop trailing data
     939     * (and PUSH and FIN); if nothing left, just ACK.
     940     */
     941    todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
     942    if (todrop > 0)
     943    {
     944        tcpstat.tcps_rcvpackafterwin++;
     945        if (todrop >= ti->ti_len)
     946        {
     947            tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
     948            /*
     949             * If a new connection request is received
     950             * while in TIME_WAIT, drop the old connection
     951             * and start over if the sequence numbers
     952             * are above the previous ones.
     953             */
     954            if (   tiflags & TH_SYN
     955                && tp->t_state == TCPS_TIME_WAIT
     956                && SEQ_GT(ti->ti_seq, tp->rcv_nxt))
     957            {
     958                iss = tp->rcv_nxt + TCP_ISSINCR;
     959                tp = tcp_close(pData, tp);
     960                goto findso;
     961            }
     962            /*
     963             * If window is closed can only take segments at
     964             * window edge, and have to drop data and PUSH from
     965             * incoming segments.  Continue processing, but
     966             * remember to ack.  Otherwise, drop segment
     967             * and ack.
     968             */
     969            if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt)
     970            {
    736971                tp->t_flags |= TF_ACKNOW;
    737                 if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
    738                         tcpstat.tcps_connects++;
    739                         soisfconnected(so);
    740                         tp->t_state = TCPS_ESTABLISHED;
    741 
    742                         /* Do window scaling on this connection? */
    743 /*                      if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
    744  *                              (TF_RCVD_SCALE|TF_REQ_SCALE)) {
    745  *                              tp->snd_scale = tp->requested_s_scale;
    746  *                              tp->rcv_scale = tp->request_r_scale;
    747  *                      }
    748  */
    749                         (void) tcp_reass(pData, tp, (struct tcphdr *)0, NULL, (struct mbuf *)0);
    750                         /*
    751                          * if we didn't have to retransmit the SYN,
    752                          * use its rtt as our initial srtt & rtt var.
    753                          */
    754                         if (tp->t_rtt)
    755                                 tcp_xmit_timer(pData, tp, tp->t_rtt);
    756                 } else
    757                         tp->t_state = TCPS_SYN_RECEIVED;
    758 
    759 trimthenstep6:
    760                 /*
    761                  * Advance ti->ti_seq to correspond to first data byte.
    762                  * If data, trim to stay within window,
    763                  * dropping FIN if necessary.
    764                  */
    765                 ti->ti_seq++;
    766                 if (ti->ti_len > tp->rcv_wnd) {
    767                         todrop = ti->ti_len - tp->rcv_wnd;
    768                         m_adj(m, -todrop);
    769                         ti->ti_len = tp->rcv_wnd;
    770                         tiflags &= ~TH_FIN;
    771                         tcpstat.tcps_rcvpackafterwin++;
    772                         tcpstat.tcps_rcvbyteafterwin += todrop;
    773                 }
    774                 tp->snd_wl1 = ti->ti_seq - 1;
    775                 tp->rcv_up = ti->ti_seq;
    776                 goto step6;
    777         } /* switch tp->t_state */
    778         /*
    779          * States other than LISTEN or SYN_SENT.
    780          * First check timestamp, if present.
    781          * Then check that at least some bytes of segment are within
    782          * receive window.  If segment begins before rcv_nxt,
    783          * drop leading data (and SYN); if nothing left, just ack.
    784          *
    785          * RFC 1323 PAWS: If we have a timestamp reply on this segment
    786          * and it's less than ts_recent, drop it.
    787          */
    788 /*      if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent &&
    789  *          TSTMP_LT(ts_val, tp->ts_recent)) {
    790  *
    791  */             /* Check to see if ts_recent is over 24 days old.  */
    792 /*              if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
    793  */                     /*
    794  *                       * Invalidate ts_recent.  If this segment updates
    795  *                       * ts_recent, the age will be reset later and ts_recent
    796  *                       * will get a valid value.  If it does not, setting
    797  *                       * ts_recent to zero will at least satisfy the
    798  *                       * requirement that zero be placed in the timestamp
    799  *                       * echo reply when ts_recent isn't valid.  The
    800  *                       * age isn't reset until we get a valid ts_recent
    801  *                       * because we don't want out-of-order segments to be
    802  *                       * dropped when ts_recent is old.
    803  *                       */
    804 /*                      tp->ts_recent = 0;
    805  *              } else {
    806  *                      tcpstat.tcps_rcvduppack++;
    807  *                      tcpstat.tcps_rcvdupbyte += ti->ti_len;
    808  *                      tcpstat.tcps_pawsdrop++;
    809  *                      goto dropafterack;
    810  *              }
    811  *      }
    812  */
    813 
    814         todrop = tp->rcv_nxt - ti->ti_seq;
    815         if (todrop > 0) {
    816                 if (tiflags & TH_SYN) {
    817                         tiflags &= ~TH_SYN;
    818                         ti->ti_seq++;
    819                         if (ti->ti_urp > 1)
    820                                 ti->ti_urp--;
    821                         else
    822                                 tiflags &= ~TH_URG;
    823                         todrop--;
    824                 }
    825                 /*
    826                  * Following if statement from Stevens, vol. 2, p. 960.
    827                  */
    828                 if (todrop > ti->ti_len
    829                     || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
    830                         /*
    831                          * Any valid FIN must be to the left of the window.
    832                          * At this point the FIN must be a duplicate or out
    833                          * of sequence; drop it.
    834                          */
    835                         tiflags &= ~TH_FIN;
    836 
    837                         /*
    838                          * Send an ACK to resynchronize and drop any data.
    839                          * But keep on processing for RST or ACK.
    840                          */
    841                         tp->t_flags |= TF_ACKNOW;
    842                         todrop = ti->ti_len;
    843                         tcpstat.tcps_rcvduppack++;
    844                         tcpstat.tcps_rcvdupbyte += todrop;
    845                 } else {
    846                         tcpstat.tcps_rcvpartduppack++;
    847                         tcpstat.tcps_rcvpartdupbyte += todrop;
    848                 }
    849                 m_adj(m, todrop);
    850                 ti->ti_seq += todrop;
    851                 ti->ti_len -= todrop;
    852                 if (ti->ti_urp > todrop)
    853                         ti->ti_urp -= todrop;
    854                 else {
    855                         tiflags &= ~TH_URG;
    856                         ti->ti_urp = 0;
    857                 }
    858         }
    859         /*
    860          * If new data are received on a connection after the
    861          * user processes are gone, then RST the other end.
    862          */
    863         if ((so->so_state & SS_NOFDREF) &&
    864             tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
    865                 tp = tcp_close(pData, tp);
    866                 tcpstat.tcps_rcvafterclose++;
    867                 goto dropwithreset;
    868         }
    869 
    870         /*
    871          * If segment ends after window, drop trailing data
    872          * (and PUSH and FIN); if nothing left, just ACK.
    873          */
    874         todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
    875         if (todrop > 0) {
    876                 tcpstat.tcps_rcvpackafterwin++;
    877                 if (todrop >= ti->ti_len) {
    878                         tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
    879                         /*
    880                          * If a new connection request is received
    881                          * while in TIME_WAIT, drop the old connection
    882                          * and start over if the sequence numbers
    883                          * are above the previous ones.
    884                          */
    885                         if (tiflags & TH_SYN &&
    886                             tp->t_state == TCPS_TIME_WAIT &&
    887                             SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
    888                                 iss = tp->rcv_nxt + TCP_ISSINCR;
    889                                 tp = tcp_close(pData, tp);
    890                                 goto findso;
    891                         }
    892                         /*
    893                          * If window is closed can only take segments at
    894                          * window edge, and have to drop data and PUSH from
    895                          * incoming segments.  Continue processing, but
    896                          * remember to ack.  Otherwise, drop segment
    897                          * and ack.
    898                          */
    899                         if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
    900                                 tp->t_flags |= TF_ACKNOW;
    901                                 tcpstat.tcps_rcvwinprobe++;
    902                         } else
    903                                 goto dropafterack;
    904                 } else
    905                         tcpstat.tcps_rcvbyteafterwin += todrop;
    906                 m_adj(m, -todrop);
    907                 ti->ti_len -= todrop;
    908                 tiflags &= ~(TH_PUSH|TH_FIN);
    909         }
    910 
    911         /*
    912          * If last ACK falls within this segment's sequence numbers,
    913          * record its timestamp.
    914          */
    915 /*      if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&
    916  *          SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len +
    917  *                 ((tiflags & (TH_SYN|TH_FIN)) != 0))) {
    918  *              tp->ts_recent_age = tcp_now;
    919  *              tp->ts_recent = ts_val;
    920  *      }
    921  */
    922 
    923         /*
    924          * If the RST bit is set examine the state:
    925          *    SYN_RECEIVED STATE:
    926          *      If passive open, return to LISTEN state.
    927          *      If active open, inform user that connection was refused.
    928          *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
    929          *      Inform user that connection was reset, and close tcb.
    930          *    CLOSING, LAST_ACK, TIME_WAIT STATES
    931          *      Close the tcb.
    932          */
    933         if (tiflags&TH_RST) switch (tp->t_state) {
    934 
    935         case TCPS_SYN_RECEIVED:
     972                tcpstat.tcps_rcvwinprobe++;
     973            }
     974            else
     975                goto dropafterack;
     976        }
     977        else
     978            tcpstat.tcps_rcvbyteafterwin += todrop;
     979        m_adj(m, -todrop);
     980        ti->ti_len -= todrop;
     981        tiflags &= ~(TH_PUSH|TH_FIN);
     982    }
     983
     984    /*
     985     * If last ACK falls within this segment's sequence numbers,
     986     * record its timestamp.
     987     */
     988#if 0
     989    if (   ts_present
     990        && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)
     991        && SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + ((tiflags & (TH_SYN|TH_FIN)) != 0)))
     992    {
     993        tp->ts_recent_age = tcp_now;
     994        tp->ts_recent = ts_val;
     995    }
     996#endif
     997
     998    /*
     999     * If the RST bit is set examine the state:
     1000     *    SYN_RECEIVED STATE:
     1001     *      If passive open, return to LISTEN state.
     1002     *      If active open, inform user that connection was refused.
     1003     *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
     1004     *      Inform user that connection was reset, and close tcb.
     1005     *    CLOSING, LAST_ACK, TIME_WAIT STATES
     1006     *      Close the tcb.
     1007     */
     1008    if (tiflags&TH_RST)
     1009        switch (tp->t_state)
     1010        {
     1011            case TCPS_SYN_RECEIVED:
    9361012/*              so->so_error = ECONNREFUSED; */
    9371013                goto close;
    9381014
    939         case TCPS_ESTABLISHED:
    940         case TCPS_FIN_WAIT_1:
    941         case TCPS_FIN_WAIT_2:
    942         case TCPS_CLOSE_WAIT:
     1015            case TCPS_ESTABLISHED:
     1016            case TCPS_FIN_WAIT_1:
     1017            case TCPS_FIN_WAIT_2:
     1018            case TCPS_CLOSE_WAIT:
    9431019/*              so->so_error = ECONNRESET; */
    944         close:
     1020close:
    9451021                tp->t_state = TCPS_CLOSED;
    9461022                tcpstat.tcps_drops++;
     
    9481024                goto drop;
    9491025
    950         case TCPS_CLOSING:
    951         case TCPS_LAST_ACK:
    952         case TCPS_TIME_WAIT:
     1026            case TCPS_CLOSING:
     1027            case TCPS_LAST_ACK:
     1028            case TCPS_TIME_WAIT:
    9531029                tp = tcp_close(pData, tp);
    9541030                goto drop;
    9551031        }
    9561032
    957         /*
    958          * If a SYN is in the window, then this is an
    959          * error and we send an RST and drop the connection.
    960          */
    961         if (tiflags & TH_SYN) {
    962                 tp = tcp_drop(pData, tp,0);
    963                 goto dropwithreset;
    964         }
    965 
    966         /*
    967          * If the ACK bit is off we drop the segment and return.
    968          */
    969         if ((tiflags & TH_ACK) == 0) goto drop;
    970 
    971         /*
    972          * Ack processing.
    973          */
    974         switch (tp->t_state) {
     1033    /*
     1034     * If a SYN is in the window, then this is an
     1035     * error and we send an RST and drop the connection.
     1036     */
     1037    if (tiflags & TH_SYN)
     1038    {
     1039        tp = tcp_drop(pData, tp,0);
     1040        goto dropwithreset;
     1041    }
     1042
     1043    /*
     1044     * If the ACK bit is off we drop the segment and return.
     1045     */
     1046    if ((tiflags & TH_ACK) == 0)
     1047        goto drop;
     1048
     1049    /*
     1050     * Ack processing.
     1051     */
     1052    switch (tp->t_state)
     1053    {
    9751054        /*
    9761055         * In SYN_RECEIVED state if the ack ACKs our SYN then enter
     
    9791058         */
    9801059        case TCPS_SYN_RECEIVED:
    981 
    982                 if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
    983                     SEQ_GT(ti->ti_ack, tp->snd_max))
    984                         goto dropwithreset;
    985                 tcpstat.tcps_connects++;
    986                 tp->t_state = TCPS_ESTABLISHED;
    987                 /*
    988                  * The sent SYN is ack'ed with our sequence number +1
    989                  * The first data byte already in the buffer will get
    990                  * lost if no correction is made.  This is only needed for
    991                  * SS_CTL since the buffer is empty otherwise.
    992                  * tp->snd_una++; or:
    993                  */
    994                 tp->snd_una=ti->ti_ack;
    995                 soisfconnected(so);
    996 
    997                 /* Do window scaling? */
    998 /*              if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
    999  *                      (TF_RCVD_SCALE|TF_REQ_SCALE)) {
    1000  *                      tp->snd_scale = tp->requested_s_scale;
    1001  *                      tp->rcv_scale = tp->request_r_scale;
    1002  *              }
    1003  */
    1004                 (void) tcp_reass(pData, tp, (struct tcphdr *)0, (int *)0, (struct mbuf *)0);
    1005                 tp->snd_wl1 = ti->ti_seq - 1;
    1006                 /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
    1007                 goto synrx_to_est;
    1008                 /* fall into ... */
    1009 
    1010         /*
    1011          * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
    1012          * ACKs.  If the ack is in the range
    1013          *      tp->snd_una < ti->ti_ack <= tp->snd_max
    1014          * then advance tp->snd_una to ti->ti_ack and drop
    1015          * data from the retransmission queue.  If this ACK reflects
    1016          * more up to date window information we update our window information.
    1017          */
     1060            if (   SEQ_GT(tp->snd_una, ti->ti_ack)
     1061                || SEQ_GT(ti->ti_ack, tp->snd_max))
     1062                goto dropwithreset;
     1063            tcpstat.tcps_connects++;
     1064            tp->t_state = TCPS_ESTABLISHED;
     1065            /*
     1066             * The sent SYN is ack'ed with our sequence number +1
     1067             * The first data byte already in the buffer will get
     1068             * lost if no correction is made.  This is only needed for
     1069             * SS_CTL since the buffer is empty otherwise.
     1070             * tp->snd_una++; or:
     1071             */
     1072            tp->snd_una = ti->ti_ack;
     1073            soisfconnected(so);
     1074
     1075            /* Do window scaling? */
     1076#if 0
     1077            if (   (tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE))
     1078                == (TF_RCVD_SCALE|TF_REQ_SCALE))
     1079            {
     1080                tp->snd_scale = tp->requested_s_scale;
     1081                tp->rcv_scale = tp->request_r_scale;
     1082            }
     1083#endif
     1084            (void) tcp_reass(pData, tp, (struct tcphdr *)0, (int *)0, (struct mbuf *)0);
     1085            tp->snd_wl1 = ti->ti_seq - 1;
     1086            /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
     1087            goto synrx_to_est;
     1088            /* fall into ... */
     1089
     1090            /*
     1091             * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
     1092             * ACKs.  If the ack is in the range
     1093             *      tp->snd_una < ti->ti_ack <= tp->snd_max
     1094             * then advance tp->snd_una to ti->ti_ack and drop
     1095             * data from the retransmission queue.  If this ACK reflects
     1096             * more up to date window information we update our window information.
     1097             */
    10181098        case TCPS_ESTABLISHED:
    10191099        case TCPS_FIN_WAIT_1:
     
    10231103        case TCPS_LAST_ACK:
    10241104        case TCPS_TIME_WAIT:
    1025 
    1026                 if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
    1027                         if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
    1028                           tcpstat.tcps_rcvdupack++;
    1029                           DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
    1030                                       (long )m, (long )so));
    1031                                 /*
    1032                                  * If we have outstanding data (other than
    1033                                  * a window probe), this is a completely
    1034                                  * duplicate ack (ie, window info didn't
    1035                                  * change), the ack is the biggest we've
    1036                                  * seen and we've seen exactly our rexmt
    1037                                  * threshold of them, assume a packet
    1038                                  * has been dropped and retransmit it.
    1039                                  * Kludge snd_nxt & the congestion
    1040                                  * window so we send only this one
    1041                                  * packet.
    1042                                  *
    1043                                  * We know we're losing at the current
    1044                                  * window size so do congestion avoidance
    1045                                  * (set ssthresh to half the current window
    1046                                  * and pull our congestion window back to
    1047                                  * the new ssthresh).
    1048                                  *
    1049                                  * Dup acks mean that packets have left the
    1050                                  * network (they're now cached at the receiver)
    1051                                  * so bump cwnd by the amount in the receiver
    1052                                  * to keep a constant cwnd packets in the
    1053                                  * network.
    1054                                  */
    1055                                 if (tp->t_timer[TCPT_REXMT] == 0 ||
    1056                                     ti->ti_ack != tp->snd_una)
    1057                                         tp->t_dupacks = 0;
    1058                                 else if (++tp->t_dupacks == tcprexmtthresh) {
    1059                                         tcp_seq onxt = tp->snd_nxt;
    1060                                         u_int win =
    1061                                             min(tp->snd_wnd, tp->snd_cwnd) / 2 /
    1062                                                 tp->t_maxseg;
    1063 
    1064                                         if (win < 2)
    1065                                                 win = 2;
    1066                                         tp->snd_ssthresh = win * tp->t_maxseg;
    1067                                         tp->t_timer[TCPT_REXMT] = 0;
    1068                                         tp->t_rtt = 0;
    1069                                         tp->snd_nxt = ti->ti_ack;
    1070                                         tp->snd_cwnd = tp->t_maxseg;
    1071                                         (void) tcp_output(pData, tp);
    1072                                         tp->snd_cwnd = tp->snd_ssthresh +
    1073                                                tp->t_maxseg * tp->t_dupacks;
    1074                                         if (SEQ_GT(onxt, tp->snd_nxt))
    1075                                                 tp->snd_nxt = onxt;
    1076                                         goto drop;
    1077                                 } else if (tp->t_dupacks > tcprexmtthresh) {
    1078                                         tp->snd_cwnd += tp->t_maxseg;
    1079                                         (void) tcp_output(pData, tp);
    1080                                         goto drop;
    1081                                 }
    1082                         } else
    1083                                 tp->t_dupacks = 0;
    1084                         break;
     1105            if (SEQ_LEQ(ti->ti_ack, tp->snd_una))
     1106            {
     1107                if (ti->ti_len == 0 && tiwin == tp->snd_wnd)
     1108                {
     1109                    tcpstat.tcps_rcvdupack++;
     1110                    DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
     1111                                (long )m, (long )so));
     1112                    /*
     1113                     * If we have outstanding data (other than
     1114                     * a window probe), this is a completely
     1115                     * duplicate ack (ie, window info didn't
     1116                     * change), the ack is the biggest we've
     1117                     * seen and we've seen exactly our rexmt
     1118                     * threshold of them, assume a packet
     1119                     * has been dropped and retransmit it.
     1120                     * Kludge snd_nxt & the congestion
     1121                     * window so we send only this one
     1122                     * packet.
     1123                     *
     1124                     * We know we're losing at the current
     1125                     * window size so do congestion avoidance
     1126                     * (set ssthresh to half the current window
     1127                     * and pull our congestion window back to
     1128                     * the new ssthresh).
     1129                     *
     1130                     * Dup acks mean that packets have left the
     1131                     * network (they're now cached at the receiver)
     1132                     * so bump cwnd by the amount in the receiver
     1133                     * to keep a constant cwnd packets in the
     1134                     * network.
     1135                     */
     1136                    if (   tp->t_timer[TCPT_REXMT] == 0
     1137                        || ti->ti_ack != tp->snd_una)
     1138                        tp->t_dupacks = 0;
     1139                    else if (++tp->t_dupacks == tcprexmtthresh)
     1140                    {
     1141                        tcp_seq onxt = tp->snd_nxt;
     1142                        u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
     1143                        if (win < 2)
     1144                            win = 2;
     1145                        tp->snd_ssthresh = win * tp->t_maxseg;
     1146                        tp->t_timer[TCPT_REXMT] = 0;
     1147                        tp->t_rtt = 0;
     1148                        tp->snd_nxt = ti->ti_ack;
     1149                        tp->snd_cwnd = tp->t_maxseg;
     1150                        (void) tcp_output(pData, tp);
     1151                        tp->snd_cwnd = tp->snd_ssthresh +
     1152                            tp->t_maxseg * tp->t_dupacks;
     1153                        if (SEQ_GT(onxt, tp->snd_nxt))
     1154                            tp->snd_nxt = onxt;
     1155                        goto drop;
     1156                    }
     1157                    else if (tp->t_dupacks > tcprexmtthresh)
     1158                    {
     1159                        tp->snd_cwnd += tp->t_maxseg;
     1160                        (void) tcp_output(pData, tp);
     1161                        goto drop;
     1162                    }
    10851163                }
    1086         synrx_to_est:
    1087                 /*
    1088                  * If the congestion window was inflated to account
    1089                  * for the other side's cached packets, retract it.
    1090                  */
    1091                 if (tp->t_dupacks > tcprexmtthresh &&
    1092                     tp->snd_cwnd > tp->snd_ssthresh)
    1093                         tp->snd_cwnd = tp->snd_ssthresh;
    1094                 tp->t_dupacks = 0;
    1095                 if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
    1096                         tcpstat.tcps_rcvacktoomuch++;
    1097                         goto dropafterack;
    1098                 }
    1099                 acked = ti->ti_ack - tp->snd_una;
    1100                 tcpstat.tcps_rcvackpack++;
    1101                 tcpstat.tcps_rcvackbyte += acked;
    1102 
    1103                 /*
    1104                  * If we have a timestamp reply, update smoothed
    1105                  * round trip time.  If no timestamp is present but
    1106                  * transmit timer is running and timed sequence
    1107                  * number was acked, update smoothed round trip time.
    1108                  * Since we now have an rtt measurement, cancel the
    1109                  * timer backoff (cf., Phil Karn's retransmit alg.).
    1110                  * Recompute the initial retransmit timer.
    1111                  */
    1112 /*              if (ts_present)
    1113  *                      tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
    1114  *              else
    1115  */
    1116                      if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
    1117                         tcp_xmit_timer(pData, tp,tp->t_rtt);
    1118 
    1119                 /*
    1120                  * If all outstanding data is acked, stop retransmit
    1121                  * timer and remember to restart (more output or persist).
    1122                  * If there is more data to be acked, restart retransmit
    1123                  * timer, using current (possibly backed-off) value.
    1124                  */
    1125                 if (ti->ti_ack == tp->snd_max) {
    1126                         tp->t_timer[TCPT_REXMT] = 0;
    1127                         needoutput = 1;
    1128                 } else if (tp->t_timer[TCPT_PERSIST] == 0)
    1129                         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
    1130                 /*
    1131                  * When new data is acked, open the congestion window.
    1132                  * If the window gives us less than ssthresh packets
    1133                  * in flight, open exponentially (maxseg per packet).
    1134                  * Otherwise open linearly: maxseg per window
    1135                  * (maxseg^2 / cwnd per packet).
    1136                  */
    1137                 {
    1138                   register u_int cw = tp->snd_cwnd;
    1139                   register u_int incr = tp->t_maxseg;
    1140 
    1141                   if (cw > tp->snd_ssthresh)
     1164                else
     1165                    tp->t_dupacks = 0;
     1166                break;
     1167            }
     1168synrx_to_est:
     1169            /*
     1170             * If the congestion window was inflated to account
     1171             * for the other side's cached packets, retract it.
     1172             */
     1173            if (   tp->t_dupacks > tcprexmtthresh
     1174                && tp->snd_cwnd > tp->snd_ssthresh)
     1175                tp->snd_cwnd = tp->snd_ssthresh;
     1176            tp->t_dupacks = 0;
     1177            if (SEQ_GT(ti->ti_ack, tp->snd_max))
     1178            {
     1179                tcpstat.tcps_rcvacktoomuch++;
     1180                goto dropafterack;
     1181            }
     1182            acked = ti->ti_ack - tp->snd_una;
     1183            tcpstat.tcps_rcvackpack++;
     1184            tcpstat.tcps_rcvackbyte += acked;
     1185
     1186            /*
     1187             * If we have a timestamp reply, update smoothed
     1188             * round trip time.  If no timestamp is present but
     1189             * transmit timer is running and timed sequence
     1190             * number was acked, update smoothed round trip time.
     1191             * Since we now have an rtt measurement, cancel the
     1192             * timer backoff (cf., Phil Karn's retransmit alg.).
     1193             * Recompute the initial retransmit timer.
     1194             */
     1195#if 0
     1196            if (ts_present)
     1197                tcp_xmit_timer(tp, tcp_now-ts_ecr+1);
     1198            else
     1199#endif
     1200                if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
     1201                    tcp_xmit_timer(pData, tp,tp->t_rtt);
     1202
     1203            /*
     1204             * If all outstanding data is acked, stop retransmit
     1205             * timer and remember to restart (more output or persist).
     1206             * If there is more data to be acked, restart retransmit
     1207             * timer, using current (possibly backed-off) value.
     1208             */
     1209            if (ti->ti_ack == tp->snd_max)
     1210            {
     1211                tp->t_timer[TCPT_REXMT] = 0;
     1212                needoutput = 1;
     1213            }
     1214            else if (tp->t_timer[TCPT_PERSIST] == 0)
     1215                tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
     1216            /*
     1217             * When new data is acked, open the congestion window.
     1218             * If the window gives us less than ssthresh packets
     1219             * in flight, open exponentially (maxseg per packet).
     1220             * Otherwise open linearly: maxseg per window
     1221             * (maxseg^2 / cwnd per packet).
     1222             */
     1223            {
     1224                register u_int cw = tp->snd_cwnd;
     1225                register u_int incr = tp->t_maxseg;
     1226
     1227                if (cw > tp->snd_ssthresh)
    11421228                    incr = incr * incr / cw;
    1143                   tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
    1144                 }
    1145                 if (acked > so->so_snd.sb_cc) {
    1146                         tp->snd_wnd -= so->so_snd.sb_cc;
    1147                         sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
    1148                         ourfinisacked = 1;
    1149                 } else {
    1150                         sbdrop(&so->so_snd, acked);
    1151                         tp->snd_wnd -= acked;
    1152                         ourfinisacked = 0;
    1153                 }
    1154                 /*
    1155                  * XXX sowwakup is called when data is acked and there's room for
    1156                  * for more data... it should read() the socket
    1157                  */
    1158 /*              if (so->so_snd.sb_flags & SB_NOTIFY)
    1159  *                      sowwakeup(so);
    1160  */
    1161                 tp->snd_una = ti->ti_ack;
    1162                 if (SEQ_LT(tp->snd_nxt, tp->snd_una))
    1163                         tp->snd_nxt = tp->snd_una;
    1164 
    1165                 switch (tp->t_state) {
    1166 
     1229                tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
     1230            }
     1231            if (acked > so->so_snd.sb_cc)
     1232            {
     1233                tp->snd_wnd -= so->so_snd.sb_cc;
     1234                sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
     1235                ourfinisacked = 1;
     1236            }
     1237            else
     1238            {
     1239                sbdrop(&so->so_snd, acked);
     1240                tp->snd_wnd -= acked;
     1241                ourfinisacked = 0;
     1242            }
     1243            /*
     1244             * XXX sowwakup is called when data is acked and there's room for
     1245             * for more data... it should read() the socket
     1246             */
     1247#if 0
     1248            if (so->so_snd.sb_flags & SB_NOTIFY)
     1249                sowwakeup(so);
     1250#endif
     1251            tp->snd_una = ti->ti_ack;
     1252            if (SEQ_LT(tp->snd_nxt, tp->snd_una))
     1253                tp->snd_nxt = tp->snd_una;
     1254
     1255            switch (tp->t_state)
     1256            {
    11671257                /*
    11681258                 * In FIN_WAIT_1 STATE in addition to the processing
     
    11711261                 */
    11721262                case TCPS_FIN_WAIT_1:
    1173                         if (ourfinisacked) {
    1174                                 /*
    1175                                  * If we can't receive any more
    1176                                  * data, then closing user can proceed.
    1177                                  * Starting the timer is contrary to the
    1178                                  * specification, but if we don't get a FIN
    1179                                  * we'll hang forever.
    1180                                  */
    1181                                 if (so->so_state & SS_FCANTRCVMORE) {
    1182                                         soisfdisconnected(so);
    1183                                         tp->t_timer[TCPT_2MSL] = tcp_maxidle;
    1184                                 }
    1185                                 tp->t_state = TCPS_FIN_WAIT_2;
     1263                    if (ourfinisacked)
     1264                    {
     1265                        /*
     1266                         * If we can't receive any more
     1267                         * data, then closing user can proceed.
     1268                         * Starting the timer is contrary to the
     1269                         * specification, but if we don't get a FIN
     1270                         * we'll hang forever.
     1271                         */
     1272                        if (so->so_state & SS_FCANTRCVMORE)
     1273                        {
     1274                            soisfdisconnected(so);
     1275                            tp->t_timer[TCPT_2MSL] = tcp_maxidle;
    11861276                        }
    1187                         break;
     1277                        tp->t_state = TCPS_FIN_WAIT_2;
     1278                    }
     1279                    break;
    11881280
    11891281                /*
     
    11941286                 */
    11951287                case TCPS_CLOSING:
    1196                         if (ourfinisacked) {
    1197                                 tp->t_state = TCPS_TIME_WAIT;
    1198                                 tcp_canceltimers(tp);
    1199                                 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
    1200                                 soisfdisconnected(so);
    1201                         }
    1202                         break;
     1288                    if (ourfinisacked)
     1289                    {
     1290                        tp->t_state = TCPS_TIME_WAIT;
     1291                        tcp_canceltimers(tp);
     1292                        tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
     1293                        soisfdisconnected(so);
     1294                    }
     1295                    break;
    12031296
    12041297                /*
     
    12091302                 */
    12101303                case TCPS_LAST_ACK:
    1211                         if (ourfinisacked) {
    1212                                 tp = tcp_close(pData, tp);
    1213                                 goto drop;
    1214                         }
    1215                         break;
     1304                    if (ourfinisacked)
     1305                    {
     1306                        tp = tcp_close(pData, tp);
     1307                        goto drop;
     1308                    }
     1309                    break;
    12161310
    12171311                /*
     
    12211315                 */
    12221316                case TCPS_TIME_WAIT:
    1223                         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
    1224                         goto dropafterack;
    1225                 }
    1226         } /* switch(tp->t_state) */
     1317                    tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
     1318                    goto dropafterack;
     1319            }
     1320    } /* switch(tp->t_state) */
    12271321
    12281322step6:
     1323    /*
     1324     * Update window information.
     1325     * Don't look at window if no ACK: TAC's send garbage on first SYN.
     1326     */
     1327    if (   (tiflags & TH_ACK)
     1328        && (   SEQ_LT(tp->snd_wl1, ti->ti_seq)
     1329            || (   tp->snd_wl1 == ti->ti_seq
     1330                && (   SEQ_LT(tp->snd_wl2, ti->ti_ack)
     1331                    || (   tp->snd_wl2 == ti->ti_ack
     1332                        && tiwin > tp->snd_wnd)))))
     1333    {
     1334        /* keep track of pure window updates */
     1335        if (   ti->ti_len == 0
     1336            && tp->snd_wl2 == ti->ti_ack
     1337            && tiwin > tp->snd_wnd)
     1338            tcpstat.tcps_rcvwinupd++;
     1339        tp->snd_wnd = tiwin;
     1340        tp->snd_wl1 = ti->ti_seq;
     1341        tp->snd_wl2 = ti->ti_ack;
     1342        if (tp->snd_wnd > tp->max_sndwnd)
     1343            tp->max_sndwnd = tp->snd_wnd;
     1344        needoutput = 1;
     1345    }
     1346
     1347    /*
     1348     * Process segments with URG.
     1349     */
     1350    if ((tiflags & TH_URG) && ti->ti_urp &&
     1351            TCPS_HAVERCVDFIN(tp->t_state) == 0)
     1352    {
    12291353        /*
    1230          * Update window information.
    1231          * Don't look at window if no ACK: TAC's send garbage on first SYN.
     1354         * This is a kludge, but if we receive and accept
     1355         * random urgent pointers, we'll crash in
     1356         * soreceive.  It's hard to imagine someone
     1357         * actually wanting to send this much urgent data.
    12321358         */
    1233         if ((tiflags & TH_ACK) &&
    1234             (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
    1235             (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
    1236             (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
    1237                 /* keep track of pure window updates */
    1238                 if (ti->ti_len == 0 &&
    1239                     tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
    1240                         tcpstat.tcps_rcvwinupd++;
    1241                 tp->snd_wnd = tiwin;
    1242                 tp->snd_wl1 = ti->ti_seq;
    1243                 tp->snd_wl2 = ti->ti_ack;
    1244                 if (tp->snd_wnd > tp->max_sndwnd)
    1245                         tp->max_sndwnd = tp->snd_wnd;
    1246                 needoutput = 1;
    1247         }
    1248 
     1359        if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen)
     1360        {
     1361            ti->ti_urp = 0;
     1362            tiflags &= ~TH_URG;
     1363            goto dodata;
     1364        }
    12491365        /*
    1250          * Process segments with URG.
     1366         * If this segment advances the known urgent pointer,
     1367         * then mark the data stream.  This should not happen
     1368         * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
     1369         * a FIN has been received from the remote side.
     1370         * In these states we ignore the URG.
     1371         *
     1372         * According to RFC961 (Assigned Protocols),
     1373         * the urgent pointer points to the last octet
     1374         * of urgent data.  We continue, however,
     1375         * to consider it to indicate the first octet
     1376         * of data past the urgent section as the original
     1377         * spec states (in one of two places).
    12511378         */
    1252         if ((tiflags & TH_URG) && ti->ti_urp &&
    1253             TCPS_HAVERCVDFIN(tp->t_state) == 0) {
    1254                 /*
    1255                  * This is a kludge, but if we receive and accept
    1256                  * random urgent pointers, we'll crash in
    1257                  * soreceive.  It's hard to imagine someone
    1258                  * actually wanting to send this much urgent data.
    1259                  */
    1260                 if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) {
    1261                         ti->ti_urp = 0;
    1262                         tiflags &= ~TH_URG;
    1263                         goto dodata;
    1264                 }
    1265                 /*
    1266                  * If this segment advances the known urgent pointer,
    1267                  * then mark the data stream.  This should not happen
    1268                  * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
    1269                  * a FIN has been received from the remote side.
    1270                  * In these states we ignore the URG.
    1271                  *
    1272                  * According to RFC961 (Assigned Protocols),
    1273                  * the urgent pointer points to the last octet
    1274                  * of urgent data.  We continue, however,
    1275                  * to consider it to indicate the first octet
    1276                  * of data past the urgent section as the original
    1277                  * spec states (in one of two places).
    1278                  */
    1279                 if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
    1280                         tp->rcv_up = ti->ti_seq + ti->ti_urp;
    1281                         so->so_urgc =  so->so_rcv.sb_cc +
    1282                                 (tp->rcv_up - tp->rcv_nxt); /* -1; */
    1283                         tp->rcv_up = ti->ti_seq + ti->ti_urp;
    1284 
    1285                 }
    1286         } else
    1287                 /*
    1288                  * If no out of band data is expected,
    1289                  * pull receive urgent pointer along
    1290                  * with the receive window.
    1291                  */
    1292                 if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
    1293                         tp->rcv_up = tp->rcv_nxt;
     1379        if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up))
     1380        {
     1381            tp->rcv_up = ti->ti_seq + ti->ti_urp;
     1382            so->so_urgc =  so->so_rcv.sb_cc +
     1383                (tp->rcv_up - tp->rcv_nxt); /* -1; */
     1384            tp->rcv_up = ti->ti_seq + ti->ti_urp;
     1385        }
     1386    }
     1387    else
     1388        /*
     1389         * If no out of band data is expected,
     1390         * pull receive urgent pointer along
     1391         * with the receive window.
     1392         */
     1393        if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
     1394            tp->rcv_up = tp->rcv_nxt;
    12941395dodata:
    12951396
     1397    /*
     1398     * If this is a small packet, then ACK now - with Nagel
     1399     *      congestion avoidance sender won't send more until
     1400     *      he gets an ACK.
     1401     *
     1402     * See above.
     1403     */
     1404    if (   ti->ti_len
     1405        && (unsigned)ti->ti_len <= 5
     1406        && ((struct tcpiphdr_2 *)ti)->first_char == (char)27)
     1407    {
     1408        tp->t_flags |= TF_ACKNOW;
     1409    }
     1410
     1411    /*
     1412     * Process the segment text, merging it into the TCP sequencing queue,
     1413     * and arranging for acknowledgment of receipt if necessary.
     1414     * This process logically involves adjusting tp->rcv_wnd as data
     1415     * is presented to the user (this happens in tcp_usrreq.c,
     1416     * case PRU_RCVD).  If a FIN has already been received on this
     1417     * connection then we just ignore the text.
     1418     */
     1419    if (   (ti->ti_len || (tiflags&TH_FIN))
     1420        && TCPS_HAVERCVDFIN(tp->t_state) == 0)
     1421    {
     1422        if (   ti->ti_seq == tp->rcv_nxt
     1423            && LIST_EMPTY(&tp->t_segq)
     1424            && tp->t_state == TCPS_ESTABLISHED)
     1425        {
     1426            DELAY_ACK(tp, ti); /* little bit different from BSD declaration see netinet/tcp_input.c */
     1427            tp->rcv_nxt += tlen;
     1428            tiflags = ti->ti_t.th_flags & TH_FIN;
     1429            tcpstat.tcps_rcvpack++;
     1430            tcpstat.tcps_rcvbyte += tlen;
     1431            if (so->so_state & SS_FCANTRCVMORE)
     1432                m_freem(pData, m);
     1433            else
     1434                sbappend(pData, so, m);
     1435        }
     1436        else
     1437        {
     1438            tiflags = tcp_reass(pData, tp, &ti->ti_t, &tlen, m);
     1439            tiflags |= TF_ACKNOW;
     1440        }
    12961441        /*
    1297          * If this is a small packet, then ACK now - with Nagel
    1298          *      congestion avoidance sender won't send more until
    1299          *      he gets an ACK.
    1300          *
    1301          * See above.
     1442         * Note the amount of data that peer has sent into
     1443         * our window, in order to estimate the sender's
     1444         * buffer size.
    13021445         */
    1303         if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
    1304             ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
    1305                 tp->t_flags |= TF_ACKNOW;
    1306         }
    1307 
    1308         /*
    1309          * Process the segment text, merging it into the TCP sequencing queue,
    1310          * and arranging for acknowledgment of receipt if necessary.
    1311          * This process logically involves adjusting tp->rcv_wnd as data
    1312          * is presented to the user (this happens in tcp_usrreq.c,
    1313          * case PRU_RCVD).  If a FIN has already been received on this
    1314          * connection then we just ignore the text.
    1315          */
    1316         if ((ti->ti_len || (tiflags&TH_FIN)) &&
    1317             TCPS_HAVERCVDFIN(tp->t_state) == 0) {
    1318                 if (ti->ti_seq == tp->rcv_nxt
    1319                 && LIST_EMPTY(&tp->t_segq)
    1320                 && tp->t_state == TCPS_ESTABLISHED) {
    1321                     DELAY_ACK(tp, ti); /* little bit different from BSD declaration see netinet/tcp_input.c */
    1322                     tp->rcv_nxt += tlen;
    1323                     tiflags = ti->ti_t.th_flags & TH_FIN;
    1324                     tcpstat.tcps_rcvpack++;
    1325                     tcpstat.tcps_rcvbyte += tlen;
    1326                     if (so->so_state & SS_FCANTRCVMORE)
    1327                         m_freem(pData, m);
    1328                     else
    1329                         sbappend(pData, so, m);
    1330                 }
    1331                 else {
    1332                     tiflags = tcp_reass(pData, tp, &ti->ti_t, &tlen, m);
    1333                     tiflags |= TF_ACKNOW;
    1334                 }
    1335                 /*
    1336                  * Note the amount of data that peer has sent into
    1337                  * our window, in order to estimate the sender's
    1338                  * buffer size.
    1339                  */
    1340                 len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt);
    1341         } else {
    1342                 m_free(pData, m);
    1343                 tiflags &= ~TH_FIN;
    1344         }
    1345 
    1346         /*
    1347          * If FIN is received ACK the FIN and let the user know
    1348          * that the connection is closing.
    1349          */
    1350         if (tiflags & TH_FIN) {
    1351                 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
    1352                         /*
    1353                          * If we receive a FIN we can't send more data,
    1354                          * set it SS_FDRAIN
    1355                          * Shutdown the socket if there is no rx data in the
    1356                          * buffer.
    1357                          * soread() is called on completion of shutdown() and
    1358                          * will got to TCPS_LAST_ACK, and use tcp_output()
    1359                          * to send the FIN.
    1360                          */
    1361 /*                      sofcantrcvmore(so); */
    1362                         sofwdrain(so);
    1363 
    1364                         tp->t_flags |= TF_ACKNOW;
    1365                         tp->rcv_nxt++;
    1366                 }
    1367                 switch (tp->t_state) {
    1368 
    1369                 /*
    1370                  * In SYN_RECEIVED and ESTABLISHED STATES
    1371                  * enter the CLOSE_WAIT state.
    1372                  */
    1373                 case TCPS_SYN_RECEIVED:
    1374                 case TCPS_ESTABLISHED:
    1375                   if(so->so_emu == EMU_CTL)        /* no shutdown on socket */
     1446        len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt);
     1447    }
     1448    else
     1449    {
     1450        m_free(pData, m);
     1451        tiflags &= ~TH_FIN;
     1452    }
     1453
     1454    /*
     1455     * If FIN is received ACK the FIN and let the user know
     1456     * that the connection is closing.
     1457     */
     1458    if (tiflags & TH_FIN)
     1459    {
     1460        if (TCPS_HAVERCVDFIN(tp->t_state) == 0)
     1461        {
     1462            /*
     1463             * If we receive a FIN we can't send more data,
     1464             * set it SS_FDRAIN
     1465             * Shutdown the socket if there is no rx data in the
     1466             * buffer.
     1467             * soread() is called on completion of shutdown() and
     1468             * will got to TCPS_LAST_ACK, and use tcp_output()
     1469             * to send the FIN.
     1470             */
     1471/*          sofcantrcvmore(so); */
     1472            sofwdrain(so);
     1473
     1474            tp->t_flags |= TF_ACKNOW;
     1475            tp->rcv_nxt++;
     1476        }
     1477        switch (tp->t_state)
     1478        {
     1479            /*
     1480             * In SYN_RECEIVED and ESTABLISHED STATES
     1481             * enter the CLOSE_WAIT state.
     1482             */
     1483            case TCPS_SYN_RECEIVED:
     1484            case TCPS_ESTABLISHED:
     1485                if(so->so_emu == EMU_CTL)        /* no shutdown on socket */
    13761486                    tp->t_state = TCPS_LAST_ACK;
    1377                   else
     1487                else
    13781488                    tp->t_state = TCPS_CLOSE_WAIT;
    1379                   break;
    1380 
    1381                 /*
    1382                  * If still in FIN_WAIT_1 STATE FIN has not been acked so
    1383                  * enter the CLOSING state.
    1384                  */
    1385                 case TCPS_FIN_WAIT_1:
    1386                         tp->t_state = TCPS_CLOSING;
    1387                         break;
    1388 
    1389                 /*
    1390                  * In FIN_WAIT_2 state enter the TIME_WAIT state,
    1391                  * starting the time-wait timer, turning off the other
    1392                  * standard timers.
    1393                  */
    1394                 case TCPS_FIN_WAIT_2:
    1395                         tp->t_state = TCPS_TIME_WAIT;
    1396                         tcp_canceltimers(tp);
    1397                         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
    1398                         soisfdisconnected(so);
    1399                         break;
    1400 
    1401                 /*
    1402                  * In TIME_WAIT state restart the 2 MSL time_wait timer.
    1403                  */
    1404                 case TCPS_TIME_WAIT:
    1405                         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
    1406                         break;
    1407                 }
    1408         }
    1409 
    1410         /*
    1411          * Return any desired output.
    1412          */
    1413         if (needoutput || (tp->t_flags & TF_ACKNOW)) {
    1414                 (void) tcp_output(pData, tp);
    1415         }
    1416         return;
     1489                break;
     1490
     1491            /*
     1492             * If still in FIN_WAIT_1 STATE FIN has not been acked so
     1493             * enter the CLOSING state.
     1494             */
     1495            case TCPS_FIN_WAIT_1:
     1496                tp->t_state = TCPS_CLOSING;
     1497                break;
     1498
     1499            /*
     1500             * In FIN_WAIT_2 state enter the TIME_WAIT state,
     1501             * starting the time-wait timer, turning off the other
     1502             * standard timers.
     1503             */
     1504            case TCPS_FIN_WAIT_2:
     1505                tp->t_state = TCPS_TIME_WAIT;
     1506                tcp_canceltimers(tp);
     1507                tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
     1508                soisfdisconnected(so);
     1509                break;
     1510
     1511            /*
     1512             * In TIME_WAIT state restart the 2 MSL time_wait timer.
     1513             */
     1514            case TCPS_TIME_WAIT:
     1515                tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
     1516                break;
     1517        }
     1518    }
     1519
     1520    /*
     1521     * Return any desired output.
     1522     */
     1523    if (needoutput || (tp->t_flags & TF_ACKNOW))
     1524        tcp_output(pData, tp);
     1525
     1526    return;
    14171527
    14181528dropafterack:
    1419         /*
    1420          * Generate an ACK dropping incoming segment if it occupies
    1421          * sequence space, where the ACK reflects our state.
    1422          */
    1423         if (tiflags & TH_RST)
    1424                 goto drop;
    1425         m_freem(pData, m);
    1426         tp->t_flags |= TF_ACKNOW;
    1427         (void) tcp_output(pData, tp);
    1428         return;
     1529    /*
     1530     * Generate an ACK dropping incoming segment if it occupies
     1531     * sequence space, where the ACK reflects our state.
     1532     */
     1533    if (tiflags & TH_RST)
     1534        goto drop;
     1535    m_freem(pData, m);
     1536    tp->t_flags |= TF_ACKNOW;
     1537    (void) tcp_output(pData, tp);
     1538    return;
    14291539
    14301540dropwithreset:
    1431         /* reuses m if m!=NULL, m_free() unnecessary */
    1432         if (tiflags & TH_ACK)
    1433                 tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
    1434         else {
    1435                 if (tiflags & TH_SYN) ti->ti_len++;
    1436                 tcp_respond(pData, tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
     1541    /* reuses m if m!=NULL, m_free() unnecessary */
     1542    if (tiflags & TH_ACK)
     1543        tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
     1544    else
     1545    {
     1546        if (tiflags & TH_SYN) ti->ti_len++;
     1547        tcp_respond(pData, tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
    14371548                    TH_RST|TH_ACK);
    1438         }
    1439 
    1440         return;
     1549    }
     1550
     1551    return;
    14411552
    14421553drop:
    1443         /*
    1444          * Drop space held by incoming segment and return.
    1445          */
    1446         m_free(pData, m);
    1447 
    1448         return;
     1554    /*
     1555     * Drop space held by incoming segment and return.
     1556     */
     1557    m_free(pData, m);
     1558
     1559    return;
    14491560}
    14501561
    1451  /* , ts_present, ts_val, ts_ecr) */
    1452 /*      int *ts_present;
    1453  *      u_int32_t *ts_val, *ts_ecr;
    1454  */
    14551562void
    14561563tcp_dooptions(PNATState pData, struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
    14571564{
    1458         u_int16_t mss;
    1459         int opt, optlen;
    1460 
    1461         DEBUG_CALL("tcp_dooptions");
    1462         DEBUG_ARGS((dfd," tp = %lx  cnt=%i \n", (long )tp, cnt));
    1463 
    1464         for (; cnt > 0; cnt -= optlen, cp += optlen) {
    1465                 opt = cp[0];
    1466                 if (opt == TCPOPT_EOL)
    1467                         break;
    1468                 if (opt == TCPOPT_NOP)
    1469                         optlen = 1;
    1470                 else {
    1471                         optlen = cp[1];
    1472                         if (optlen <= 0)
    1473                                 break;
     1565    u_int16_t mss;
     1566    int opt, optlen;
     1567
     1568    DEBUG_CALL("tcp_dooptions");
     1569    DEBUG_ARGS((dfd," tp = %lx  cnt=%i \n", (long )tp, cnt));
     1570
     1571    for (; cnt > 0; cnt -= optlen, cp += optlen)
     1572    {
     1573        opt = cp[0];
     1574        if (opt == TCPOPT_EOL)
     1575            break;
     1576        if (opt == TCPOPT_NOP)
     1577            optlen = 1;
     1578        else
     1579        {
     1580            optlen = cp[1];
     1581            if (optlen <= 0)
     1582                break;
     1583        }
     1584        switch (opt)
     1585        {
     1586            default:
     1587                continue;
     1588
     1589            case TCPOPT_MAXSEG:
     1590                if (optlen != TCPOLEN_MAXSEG)
     1591                    continue;
     1592                if (!(ti->ti_flags & TH_SYN))
     1593                    continue;
     1594                memcpy((char *) &mss, (char *) cp + 2, sizeof(mss));
     1595                NTOHS(mss);
     1596                (void) tcp_mss(pData, tp, mss); /* sets t_maxseg */
     1597                break;
     1598
     1599#if 0
     1600            case TCPOPT_WINDOW:
     1601                if (optlen != TCPOLEN_WINDOW)
     1602                    continue;
     1603                if (!(ti->ti_flags & TH_SYN))
     1604                    continue;
     1605                tp->t_flags |= TF_RCVD_SCALE;
     1606                tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);
     1607                break;
     1608
     1609            case TCPOPT_TIMESTAMP:
     1610                if (optlen != TCPOLEN_TIMESTAMP)
     1611                    continue;
     1612                *ts_present = 1;
     1613                memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val));
     1614                NTOHL(*ts_val);
     1615                memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr));
     1616                NTOHL(*ts_ecr);
     1617
     1618                /*
     1619                 * A timestamp received in a SYN makes
     1620                 * it ok to send timestamp requests and replies.
     1621                 */
     1622                if (ti->ti_flags & TH_SYN)
     1623                {
     1624                    tp->t_flags |= TF_RCVD_TSTMP;
     1625                    tp->ts_recent = *ts_val;
     1626                    tp->ts_recent_age = tcp_now;
    14741627                }
    1475                 switch (opt) {
    1476 
    1477                 default:
    1478                         continue;
    1479 
    1480                 case TCPOPT_MAXSEG:
    1481                         if (optlen != TCPOLEN_MAXSEG)
    1482                                 continue;
    1483                         if (!(ti->ti_flags & TH_SYN))
    1484                                 continue;
    1485                         memcpy((char *) &mss, (char *) cp + 2, sizeof(mss));
    1486                         NTOHS(mss);
    1487                         (void) tcp_mss(pData, tp, mss); /* sets t_maxseg */
    1488                         break;
    1489 
    1490 /*              case TCPOPT_WINDOW:
    1491  *                      if (optlen != TCPOLEN_WINDOW)
    1492  *                              continue;
    1493  *                      if (!(ti->ti_flags & TH_SYN))
    1494  *                              continue;
    1495  *                      tp->t_flags |= TF_RCVD_SCALE;
    1496  *                      tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);
    1497  *                      break;
    1498  */
    1499 /*              case TCPOPT_TIMESTAMP:
    1500  *                      if (optlen != TCPOLEN_TIMESTAMP)
    1501  *                              continue;
    1502  *                      *ts_present = 1;
    1503  *                      memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val));
    1504  *                      NTOHL(*ts_val);
    1505  *                      memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr));
    1506  *                      NTOHL(*ts_ecr);
    1507  *
    1508  */                     /*
    1509  *                       * A timestamp received in a SYN makes
    1510  *                       * it ok to send timestamp requests and replies.
    1511  *                       */
    1512 /*                      if (ti->ti_flags & TH_SYN) {
    1513  *                              tp->t_flags |= TF_RCVD_TSTMP;
    1514  *                              tp->ts_recent = *ts_val;
    1515  *                              tp->ts_recent_age = tcp_now;
    1516  *                      }
    1517  */                     break;
     1628                break;
     1629#endif
    15181630                }
    15191631        }
     
    15281640 */
    15291641
    1530 #ifdef notdef
    1531 
     1642#if 0
    15321643void
    1533 tcp_pulloutofband(so, ti, m)
    1534         struct socket *so;
    1535         struct tcpiphdr *ti;
    1536         register struct mbuf *m;
     1644tcp_pulloutofband(struct socket *so, struct tcpiphdr *ti, struct mbuf *m)
    15371645{
    1538         int cnt = ti->ti_urp - 1;
    1539 
    1540         while (cnt >= 0) {
    1541                 if (m->m_len > cnt) {
    1542                         char *cp = mtod(m, caddr_t) + cnt;
    1543                         struct tcpcb *tp = sototcpcb(so);
    1544 
    1545                         tp->t_iobc = *cp;
    1546                         tp->t_oobflags |= TCPOOB_HAVEDATA;
    1547                         memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1));
    1548                         m->m_len--;
    1549                         return;
    1550                 }
    1551                 cnt -= m->m_len;
    1552                 m = m->m_next; /* XXX WRONG! Fix it! */
    1553                 if (m == 0)
    1554                         break;
    1555         }
    1556         panic("tcp_pulloutofband");
     1646    int cnt = ti->ti_urp - 1;
     1647
     1648    while (cnt >= 0)
     1649    {
     1650        if (m->m_len > cnt)
     1651        {
     1652            char *cp = mtod(m, caddr_t) + cnt;
     1653            struct tcpcb *tp = sototcpcb(so);
     1654
     1655            tp->t_iobc = *cp;
     1656            tp->t_oobflags |= TCPOOB_HAVEDATA;
     1657            memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1));
     1658            m->m_len--;
     1659            return;
     1660        }
     1661        cnt -= m->m_len;
     1662        m = m->m_next; /* XXX WRONG! Fix it! */
     1663        if (m == 0)
     1664            break;
     1665    }
     1666    panic("tcp_pulloutofband");
    15571667}
    1558 
    1559 #endif /* notdef */
     1668#endif
    15601669
    15611670/*
     
    15671676tcp_xmit_timer(PNATState pData, register struct tcpcb *tp, int rtt)
    15681677{
    1569         register short delta;
    1570 
    1571         DEBUG_CALL("tcp_xmit_timer");
    1572         DEBUG_ARG("tp = %lx", (long)tp);
    1573         DEBUG_ARG("rtt = %d", rtt);
    1574 
    1575         tcpstat.tcps_rttupdated++;
    1576         if (tp->t_srtt != 0) {
    1577                 /*
    1578                  * srtt is stored as fixed point with 3 bits after the
    1579                  * binary point (i.e., scaled by 8).  The following magic
    1580                  * is equivalent to the smoothing algorithm in rfc793 with
    1581                  * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed
    1582                  * point).  Adjust rtt to origin 0.
    1583                  */
    1584                 delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT);
    1585                 if ((tp->t_srtt += delta) <= 0)
    1586                         tp->t_srtt = 1;
    1587                 /*
    1588                  * We accumulate a smoothed rtt variance (actually, a
    1589                  * smoothed mean difference), then set the retransmit
    1590                  * timer to smoothed rtt + 4 times the smoothed variance.
    1591                  * rttvar is stored as fixed point with 2 bits after the
    1592                  * binary point (scaled by 4).  The following is
    1593                  * equivalent to rfc793 smoothing with an alpha of .75
    1594                  * (rttvar = rttvar*3/4 + |delta| / 4).  This replaces
    1595                  * rfc793's wired-in beta.
    1596                  */
    1597                 if (delta < 0)
    1598                         delta = -delta;
    1599                 delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT);
    1600                 if ((tp->t_rttvar += delta) <= 0)
    1601                         tp->t_rttvar = 1;
    1602         } else {
    1603                 /*
    1604                  * No rtt measurement yet - use the unsmoothed rtt.
    1605                  * Set the variance to half the rtt (so our first
    1606                  * retransmit happens at 3*rtt).
    1607                  */
    1608                 tp->t_srtt = rtt << TCP_RTT_SHIFT;
    1609                 tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);
    1610         }
    1611         tp->t_rtt = 0;
    1612         tp->t_rxtshift = 0;
    1613 
     1678    register short delta;
     1679
     1680    DEBUG_CALL("tcp_xmit_timer");
     1681    DEBUG_ARG("tp = %lx", (long)tp);
     1682    DEBUG_ARG("rtt = %d", rtt);
     1683
     1684    tcpstat.tcps_rttupdated++;
     1685    if (tp->t_srtt != 0)
     1686    {
    16141687        /*
    1615          * the retransmit should happen at rtt + 4 * rttvar.
    1616          * Because of the way we do the smoothing, srtt and rttvar
    1617          * will each average +1/2 tick of bias.  When we compute
    1618          * the retransmit timer, we want 1/2 tick of rounding and
    1619          * 1 extra tick because of +-1/2 tick uncertainty in the
    1620          * firing of the timer.  The bias will give us exactly the
    1621          * 1.5 tick we need.  But, because the bias is
    1622          * statistical, we have to test that we don't drop below
    1623          * the minimum feasible timer (which is 2 ticks).
     1688         * srtt is stored as fixed point with 3 bits after the
     1689         * binary point (i.e., scaled by 8).  The following magic
     1690         * is equivalent to the smoothing algorithm in rfc793 with
     1691         * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed
     1692         * point).  Adjust rtt to origin 0.
    16241693         */
    1625         TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
    1626             (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
    1627 
     1694        delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT);
     1695        if ((tp->t_srtt += delta) <= 0)
     1696            tp->t_srtt = 1;
    16281697        /*
    1629          * We received an ack for a packet that wasn't retransmitted;
    1630          * it is probably safe to discard any error indications we've
    1631          * received recently.  This isn't quite right, but close enough
    1632          * for now (a route might have failed after we sent a segment,
    1633          * and the return path might not be symmetrical).
     1698         * We accumulate a smoothed rtt variance (actually, a
     1699         * smoothed mean difference), then set the retransmit
     1700         * timer to smoothed rtt + 4 times the smoothed variance.
     1701         * rttvar is stored as fixed point with 2 bits after the
     1702         * binary point (scaled by 4).  The following is
     1703         * equivalent to rfc793 smoothing with an alpha of .75
     1704         * (rttvar = rttvar*3/4 + |delta| / 4).  This replaces
     1705         * rfc793's wired-in beta.
    16341706         */
    1635         tp->t_softerror = 0;
     1707        if (delta < 0)
     1708            delta = -delta;
     1709        delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT);
     1710        if ((tp->t_rttvar += delta) <= 0)
     1711            tp->t_rttvar = 1;
     1712    }
     1713    else
     1714    {
     1715        /*
     1716         * No rtt measurement yet - use the unsmoothed rtt.
     1717         * Set the variance to half the rtt (so our first
     1718         * retransmit happens at 3*rtt).
     1719         */
     1720        tp->t_srtt = rtt << TCP_RTT_SHIFT;
     1721        tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);
     1722    }
     1723    tp->t_rtt = 0;
     1724    tp->t_rxtshift = 0;
     1725
     1726    /*
     1727     * the retransmit should happen at rtt + 4 * rttvar.
     1728     * Because of the way we do the smoothing, srtt and rttvar
     1729     * will each average +1/2 tick of bias.  When we compute
     1730     * the retransmit timer, we want 1/2 tick of rounding and
     1731     * 1 extra tick because of +-1/2 tick uncertainty in the
     1732     * firing of the timer.  The bias will give us exactly the
     1733     * 1.5 tick we need.  But, because the bias is
     1734     * statistical, we have to test that we don't drop below
     1735     * the minimum feasible timer (which is 2 ticks).
     1736     */
     1737    TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
     1738                  (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
     1739
     1740    /*
     1741     * We received an ack for a packet that wasn't retransmitted;
     1742     * it is probably safe to discard any error indications we've
     1743     * received recently.  This isn't quite right, but close enough
     1744     * for now (a route might have failed after we sent a segment,
     1745     * and the return path might not be symmetrical).
     1746     */
     1747    tp->t_softerror = 0;
    16361748}
    16371749
     
    16551767tcp_mss(PNATState pData, register struct tcpcb *tp, u_int offer)
    16561768{
    1657         struct socket *so = tp->t_socket;
    1658         int mss;
    1659 
    1660         DEBUG_CALL("tcp_mss");
    1661         DEBUG_ARG("tp = %lx", (long)tp);
    1662         DEBUG_ARG("offer = %d", offer);
    1663 
    1664         mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);
    1665         if (offer)
    1666                 mss = min(mss, offer);
    1667         mss = max(mss, 32);
    1668         if (mss < tp->t_maxseg || offer != 0)
    1669            tp->t_maxseg = mss;
    1670 
    1671         tp->snd_cwnd = mss;
    1672 
    1673         sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
    1674         sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
    1675 
    1676         DEBUG_MISC((dfd, " returning mss = %d\n", mss));
    1677 
    1678         return mss;
     1769    struct socket *so = tp->t_socket;
     1770    int mss;
     1771
     1772    DEBUG_CALL("tcp_mss");
     1773    DEBUG_ARG("tp = %lx", (long)tp);
     1774    DEBUG_ARG("offer = %d", offer);
     1775
     1776    mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr);
     1777    if (offer)
     1778        mss = min(mss, offer);
     1779    mss = max(mss, 32);
     1780    if (mss < tp->t_maxseg || offer != 0)
     1781        tp->t_maxseg = mss;
     1782
     1783    tp->snd_cwnd = mss;
     1784
     1785    sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0));
     1786    sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0));
     1787
     1788    DEBUG_MISC((dfd, " returning mss = %d\n", mss));
     1789
     1790    return mss;
    16791791}
  • trunk/src/VBox/Devices/Network/slirp/udp.c

    r15453 r15472  
    246246    }
    247247#endif
    248     if(sosendto(pData, so,m) == -1)
     248    if (sosendto(pData, so, m) == -1)
    249249    {
    250250        m->m_len += iphlen;
    251251        m->m_data -= iphlen;
    252252        *ip = save_ip;
    253         DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
    254         icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
     253        DEBUG_MISC((dfd,"udp tx errno = %d-%s\n", errno, strerror(errno)));
     254        icmp_error(pData, m, ICMP_UNREACH,ICMP_UNREACH_NET, 0, strerror(errno));
    255255    }
    256256
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette