VirtualBox

Changeset 15074 in vbox for trunk


Ignore:
Timestamp:
Dec 7, 2008 10:13:12 PM (16 years ago)
Author:
vboxsync
Message:

slirp: better readability

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/debug.h

    r14882 r15074  
    1111/* Unused anyway, using VBox Log facility. */
    1212#define dfd NULL
    13 extern int dostats;
    14 extern int slirp_debug;
    1513
    1614#define DBG_CALL 0x1
  • trunk/src/VBox/Devices/Network/slirp/tcp_output.c

    r14470 r15074  
    4949 * names instead of the REAL names
    5050 */
    51 const char * const tcpstates[] = {
    52 /*      "CLOSED",       "LISTEN",       "SYN_SENT",     "SYN_RCVD", */
    53         "REDIRECT",     "LISTEN",       "SYN_SENT",     "SYN_RCVD",
    54         "ESTABLISHED",  "CLOSE_WAIT",   "FIN_WAIT_1",   "CLOSING",
    55         "LAST_ACK",     "FIN_WAIT_2",   "TIME_WAIT",
     51const char * const tcpstates[] =
     52{
     53/*  "CLOSED",       "LISTEN",       "SYN_SENT",     "SYN_RCVD", */
     54    "REDIRECT",     "LISTEN",       "SYN_SENT",     "SYN_RCVD",
     55    "ESTABLISHED",  "CLOSE_WAIT",   "FIN_WAIT_1",   "CLOSING",
     56    "LAST_ACK",     "FIN_WAIT_2",   "TIME_WAIT",
    5657};
    5758
    58 static const u_char  tcp_outflags[TCP_NSTATES] = {
    59         TH_RST|TH_ACK, 0,      TH_SYN,        TH_SYN|TH_ACK,
    60         TH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
    61         TH_FIN|TH_ACK, TH_ACK, TH_ACK,
     59static const u_char  tcp_outflags[TCP_NSTATES] =
     60{
     61    TH_RST|TH_ACK, 0,      TH_SYN,        TH_SYN|TH_ACK,
     62    TH_ACK,        TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
     63    TH_FIN|TH_ACK, TH_ACK, TH_ACK,
    6264};
    6365
     
    7173tcp_output(PNATState pData, register struct tcpcb *tp)
    7274{
    73         register struct socket *so = tp->t_socket;
    74         register long len, win;
    75         int off, flags, error;
    76         register struct mbuf *m;
    77         register struct tcpiphdr *ti;
    78         u_char opt[MAX_TCPOPTLEN];
    79         unsigned optlen, hdrlen;
    80         int idle, sendalot;
    81 
    82         DEBUG_CALL("tcp_output");
    83         DEBUG_ARG("tp = %lx", (long )tp);
    84 
    85         /*
    86          * Determine length of data that should be transmitted,
    87          * and flags that will be used.
    88          * If there is some data or critical controls (SYN, RST)
    89          * to send, then transmit; otherwise, investigate further.
    90          */
    91         idle = (tp->snd_max == tp->snd_una);
    92         if (idle && tp->t_idle >= tp->t_rxtcur)
    93                 /*
    94                  * We have been idle for "a while" and no acks are
    95                  * expected to clock out any data we send --
    96                  * slow start to get ack "clock" running again.
    97                  */
    98                 tp->snd_cwnd = tp->t_maxseg;
     75    register struct socket *so = tp->t_socket;
     76    register long len, win;
     77    int off, flags, error;
     78    register struct mbuf *m;
     79    register struct tcpiphdr *ti;
     80    u_char opt[MAX_TCPOPTLEN];
     81    unsigned optlen, hdrlen;
     82    int idle, sendalot;
     83
     84    DEBUG_CALL("tcp_output");
     85    DEBUG_ARG("tp = %lx", (long )tp);
     86
     87    /*
     88     * Determine length of data that should be transmitted,
     89     * and flags that will be used.
     90     * If there is some data or critical controls (SYN, RST)
     91     * to send, then transmit; otherwise, investigate further.
     92     */
     93    idle = (tp->snd_max == tp->snd_una);
     94    if (idle && tp->t_idle >= tp->t_rxtcur)
     95        /*
     96         * We have been idle for "a while" and no acks are
     97         * expected to clock out any data we send --
     98         * slow start to get ack "clock" running again.
     99         */
     100        tp->snd_cwnd = tp->t_maxseg;
     101
    99102again:
    100         sendalot = 0;
    101         off = tp->snd_nxt - tp->snd_una;
    102         win = min(tp->snd_wnd, tp->snd_cwnd);
    103 
    104         flags = tcp_outflags[tp->t_state];
    105 
    106         DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
    107 
    108         /*
    109          * If in persist timeout with window of 0, send 1 byte.
    110          * Otherwise, if window is small but nonzero
    111          * and timer expired, we will send what we can
    112          * and go to transmit state.
    113          */
    114         if (tp->t_force) {
    115                 if (win == 0) {
    116                         /*
    117                          * If we still have some data to send, then
    118                          * clear the FIN bit.  Usually this would
    119                          * happen below when it realizes that we
    120                          * aren't sending all the data.  However,
    121                          * if we have exactly 1 byte of unset data,
    122                          * then it won't clear the FIN bit below,
    123                          * and if we are in persist state, we wind
    124                          * up sending the packet without recording
    125                          * that we sent the FIN bit.
    126                          *
    127                          * We can't just blindly clear the FIN bit,
    128                          * because if we don't have any more data
    129                          * to send then the probe will be the FIN
    130                          * itself.
    131                          */
    132                         if (off < so->so_snd.sb_cc)
    133                                 flags &= ~TH_FIN;
    134                         win = 1;
    135                 } else {
    136                         tp->t_timer[TCPT_PERSIST] = 0;
    137                         tp->t_rxtshift = 0;
    138                 }
    139         }
    140 
    141         len = min(so->so_snd.sb_cc, win) - off;
    142 
    143         if (len < 0) {
    144                 /*
    145                  * If FIN has been sent but not acked,
    146                  * but we haven't been called to retransmit,
    147                  * len will be -1.  Otherwise, window shrank
    148                  * after we sent into it.  If window shrank to 0,
    149                  * cancel pending retransmit and pull snd_nxt
    150                  * back to (closed) window.  We will enter persist
    151                  * state below.  If the window didn't close completely,
    152                  * just wait for an ACK.
    153                  */
     103    sendalot = 0;
     104    off = tp->snd_nxt - tp->snd_una;
     105    win = min(tp->snd_wnd, tp->snd_cwnd);
     106
     107    flags = tcp_outflags[tp->t_state];
     108
     109    DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
     110
     111    /*
     112     * If in persist timeout with window of 0, send 1 byte.
     113     * Otherwise, if window is small but nonzero
     114     * and timer expired, we will send what we can
     115     * and go to transmit state.
     116     */
     117    if (tp->t_force)
     118    {
     119        if (win == 0)
     120        {
     121            /*
     122             * If we still have some data to send, then
     123             * clear the FIN bit.  Usually this would
     124             * happen below when it realizes that we
     125             * aren't sending all the data.  However,
     126             * if we have exactly 1 byte of unset data,
     127             * then it won't clear the FIN bit below,
     128             * and if we are in persist state, we wind
     129             * up sending the packet without recording
     130             * that we sent the FIN bit.
     131             *
     132             * We can't just blindly clear the FIN bit,
     133             * because if we don't have any more data
     134             * to send then the probe will be the FIN
     135             * itself.
     136             */
     137            if (off < so->so_snd.sb_cc)
     138                flags &= ~TH_FIN;
     139            win = 1;
     140        }
     141        else
     142        {
     143            tp->t_timer[TCPT_PERSIST] = 0;
     144            tp->t_rxtshift = 0;
     145        }
     146    }
     147
     148    len = min(so->so_snd.sb_cc, win) - off;
     149    if (len < 0)
     150    {
     151        /*
     152         * If FIN has been sent but not acked,
     153         * but we haven't been called to retransmit,
     154         * len will be -1.  Otherwise, window shrank
     155         * after we sent into it.  If window shrank to 0,
     156         * cancel pending retransmit and pull snd_nxt
     157         * back to (closed) window.  We will enter persist
     158         * state below.  If the window didn't close completely,
     159         * just wait for an ACK.
     160         */
     161        len = 0;
     162        if (win == 0)
     163        {
     164            tp->t_timer[TCPT_REXMT] = 0;
     165            tp->snd_nxt = tp->snd_una;
     166        }
     167    }
     168    if (len > tp->t_maxseg)
     169    {
     170        len = tp->t_maxseg;
     171        sendalot = 1;
     172    }
     173    if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
     174        flags &= ~TH_FIN;
     175
     176    win = sbspace(&so->so_rcv);
     177
     178    /*
     179     * Sender silly window avoidance.  If connection is idle
     180     * and can send all data, a maximum segment,
     181     * at least a maximum default-size segment do it,
     182     * or are forced, do it; otherwise don't bother.
     183     * If peer's buffer is tiny, then send
     184     * when window is at least half open.
     185     * If retransmitting (possibly after persist timer forced us
     186     * to send into a small window), then must resend.
     187     */
     188    if (len)
     189    {
     190        if (len == tp->t_maxseg)
     191            goto send;
     192        if ((1 || idle || tp->t_flags & TF_NODELAY) &&
     193                len + off >= so->so_snd.sb_cc)
     194            goto send;
     195        if (tp->t_force)
     196            goto send;
     197        if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
     198            goto send;
     199        if (SEQ_LT(tp->snd_nxt, tp->snd_max))
     200            goto send;
     201    }
     202
     203    /*
     204     * Compare available window to amount of window
     205     * known to peer (as advertised window less
     206     * next expected input).  If the difference is at least two
     207     * max size segments, or at least 50% of the maximum possible
     208     * window, then want to send a window update to peer.
     209     */
     210    if (win > 0)
     211    {
     212        /*
     213         * "adv" is the amount we can increase the window,
     214         * taking into account that we are limited by
     215         * TCP_MAXWIN << tp->rcv_scale.
     216         */
     217        long adv = min(win,
     218                       (long)TCP_MAXWIN << tp->rcv_scale) -
     219                       (tp->rcv_adv - tp->rcv_nxt);
     220
     221        if (adv >= (long) (2 * tp->t_maxseg))
     222            goto send;
     223        if (2 * adv >= (long) so->so_rcv.sb_datalen)
     224            goto send;
     225    }
     226
     227    /*
     228     * Send if we owe peer an ACK.
     229     */
     230    if (tp->t_flags & TF_ACKNOW)
     231        goto send;
     232    if (flags & (TH_SYN|TH_RST))
     233        goto send;
     234    if (SEQ_GT(tp->snd_up, tp->snd_una))
     235        goto send;
     236    /*
     237     * If our state indicates that FIN should be sent
     238     * and we have not yet done so, or we're retransmitting the FIN,
     239     * then we need to send.
     240     */
     241    if (   flags & TH_FIN
     242        && ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
     243        goto send;
     244
     245    /*
     246     * TCP window updates are not reliable, rather a polling protocol
     247     * using ``persist'' packets is used to insure receipt of window
     248     * updates.  The three ``states'' for the output side are:
     249     *      idle                    not doing retransmits or persists
     250     *      persisting              to move a small or zero window
     251     *      (re)transmitting        and thereby not persisting
     252     *
     253     * tp->t_timer[TCPT_PERSIST]
     254     *      is set when we are in persist state.
     255     * tp->t_force
     256     *      is set when we are called to send a persist packet.
     257     * tp->t_timer[TCPT_REXMT]
     258     *      is set when we are retransmitting
     259     * The output side is idle when both timers are zero.
     260     *
     261     * If send window is too small, there is data to transmit, and no
     262     * retransmit or persist is pending, then go to persist state.
     263     * If nothing happens soon, send when timer expires:
     264     * if window is nonzero, transmit what we can,
     265     * otherwise force out a byte.
     266     */
     267    if (   so->so_snd.sb_cc
     268        && tp->t_timer[TCPT_REXMT] == 0
     269        && tp->t_timer[TCPT_PERSIST] == 0)
     270    {
     271        tp->t_rxtshift = 0;
     272        tcp_setpersist(tp);
     273    }
     274
     275    /*
     276     * No reason to send a segment, just return.
     277     */
     278    tcpstat.tcps_didnuttin++;
     279
     280    return (0);
     281
     282send:
     283    /*
     284     * Before ESTABLISHED, force sending of initial options
     285     * unless TCP set not to do any options.
     286     * NOTE: we assume that the IP/TCP header plus TCP options
     287     * always fit in a single mbuf, leaving room for a maximum
     288     * link header, i.e.
     289     *      max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
     290     */
     291    optlen = 0;
     292    hdrlen = sizeof (struct tcpiphdr);
     293    if (flags & TH_SYN)
     294    {
     295        tp->snd_nxt = tp->iss;
     296        if ((tp->t_flags & TF_NOOPT) == 0)
     297        {
     298            u_int16_t mss;
     299
     300            opt[0] = TCPOPT_MAXSEG;
     301            opt[1] = 4;
     302            mss = htons((u_int16_t) tcp_mss(pData, tp, 0));
     303            memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
     304            optlen = 4;
     305
     306#if 0
     307            if (   (tp->t_flags & TF_REQ_SCALE)
     308                && (   (flags & TH_ACK) == 0
     309                    || (tp->t_flags & TF_RCVD_SCALE)))
     310            {
     311                *((u_int32_t *) (opt + optlen)) = htonl(  TCPOPT_NOP << 24
     312                                                        | TCPOPT_WINDOW << 16
     313                                                        | TCPOLEN_WINDOW << 8
     314                                                        | tp->request_r_scale);
     315                optlen += 4;
     316            }
     317#endif
     318        }
     319    }
     320
     321    /*
     322     * Send a timestamp and echo-reply if this is a SYN and our side
     323     * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
     324     * and our peer have sent timestamps in our SYN's.
     325     */
     326#if 0
     327    if (   (tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP
     328        && (flags & TH_RST) == 0
     329        && (   (flags & (TH_SYN|TH_ACK)) == TH_SYN
     330            || (tp->t_flags & TF_RCVD_TSTMP)))
     331    {
     332        u_int32_t *lp = (u_int32_t *)(opt + optlen);
     333
     334        /* Form timestamp option as shown in appendix A of RFC 1323. */
     335        *lp++ = htonl(TCPOPT_TSTAMP_HDR);
     336        *lp++ = htonl(tcp_now);
     337        *lp   = htonl(tp->ts_recent);
     338        optlen += TCPOLEN_TSTAMP_APPA;
     339    }
     340#endif
     341    hdrlen += optlen;
     342
     343    /*
     344     * Adjust data length if insertion of options will
     345     * bump the packet length beyond the t_maxseg length.
     346     */
     347    if (len > tp->t_maxseg - optlen)
     348    {
     349        len = tp->t_maxseg - optlen;
     350        sendalot = 1;
     351    }
     352
     353    /*
     354     * Grab a header mbuf, attaching a copy of data to
     355     * be transmitted, and initialize the header from
     356     * the template for sends on this connection.
     357     */
     358    if (len)
     359    {
     360        if (tp->t_force && len == 1)
     361            tcpstat.tcps_sndprobe++;
     362        else if (SEQ_LT(tp->snd_nxt, tp->snd_max))
     363        {
     364            tcpstat.tcps_sndrexmitpack++;
     365            tcpstat.tcps_sndrexmitbyte += len;
     366        }
     367        else
     368        {
     369            tcpstat.tcps_sndpack++;
     370            tcpstat.tcps_sndbyte += len;
     371        }
     372
     373        m = m_get(pData);
     374        if (m == NULL)
     375        {
     376/*          error = ENOBUFS; */
     377            error = 1;
     378            goto out;
     379        }
     380        m->m_data += if_maxlinkhdr;
     381        m->m_len = hdrlen;
     382
     383        /*
     384         * This will always succeed, since we make sure our mbufs
     385         * are big enough to hold one MSS packet + header + ... etc.
     386         */
     387#if 0
     388        if (len <= MHLEN - hdrlen - max_linkhdr)
     389        {
     390#endif
     391            sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
     392            m->m_len += len;
     393#if 0
     394        }
     395        else
     396        {
     397            m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
     398            if (m->m_next == 0)
    154399                len = 0;
    155                 if (win == 0) {
    156                         tp->t_timer[TCPT_REXMT] = 0;
    157                         tp->snd_nxt = tp->snd_una;
    158                 }
    159         }
    160 
    161         if (len > tp->t_maxseg) {
    162                 len = tp->t_maxseg;
    163                 sendalot = 1;
    164         }
    165         if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
    166                 flags &= ~TH_FIN;
    167 
    168         win = sbspace(&so->so_rcv);
    169 
    170         /*
    171          * Sender silly window avoidance.  If connection is idle
    172          * and can send all data, a maximum segment,
    173          * at least a maximum default-size segment do it,
    174          * or are forced, do it; otherwise don't bother.
    175          * If peer's buffer is tiny, then send
    176          * when window is at least half open.
    177          * If retransmitting (possibly after persist timer forced us
    178          * to send into a small window), then must resend.
    179          */
    180         if (len) {
    181                 if (len == tp->t_maxseg)
    182                         goto send;
    183                 if ((1 || idle || tp->t_flags & TF_NODELAY) &&
    184                     len + off >= so->so_snd.sb_cc)
    185                         goto send;
    186                 if (tp->t_force)
    187                         goto send;
    188                 if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
    189                         goto send;
    190                 if (SEQ_LT(tp->snd_nxt, tp->snd_max))
    191                         goto send;
    192         }
    193 
    194         /*
    195          * Compare available window to amount of window
    196          * known to peer (as advertised window less
    197          * next expected input).  If the difference is at least two
    198          * max size segments, or at least 50% of the maximum possible
    199          * window, then want to send a window update to peer.
    200          */
    201         if (win > 0) {
    202                 /*
    203                  * "adv" is the amount we can increase the window,
    204                  * taking into account that we are limited by
    205                  * TCP_MAXWIN << tp->rcv_scale.
    206                  */
    207                 long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
    208                         (tp->rcv_adv - tp->rcv_nxt);
    209 
    210                 if (adv >= (long) (2 * tp->t_maxseg))
    211                         goto send;
    212                 if (2 * adv >= (long) so->so_rcv.sb_datalen)
    213                         goto send;
    214         }
    215 
    216         /*
    217          * Send if we owe peer an ACK.
    218          */
     400        }
     401#endif
     402        /*
     403         * If we're sending everything we've got, set PUSH.
     404         * (This will keep happy those implementations which only
     405         * give data to the user when a buffer fills or
     406         * a PUSH comes in.)
     407         */
     408        if (off + len == so->so_snd.sb_cc)
     409            flags |= TH_PUSH;
     410    }
     411    else
     412    {
    219413        if (tp->t_flags & TF_ACKNOW)
    220                 goto send;
    221         if (flags & (TH_SYN|TH_RST))
    222                 goto send;
    223         if (SEQ_GT(tp->snd_up, tp->snd_una))
    224                 goto send;
    225         /*
    226          * If our state indicates that FIN should be sent
    227          * and we have not yet done so, or we're retransmitting the FIN,
    228          * then we need to send.
    229          */
    230         if (flags & TH_FIN &&
    231             ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
    232                 goto send;
    233 
    234         /*
    235          * TCP window updates are not reliable, rather a polling protocol
    236          * using ``persist'' packets is used to insure receipt of window
    237          * updates.  The three ``states'' for the output side are:
    238          *      idle                    not doing retransmits or persists
    239          *      persisting              to move a small or zero window
    240          *      (re)transmitting        and thereby not persisting
    241          *
    242          * tp->t_timer[TCPT_PERSIST]
    243          *      is set when we are in persist state.
    244          * tp->t_force
    245          *      is set when we are called to send a persist packet.
    246          * tp->t_timer[TCPT_REXMT]
    247          *      is set when we are retransmitting
    248          * The output side is idle when both timers are zero.
    249          *
    250          * If send window is too small, there is data to transmit, and no
    251          * retransmit or persist is pending, then go to persist state.
    252          * If nothing happens soon, send when timer expires:
    253          * if window is nonzero, transmit what we can,
    254          * otherwise force out a byte.
    255          */
    256         if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
    257             tp->t_timer[TCPT_PERSIST] == 0) {
     414            tcpstat.tcps_sndacks++;
     415        else if (flags & (TH_SYN|TH_FIN|TH_RST))
     416            tcpstat.tcps_sndctrl++;
     417        else if (SEQ_GT(tp->snd_up, tp->snd_una))
     418            tcpstat.tcps_sndurg++;
     419        else
     420            tcpstat.tcps_sndwinup++;
     421
     422        m = m_get(pData);
     423        if (m == NULL)
     424        {
     425/*          error = ENOBUFS; */
     426            error = 1;
     427            goto out;
     428        }
     429        m->m_data += if_maxlinkhdr;
     430        m->m_len = hdrlen;
     431    }
     432
     433    ti = mtod(m, struct tcpiphdr *);
     434
     435    memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
     436
     437    /*
     438     * Fill in fields, remembering maximum advertised
     439     * window for use in delaying messages about window sizes.
     440     * If resending a FIN, be sure not to use a new sequence number.
     441     */
     442    if (   flags & TH_FIN
     443        && tp->t_flags & TF_SENTFIN
     444        && tp->snd_nxt == tp->snd_max)
     445        tp->snd_nxt--;
     446    /*
     447     * If we are doing retransmissions, then snd_nxt will
     448     * not reflect the first unsent octet.  For ACK only
     449     * packets, we do not want the sequence number of the
     450     * retransmitted packet, we want the sequence number
     451     * of the next unsent octet.  So, if there is no data
     452     * (and no SYN or FIN), use snd_max instead of snd_nxt
     453     * when filling in ti_seq.  But if we are in persist
     454     * state, snd_max might reflect one byte beyond the
     455     * right edge of the window, so use snd_nxt in that
     456     * case, since we know we aren't doing a retransmission.
     457     * (retransmit and persist are mutually exclusive...)
     458     */
     459    if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
     460        ti->ti_seq = htonl(tp->snd_nxt);
     461    else
     462        ti->ti_seq = htonl(tp->snd_max);
     463    ti->ti_ack = htonl(tp->rcv_nxt);
     464    if (optlen)
     465    {
     466        memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
     467        ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
     468    }
     469    ti->ti_flags = flags;
     470    /*
     471     * Calculate receive window.  Don't shrink window,
     472     * but avoid silly window syndrome.
     473     */
     474    if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
     475        win = 0;
     476    if (win > (long)TCP_MAXWIN << tp->rcv_scale)
     477        win = (long)TCP_MAXWIN << tp->rcv_scale;
     478    if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
     479        win = (long)(tp->rcv_adv - tp->rcv_nxt);
     480    ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
     481
     482#if 0
     483    if (SEQ_GT(tp->snd_up, tp->snd_nxt))
     484    {
     485        ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
     486#else
     487    if (SEQ_GT(tp->snd_up, tp->snd_una))
     488    {
     489        ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
     490#endif
     491        ti->ti_flags |= TH_URG;
     492    }
     493    else
     494        /*
     495         * If no urgent pointer to send, then we pull
     496         * the urgent pointer to the left edge of the send window
     497         * so that it doesn't drift into the send window on sequence
     498         * number wraparound.
     499         */
     500        tp->snd_up = tp->snd_una;               /* drag it along */
     501
     502    /*
     503     * Put TCP length in extended header, and then
     504     * checksum extended header and data.
     505     */
     506    if (len + optlen)
     507        ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr)
     508                                       + optlen + len));
     509    ti->ti_sum = cksum(m, (int)(hdrlen + len));
     510
     511    /*
     512     * In transmit state, time the transmission and arrange for
     513     * the retransmit.  In persist state, just set snd_max.
     514     */
     515    if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0)
     516    {
     517        tcp_seq startseq = tp->snd_nxt;
     518
     519        /*
     520         * Advance snd_nxt over sequence space of this segment.
     521         */
     522        if (flags & (TH_SYN|TH_FIN))
     523        {
     524            if (flags & TH_SYN)
     525                tp->snd_nxt++;
     526            if (flags & TH_FIN)
     527            {
     528                tp->snd_nxt++;
     529                tp->t_flags |= TF_SENTFIN;
     530            }
     531        }
     532        tp->snd_nxt += len;
     533        if (SEQ_GT(tp->snd_nxt, tp->snd_max))
     534        {
     535            tp->snd_max = tp->snd_nxt;
     536            /*
     537             * Time this transmission if not a retransmission and
     538             * not currently timing anything.
     539             */
     540            if (tp->t_rtt == 0)
     541            {
     542                tp->t_rtt = 1;
     543                tp->t_rtseq = startseq;
     544                tcpstat.tcps_segstimed++;
     545            }
     546        }
     547
     548        /*
     549         * Set retransmit timer if not currently set,
     550         * and not doing an ack or a keep-alive probe.
     551         * Initial value for retransmit timer is smoothed
     552         * round-trip time + 2 * round-trip time variance.
     553         * Initialize shift counter which is used for backoff
     554         * of retransmit time.
     555         */
     556        if (   tp->t_timer[TCPT_REXMT] == 0
     557            && tp->snd_nxt != tp->snd_una)
     558        {
     559            tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
     560            if (tp->t_timer[TCPT_PERSIST])
     561            {
     562                tp->t_timer[TCPT_PERSIST] = 0;
    258563                tp->t_rxtshift = 0;
    259                 tcp_setpersist(tp);
    260         }
    261 
    262         /*
    263          * No reason to send a segment, just return.
    264          */
    265         tcpstat.tcps_didnuttin++;
    266 
    267         return (0);
    268 
    269 send:
    270         /*
    271          * Before ESTABLISHED, force sending of initial options
    272          * unless TCP set not to do any options.
    273          * NOTE: we assume that the IP/TCP header plus TCP options
    274          * always fit in a single mbuf, leaving room for a maximum
    275          * link header, i.e.
    276          *      max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
    277          */
    278         optlen = 0;
    279         hdrlen = sizeof (struct tcpiphdr);
    280         if (flags & TH_SYN) {
    281                 tp->snd_nxt = tp->iss;
    282                 if ((tp->t_flags & TF_NOOPT) == 0) {
    283                         u_int16_t mss;
    284 
    285                         opt[0] = TCPOPT_MAXSEG;
    286                         opt[1] = 4;
    287                         mss = htons((u_int16_t) tcp_mss(pData, tp, 0));
    288                         memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
    289                         optlen = 4;
    290 
    291 /*                      if ((tp->t_flags & TF_REQ_SCALE) &&
    292  *                          ((flags & TH_ACK) == 0 ||
    293  *                          (tp->t_flags & TF_RCVD_SCALE))) {
    294  *                              *((u_int32_t *) (opt + optlen)) = htonl(
    295  *                                      TCPOPT_NOP << 24 |
    296  *                                      TCPOPT_WINDOW << 16 |
    297  *                                      TCPOLEN_WINDOW << 8 |
    298  *                                      tp->request_r_scale);
    299  *                              optlen += 4;
    300  *                      }
    301  */
    302                 }
    303         }
    304 
    305         /*
    306          * Send a timestamp and echo-reply if this is a SYN and our side
    307          * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
    308          * and our peer have sent timestamps in our SYN's.
    309          */
    310 /*      if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
    311  *           (flags & TH_RST) == 0 &&
    312  *          ((flags & (TH_SYN|TH_ACK)) == TH_SYN ||
    313  *           (tp->t_flags & TF_RCVD_TSTMP))) {
    314  *              u_int32_t *lp = (u_int32_t *)(opt + optlen);
    315  *
    316  *              / * Form timestamp option as shown in appendix A of RFC 1323. *  /
    317  *              *lp++ = htonl(TCPOPT_TSTAMP_HDR);
    318  *              *lp++ = htonl(tcp_now);
    319  *              *lp   = htonl(tp->ts_recent);
    320  *              optlen += TCPOLEN_TSTAMP_APPA;
    321  *      }
    322  */
    323         hdrlen += optlen;
    324 
    325         /*
    326          * Adjust data length if insertion of options will
    327          * bump the packet length beyond the t_maxseg length.
    328          */
    329          if (len > tp->t_maxseg - optlen) {
    330                 len = tp->t_maxseg - optlen;
    331                 sendalot = 1;
    332          }
    333 
    334         /*
    335          * Grab a header mbuf, attaching a copy of data to
    336          * be transmitted, and initialize the header from
    337          * the template for sends on this connection.
    338          */
    339         if (len) {
    340                 if (tp->t_force && len == 1)
    341                         tcpstat.tcps_sndprobe++;
    342                 else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
    343                         tcpstat.tcps_sndrexmitpack++;
    344                         tcpstat.tcps_sndrexmitbyte += len;
    345                 } else {
    346                         tcpstat.tcps_sndpack++;
    347                         tcpstat.tcps_sndbyte += len;
    348                 }
    349 
    350                 m = m_get(pData);
    351                 if (m == NULL) {
    352 /*                      error = ENOBUFS; */
    353                         error = 1;
    354                         goto out;
    355                 }
    356                 m->m_data += if_maxlinkhdr;
    357                 m->m_len = hdrlen;
    358 
    359                 /*
    360                  * This will always succeed, since we make sure our mbufs
    361                  * are big enough to hold one MSS packet + header + ... etc.
    362                  */
    363 /*              if (len <= MHLEN - hdrlen - max_linkhdr) { */
    364 
    365                         sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
    366                         m->m_len += len;
    367 
    368 /*              } else {
    369  *                      m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
    370  *                      if (m->m_next == 0)
    371  *                              len = 0;
    372  *              }
    373  */
    374                 /*
    375                  * If we're sending everything we've got, set PUSH.
    376                  * (This will keep happy those implementations which only
    377                  * give data to the user when a buffer fills or
    378                  * a PUSH comes in.)
    379                  */
    380                 if (off + len == so->so_snd.sb_cc)
    381                         flags |= TH_PUSH;
    382         } else {
    383                 if (tp->t_flags & TF_ACKNOW)
    384                         tcpstat.tcps_sndacks++;
    385                 else if (flags & (TH_SYN|TH_FIN|TH_RST))
    386                         tcpstat.tcps_sndctrl++;
    387                 else if (SEQ_GT(tp->snd_up, tp->snd_una))
    388                         tcpstat.tcps_sndurg++;
    389                 else
    390                         tcpstat.tcps_sndwinup++;
    391 
    392                 m = m_get(pData);
    393                 if (m == NULL) {
    394 /*                      error = ENOBUFS; */
    395                         error = 1;
    396                         goto out;
    397                 }
    398                 m->m_data += if_maxlinkhdr;
    399                 m->m_len = hdrlen;
    400         }
    401 
    402         ti = mtod(m, struct tcpiphdr *);
    403 
    404         memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
    405 
    406         /*
    407          * Fill in fields, remembering maximum advertised
    408          * window for use in delaying messages about window sizes.
    409          * If resending a FIN, be sure not to use a new sequence number.
    410          */
    411         if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
    412             tp->snd_nxt == tp->snd_max)
    413                 tp->snd_nxt--;
    414         /*
    415          * If we are doing retransmissions, then snd_nxt will
    416          * not reflect the first unsent octet.  For ACK only
    417          * packets, we do not want the sequence number of the
    418          * retransmitted packet, we want the sequence number
    419          * of the next unsent octet.  So, if there is no data
    420          * (and no SYN or FIN), use snd_max instead of snd_nxt
    421          * when filling in ti_seq.  But if we are in persist
    422          * state, snd_max might reflect one byte beyond the
    423          * right edge of the window, so use snd_nxt in that
    424          * case, since we know we aren't doing a retransmission.
    425          * (retransmit and persist are mutually exclusive...)
    426          */
    427         if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
    428                 ti->ti_seq = htonl(tp->snd_nxt);
    429         else
    430                 ti->ti_seq = htonl(tp->snd_max);
    431         ti->ti_ack = htonl(tp->rcv_nxt);
    432         if (optlen) {
    433                 memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
    434                 ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
    435         }
    436         ti->ti_flags = flags;
    437         /*
    438          * Calculate receive window.  Don't shrink window,
    439          * but avoid silly window syndrome.
    440          */
    441         if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
    442                 win = 0;
    443         if (win > (long)TCP_MAXWIN << tp->rcv_scale)
    444                 win = (long)TCP_MAXWIN << tp->rcv_scale;
    445         if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
    446                 win = (long)(tp->rcv_adv - tp->rcv_nxt);
    447         ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
    448 
    449         if (SEQ_GT(tp->snd_up, tp->snd_una)) {
    450                 ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
    451 #ifdef notdef
    452         if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
    453                 ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
    454 #endif
    455                 ti->ti_flags |= TH_URG;
    456         } else
    457                 /*
    458                  * If no urgent pointer to send, then we pull
    459                  * the urgent pointer to the left edge of the send window
    460                  * so that it doesn't drift into the send window on sequence
    461                  * number wraparound.
    462                  */
    463                 tp->snd_up = tp->snd_una;               /* drag it along */
    464 
    465         /*
    466          * Put TCP length in extended header, and then
    467          * checksum extended header and data.
    468          */
    469         if (len + optlen)
    470                 ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) +
    471                     optlen + len));
    472         ti->ti_sum = cksum(m, (int)(hdrlen + len));
    473 
    474         /*
    475          * In transmit state, time the transmission and arrange for
    476          * the retransmit.  In persist state, just set snd_max.
    477          */
    478         if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
    479                 tcp_seq startseq = tp->snd_nxt;
    480 
    481                 /*
    482                  * Advance snd_nxt over sequence space of this segment.
    483                  */
    484                 if (flags & (TH_SYN|TH_FIN)) {
    485                         if (flags & TH_SYN)
    486                                 tp->snd_nxt++;
    487                         if (flags & TH_FIN) {
    488                                 tp->snd_nxt++;
    489                                 tp->t_flags |= TF_SENTFIN;
    490                         }
    491                 }
    492                 tp->snd_nxt += len;
    493                 if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
    494                         tp->snd_max = tp->snd_nxt;
    495                         /*
    496                          * Time this transmission if not a retransmission and
    497                          * not currently timing anything.
    498                          */
    499                         if (tp->t_rtt == 0) {
    500                                 tp->t_rtt = 1;
    501                                 tp->t_rtseq = startseq;
    502                                 tcpstat.tcps_segstimed++;
    503                         }
    504                 }
    505 
    506                 /*
    507                  * Set retransmit timer if not currently set,
    508                  * and not doing an ack or a keep-alive probe.
    509                  * Initial value for retransmit timer is smoothed
    510                  * round-trip time + 2 * round-trip time variance.
    511                  * Initialize shift counter which is used for backoff
    512                  * of retransmit time.
    513                  */
    514                 if (tp->t_timer[TCPT_REXMT] == 0 &&
    515                     tp->snd_nxt != tp->snd_una) {
    516                         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
    517                         if (tp->t_timer[TCPT_PERSIST]) {
    518                                 tp->t_timer[TCPT_PERSIST] = 0;
    519                                 tp->t_rxtshift = 0;
    520                         }
    521                 }
    522         } else
    523                 if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
    524                         tp->snd_max = tp->snd_nxt + len;
    525 
    526         /*
    527          * Fill in IP length and desired time to live and
    528          * send to IP level.  There should be a better way
    529          * to handle ttl and tos; we could keep them in
    530          * the template, but need a way to checksum without them.
    531          */
    532         m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
    533 
    534     {
    535 
     564            }
     565        }
     566    }
     567    else
     568        if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
     569            tp->snd_max = tp->snd_nxt + len;
     570
     571    /*
     572     * Fill in IP length and desired time to live and
     573     * send to IP level.  There should be a better way
     574     * to handle ttl and tos; we could keep them in
     575     * the template, but need a way to checksum without them.
     576     */
     577    m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
     578
     579    {
    536580        ((struct ip *)ti)->ip_len = m->m_len;
    537 
    538581        ((struct ip *)ti)->ip_ttl = ip_defttl;
    539582        ((struct ip *)ti)->ip_tos = so->so_iptos;
    540583
    541 /* #if BSD >= 43 */
     584        /* #if BSD >= 43 */
    542585        /* Don't do IP options... */
    543 /*      error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
    544  *          so->so_options & SO_DONTROUTE, 0);
    545  */
     586#if 0
     587        error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
     588                         so->so_options & SO_DONTROUTE, 0);
     589#endif
    546590        error = ip_output(pData, so, m);
    547591
    548 /* #else
    549  *      error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
    550  *          so->so_options & SO_DONTROUTE);
    551  * #endif
    552  */
    553     }
    554         if (error) {
     592#if 0
     593/* #else */
     594        error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
     595                          so->so_options & SO_DONTROUTE);
     596/* #endif */
     597#endif
     598    }
     599    if (error)
     600    {
    555601out:
    556 /*              if (error == ENOBUFS) {
    557  *                      tcp_quench(tp->t_inpcb, 0);
    558  *                      return (0);
    559  *              }
    560  */
    561 /*              if ((error == EHOSTUNREACH || error == ENETDOWN)
    562  *                  && TCPS_HAVERCVDSYN(tp->t_state)) {
    563  *                      tp->t_softerror = error;
    564  *                      return (0);
    565  *              }
    566  */
    567                 return (error);
    568         }
    569         tcpstat.tcps_sndtotal++;
    570 
    571         /*
    572          * Data sent (as far as we can tell).
    573          * If this advertises a larger window than any other segment,
    574          * then remember the size of the advertised window.
    575          * Any pending ACK has now been sent.
    576          */
    577         if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
    578                 tp->rcv_adv = tp->rcv_nxt + win;
    579         tp->last_ack_sent = tp->rcv_nxt;
    580         tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
    581         if (sendalot)
    582                 goto again;
    583 
    584         return (0);
     602#if 0
     603        if (error == ENOBUFS)
     604        {
     605            tcp_quench(tp->t_inpcb, 0);
     606            return (0);
     607        }
     608
     609        if (  (   error == EHOSTUNREACH
     610               || error == ENETDOWN)
     611            && TCPS_HAVERCVDSYN(tp->t_state))
     612        {
     613            tp->t_softerror = error;
     614            return (0);
     615        }
     616#endif
     617        return (error);
     618    }
     619    tcpstat.tcps_sndtotal++;
     620
     621    /*
     622     * Data sent (as far as we can tell).
     623     * If this advertises a larger window than any other segment,
     624     * then remember the size of the advertised window.
     625     * Any pending ACK has now been sent.
     626     */
     627    if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
     628        tp->rcv_adv = tp->rcv_nxt + win;
     629    tp->last_ack_sent = tp->rcv_nxt;
     630    tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
     631    if (sendalot)
     632        goto again;
     633
     634    return (0);
    585635}
    586636
    587637void
    588 tcp_setpersist(tp)
    589         register struct tcpcb *tp;
     638tcp_setpersist(struct tcpcb *tp)
    590639{
    591640    int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
    592641
    593 /*      if (tp->t_timer[TCPT_REXMT])
    594  *              panic("tcp_output REXMT");
    595  */
    596         /*
    597          * Start/restart persistence timer.
    598          */
    599         TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
    600             t * tcp_backoff[tp->t_rxtshift],
    601             TCPTV_PERSMIN, TCPTV_PERSMAX);
    602         if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
    603                 tp->t_rxtshift++;
     642#if 0
     643    if (tp->t_timer[TCPT_REXMT])
     644        panic("tcp_output REXMT");
     645#endif
     646    /*
     647     * Start/restart persistence timer.
     648     */
     649    TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
     650                  t * tcp_backoff[tp->t_rxtshift],
     651                  TCPTV_PERSMIN, TCPTV_PERSMAX);
     652    if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
     653        tp->t_rxtshift++;
    604654}
  • trunk/src/VBox/Devices/Network/slirp/tcp_subr.c

    r14638 r15074  
    5353tcp_init(PNATState pData)
    5454{
    55         tcp_iss = 1;            /* wrong */
    56         tcb.so_next = tcb.so_prev = &tcb;
    57         tcp_last_so = &tcb;
     55    tcp_iss = 1;            /* wrong */
     56    tcb.so_next = tcb.so_prev = &tcb;
     57    tcp_last_so = &tcb;
    5858#ifdef VBOX_WITH_BSD_REASS
    59         tcp_reass_maxqlen = 48;
    60         tcp_reass_maxseg  = 256;
     59    tcp_reass_maxqlen = 48;
     60    tcp_reass_maxseg  = 256;
    6161#endif /* VBOX_WITH_BSD_REASS */
    6262}
     
    7070/* struct tcpiphdr * */
    7171void
    72 tcp_template(tp)
    73         struct tcpcb *tp;
    74 {
    75         struct socket *so = tp->t_socket;
    76         register struct tcpiphdr *n = &tp->t_template;
     72tcp_template(struct tcpcb *tp)
     73{
     74    struct socket *so = tp->t_socket;
     75    register struct tcpiphdr *n = &tp->t_template;
    7776
    7877#if !defined(VBOX_WITH_BSD_REASS)
    79         n->ti_next = n->ti_prev = 0;
    80         n->ti_x1 = 0;
     78    n->ti_next = n->ti_prev = 0;
     79    n->ti_x1 = 0;
    8180#else
    82         memset(n->ti_x1, 0, 9);
     81    memset(n->ti_x1, 0, 9);
    8382#endif
    84         n->ti_pr = IPPROTO_TCP;
    85         n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
    86         n->ti_src = so->so_faddr;
    87         n->ti_dst = so->so_laddr;
    88         n->ti_sport = so->so_fport;
    89         n->ti_dport = so->so_lport;
    90 
    91         n->ti_seq = 0;
    92         n->ti_ack = 0;
    93         n->ti_x2 = 0;
    94         n->ti_off = 5;
    95         n->ti_flags = 0;
    96         n->ti_win = 0;
    97         n->ti_sum = 0;
    98         n->ti_urp = 0;
     83    n->ti_pr = IPPROTO_TCP;
     84    n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
     85    n->ti_src = so->so_faddr;
     86    n->ti_dst = so->so_laddr;
     87    n->ti_sport = so->so_fport;
     88    n->ti_dport = so->so_lport;
     89
     90    n->ti_seq = 0;
     91    n->ti_ack = 0;
     92    n->ti_x2 = 0;
     93    n->ti_off = 5;
     94    n->ti_flags = 0;
     95    n->ti_win = 0;
     96    n->ti_sum = 0;
     97    n->ti_urp = 0;
    9998}
    10099
     
    115114tcp_respond(PNATState pData, struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags)
    116115{
    117         register int tlen;
    118         int win = 0;
    119 
    120         DEBUG_CALL("tcp_respond");
    121         DEBUG_ARG("tp = %lx", (long)tp);
    122         DEBUG_ARG("ti = %lx", (long)ti);
    123         DEBUG_ARG("m = %lx", (long)m);
    124         DEBUG_ARG("ack = %u", ack);
    125         DEBUG_ARG("seq = %u", seq);
    126         DEBUG_ARG("flags = %x", flags);
    127 
    128         if (tp)
    129                 win = sbspace(&tp->t_socket->so_rcv);
    130         if (m == 0) {
    131                 if ((m = m_get(pData)) == NULL)
    132                         return;
     116    register int tlen;
     117    int win = 0;
     118
     119    DEBUG_CALL("tcp_respond");
     120    DEBUG_ARG("tp = %lx", (long)tp);
     121    DEBUG_ARG("ti = %lx", (long)ti);
     122    DEBUG_ARG("m = %lx", (long)m);
     123    DEBUG_ARG("ack = %u", ack);
     124    DEBUG_ARG("seq = %u", seq);
     125    DEBUG_ARG("flags = %x", flags);
     126
     127    if (tp)
     128        win = sbspace(&tp->t_socket->so_rcv);
     129    if (m == 0)
     130    {
     131        if ((m = m_get(pData)) == NULL)
     132            return;
    133133#ifdef TCP_COMPAT_42
    134                 tlen = 1;
     134        tlen = 1;
    135135#else
    136                 tlen = 0;
     136        tlen = 0;
    137137#endif
    138                 m->m_data += if_maxlinkhdr;
    139                 *mtod(m, struct tcpiphdr *) = *ti;
    140                 ti = mtod(m, struct tcpiphdr *);
    141                 flags = TH_ACK;
    142         } else {
    143                 /*
    144                  * ti points into m so the next line is just making
    145                  * the mbuf point to ti
    146                  */
    147                 m->m_data = (caddr_t)ti;
    148 
    149                 m->m_len = sizeof (struct tcpiphdr);
    150                 tlen = 0;
     138        m->m_data += if_maxlinkhdr;
     139        *mtod(m, struct tcpiphdr *) = *ti;
     140        ti = mtod(m, struct tcpiphdr *);
     141        flags = TH_ACK;
     142    }
     143    else
     144    {
     145        /*
     146         * ti points into m so the next line is just making
     147         * the mbuf point to ti
     148         */
     149        m->m_data = (caddr_t)ti;
     150
     151        m->m_len = sizeof (struct tcpiphdr);
     152        tlen = 0;
    151153#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
    152                 xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
    153                 xchg(ti->ti_dport, ti->ti_sport, u_int16_t);
     154        xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
     155        xchg(ti->ti_dport, ti->ti_sport, u_int16_t);
    154156#undef xchg
    155         }
    156         ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
    157         tlen += sizeof (struct tcpiphdr);
    158         m->m_len = tlen;
     157    }
     158    ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
     159    tlen += sizeof (struct tcpiphdr);
     160    m->m_len = tlen;
    159161
    160162#if !defined(VBOX_WITH_BSD_REASS)
    161         ti->ti_next = ti->ti_prev = 0;
    162         ti->ti_x1 = 0;
     163    ti->ti_next = ti->ti_prev = 0;
     164    ti->ti_x1 = 0;
    163165#else
    164         memset(ti->ti_x1, 0, 9);
     166    memset(ti->ti_x1, 0, 9);
    165167#endif
    166         ti->ti_seq = htonl(seq);
    167         ti->ti_ack = htonl(ack);
    168         ti->ti_x2 = 0;
    169         ti->ti_off = sizeof (struct tcphdr) >> 2;
    170         ti->ti_flags = flags;
    171         if (tp)
    172                 ti->ti_win = htons((u_int16_t) (win >> tp->rcv_scale));
    173         else
    174                 ti->ti_win = htons((u_int16_t)win);
    175         ti->ti_urp = 0;
    176         ti->ti_sum = 0;
    177         ti->ti_sum = cksum(m, tlen);
    178         ((struct ip *)ti)->ip_len = tlen;
    179 
    180         if(flags & TH_RST)
    181           ((struct ip *)ti)->ip_ttl = MAXTTL;
    182         else
    183           ((struct ip *)ti)->ip_ttl = ip_defttl;
    184 
    185         (void) ip_output(pData, (struct socket *)0, m);
     168    ti->ti_seq = htonl(seq);
     169    ti->ti_ack = htonl(ack);
     170    ti->ti_x2 = 0;
     171    ti->ti_off = sizeof (struct tcphdr) >> 2;
     172    ti->ti_flags = flags;
     173    if (tp)
     174        ti->ti_win = htons((u_int16_t) (win >> tp->rcv_scale));
     175    else
     176        ti->ti_win = htons((u_int16_t)win);
     177    ti->ti_urp = 0;
     178    ti->ti_sum = 0;
     179    ti->ti_sum = cksum(m, tlen);
     180    ((struct ip *)ti)->ip_len = tlen;
     181
     182    if(flags & TH_RST)
     183        ((struct ip *)ti)->ip_ttl = MAXTTL;
     184    else
     185        ((struct ip *)ti)->ip_ttl = ip_defttl;
     186
     187    (void) ip_output(pData, (struct socket *)0, m);
    186188}
    187189
     
    194196tcp_newtcpcb(PNATState pData, struct socket *so)
    195197{
    196         register struct tcpcb *tp;
    197 
    198         tp = (struct tcpcb *)malloc(sizeof(*tp));
    199         if (tp == NULL)
    200                 return ((struct tcpcb *)0);
    201 
    202         memset((char *) tp, 0, sizeof(struct tcpcb));
     198    register struct tcpcb *tp;
     199
     200    tp = (struct tcpcb *)malloc(sizeof(*tp));
     201    if (tp == NULL)
     202        return ((struct tcpcb *)0);
     203
     204    memset((char *) tp, 0, sizeof(struct tcpcb));
    203205#ifndef VBOX_WITH_BSD_REASS
    204         tp->seg_next = tp->seg_prev = ptr_to_u32(pData, (struct tcpiphdr *)tp);
     206    tp->seg_next = tp->seg_prev = ptr_to_u32(pData, (struct tcpiphdr *)tp);
    205207#endif /* !VBOX_WITH_BSD_REASS */
    206         tp->t_maxseg = tcp_mssdflt;
    207 
    208         tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
    209         tp->t_socket = so;
    210 
    211         /*
    212          * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
    213          * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
    214          * reasonable initial retransmit time.
    215          */
    216         tp->t_srtt = TCPTV_SRTTBASE;
    217         tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
    218         tp->t_rttmin = TCPTV_MIN;
    219 
    220         TCPT_RANGESET(tp->t_rxtcur,
    221             ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
    222             TCPTV_MIN, TCPTV_REXMTMAX);
    223 
    224         tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
    225         tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
    226         tp->t_state = TCPS_CLOSED;
    227 
    228         so->so_tcpcb = tp;
    229 
    230         return (tp);
     208    tp->t_maxseg = tcp_mssdflt;
     209
     210    tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
     211    tp->t_socket = so;
     212
     213    /*
     214     * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
     215     * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
     216     * reasonable initial retransmit time.
     217     */
     218    tp->t_srtt = TCPTV_SRTTBASE;
     219    tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2;
     220    tp->t_rttmin = TCPTV_MIN;
     221
     222    TCPT_RANGESET(tp->t_rxtcur,
     223                  ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
     224                  TCPTV_MIN, TCPTV_REXMTMAX);
     225
     226    tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
     227    tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
     228    tp->t_state = TCPS_CLOSED;
     229
     230    so->so_tcpcb = tp;
     231
     232    return (tp);
    231233}
    232234
     
    243245{
    244246*/
    245 
    246         DEBUG_CALL("tcp_drop");
    247         DEBUG_ARG("tp = %lx", (long)tp);
    248         DEBUG_ARG("errno = %d", errno);
    249 
    250         if (TCPS_HAVERCVDSYN(tp->t_state)) {
    251                 tp->t_state = TCPS_CLOSED;
    252                 (void) tcp_output(pData, tp);
    253                 tcpstat.tcps_drops++;
    254         } else
    255                 tcpstat.tcps_conndrops++;
    256 /*      if (errno == ETIMEDOUT && tp->t_softerror)
    257  *              errno = tp->t_softerror;
    258  */
    259 /*      so->so_error = errno; */
    260         return (tcp_close(pData, tp));
     247    DEBUG_CALL("tcp_drop");
     248    DEBUG_ARG("tp = %lx", (long)tp);
     249    DEBUG_ARG("errno = %d", errno);
     250
     251    if (TCPS_HAVERCVDSYN(tp->t_state))
     252    {
     253        tp->t_state = TCPS_CLOSED;
     254        (void) tcp_output(pData, tp);
     255        tcpstat.tcps_drops++;
     256    }
     257    else
     258        tcpstat.tcps_conndrops++;
     259#if 0
     260      if (errno == ETIMEDOUT && tp->t_softerror)
     261              errno = tp->t_softerror;
     262
     263      so->so_error = errno;
     264#endif
     265      return (tcp_close(pData, tp));
    261266}
    262267
     
    270275tcp_close(PNATState pData, register struct tcpcb *tp)
    271276{
    272         register struct tcpiphdr *t;
    273         struct socket *so = tp->t_socket;
    274         register struct mbuf *m;
     277    register struct tcpiphdr *t;
     278    struct socket *so = tp->t_socket;
     279    register struct mbuf *m;
    275280
    276281#ifndef VBOX_WITH_BSD_REASS
    277         DEBUG_CALL("tcp_close");
    278         DEBUG_ARG("tp = %lx", (long )tp);
    279 
    280         /* free the reassembly queue, if any */
    281         t = u32_to_ptr(pData, tp->seg_next, struct tcpiphdr *);
    282         while (t != (struct tcpiphdr *)tp) {
    283                 t = u32_to_ptr(pData, t->ti_next, struct tcpiphdr *);
    284                 m = REASS_MBUF_GET(u32_to_ptr(pData, t->ti_prev, struct tcpiphdr *));
    285                 remque_32(pData, u32_to_ptr(pData, t->ti_prev, struct tcpiphdr *));
    286                 m_freem(pData, m);
    287         }
    288         /* It's static */
    289 /*      if (tp->t_template)
    290  *              (void) m_free(dtom(tp->t_template));
    291  */
    292 /*      free(tp, M_PCB);  */
    293         u32ptr_done(pData, ptr_to_u32(pData, tp), tp);
     282    DEBUG_CALL("tcp_close");
     283    DEBUG_ARG("tp = %lx", (long )tp);
     284
     285    /* free the reassembly queue, if any */
     286    t = u32_to_ptr(pData, tp->seg_next, struct tcpiphdr *);
     287    while (t != (struct tcpiphdr *)tp)
     288    {
     289        t = u32_to_ptr(pData, t->ti_next, struct tcpiphdr *);
     290        m = REASS_MBUF_GET(u32_to_ptr(pData, t->ti_prev, struct tcpiphdr *));
     291        remque_32(pData, u32_to_ptr(pData, t->ti_prev, struct tcpiphdr *));
     292        m_freem(pData, m);
     293    }
     294    /* It's static */
     295#if 0
     296    if (tp->t_template)
     297        (void) m_free(dtom(tp->t_template));
     298
     299    free(tp, M_PCB); 
     300#endif
     301    u32ptr_done(pData, ptr_to_u32(pData, tp), tp);
    294302#else  /* VBOX_WITH_BSD_REASS */
    295         struct tseg_qent *te;
    296         DEBUG_CALL("tcp_close");
    297         DEBUG_ARG("tp = %lx", (long )tp);
    298         /*XXX: freeing the reassembly queue */
    299         LIST_FOREACH(te, &tp->t_segq, tqe_q) {
    300             LIST_REMOVE(te, tqe_q);
    301             m_freem(pData, te->tqe_m);
    302             free(te);
    303             tcp_reass_qsize--;
    304         }
     303    struct tseg_qent *te;
     304    DEBUG_CALL("tcp_close");
     305    DEBUG_ARG("tp = %lx", (long )tp);
     306    /*XXX: freeing the reassembly queue */
     307    LIST_FOREACH(te, &tp->t_segq, tqe_q)
     308    {
     309        LIST_REMOVE(te, tqe_q);
     310        m_freem(pData, te->tqe_m);
     311        free(te);
     312        tcp_reass_qsize--;
     313    }
    305314#endif /* VBOX_WITH_BSD_REASS */
    306         free(tp);
    307         so->so_tcpcb = 0;
    308         soisfdisconnected(so);
    309         /* clobber input socket cache if we're closing the cached connection */
    310         if (so == tcp_last_so)
    311                 tcp_last_so = &tcb;
    312         closesocket(so->s);
    313         sbfree(&so->so_rcv);
    314         sbfree(&so->so_snd);
    315         sofree(pData, so);
    316         tcpstat.tcps_closed++;
    317         return ((struct tcpcb *)0);
     315    free(tp);
     316    so->so_tcpcb = 0;
     317    soisfdisconnected(so);
     318    /* clobber input socket cache if we're closing the cached connection */
     319    if (so == tcp_last_so)
     320        tcp_last_so = &tcb;
     321    closesocket(so->s);
     322    sbfree(&so->so_rcv);
     323    sbfree(&so->so_snd);
     324    sofree(pData, so);
     325    tcpstat.tcps_closed++;
     326    return ((struct tcpcb *)0);
    318327}
    319328
     
    321330tcp_drain()
    322331{
    323         /* XXX */
     332    /* XXX */
    324333}
    325334
     
    329338 */
    330339
    331 #ifdef notdef
     340#if 0
    332341
    333342void
    334 tcp_quench(i, errno)
    335 
    336         int errno;
    337 {
    338         struct tcpcb *tp = intotcpcb(inp);
    339 
    340         if (tp)
    341                 tp->snd_cwnd = tp->t_maxseg;
    342 }
    343 
    344 #endif /* notdef */
     343tcp_quench(i, int errno)
     344{
     345    struct tcpcb *tp = intotcpcb(inp);
     346
     347    if (tp)
     348        tp->snd_cwnd = tp->t_maxseg;
     349}
     350
     351#endif
    345352
    346353/*
     
    361368tcp_sockclosed(PNATState pData, struct tcpcb *tp)
    362369{
    363 
    364         DEBUG_CALL("tcp_sockclosed");
    365         DEBUG_ARG("tp = %lx", (long)tp);
    366 
    367         switch (tp->t_state) {
    368 
     370    DEBUG_CALL("tcp_sockclosed");
     371    DEBUG_ARG("tp = %lx", (long)tp);
     372
     373    switch (tp->t_state)
     374    {
    369375        case TCPS_CLOSED:
    370376        case TCPS_LISTEN:
    371377        case TCPS_SYN_SENT:
    372                 tp->t_state = TCPS_CLOSED;
    373                 tp = tcp_close(pData, tp);
    374                 break;
     378            tp->t_state = TCPS_CLOSED;
     379            tp = tcp_close(pData, tp);
     380            break;
    375381
    376382        case TCPS_SYN_RECEIVED:
    377383        case TCPS_ESTABLISHED:
    378                 tp->t_state = TCPS_FIN_WAIT_1;
    379                 break;
     384            tp->t_state = TCPS_FIN_WAIT_1;
     385            break;
    380386
    381387        case TCPS_CLOSE_WAIT:
    382                 tp->t_state = TCPS_LAST_ACK;
    383                 break;
    384         }
    385 /*      soisfdisconnecting(tp->t_socket); */
    386         if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
    387                 soisfdisconnected(tp->t_socket);
    388         if (tp)
    389                 tcp_output(pData, tp);
     388            tp->t_state = TCPS_LAST_ACK;
     389            break;
     390    }
     391/*  soisfdisconnecting(tp->t_socket); */
     392    if (   tp
     393        && tp->t_state >= TCPS_FIN_WAIT_2)
     394        soisfdisconnected(tp->t_socket);
     395    if (tp)
     396        tcp_output(pData, tp);
    390397}
    391398
     
    402409int tcp_fconnect(PNATState pData, struct socket *so)
    403410{
    404   int ret=0;
    405 
    406   DEBUG_CALL("tcp_fconnect");
    407   DEBUG_ARG("so = %lx", (long )so);
    408 
    409   if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) {
    410     int opt, s=so->s;
    411     struct sockaddr_in addr;
    412 
    413     fd_nonblock(s);
    414     opt = 1;
    415     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
    416     opt = 1;
    417     setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
    418 
    419     addr.sin_family = AF_INET;
    420     if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr) {
    421       /* It's an alias */
    422       switch(ntohl(so->so_faddr.s_addr) & ~pData->netmask) {
    423       case CTL_DNS:
    424         if (!get_dns_addr(pData, &dns_addr))
    425             addr.sin_addr = dns_addr;
     411    int ret=0;
     412
     413    DEBUG_CALL("tcp_fconnect");
     414    DEBUG_ARG("so = %lx", (long )so);
     415
     416    if ((ret = so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0)
     417    {
     418        int opt, s=so->s;
     419        struct sockaddr_in addr;
     420
     421        fd_nonblock(s);
     422        opt = 1;
     423        setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt, sizeof(opt));
     424        opt = 1;
     425        setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt, sizeof(opt));
     426
     427        addr.sin_family = AF_INET;
     428        if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr)
     429        {
     430            /* It's an alias */
     431            switch(ntohl(so->so_faddr.s_addr) & ~pData->netmask)
     432            {
     433                case CTL_DNS:
     434                    if (!get_dns_addr(pData, &dns_addr))
     435                        addr.sin_addr = dns_addr;
     436                    else
     437                        addr.sin_addr = loopback_addr;
     438                    break;
     439                case CTL_ALIAS:
     440                default:
     441                    addr.sin_addr = loopback_addr;
     442                    break;
     443            }
     444        }
    426445        else
    427             addr.sin_addr = loopback_addr;
    428         break;
    429       case CTL_ALIAS:
    430       default:
    431         addr.sin_addr = loopback_addr;
    432         break;
    433       }
    434     } else
    435       addr.sin_addr = so->so_faddr;
    436     addr.sin_port = so->so_fport;
    437 
    438     DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
    439                 "addr.sin_addr.s_addr=%.16s\n",
    440                 ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
    441     /* We don't care what port we get */
    442     ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
    443 
    444     /*
    445      * If it's not in progress, it failed, so we just return 0,
    446      * without clearing SS_NOFDREF
    447      */
    448     soisfconnecting(so);
    449   }
    450 
    451   return(ret);
     446            addr.sin_addr = so->so_faddr;
     447        addr.sin_port = so->so_fport;
     448
     449        DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
     450                         "addr.sin_addr.s_addr=%.16s\n",
     451                         ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
     452        /* We don't care what port we get */
     453        ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
     454
     455        /*
     456         * If it's not in progress, it failed, so we just return 0,
     457         * without clearing SS_NOFDREF
     458         */
     459        soisfconnecting(so);
     460    }
     461
     462    return(ret);
    452463}
    453464
     
    467478tcp_connect(PNATState pData, struct socket *inso)
    468479{
    469         struct socket *so;
    470         struct sockaddr_in addr;
    471         socklen_t addrlen = sizeof(struct sockaddr_in);
    472         struct tcpcb *tp;
    473         int s, opt;
    474 
    475         DEBUG_CALL("tcp_connect");
    476         DEBUG_ARG("inso = %lx", (long)inso);
    477 
    478         /*
    479          * If it's an SS_ACCEPTONCE socket, no need to socreate()
    480          * another socket, just use the accept() socket.
    481          */
    482         if (inso->so_state & SS_FACCEPTONCE) {
    483                 /* FACCEPTONCE already have a tcpcb */
    484                 so = inso;
    485         } else {
    486                 if ((so = socreate()) == NULL) {
    487                         /* If it failed, get rid of the pending connection */
    488                         closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
    489                         return;
    490                 }
    491                 if (tcp_attach(pData, so) < 0) {
    492                         free(so); /* NOT sofree */
    493                         return;
    494                 }
    495                 so->so_laddr = inso->so_laddr;
    496                 so->so_lport = inso->so_lport;
     480    struct socket *so;
     481    struct sockaddr_in addr;
     482    socklen_t addrlen = sizeof(struct sockaddr_in);
     483    struct tcpcb *tp;
     484    int s, opt;
     485
     486    DEBUG_CALL("tcp_connect");
     487    DEBUG_ARG("inso = %lx", (long)inso);
     488
     489    /*
     490     * If it's an SS_ACCEPTONCE socket, no need to socreate()
     491     * another socket, just use the accept() socket.
     492     */
     493    if (inso->so_state & SS_FACCEPTONCE)
     494    {
     495        /* FACCEPTONCE already have a tcpcb */
     496        so = inso;
     497    }
     498    else
     499    {
     500        if ((so = socreate()) == NULL)
     501        {
     502            /* If it failed, get rid of the pending connection */
     503            closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
     504            return;
    497505        }
    498 
    499         (void) tcp_mss(pData, sototcpcb(so), 0);
    500 
    501         if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
    502                 tcp_close(pData, sototcpcb(so)); /* This will sofree() as well */
    503                 return;
     506        if (tcp_attach(pData, so) < 0)
     507        {
     508            free(so); /* NOT sofree */
     509            return;
    504510        }
    505         fd_nonblock(s);
    506         opt = 1;
    507         setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
    508         opt = 1;
    509         setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
    510         opt = 1;
    511         setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
    512 
    513         so->so_fport = addr.sin_port;
    514         so->so_faddr = addr.sin_addr;
    515         /* Translate connections from localhost to the real hostname */
    516         if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
    517            so->so_faddr = alias_addr;
    518 
    519         /* Close the accept() socket, set right state */
    520         if (inso->so_state & SS_FACCEPTONCE) {
    521                 closesocket(so->s); /* If we only accept once, close the accept() socket */
    522                 so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
    523                                            /* if it's not FACCEPTONCE, it's already NOFDREF */
    524         }
    525         so->s = s;
    526 
    527         so->so_iptos = tcp_tos(so);
    528         tp = sototcpcb(so);
    529 
    530         tcp_template(tp);
    531 
    532         /* Compute window scaling to request.  */
    533 /*      while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
    534  *              (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
    535  *              tp->request_r_scale++;
    536  */
    537 
    538 /*      soisconnecting(so); */ /* NOFDREF used instead */
    539         tcpstat.tcps_connattempt++;
    540 
    541         tp->t_state = TCPS_SYN_SENT;
    542         tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
    543         tp->iss = tcp_iss;
    544         tcp_iss += TCP_ISSINCR/2;
    545         tcp_sendseqinit(tp);
    546         tcp_output(pData, tp);
     511        so->so_laddr = inso->so_laddr;
     512        so->so_lport = inso->so_lport;
     513    }
     514
     515    (void) tcp_mss(pData, sototcpcb(so), 0);
     516
     517    if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0)
     518    {
     519        tcp_close(pData, sototcpcb(so)); /* This will sofree() as well */
     520        return;
     521    }
     522    fd_nonblock(s);
     523    opt = 1;
     524    setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
     525    opt = 1;
     526    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
     527    opt = 1;
     528    setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
     529
     530    so->so_fport = addr.sin_port;
     531    so->so_faddr = addr.sin_addr;
     532    /* Translate connections from localhost to the real hostname */
     533    if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
     534        so->so_faddr = alias_addr;
     535
     536    /* Close the accept() socket, set right state */
     537    if (inso->so_state & SS_FACCEPTONCE)
     538    {
     539        closesocket(so->s);        /* If we only accept once, close the accept() socket */
     540        so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
     541                                   /* if it's not FACCEPTONCE, it's already NOFDREF */
     542    }
     543    so->s = s;
     544
     545    so->so_iptos = tcp_tos(so);
     546    tp = sototcpcb(so);
     547
     548    tcp_template(tp);
     549
     550    /* Compute window scaling to request.  */
     551/*  while (tp->request_r_scale < TCP_MAX_WINSHIFT
     552 *         && (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
     553 *      tp->request_r_scale++;
     554 */
     555
     556/*  soisconnecting(so); */ /* NOFDREF used instead */
     557    tcpstat.tcps_connattempt++;
     558
     559    tp->t_state = TCPS_SYN_SENT;
     560    tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
     561    tp->iss = tcp_iss;
     562    tcp_iss += TCP_ISSINCR/2;
     563    tcp_sendseqinit(tp);
     564    tcp_output(pData, tp);
    547565}
    548566
     
    553571tcp_attach(PNATState pData, struct socket *so)
    554572{
    555         if ((so->so_tcpcb = tcp_newtcpcb(pData, so)) == NULL)
    556            return -1;
    557 
    558         insque(pData, so, &tcb);
    559 
    560         return 0;
     573    if ((so->so_tcpcb = tcp_newtcpcb(pData, so)) == NULL)
     574        return -1;
     575
     576    insque(pData, so, &tcb);
     577    return 0;
    561578}
    562579
     
    564581 * Set the socket's type of service field
    565582 */
    566 static const struct tos_t tcptos[] = {
    567           {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */
    568           {21, 21, IPTOS_LOWDELAY,  EMU_FTP},   /* ftp control */
    569           {0, 23, IPTOS_LOWDELAY, 0},   /* telnet */
    570           {0, 80, IPTOS_THROUGHPUT, 0}, /* WWW */
    571           {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},   /* rlogin */
    572           {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},      /* shell */
    573           {0, 544, IPTOS_LOWDELAY, EMU_KSH},            /* kshell */
    574           {0, 543, IPTOS_LOWDELAY, 0},  /* klogin */
    575           {0, 6667, IPTOS_THROUGHPUT, EMU_IRC}, /* IRC */
    576           {0, 6668, IPTOS_THROUGHPUT, EMU_IRC}, /* IRC undernet */
    577           {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */
    578           {0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */
    579           {0, 0, 0, 0}
     583static const struct tos_t tcptos[] =
     584{
     585    {0, 20, IPTOS_THROUGHPUT, 0},                       /* ftp data */
     586    {21, 21, IPTOS_LOWDELAY,  EMU_FTP},                 /* ftp control */
     587    {0, 23, IPTOS_LOWDELAY, 0},                         /* telnet */
     588    {0, 80, IPTOS_THROUGHPUT, 0},                       /* WWW */
     589    {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT}, /* rlogin */
     590    {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},    /* shell */
     591    {0, 544, IPTOS_LOWDELAY, EMU_KSH},                  /* kshell */
     592    {0, 543, IPTOS_LOWDELAY, 0},                        /* klogin */
     593    {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},               /* IRC */
     594    {0, 6668, IPTOS_THROUGHPUT, EMU_IRC},               /* IRC undernet */
     595    {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO },          /* RealAudio control */
     596    {0, 113, IPTOS_LOWDELAY, EMU_IDENT },               /* identd protocol */
     597    {0, 0, 0, 0}
    580598};
    581599
     
    584602 */
    585603u_int8_t
    586 tcp_tos(so)
    587         struct socket *so;
    588 {
    589         int i = 0;
    590 
    591         while(tcptos[i].tos) {
    592                 if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
    593                     (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
    594                         so->so_emu = tcptos[i].emu;
    595                         return tcptos[i].tos;
    596                 }
    597                 i++;
     604tcp_tos(struct socket *so)
     605{
     606    int i = 0;
     607
     608    while(tcptos[i].tos)
     609    {
     610        if (   (tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport))
     611            || (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport)))
     612        {
     613            so->so_emu = tcptos[i].emu;
     614            return tcptos[i].tos;
    598615        }
    599 
    600         return 0;
    601 }
    602 
    603 /*
    604  * Emulate programs that try and connect to us
    605  * This includes ftp (the data connection is
    606  * initiated by the server) and IRC (DCC CHAT and
    607  * DCC SEND) for now
     616        i++;
     617    }
     618
     619    return 0;
     620}
     621
     622/*
     623 * Emulate programs that try and connect to us. This includes ftp (the data
     624 * connection is initiated by the server) and IRC (DCC CHAT and DCC SEND)
     625 * for now
    608626 *
    609  * NOTE: It's possible to crash SLiRP by sending it
    610  * unstandard strings to emulate... if this is a problem,
    611  * more checks are needed here
     627 * NOTE: It's possible to crash SLiRP by sending it unstandard strings to
     628 * emulate... if this is a problem, more checks are needed here.
    612629 *
    613  * XXX Assumes the whole command came in one packet
     630 * XXX Assumes the whole command cames in one packet
    614631 *
    615  * XXX Some ftp clients will have their TOS set to
    616  * LOWDELAY and so Nagel will kick in.  Because of this,
    617  * we'll get the first letter, followed by the rest, so
    618  * we simply scan for ORT instead of PORT...
    619  * DCC doesn't have this problem because there's other stuff
    620  * in the packet before the DCC command.
     632 * XXX Some ftp clients will have their TOS set to LOWDELAY and so Nagel will
     633 * kick in.  Because of this, we'll get the first letter, followed by the
     634 * rest, so we simply scan for ORT instead of PORT... DCC doesn't have this
     635 * problem because there's other stuff in the packet before the DCC command.
    621636 *
    622  * Return 1 if the mbuf m is still valid and should be
    623  * sbappend()ed
     637 * Return 1 if the mbuf m is still valid and should be sbappend()ed
    624638 *
    625639 * NOTE: if you return 0 you MUST m_free() the mbuf!
     
    628642tcp_emu(PNATState pData, struct socket *so, struct mbuf *m)
    629643{
    630         u_int n1, n2, n3, n4, n5, n6;
    631         char buff[256];
    632         u_int32_t laddr;
    633         u_int lport;
    634         char *bptr;
    635 
    636         DEBUG_CALL("tcp_emu");
    637         DEBUG_ARG("so = %lx", (long)so);
    638         DEBUG_ARG("m = %lx", (long)m);
    639 
    640         switch(so->so_emu) {
    641                 int x, i;
    642 
    643          case EMU_IDENT:
     644    u_int n1, n2, n3, n4, n5, n6;
     645    char buff[256];
     646    u_int32_t laddr;
     647    u_int lport;
     648    char *bptr;
     649
     650    DEBUG_CALL("tcp_emu");
     651    DEBUG_ARG("so = %lx", (long)so);
     652    DEBUG_ARG("m = %lx", (long)m);
     653
     654    switch(so->so_emu)
     655    {
     656        int x, i;
     657
     658        case EMU_IDENT:
     659        /*
     660         * Identification protocol as per rfc-1413
     661         */
     662        {
     663            struct socket *tmpso;
     664            struct sockaddr_in addr;
     665            socklen_t addrlen = sizeof(struct sockaddr_in);
     666            struct sbuf *so_rcv = &so->so_rcv;
     667
     668            memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
     669            so_rcv->sb_wptr += m->m_len;
     670            so_rcv->sb_rptr += m->m_len;
     671            m->m_data[m->m_len] = 0; /* NULL terminate */
     672            if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n'))
     673            {
     674                if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2)
     675                {
     676                    HTONS(n1);
     677                    HTONS(n2);
     678                    /* n2 is the one on our host */
     679                    for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next)
     680                    {
     681                        if (   tmpso->so_laddr.s_addr == so->so_laddr.s_addr
     682                            && tmpso->so_lport == n2
     683                            && tmpso->so_faddr.s_addr == so->so_faddr.s_addr
     684                            && tmpso->so_fport == n1)
     685                        {
     686                            if (getsockname(tmpso->s,
     687                                            (struct sockaddr *)&addr, &addrlen) == 0)
     688                                n2 = ntohs(addr.sin_port);
     689                            break;
     690                        }
     691                    }
     692                }
     693                so_rcv->sb_cc = sprintf(so_rcv->sb_data, "%d,%d\r\n", n1, n2);
     694                so_rcv->sb_rptr = so_rcv->sb_data;
     695                so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
     696            }
     697            m_free(pData, m);
     698            return 0;
     699        }
     700
     701        case EMU_FTP:
     702            *(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
     703            if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL)
     704            {
    644705                /*
    645                  * Identification protocol as per rfc-1413
     706                 * Need to emulate the PORT command
    646707                 */
    647 
     708                x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
     709                           &n1, &n2, &n3, &n4, &n5, &n6, buff);
     710                if (x < 6)
     711                    return 1;
     712
     713                laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
     714                lport = htons((n5 << 8) | (n6));
     715
     716                if ((so = solisten(pData, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
     717                    return 1;
     718
     719                n6 = ntohs(so->so_fport);
     720
     721                n5 = (n6 >> 8) & 0xff;
     722                n6 &= 0xff;
     723
     724                laddr = ntohl(so->so_faddr.s_addr);
     725
     726                n1 = ((laddr >> 24) & 0xff);
     727                n2 = ((laddr >> 16) & 0xff);
     728                n3 = ((laddr >> 8)  & 0xff);
     729                n4 = ( laddr        & 0xff);
     730
     731                m->m_len = bptr - m->m_data; /* Adjust length */
     732                m->m_len += sprintf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%s",
     733                                    n1, n2, n3, n4, n5, n6, x==7?buff:"");
     734                return 1;
     735            }
     736            else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL)
     737            {
     738                /*
     739                 * Need to emulate the PASV response
     740                 */
     741                x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
     742                           &n1, &n2, &n3, &n4, &n5, &n6, buff);
     743                if (x < 6)
     744                    return 1;
     745
     746                laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
     747                lport = htons((n5 << 8) | (n6));
     748
     749                if ((so = solisten(pData, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
     750                    return 1;
     751
     752                n6 = ntohs(so->so_fport);
     753
     754                n5 = (n6 >> 8) & 0xff;
     755                n6 &= 0xff;
     756
     757                laddr = ntohl(so->so_faddr.s_addr);
     758
     759                n1 = ((laddr >> 24) & 0xff);
     760                n2 = ((laddr >> 16) & 0xff);
     761                n3 = ((laddr >> 8)  & 0xff);
     762                n4 =  (laddr & 0xff);
     763
     764                m->m_len = bptr - m->m_data; /* Adjust length */
     765                m->m_len += sprintf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
     766                                    n1, n2, n3, n4, n5, n6, x==7?buff:"");
     767
     768                return 1;
     769            }
     770            return 1;
     771
     772        case EMU_KSH:
     773            /*
     774             * The kshell (Kerberos rsh) and shell services both pass
     775             * a local port port number to carry signals to the server
     776             * and stderr to the client.  It is passed at the beginning
     777             * of the connection as a NUL-terminated decimal ASCII string.
     778             */
     779            so->so_emu = 0;
     780            for (lport = 0, i = 0; i < m->m_len-1; ++i)
     781            {
     782                if (m->m_data[i] < '0' || m->m_data[i] > '9')
     783                    return 1;       /* invalid number */
     784                lport *= 10;
     785                lport += m->m_data[i] - '0';
     786            }
     787            if (   m->m_data[m->m_len-1] == '\0'
     788                && lport != 0
     789                && (so = solisten(pData, 0, so->so_laddr.s_addr,
     790                                  htons(lport), SS_FACCEPTONCE)) != NULL)
     791                m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
     792            return 1;
     793
     794        case EMU_IRC:
     795            /*
     796             * Need to emulate DCC CHAT, DCC SEND and DCC MOVE
     797             */
     798            *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
     799            if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
     800                return 1;
     801
     802            /* The %256s is for the broken mIRC */
     803            if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3)
     804            {
     805                if ((so = solisten(pData, 0, htonl(laddr),
     806                                   htons(lport), SS_FACCEPTONCE)) == NULL)
     807                    return 1;
     808
     809                m->m_len = bptr - m->m_data; /* Adjust length */
     810                m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
     811                                    (unsigned long)ntohl(so->so_faddr.s_addr),
     812                                    ntohs(so->so_fport), 1);
     813            }
     814            else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4)
     815            {
     816                if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
     817                    return 1;
     818
     819                m->m_len = bptr - m->m_data; /* Adjust length */
     820                m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
     821                                    buff, (unsigned long)ntohl(so->so_faddr.s_addr),
     822                                    ntohs(so->so_fport), n1, 1);
     823            }
     824            else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4)
     825            {
     826                if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
     827                    return 1;
     828
     829                m->m_len = bptr - m->m_data; /* Adjust length */
     830                m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
     831                                    buff, (unsigned long)ntohl(so->so_faddr.s_addr),
     832                                    ntohs(so->so_fport), n1, 1);
     833            }
     834            return 1;
     835
     836#ifdef VBOX
     837            /** @todo Disabled EMU_REALAUDIO, because it uses a static variable.
     838             * This is not legal when more than one slirp instance is active. */
     839#else /* !VBOX */
     840        case EMU_REALAUDIO:
     841            /*
     842             * RealAudio emulation - JP. We must try to parse the incoming
     843             * data and try to find the two characters that contain the
     844             * port number. Then we redirect an udp port and replace the
     845             * number with the real port we got.
     846             *
     847             * The 1.0 beta versions of the player are not supported
     848             * any more.
     849             *
     850             * A typical packet for player version 1.0 (release version):
     851             *
     852             * 0000:50 4E 41 00 05
     853             * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P
     854             * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
     855             * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
     856             * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
     857             *
     858             * Now the port number 0x1BD7 is found at offset 0x04 of the
     859             * Now the port number 0x1BD7 is found at offset 0x04 of the
     860             * second packet. This time we received five bytes first and
     861             * then the rest. You never know how many bytes you get.
     862             *
     863             * A typical packet for player version 2.0 (beta):
     864             *
     865             * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á.
     866             * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0
     867             * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
     868             * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
     869             * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
     870             *
     871             * Port number 0x1BC1 is found at offset 0x0d.
     872             *
     873             * This is just a horrible switch statement. Variable ra tells
     874             * us where we're going.
     875             */
     876
     877            bptr = m->m_data;
     878            while (bptr < m->m_data + m->m_len)
     879            {
     880                u_short p;
     881                static int ra = 0;
     882                char ra_tbl[4];
     883
     884                ra_tbl[0] = 0x50;
     885                ra_tbl[1] = 0x4e;
     886                ra_tbl[2] = 0x41;
     887                ra_tbl[3] = 0;
     888
     889                switch (ra)
    648890                {
    649                         struct socket *tmpso;
    650                         struct sockaddr_in addr;
    651                         socklen_t addrlen = sizeof(struct sockaddr_in);
    652                         struct sbuf *so_rcv = &so->so_rcv;
    653 
    654                         memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
    655                         so_rcv->sb_wptr += m->m_len;
    656                         so_rcv->sb_rptr += m->m_len;
    657                         m->m_data[m->m_len] = 0; /* NULL terminate */
    658                         if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
    659                                 if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
    660                                         HTONS(n1);
    661                                         HTONS(n2);
    662                                         /* n2 is the one on our host */
    663                                         for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
    664                                                 if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
    665                                                     tmpso->so_lport == n2 &&
    666                                                     tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
    667                                                     tmpso->so_fport == n1) {
    668                                                         if (getsockname(tmpso->s,
    669                                                                 (struct sockaddr *)&addr, &addrlen) == 0)
    670                                                            n2 = ntohs(addr.sin_port);
    671                                                         break;
    672                                                 }
    673                                         }
    674                                 }
    675                                 so_rcv->sb_cc = sprintf(so_rcv->sb_data, "%d,%d\r\n", n1, n2);
    676                                 so_rcv->sb_rptr = so_rcv->sb_data;
    677                                 so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
     891                    case 0:
     892                    case 2:
     893                    case 3:
     894                        if (*bptr++ != ra_tbl[ra])
     895                        {
     896                            ra = 0;
     897                            continue;
    678898                        }
    679                         m_free(pData, m);
    680                         return 0;
     899                        break;
     900
     901                    case 1:
     902                        /*
     903                         * We may get 0x50 several times, ignore them
     904                         */
     905                        if (*bptr == 0x50)
     906                        {
     907                            ra = 1;
     908                            bptr++;
     909                            continue;
     910                        }
     911                        else if (*bptr++ != ra_tbl[ra])
     912                        {
     913                            ra = 0;
     914                            continue;
     915                        }
     916                        break;
     917
     918                    case 4:
     919                        /*
     920                         * skip version number
     921                         */
     922                        bptr++;
     923                        break;
     924
     925                    case 5:
     926                        /*
     927                         * The difference between versions 1.0 and
     928                         * 2.0 is here. For future versions of
     929                         * the player this may need to be modified.
     930                         */
     931                        if (*(bptr + 1) == 0x02)
     932                            bptr += 8;
     933                        else
     934                            bptr += 4;
     935                        break;
     936
     937                    case 6:
     938                        /* This is the field containing the port
     939                         * number that RA-player is listening to.
     940                         */
     941                        lport = (((u_char*)bptr)[0] << 8)
     942                              + ((u_char *)bptr)[1];
     943                        if (lport < 6970)
     944                            lport += 256;   /* don't know why */
     945                        if (lport < 6970 || lport > 7170)
     946                            return 1;       /* failed */
     947
     948                        /* try to get udp port between 6970 - 7170 */
     949                        for (p = 6970; p < 7071; p++)
     950                        {
     951                            if (udp_listen(htons(p),
     952                                           so->so_laddr.s_addr,
     953                                           htons(lport),
     954                                           SS_FACCEPTONCE))
     955                            {
     956                                break;
     957                            }
     958                        }
     959                        if (p == 7071)
     960                            p = 0;
     961                        *(u_char *)bptr++ = (p >> 8) & 0xff;
     962                        *(u_char *)bptr++ = p & 0xff;
     963                        ra = 0;
     964                        return 1;   /* port redirected, we're done */
     965                        break;
     966
     967                    default:
     968                        ra = 0;
    681969                }
    682 
    683         case EMU_FTP: /* ftp */
    684                 *(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
    685                 if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
    686                         /*
    687                          * Need to emulate the PORT command
    688                          */
    689                         x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
    690                                    &n1, &n2, &n3, &n4, &n5, &n6, buff);
    691                         if (x < 6)
    692                            return 1;
    693 
    694                         laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
    695                         lport = htons((n5 << 8) | (n6));
    696 
    697                         if ((so = solisten(pData, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
    698                            return 1;
    699 
    700                         n6 = ntohs(so->so_fport);
    701 
    702                         n5 = (n6 >> 8) & 0xff;
    703                         n6 &= 0xff;
    704 
    705                         laddr = ntohl(so->so_faddr.s_addr);
    706 
    707                         n1 = ((laddr >> 24) & 0xff);
    708                         n2 = ((laddr >> 16) & 0xff);
    709                         n3 = ((laddr >> 8)  & 0xff);
    710                         n4 =  (laddr & 0xff);
    711 
    712                         m->m_len = bptr - m->m_data; /* Adjust length */
    713                         m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s",
    714                                             n1, n2, n3, n4, n5, n6, x==7?buff:"");
    715                         return 1;
    716                 } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
    717                         /*
    718                          * Need to emulate the PASV response
    719                          */
    720                         x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
    721                                    &n1, &n2, &n3, &n4, &n5, &n6, buff);
    722                         if (x < 6)
    723                            return 1;
    724 
    725                         laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
    726                         lport = htons((n5 << 8) | (n6));
    727 
    728                         if ((so = solisten(pData, 0, laddr, lport, SS_FACCEPTONCE)) == NULL)
    729                            return 1;
    730 
    731                         n6 = ntohs(so->so_fport);
    732 
    733                         n5 = (n6 >> 8) & 0xff;
    734                         n6 &= 0xff;
    735 
    736                         laddr = ntohl(so->so_faddr.s_addr);
    737 
    738                         n1 = ((laddr >> 24) & 0xff);
    739                         n2 = ((laddr >> 16) & 0xff);
    740                         n3 = ((laddr >> 8)  & 0xff);
    741                         n4 =  (laddr & 0xff);
    742 
    743                         m->m_len = bptr - m->m_data; /* Adjust length */
    744                         m->m_len += sprintf(bptr,"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
    745                                             n1, n2, n3, n4, n5, n6, x==7?buff:"");
    746 
    747                         return 1;
    748                 }
    749 
    750                 return 1;
    751 
    752          case EMU_KSH:
    753                 /*
    754                  * The kshell (Kerberos rsh) and shell services both pass
    755                  * a local port port number to carry signals to the server
    756                  * and stderr to the client.  It is passed at the beginning
    757                  * of the connection as a NUL-terminated decimal ASCII string.
    758                  */
    759                 so->so_emu = 0;
    760                 for (lport = 0, i = 0; i < m->m_len-1; ++i) {
    761                         if (m->m_data[i] < '0' || m->m_data[i] > '9')
    762                                 return 1;       /* invalid number */
    763                         lport *= 10;
    764                         lport += m->m_data[i] - '0';
    765                 }
    766                 if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
    767                     (so = solisten(pData, 0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
    768                         m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
    769                 return 1;
    770 
    771          case EMU_IRC:
    772                 /*
    773                  * Need to emulate DCC CHAT, DCC SEND and DCC MOVE
    774                  */
    775                 *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
    776                 if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
    777                          return 1;
    778 
    779                 /* The %256s is for the broken mIRC */
    780                 if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
    781                         if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
    782                                 return 1;
    783 
    784                         m->m_len = bptr - m->m_data; /* Adjust length */
    785                         m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
    786                              (unsigned long)ntohl(so->so_faddr.s_addr),
    787                              ntohs(so->so_fport), 1);
    788                 } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
    789                         if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
    790                                 return 1;
    791 
    792                         m->m_len = bptr - m->m_data; /* Adjust length */
    793                         m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
    794                               buff, (unsigned long)ntohl(so->so_faddr.s_addr),
    795                               ntohs(so->so_fport), n1, 1);
    796                 } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
    797                         if ((so = solisten(pData, 0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
    798                                 return 1;
    799 
    800                         m->m_len = bptr - m->m_data; /* Adjust length */
    801                         m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
    802                               buff, (unsigned long)ntohl(so->so_faddr.s_addr),
    803                               ntohs(so->so_fport), n1, 1);
    804                 }
    805                 return 1;
    806 
    807 #ifdef VBOX
    808          /** @todo Disabled EMU_REALAUDIO, because it uses a static variable.
    809           * This is not legal when more than one slirp instance is active. */
    810 #else /* !VBOX */
    811          case EMU_REALAUDIO:
    812                 /*
    813                  * RealAudio emulation - JP. We must try to parse the incoming
    814                  * data and try to find the two characters that contain the
    815                  * port number. Then we redirect an udp port and replace the
    816                  * number with the real port we got.
    817                  *
    818                  * The 1.0 beta versions of the player are not supported
    819                  * any more.
    820                  *
    821                  * A typical packet for player version 1.0 (release version):
    822                  *
    823                  * 0000:50 4E 41 00 05
    824                  * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P
    825                  * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
    826                  * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
    827                  * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
    828                  *
    829                  * Now the port number 0x1BD7 is found at offset 0x04 of the
    830                  * Now the port number 0x1BD7 is found at offset 0x04 of the
    831                  * second packet. This time we received five bytes first and
    832                  * then the rest. You never know how many bytes you get.
    833                  *
    834                  * A typical packet for player version 2.0 (beta):
    835                  *
    836                  * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á.
    837                  * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0
    838                  * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
    839                  * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
    840                  * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
    841                  *
    842                  * Port number 0x1BC1 is found at offset 0x0d.
    843                  *
    844                  * This is just a horrible switch statement. Variable ra tells
    845                  * us where we're going.
    846                  */
    847 
    848                 bptr = m->m_data;
    849                 while (bptr < m->m_data + m->m_len) {
    850                         u_short p;
    851                         static int ra = 0;
    852                         char ra_tbl[4];
    853 
    854                         ra_tbl[0] = 0x50;
    855                         ra_tbl[1] = 0x4e;
    856                         ra_tbl[2] = 0x41;
    857                         ra_tbl[3] = 0;
    858 
    859                         switch (ra) {
    860                          case 0:
    861                          case 2:
    862                          case 3:
    863                                 if (*bptr++ != ra_tbl[ra]) {
    864                                         ra = 0;
    865                                         continue;
    866                                 }
    867                                 break;
    868 
    869                          case 1:
    870                                 /*
    871                                  * We may get 0x50 several times, ignore them
    872                                  */
    873                                 if (*bptr == 0x50) {
    874                                         ra = 1;
    875                                         bptr++;
    876                                         continue;
    877                                 } else if (*bptr++ != ra_tbl[ra]) {
    878                                         ra = 0;
    879                                         continue;
    880                                 }
    881                                 break;
    882 
    883                          case 4:
    884                                 /*
    885                                  * skip version number
    886                                  */
    887                                 bptr++;
    888                                 break;
    889 
    890                          case 5:
    891                                 /*
    892                                  * The difference between versions 1.0 and
    893                                  * 2.0 is here. For future versions of
    894                                  * the player this may need to be modified.
    895                                  */
    896                                 if (*(bptr + 1) == 0x02)
    897                                    bptr += 8;
    898                                 else
    899                                    bptr += 4;
    900                                 break;
    901 
    902                          case 6:
    903                                 /* This is the field containing the port
    904                                  * number that RA-player is listening to.
    905                                  */
    906                                 lport = (((u_char*)bptr)[0] << 8)
    907                                 + ((u_char *)bptr)[1];
    908                                 if (lport < 6970)
    909                                    lport += 256;   /* don't know why */
    910                                 if (lport < 6970 || lport > 7170)
    911                                    return 1;       /* failed */
    912 
    913                                 /* try to get udp port between 6970 - 7170 */
    914                                 for (p = 6970; p < 7071; p++) {
    915                                         if (udp_listen( htons(p),
    916                                                        so->so_laddr.s_addr,
    917                                                        htons(lport),
    918                                                        SS_FACCEPTONCE)) {
    919                                                 break;
    920                                         }
    921                                 }
    922                                 if (p == 7071)
    923                                    p = 0;
    924                                 *(u_char *)bptr++ = (p >> 8) & 0xff;
    925                                 *(u_char *)bptr++ = p & 0xff;
    926                                 ra = 0;
    927                                 return 1;   /* port redirected, we're done */
    928                                 break;
    929 
    930                          default:
    931                                 ra = 0;
    932                         }
    933                         ra++;
    934                 }
    935                 return 1;
     970                ra++;
     971            }
     972            return 1;
    936973#endif /* !VBOX */
    937974
    938          default:
    939                 /* Ooops, not emulated, won't call tcp_emu again */
    940                 so->so_emu = 0;
    941                 return 1;
    942         }
     975        default:
     976            /* Ooops, not emulated, won't call tcp_emu again */
     977            so->so_emu = 0;
     978            return 1;
     979    }
    943980}
    944981
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