tcp_subr.c revision 8c2d9d7577b4de8ac96614f700b1ec83e0745336
/*
* Copyright (c) 1982, 1986, 1988, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93
* tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp
*/
/*
* Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
#define WANT_SYS_IOCTL_H
#include <slirp.h>
/*
* Tcp initialization
*/
void
{
tcp_last_so = &tcb;
tcp_reass_maxqlen = 48;
tcp_reass_maxseg = 256;
}
/*
* Create template to be used to send tcp packets on a connection.
* Call after host entry created, fills
* necessary when the connection is used.
*/
/* struct tcpiphdr * */
void
{
n->ti_pr = IPPROTO_TCP;
n->ti_seq = 0;
n->ti_ack = 0;
n->ti_x2 = 0;
n->ti_off = 5;
n->ti_flags = 0;
n->ti_win = 0;
n->ti_sum = 0;
n->ti_urp = 0;
}
/*
* Send a single message to the TCP at address specified by
* of the tcpiphdr at ti and send directly to the addressed host.
* This is used to force keep alive messages out using the TCP
* template for a connection tp->t_template. If flags are given
* then we send a message back to the TCP which originated the
* segment ti, and discard the mbuf containing it and any other
* attached mbufs.
*
* In any case the ack and sequence number of the transmitted
* segment are as specified by the parameters.
*/
void
tcp_respond(PNATState pData, struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags)
{
register int tlen;
int win = 0;
DEBUG_CALL("tcp_respond");
DEBUG_ARG("m = %lx", (long)m);
if (tp)
if (m == 0)
{
#ifndef VBOX_WITH_SLIRP_BSD_MBUF
#else
#endif
return;
#ifdef TCP_COMPAT_42
tlen = 1;
#else
tlen = 0;
#endif
m->m_data += if_maxlinkhdr;
#ifdef VBOX_WITH_SLIRP_BSD_MBUF
#endif
}
else
{
/*
* ti points into m so the next line is just making
* the mbuf point to ti
*/
tlen = 0;
}
if (tp)
else
else
}
/*
* Create a new TCP control block, making an
* empty reassembly queue and hooking it to the argument
* protocol control block.
*/
struct tcpcb *
{
return ((struct tcpcb *)0);
/*
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
* rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
* reasonable initial retransmit time.
*/
return (tp);
}
/*
* Drop a TCP connection, reporting
* the specified error. If connection is synchronized,
* then send a RST to peer.
*/
{
/* tcp_drop(tp, errno)
register struct tcpcb *tp;
int errno;
{
*/
DEBUG_CALL("tcp_drop");
{
}
else
#if 0
#endif
}
/*
* Close a TCP control block:
* discard all space held by the tcp
* discard internet protocol block
* wake up any sleepers
*/
struct tcpcb *
{
DEBUG_CALL("tcp_close");
/*XXX: freeing the reassembly queue */
{
}
/* clobber input socket cache if we're closing the cached connection */
if (so == tcp_last_so)
tcp_last_so = &tcb;
closesocket(so->s);
return ((struct tcpcb *)0);
}
void
{
/* XXX */
}
/*
* When a source quench is received, close congestion window
* to one segment. We will gradually open it again as we proceed.
*/
#if 0
void
tcp_quench(i, int errno)
{
if (tp)
}
#endif
/*
* TCP protocol interface to socket abstraction.
*/
/*
* User issued close, and wish to trail through shutdown states:
* if never received SYN, just forget it. If got a SYN from peer,
* but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
* If already got a FIN from peer, then almost done; go to LAST_ACK
* state. In all other cases, have already sent FIN to peer (e.g.
* after PRU_SHUTDOWN), and just have to play tedious game waiting
* for peer to send FIN or not respond to keep-alives, etc.
* We can let the user exit from the close as soon as the FIN is acked.
*/
void
{
DEBUG_CALL("tcp_sockclosed");
{
case TCPS_CLOSED:
case TCPS_LISTEN:
case TCPS_SYN_SENT:
break;
case TCPS_SYN_RECEIVED:
case TCPS_ESTABLISHED:
break;
case TCPS_CLOSE_WAIT:
break;
}
/* soisfdisconnecting(tp->t_socket); */
if ( tp
/*
* (vasily) there're situations when the FIN or FIN,ACK are lost (Windows host)
* and retransmitting keeps VBox busy on sending closing sequences *very* frequent,
* easting a lot of CPU. To avoid this we don't sent on sockets marked as closed
* (see slirp.c for details about setting so_close member).
*/
if ( tp
#ifdef RT_OS_WINDOWS
#endif
)
}
/*
* Connect to a host on the Internet
* Called by tcp_input
* Only do a connect, the tcp fields will be set in tcp_input
* return 0 if there's a result of the connect,
* else return -1 means we're still connecting
* The return value is almost always -1 since the socket is
* nonblocking. Connect returns after the SYN is sent, and does
* not wait for ACK+SYN.
*/
{
int ret = 0;
DEBUG_CALL("tcp_fconnect");
{
struct sockaddr_in addr;
fd_nonblock(s);
opt = 1;
opt = 1;
{
/* It's an alias */
{
case CTL_DNS:
case CTL_ALIAS:
default:
break;
}
}
else
"addr.sin_addr.s_addr=%.16s\n",
/* We don't care what port we get */
/*
* If it's not in progress, it failed, so we just return 0,
* without clearing SS_NOFDREF
*/
}
return(ret);
}
/*
* Accept the socket and connect to the local-host
*
* We have a problem. The correct thing to do would be
* to first connect to the local-host, and only if the
* connection is accepted, then do an accept() here.
* But, a) we need to know who's trying to connect
* to the socket to be able to SYN the local-host, and
* b) we are already connected to the foreign host by
* the time it gets to accept(), so... We simply accept
* here and SYN the local-host.
*/
void
{
struct sockaddr_in addr;
int s, opt;
int status;
static int cVerbose = 1;
DEBUG_CALL("tcp_connect");
/*
* If it's an SS_ACCEPTONCE socket, no need to socreate()
* another socket, just use the accept() socket.
*/
{
/* FACCEPTONCE already have a tcpcb */
}
else
{
{
/* If it failed, get rid of the pending connection */
return;
}
{
return;
}
}
fd_nonblock(inso->s);
{
return;
}
fd_nonblock(s);
opt = 1;
opt = 1;
#if 0
opt = 1;
#endif
optlen = sizeof(int);
if (status < 0)
{
goto no_sockopt;
}
if (cVerbose > 0)
/* @todo (r-vvl) make it configurable (via extra data) */
if (status < 0)
{
goto no_sockopt;
}
optlen = sizeof(int);
if (status < 0)
{
goto no_sockopt;
}
if (cVerbose > 0)
if (status < 0)
{
goto no_sockopt;
}
if (cVerbose > 0)
cVerbose--;
/* Translate connections from localhost to the real hostname */
/* Close the accept() socket, set right state */
{
/* if it's not FACCEPTONCE, it's already NOFDREF */
}
so->s = s;
/* Compute window scaling to request. */
/* while (tp->request_r_scale < TCP_MAX_WINSHIFT
* && (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
* tp->request_r_scale++;
*/
/* soisconnecting(so); */ /* NOFDREF used instead */
}
/*
* Attach a TCPCB to a socket.
*/
int
{
return -1;
NSOCK_INC();
return 0;
}
/*
* Set the socket's type of service field
*/
{
{0, 0, 0, 0}
};
/*
* Return TOS according to the above table
*/
{
return 0;
}
/*
* Emulate programs that try and connect to us. This includes ftp (the data
* connection is initiated by the server) and IRC (DCC CHAT and DCC SEND)
* for now
*
* NOTE: It's possible to crash SLiRP by sending it unstandard strings to
* emulate... if this is a problem, more checks are needed here.
*
* XXX Assumes the whole command cames in one packet
*
* XXX Some ftp clients will have their TOS set to LOWDELAY and so Nagel will
* kick in. Because of this, we'll get the first letter, followed by the
* rest, so we simply scan for ORT instead of PORT... DCC doesn't have this
* problem because there's other stuff in the packet before the DCC command.
*
* Return 1 if the mbuf m is still valid and should be sbappend()ed
*
* NOTE: if you return 0 you MUST m_free() the mbuf!
*/
int
{
/*XXX: libalias should care about it */
return 1;
}