Merge Transaction TCP, courtesy of Andras Olah <olah@cs.utwente.nl> and
Bob Braden <braden@isi.edu>. NB: This has not had David's TCP ACK hack re-integrated. It is not clear what the correct solution to this problem is, if any. If a better solution doesn't pop up in response to this message, I'll put David's code back in (or he's welcome to do so himself).
This commit is contained in:
parent
fd65acba73
commit
a0292f2375
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6283
@ -97,15 +97,12 @@ struct protosw inetsw[] = {
|
||||
#ifdef TTCP
|
||||
{ SOCK_STREAM, &inetdomain, IPPROTO_TCP,
|
||||
PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD,
|
||||
#else
|
||||
{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD,
|
||||
#endif
|
||||
tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
|
||||
tcp_usrreq,
|
||||
tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain, tcp_sysctl
|
||||
#else
|
||||
{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD,
|
||||
tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
|
||||
tcp_usrreq,
|
||||
tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain,
|
||||
#endif
|
||||
},
|
||||
{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR,
|
||||
rip_input, rip_output, 0, rip_ctloutput,
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_debug.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id$
|
||||
* $Id: tcp_debug.c,v 1.2 1994/08/02 07:48:54 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifdef TCPDEBUG
|
||||
@ -102,7 +102,7 @@ tcp_trace(act, ostate, tp, ti, req)
|
||||
if (tcpconsdebug == 0)
|
||||
return;
|
||||
if (tp)
|
||||
printf("%x %s:", tp, tcpstates[ostate]);
|
||||
printf("%p %s:", tp, tcpstates[ostate]);
|
||||
else
|
||||
printf("???????? ");
|
||||
printf("%s ", tanames[act]);
|
||||
@ -130,11 +130,14 @@ tcp_trace(act, ostate, tp, ti, req)
|
||||
printf("@%x, urp=%x", ack, ti->ti_urp);
|
||||
flags = ti->ti_flags;
|
||||
if (flags) {
|
||||
#ifndef lint
|
||||
char *cp = "<";
|
||||
#define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } }
|
||||
#define pf(f) { \
|
||||
if (ti->ti_flags & TH_##f) { \
|
||||
printf("%s%s", cp, #f); \
|
||||
cp = ","; \
|
||||
} \
|
||||
}
|
||||
pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
|
||||
#endif
|
||||
printf(">");
|
||||
}
|
||||
break;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_output.c 8.3 (Berkeley) 12/30/93
|
||||
* $Id: tcp_output.c,v 1.5 1995/01/24 08:03:22 davidg Exp $
|
||||
* $Id: tcp_output.c,v 1.6 1995/01/26 03:56:20 davidg Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -66,8 +66,6 @@ extern struct mbuf *m_copypack();
|
||||
#endif
|
||||
|
||||
|
||||
#define MAX_TCPOPTLEN 32 /* max # bytes that go in options */
|
||||
|
||||
/*
|
||||
* Tcp output routine: figure out what should be sent and send it.
|
||||
*/
|
||||
@ -80,9 +78,13 @@ tcp_output(tp)
|
||||
int off, flags, error;
|
||||
register struct mbuf *m;
|
||||
register struct tcpiphdr *ti;
|
||||
u_char opt[MAX_TCPOPTLEN];
|
||||
u_char opt[TCP_MAXOLEN];
|
||||
unsigned optlen, hdrlen;
|
||||
int idle, sendalot;
|
||||
#ifdef TTCP
|
||||
struct rmxp_tao *taop;
|
||||
struct rmxp_tao tao_noncached;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Determine length of data that should be transmitted,
|
||||
@ -104,6 +106,17 @@ tcp_output(tp)
|
||||
win = min(tp->snd_wnd, tp->snd_cwnd);
|
||||
|
||||
flags = tcp_outflags[tp->t_state];
|
||||
#ifdef TTCP
|
||||
/*
|
||||
* Get standard flags, and add SYN or FIN if requested by 'hidden'
|
||||
* state flags.
|
||||
*/
|
||||
if (tp->t_flags & TF_NEEDFIN)
|
||||
flags |= TH_FIN;
|
||||
if (tp->t_flags & TF_NEEDSYN)
|
||||
flags |= TH_SYN;
|
||||
#endif /* TTCP */
|
||||
|
||||
/*
|
||||
* If in persist timeout with window of 0, send 1 byte.
|
||||
* Otherwise, if window is small but nonzero
|
||||
@ -139,6 +152,26 @@ tcp_output(tp)
|
||||
|
||||
len = min(so->so_snd.sb_cc, win) - off;
|
||||
|
||||
#ifdef TTCP
|
||||
if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) {
|
||||
taop = &tao_noncached;
|
||||
bzero(taop, sizeof(*taop));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lop off SYN bit if it has already been sent. However, if this
|
||||
* is SYN-SENT state and if segment contains data and if we don't
|
||||
* know that foreign host supports TAO, suppress sending segment.
|
||||
*/
|
||||
if ((flags & TH_SYN) && SEQ_GT(tp->snd_nxt, tp->snd_una)) {
|
||||
flags &= ~TH_SYN;
|
||||
off--, len++;
|
||||
if (len > 0 && tp->t_state == TCPS_SYN_SENT &&
|
||||
taop->tao_ccsent == 0)
|
||||
return 0;
|
||||
}
|
||||
#endif /* TTCP */
|
||||
|
||||
if (len < 0) {
|
||||
/*
|
||||
* If FIN has been sent but not acked,
|
||||
@ -179,11 +212,18 @@ tcp_output(tp)
|
||||
if (len == tp->t_maxseg)
|
||||
goto send;
|
||||
if ((idle || tp->t_flags & TF_NODELAY) &&
|
||||
#ifdef TTCP
|
||||
(tp->t_flags & TF_NOPUSH) == 0 &&
|
||||
#endif
|
||||
len + off >= so->so_snd.sb_cc)
|
||||
goto send;
|
||||
if (tp->t_force)
|
||||
goto send;
|
||||
#ifdef TTCP
|
||||
if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
|
||||
#else
|
||||
if (len >= tp->max_sndwnd / 2)
|
||||
#endif
|
||||
goto send;
|
||||
if (SEQ_LT(tp->snd_nxt, tp->snd_max))
|
||||
goto send;
|
||||
@ -216,7 +256,12 @@ tcp_output(tp)
|
||||
*/
|
||||
if (tp->t_flags & TF_ACKNOW)
|
||||
goto send;
|
||||
#ifdef TTCP
|
||||
if ((flags & TH_RST) ||
|
||||
((flags & TH_SYN) && (tp->t_flags & TF_NEEDSYN) == 0))
|
||||
#else
|
||||
if (flags & (TH_SYN|TH_RST))
|
||||
#endif
|
||||
goto send;
|
||||
if (SEQ_GT(tp->snd_up, tp->snd_una))
|
||||
goto send;
|
||||
@ -279,10 +324,10 @@ tcp_output(tp)
|
||||
u_short mss;
|
||||
|
||||
opt[0] = TCPOPT_MAXSEG;
|
||||
opt[1] = 4;
|
||||
mss = htons((u_short) tcp_mss(tp, 0));
|
||||
opt[1] = TCPOLEN_MAXSEG;
|
||||
mss = htons((u_short) tcp_mssopt(tp));
|
||||
bcopy((caddr_t)&mss, (caddr_t)(opt + 2), sizeof(mss));
|
||||
optlen = 4;
|
||||
optlen = TCPOLEN_MAXSEG;
|
||||
|
||||
if ((tp->t_flags & TF_REQ_SCALE) &&
|
||||
((flags & TH_ACK) == 0 ||
|
||||
@ -303,8 +348,12 @@ tcp_output(tp)
|
||||
* and our peer have sent timestamps in our SYN's.
|
||||
*/
|
||||
if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
|
||||
(flags & TH_RST) == 0 &&
|
||||
(flags & TH_RST) == 0 &&
|
||||
#ifdef TTCP
|
||||
((flags & TH_ACK) == 0 ||
|
||||
#else
|
||||
((flags & (TH_SYN|TH_ACK)) == TH_SYN ||
|
||||
#endif
|
||||
(tp->t_flags & TF_RCVD_TSTMP))) {
|
||||
u_long *lp = (u_long *)(opt + optlen);
|
||||
|
||||
@ -315,27 +364,108 @@ tcp_output(tp)
|
||||
optlen += TCPOLEN_TSTAMP_APPA;
|
||||
}
|
||||
|
||||
#ifdef TTCP
|
||||
/*
|
||||
* Send `CC-family' options if our side wants to use them (TF_REQ_CC),
|
||||
* options are allowed (!TF_NOOPT) and it's not a RST.
|
||||
*/
|
||||
if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
|
||||
(flags & TH_RST) == 0) {
|
||||
switch (flags & (TH_SYN|TH_ACK)) {
|
||||
/*
|
||||
* This is a normal ACK, send CC if we received CC before
|
||||
* from our peer.
|
||||
*/
|
||||
case TH_ACK:
|
||||
if (!(tp->t_flags & TF_RCVD_CC))
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
/*
|
||||
* We can only get here in T/TCP's SYN_SENT* state, when
|
||||
* we're a sending a non-SYN segment without waiting for
|
||||
* the ACK of our SYN. A check above assures that we only
|
||||
* do this if our peer understands T/TCP.
|
||||
*/
|
||||
case 0:
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_CC;
|
||||
opt[optlen++] = TCPOLEN_CC;
|
||||
*(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
|
||||
|
||||
optlen += 4;
|
||||
break;
|
||||
|
||||
/*
|
||||
* This is our initial SYN, check whether we have to use
|
||||
* CC or CC.new.
|
||||
*/
|
||||
case TH_SYN:
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
|
||||
if (taop->tao_ccsent != 0 &&
|
||||
CC_GEQ(tp->cc_send, taop->tao_ccsent)) {
|
||||
opt[optlen++] = TCPOPT_CC;
|
||||
taop->tao_ccsent = tp->cc_send;
|
||||
} else {
|
||||
opt[optlen++] = TCPOPT_CCNEW;
|
||||
taop->tao_ccsent = 0;
|
||||
}
|
||||
opt[optlen++] = TCPOLEN_CC;
|
||||
*(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
|
||||
optlen += 4;
|
||||
break;
|
||||
|
||||
/*
|
||||
* This is a SYN,ACK; send CC and CC.echo if we received
|
||||
* CC from our peer.
|
||||
*/
|
||||
case (TH_SYN|TH_ACK):
|
||||
if (tp->t_flags & TF_RCVD_CC) {
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_CC;
|
||||
opt[optlen++] = TCPOLEN_CC;
|
||||
*(u_int32_t *)&opt[optlen] =
|
||||
htonl(tp->cc_send);
|
||||
optlen += 4;
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_NOP;
|
||||
opt[optlen++] = TCPOPT_CCECHO;
|
||||
opt[optlen++] = TCPOLEN_CC;
|
||||
*(u_int32_t *)&opt[optlen] =
|
||||
htonl(tp->cc_recv);
|
||||
optlen += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* TTCP */
|
||||
|
||||
hdrlen += optlen;
|
||||
|
||||
/*
|
||||
* Adjust data length if insertion of options will
|
||||
* bump the packet length beyond the t_maxseg length.
|
||||
* bump the packet length beyond the t_maxopd length.
|
||||
* Clear the FIN bit because we cut off the tail of
|
||||
* the segment.
|
||||
*/
|
||||
if (len > tp->t_maxseg - optlen) {
|
||||
if (len + optlen > tp->t_maxopd) {
|
||||
/*
|
||||
* If there is still more to send, don't close the connection.
|
||||
*/
|
||||
flags &= ~TH_FIN;
|
||||
|
||||
len = tp->t_maxseg - optlen;
|
||||
len = tp->t_maxopd - optlen;
|
||||
sendalot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
/*#ifdef DIAGNOSTIC*/
|
||||
if (max_linkhdr + hdrlen > MHLEN)
|
||||
panic("tcphdr too big");
|
||||
#endif
|
||||
/*#endif*/
|
||||
|
||||
/*
|
||||
* Grab a header mbuf, attaching a copy of data to
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: tcp_subr.c,v 1.4 1994/10/02 17:48:44 phk Exp $
|
||||
* $Id: tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -54,16 +54,24 @@
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#define TCPOUTFLAGS
|
||||
#include <netinet/tcp_fsm.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
#include <netinet/tcp_timer.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#include <netinet/tcpip.h>
|
||||
#ifdef TCPDEBUG
|
||||
#include <netinet/tcp_debug.h>
|
||||
#endif
|
||||
|
||||
/* patchable/settable parameters for tcp */
|
||||
int tcp_mssdflt = TCP_MSS;
|
||||
int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
|
||||
int tcp_do_rfc1323 = 1;
|
||||
#ifdef TTCP
|
||||
int tcp_do_rfc1644 = 1;
|
||||
static void tcp_cleartaocache(void);
|
||||
#endif
|
||||
|
||||
extern struct inpcb *tcp_last_inpcb;
|
||||
|
||||
@ -75,6 +83,10 @@ tcp_init()
|
||||
{
|
||||
|
||||
tcp_iss = 1; /* wrong */
|
||||
#ifdef TTCP
|
||||
tcp_ccgen = 1;
|
||||
tcp_cleartaocache();
|
||||
#endif
|
||||
tcb.inp_next = tcb.inp_prev = &tcb;
|
||||
if (max_protohdr < sizeof(struct tcpiphdr))
|
||||
max_protohdr = sizeof(struct tcpiphdr);
|
||||
@ -196,6 +208,10 @@ tcp_respond(tp, ti, m, ack, seq, flags)
|
||||
ti->ti_sum = in_cksum(m, tlen);
|
||||
((struct ip *)ti)->ip_len = tlen;
|
||||
((struct ip *)ti)->ip_ttl = ip_defttl;
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
tcp_trace(TA_OUTPUT, 0, tp, ti, 0);
|
||||
#endif
|
||||
(void) ip_output(m, NULL, ro, 0, NULL);
|
||||
}
|
||||
|
||||
@ -215,9 +231,14 @@ tcp_newtcpcb(inp)
|
||||
return ((struct tcpcb *)0);
|
||||
bzero((char *) tp, sizeof(struct tcpcb));
|
||||
tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
|
||||
tp->t_maxseg = tcp_mssdflt;
|
||||
tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
|
||||
|
||||
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
|
||||
if (tcp_do_rfc1323)
|
||||
tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
|
||||
#ifdef TTCP
|
||||
if (tcp_do_rfc1644)
|
||||
tp->t_flags |= TF_REQ_CC;
|
||||
#endif
|
||||
tp->t_inpcb = inp;
|
||||
/*
|
||||
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
|
||||
@ -444,3 +465,65 @@ tcp_quench(inp, errno)
|
||||
if (tp)
|
||||
tp->snd_cwnd = tp->t_maxseg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look-up the routing entry to the peer of this inpcb. If no route
|
||||
* is found and it cannot be allocated the return NULL. This routine
|
||||
* is called by TCP routines that access the rmx structure and by tcp_mss
|
||||
* to get the interface MTU.
|
||||
*/
|
||||
struct rtentry *
|
||||
tcp_rtlookup(inp)
|
||||
struct inpcb *inp;
|
||||
{
|
||||
struct route *ro;
|
||||
struct rtentry *rt;
|
||||
|
||||
ro = &inp->inp_route;
|
||||
rt = ro->ro_rt;
|
||||
if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
|
||||
/* No route yet, so try to acquire one */
|
||||
if (inp->inp_faddr.s_addr != INADDR_ANY) {
|
||||
ro->ro_dst.sa_family = AF_INET;
|
||||
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
|
||||
((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
|
||||
inp->inp_faddr;
|
||||
rtalloc(ro);
|
||||
rt = ro->ro_rt;
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
#ifdef TTCP
|
||||
/*
|
||||
* Return a pointer to the cached information about the remote host.
|
||||
* The cached information is stored in the protocol specific part of
|
||||
* the route metrics.
|
||||
*/
|
||||
struct rmxp_tao *
|
||||
tcp_gettaocache(inp)
|
||||
struct inpcb *inp;
|
||||
{
|
||||
struct rtentry *rt = tcp_rtlookup(inp);
|
||||
|
||||
/* Make sure this is a host route and is up. */
|
||||
if (rt == NULL ||
|
||||
(rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST))
|
||||
return NULL;
|
||||
|
||||
return rmx_taop(rt->rt_rmx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the TAO cache entries, called from tcp_init.
|
||||
*
|
||||
* XXX
|
||||
* This routine is just an empty one, because we assume that the routing
|
||||
* routing tables are initialized at the same time when TCP, so there is
|
||||
* nothing in the cache left over.
|
||||
*/
|
||||
static void
|
||||
tcp_cleartaocache(void)
|
||||
{ }
|
||||
#endif /* TTCP */
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_timer.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id$
|
||||
* $Id: tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef TUBA_INCLUDE
|
||||
@ -123,6 +123,9 @@ tcp_slowtimo()
|
||||
}
|
||||
}
|
||||
tp->t_idle++;
|
||||
#ifdef TTCP
|
||||
tp->t_duration++;
|
||||
#endif
|
||||
if (tp->t_rtt)
|
||||
tp->t_rtt++;
|
||||
tpgone:
|
||||
@ -212,6 +215,12 @@ tcp_timers(tp, timer)
|
||||
tp->t_srtt = 0;
|
||||
}
|
||||
tp->snd_nxt = tp->snd_una;
|
||||
#ifdef TTCP
|
||||
/*
|
||||
* Force a segment to be sent.
|
||||
*/
|
||||
tp->t_flags |= TF_ACKNOW;
|
||||
#endif
|
||||
/*
|
||||
* If timing a segment in this window, stop the timer.
|
||||
*/
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93
|
||||
* $Id: tcp_subr.c,v 1.4 1994/10/02 17:48:44 phk Exp $
|
||||
* $Id: tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -54,16 +54,24 @@
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#define TCPOUTFLAGS
|
||||
#include <netinet/tcp_fsm.h>
|
||||
#include <netinet/tcp_seq.h>
|
||||
#include <netinet/tcp_timer.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#include <netinet/tcpip.h>
|
||||
#ifdef TCPDEBUG
|
||||
#include <netinet/tcp_debug.h>
|
||||
#endif
|
||||
|
||||
/* patchable/settable parameters for tcp */
|
||||
int tcp_mssdflt = TCP_MSS;
|
||||
int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
|
||||
int tcp_do_rfc1323 = 1;
|
||||
#ifdef TTCP
|
||||
int tcp_do_rfc1644 = 1;
|
||||
static void tcp_cleartaocache(void);
|
||||
#endif
|
||||
|
||||
extern struct inpcb *tcp_last_inpcb;
|
||||
|
||||
@ -75,6 +83,10 @@ tcp_init()
|
||||
{
|
||||
|
||||
tcp_iss = 1; /* wrong */
|
||||
#ifdef TTCP
|
||||
tcp_ccgen = 1;
|
||||
tcp_cleartaocache();
|
||||
#endif
|
||||
tcb.inp_next = tcb.inp_prev = &tcb;
|
||||
if (max_protohdr < sizeof(struct tcpiphdr))
|
||||
max_protohdr = sizeof(struct tcpiphdr);
|
||||
@ -196,6 +208,10 @@ tcp_respond(tp, ti, m, ack, seq, flags)
|
||||
ti->ti_sum = in_cksum(m, tlen);
|
||||
((struct ip *)ti)->ip_len = tlen;
|
||||
((struct ip *)ti)->ip_ttl = ip_defttl;
|
||||
#ifdef TCPDEBUG
|
||||
if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
|
||||
tcp_trace(TA_OUTPUT, 0, tp, ti, 0);
|
||||
#endif
|
||||
(void) ip_output(m, NULL, ro, 0, NULL);
|
||||
}
|
||||
|
||||
@ -215,9 +231,14 @@ tcp_newtcpcb(inp)
|
||||
return ((struct tcpcb *)0);
|
||||
bzero((char *) tp, sizeof(struct tcpcb));
|
||||
tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
|
||||
tp->t_maxseg = tcp_mssdflt;
|
||||
tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
|
||||
|
||||
tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
|
||||
if (tcp_do_rfc1323)
|
||||
tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
|
||||
#ifdef TTCP
|
||||
if (tcp_do_rfc1644)
|
||||
tp->t_flags |= TF_REQ_CC;
|
||||
#endif
|
||||
tp->t_inpcb = inp;
|
||||
/*
|
||||
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
|
||||
@ -444,3 +465,65 @@ tcp_quench(inp, errno)
|
||||
if (tp)
|
||||
tp->snd_cwnd = tp->t_maxseg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look-up the routing entry to the peer of this inpcb. If no route
|
||||
* is found and it cannot be allocated the return NULL. This routine
|
||||
* is called by TCP routines that access the rmx structure and by tcp_mss
|
||||
* to get the interface MTU.
|
||||
*/
|
||||
struct rtentry *
|
||||
tcp_rtlookup(inp)
|
||||
struct inpcb *inp;
|
||||
{
|
||||
struct route *ro;
|
||||
struct rtentry *rt;
|
||||
|
||||
ro = &inp->inp_route;
|
||||
rt = ro->ro_rt;
|
||||
if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
|
||||
/* No route yet, so try to acquire one */
|
||||
if (inp->inp_faddr.s_addr != INADDR_ANY) {
|
||||
ro->ro_dst.sa_family = AF_INET;
|
||||
ro->ro_dst.sa_len = sizeof(ro->ro_dst);
|
||||
((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
|
||||
inp->inp_faddr;
|
||||
rtalloc(ro);
|
||||
rt = ro->ro_rt;
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
#ifdef TTCP
|
||||
/*
|
||||
* Return a pointer to the cached information about the remote host.
|
||||
* The cached information is stored in the protocol specific part of
|
||||
* the route metrics.
|
||||
*/
|
||||
struct rmxp_tao *
|
||||
tcp_gettaocache(inp)
|
||||
struct inpcb *inp;
|
||||
{
|
||||
struct rtentry *rt = tcp_rtlookup(inp);
|
||||
|
||||
/* Make sure this is a host route and is up. */
|
||||
if (rt == NULL ||
|
||||
(rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST))
|
||||
return NULL;
|
||||
|
||||
return rmx_taop(rt->rt_rmx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear all the TAO cache entries, called from tcp_init.
|
||||
*
|
||||
* XXX
|
||||
* This routine is just an empty one, because we assume that the routing
|
||||
* routing tables are initialized at the same time when TCP, so there is
|
||||
* nothing in the cache left over.
|
||||
*/
|
||||
static void
|
||||
tcp_cleartaocache(void)
|
||||
{ }
|
||||
#endif /* TTCP */
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
|
||||
* $Id: tcp_usrreq.c,v 1.5 1994/09/15 10:36:56 davidg Exp $
|
||||
* $Id: tcp_usrreq.c,v 1.6 1994/12/15 20:39:34 wollman Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -84,7 +84,9 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
struct sockaddr_in *sinp;
|
||||
int s;
|
||||
int error = 0;
|
||||
#ifdef TCPDEBUG
|
||||
int ostate;
|
||||
#endif
|
||||
|
||||
if (req == PRU_CONTROL)
|
||||
return (in_control(so, (int)m, (caddr_t)nam,
|
||||
@ -113,9 +115,14 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
#ifdef KPROF
|
||||
tcp_acounts[tp->t_state][req]++;
|
||||
#endif
|
||||
#ifdef TCPDEBUG
|
||||
ostate = tp->t_state;
|
||||
} else
|
||||
ostate = 0;
|
||||
#else /* TCPDEBUG */
|
||||
}
|
||||
#endif /* TCPDEBUG */
|
||||
|
||||
switch (req) {
|
||||
|
||||
/*
|
||||
@ -196,6 +203,10 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TTCP
|
||||
if ((error = tcp_connect(tp, nam)) != 0)
|
||||
break;
|
||||
#else /* TTCP */
|
||||
if (inp->inp_lport == 0) {
|
||||
error = in_pcbbind(inp, (struct mbuf *)0);
|
||||
if (error)
|
||||
@ -220,6 +231,7 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
|
||||
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
|
||||
tcp_sendseqinit(tp);
|
||||
#endif /* TTCP */
|
||||
error = tcp_output(tp);
|
||||
break;
|
||||
|
||||
@ -275,9 +287,37 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
* Do a send by putting data in output queue and updating urgent
|
||||
* marker if URG set. Possibly send more data.
|
||||
*/
|
||||
#ifdef TTCP
|
||||
case PRU_SEND_EOF:
|
||||
#endif
|
||||
case PRU_SEND:
|
||||
sbappend(&so->so_snd, m);
|
||||
error = tcp_output(tp);
|
||||
#ifdef TTCP
|
||||
if (nam && tp->t_state < TCPS_SYN_SENT) {
|
||||
/*
|
||||
* Do implied connect if not yet connected,
|
||||
* initialize window to default value, and
|
||||
* initialize maxseg/maxopd using peer's cached
|
||||
* MSS.
|
||||
*/
|
||||
error = tcp_connect(tp, nam);
|
||||
if (error)
|
||||
break;
|
||||
tp->snd_wnd = TTCP_CLIENT_SND_WND;
|
||||
tcp_mss(tp, -1);
|
||||
}
|
||||
|
||||
if (req == PRU_SEND_EOF) {
|
||||
/*
|
||||
* Close the send side of the connection after
|
||||
* the data is sent.
|
||||
*/
|
||||
socantsendmore(so);
|
||||
tp = tcp_usrclosed(tp);
|
||||
}
|
||||
if (tp != NULL)
|
||||
#endif TTCP
|
||||
error = tcp_output(tp);
|
||||
break;
|
||||
|
||||
/*
|
||||
@ -345,7 +385,9 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
*/
|
||||
case PRU_SLOWTIMO:
|
||||
tp = tcp_timers(tp, (int)nam);
|
||||
#ifdef TCPDEBUG
|
||||
req |= (int)nam << 8; /* for debug's sake */
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -359,6 +401,83 @@ tcp_usrreq(so, req, m, nam, control)
|
||||
return (error);
|
||||
}
|
||||
|
||||
#ifdef TTCP
|
||||
/*
|
||||
* Common subroutine to open a TCP connection to remote host specified
|
||||
* by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local
|
||||
* port number if needed. Call in_pcbladdr to do the routing and to choose
|
||||
* a local host address (interface). If there is an existing incarnation
|
||||
* of the same connection in TIME-WAIT state and if the remote host was
|
||||
* sending CC options and if the connection duration was < MSL, then
|
||||
* truncate the previous TIME-WAIT state and proceed.
|
||||
* Initialize connection parameters and enter SYN-SENT state.
|
||||
*/
|
||||
int
|
||||
tcp_connect(tp, nam)
|
||||
register struct tcpcb *tp;
|
||||
struct mbuf *nam;
|
||||
{
|
||||
struct inpcb *inp = tp->t_inpcb, *oinp;
|
||||
struct socket *so = inp->inp_socket;
|
||||
struct tcpcb *otp;
|
||||
struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
|
||||
struct sockaddr_in *ifaddr;
|
||||
int error;
|
||||
|
||||
if (inp->inp_lport == 0) {
|
||||
error = in_pcbbind(inp, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cannot simply call in_pcbconnect, because there might be an
|
||||
* earlier incarnation of this same connection still in
|
||||
* TIME_WAIT state, creating an ADDRINUSE error.
|
||||
*/
|
||||
error = in_pcbladdr(inp, nam, &ifaddr);
|
||||
oinp = in_pcblookup(inp->inp_head,
|
||||
sin->sin_addr, sin->sin_port,
|
||||
inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
|
||||
: ifaddr->sin_addr,
|
||||
inp->inp_lport, 0);
|
||||
if (oinp) {
|
||||
if (oinp != inp && (otp = intotcpcb(oinp)) != NULL &&
|
||||
otp->t_state == TCPS_TIME_WAIT &&
|
||||
otp->t_duration < TCPTV_MSL &&
|
||||
(otp->t_flags & TF_RCVD_CC))
|
||||
otp = tcp_close(otp);
|
||||
else
|
||||
return EADDRINUSE;
|
||||
}
|
||||
if (inp->inp_laddr.s_addr == INADDR_ANY)
|
||||
inp->inp_laddr = ifaddr->sin_addr;
|
||||
inp->inp_faddr = sin->sin_addr;
|
||||
inp->inp_fport = sin->sin_port;
|
||||
|
||||
tp->t_template = tcp_template(tp);
|
||||
if (tp->t_template == 0) {
|
||||
in_pcbdisconnect(inp);
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
tcpstat.tcps_connattempt++;
|
||||
tp->t_state = TCPS_SYN_SENT;
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
|
||||
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
|
||||
tcp_sendseqinit(tp);
|
||||
tp->cc_send = CC_INC(tcp_ccgen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TTCP */
|
||||
|
||||
int
|
||||
tcp_ctloutput(op, so, level, optname, mp)
|
||||
int op;
|
||||
@ -409,6 +528,26 @@ tcp_ctloutput(op, so, level, optname, mp)
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
||||
#ifdef TTCP
|
||||
case TCP_NOOPT:
|
||||
if (m == NULL || m->m_len < sizeof (int))
|
||||
error = EINVAL;
|
||||
else if (*mtod(m, int *))
|
||||
tp->t_flags |= TF_NOOPT;
|
||||
else
|
||||
tp->t_flags &= ~TF_NOOPT;
|
||||
break;
|
||||
|
||||
case TCP_NOPUSH:
|
||||
if (m == NULL || m->m_len < sizeof (int))
|
||||
error = EINVAL;
|
||||
else if (*mtod(m, int *))
|
||||
tp->t_flags |= TF_NOPUSH;
|
||||
else
|
||||
tp->t_flags &= ~TF_NOPUSH;
|
||||
break;
|
||||
#endif /* TTCP */
|
||||
|
||||
default:
|
||||
error = ENOPROTOOPT;
|
||||
break;
|
||||
@ -428,6 +567,14 @@ tcp_ctloutput(op, so, level, optname, mp)
|
||||
case TCP_MAXSEG:
|
||||
*mtod(m, int *) = tp->t_maxseg;
|
||||
break;
|
||||
#ifdef TTCP
|
||||
case TCP_NOOPT:
|
||||
*mtod(m, int *) = tp->t_flags & TF_NOOPT;
|
||||
break;
|
||||
case TCP_NOPUSH:
|
||||
*mtod(m, int *) = tp->t_flags & TF_NOPUSH;
|
||||
break;
|
||||
#endif /* TTCP */
|
||||
default:
|
||||
error = ENOPROTOOPT;
|
||||
break;
|
||||
@ -533,12 +680,22 @@ tcp_usrclosed(tp)
|
||||
|
||||
case TCPS_CLOSED:
|
||||
case TCPS_LISTEN:
|
||||
#ifndef TTCP
|
||||
case TCPS_SYN_SENT:
|
||||
#endif
|
||||
tp->t_state = TCPS_CLOSED;
|
||||
tp = tcp_close(tp);
|
||||
break;
|
||||
|
||||
#ifdef TTCP
|
||||
case TCPS_SYN_SENT:
|
||||
case TCPS_SYN_RECEIVED:
|
||||
tp->t_flags |= TF_NEEDFIN;
|
||||
break;
|
||||
|
||||
#else
|
||||
case TCPS_SYN_RECEIVED:
|
||||
#endif
|
||||
case TCPS_ESTABLISHED:
|
||||
tp->t_state = TCPS_FIN_WAIT_1;
|
||||
break;
|
||||
@ -551,3 +708,43 @@ tcp_usrclosed(tp)
|
||||
soisdisconnected(tp->t_inpcb->inp_socket);
|
||||
return (tp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sysctl for tcp variables.
|
||||
*/
|
||||
int
|
||||
tcp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
|
||||
int *name;
|
||||
u_int namelen;
|
||||
void *oldp;
|
||||
size_t *oldlenp;
|
||||
void *newp;
|
||||
size_t newlen;
|
||||
{
|
||||
extern int tcp_do_rfc1323;
|
||||
#ifdef TTCP
|
||||
extern int tcp_do_rfc1644;
|
||||
#endif
|
||||
extern int tcp_mssdflt;
|
||||
|
||||
/* All sysctl names at this level are terminal. */
|
||||
if (namelen != 1)
|
||||
return (ENOTDIR);
|
||||
|
||||
switch (name[0]) {
|
||||
case TCPCTL_DO_RFC1323:
|
||||
return (sysctl_int(oldp, oldlenp, newp, newlen,
|
||||
&tcp_do_rfc1323));
|
||||
#ifdef TTCP
|
||||
case TCPCTL_DO_RFC1644:
|
||||
return (sysctl_int(oldp, oldlenp, newp, newlen,
|
||||
&tcp_do_rfc1644));
|
||||
#endif
|
||||
case TCPCTL_MSSDFLT:
|
||||
return (sysctl_int(oldp, oldlenp, newp, newlen,
|
||||
&tcp_mssdflt));
|
||||
default:
|
||||
return (ENOPROTOOPT);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ struct rmxp_tao {
|
||||
#define TAOF_UNDEF 0 /* we don't know yet */
|
||||
#endif /* notyet */
|
||||
};
|
||||
#define rmx_taop(r) ((struct rmxp_tao *)&(r).rmx_pspec)
|
||||
#define rmx_taop(r) ((struct rmxp_tao *)(r).rmx_filler)
|
||||
#endif /* TTCP */
|
||||
|
||||
#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb)
|
||||
@ -333,11 +333,7 @@ struct rmxp_tao *
|
||||
#endif
|
||||
void tcp_init __P((void));
|
||||
void tcp_input __P((struct mbuf *, int));
|
||||
#ifdef TTCP
|
||||
void tcp_mss __P((struct tcpcb *, int));
|
||||
#else
|
||||
int tcp_mss __P((struct tcpcb *, u_int));
|
||||
#endif
|
||||
int tcp_mssopt __P((struct tcpcb *));
|
||||
struct tcpcb *
|
||||
tcp_newtcpcb __P((struct inpcb *));
|
||||
|
Loading…
Reference in New Issue
Block a user