Thread View: comp.bugs.4bsd.ucb-fixes
1 messages
1 total messages
Started by Keith Bostic
Tue, 05 Apr 1988 03:18
V1.56 ((tcp 2 of 2) updated IP/TCP and XNS sources for 4.3BSD)
Author: Keith Bostic
Date: Tue, 05 Apr 1988 03:18
Date: Tue, 05 Apr 1988 03:18
1549 lines
46575 bytes
46575 bytes
Subject: (tcp 2 of 2) updated IP/TCP and XNS sources for 4.3BSD
Index: sys 4.3BSD
Description:
This is number 11 of 11 total articles posted to the newsgroup
comp.bugs.4bsd.ucb-fixes. This archive is number 2 of the 2
articles that make up the tcp posting.
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# netinet
# netinet/tcp_seq.h
# netinet/tcp_subr.c
# netinet/tcp_timer.c
# netinet/tcp_timer.h
# netinet/tcp_usrreq.c
# netinet/tcp_var.h
# netinet/tcpip.h
#
echo c - netinet
mkdir netinet > /dev/null 2>&1
echo x - netinet/tcp_seq.h
sed 's/^X//' >netinet/tcp_seq.h << 'END-of-netinet/tcp_seq.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcp_seq.h 7.2 (Berkeley) 12/7/87
X */
X
X/*
X * TCP sequence numbers are 32 bit integers operated
X * on with modular arithmetic. These macros can be
X * used to compare such integers.
X */
X#define SEQ_LT(a,b) ((int)((a)-(b)) < 0)
X#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
X#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
X#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
X
X/*
X * Macros to initialize tcp sequence numbers for
X * send and receive from initial send and receive
X * sequence numbers.
X */
X#define tcp_rcvseqinit(tp) \
X (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1
X
X#define tcp_sendseqinit(tp) \
X (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \
X (tp)->iss
X
X#define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */
X
X#ifdef KERNEL
Xtcp_seq tcp_iss; /* tcp initial send seq # */
X#endif
END-of-netinet/tcp_seq.h
echo x - netinet/tcp_subr.c
sed 's/^X//' >netinet/tcp_subr.c << 'END-of-netinet/tcp_subr.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcp_subr.c 7.13.1.1 (Berkeley) 2/7/88
X */
X
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "protosw.h"
X#include "errno.h"
X
X#include "../net/route.h"
X#include "../net/if.h"
X
X#include "in.h"
X#include "in_pcb.h"
X#include "in_systm.h"
X#include "ip.h"
X#include "ip_var.h"
X#include "ip_icmp.h"
X#include "tcp.h"
X#include "tcp_fsm.h"
X#include "tcp_seq.h"
X#include "tcp_timer.h"
X#include "tcp_var.h"
X#include "tcpip.h"
X
Xint tcp_ttl = TCP_TTL;
X
X/*
X * Tcp initialization
X */
Xtcp_init()
X{
X
X tcp_iss = 1; /* wrong */
X tcb.inp_next = tcb.inp_prev = &tcb;
X}
X
X/*
X * Create template to be used to send tcp packets on a connection.
X * Call after host entry created, allocates an mbuf and fills
X * in a skeletal tcp/ip header, minimizing the amount of work
X * necessary when the connection is used.
X */
Xstruct tcpiphdr *
Xtcp_template(tp)
X struct tcpcb *tp;
X{
X register struct inpcb *inp = tp->t_inpcb;
X register struct mbuf *m;
X register struct tcpiphdr *n;
X
X if ((n = tp->t_template) == 0) {
X m = m_get(M_DONTWAIT, MT_HEADER);
X if (m == NULL)
X return (0);
X m->m_off = MMAXOFF - sizeof (struct tcpiphdr);
X m->m_len = sizeof (struct tcpiphdr);
X n = mtod(m, struct tcpiphdr *);
X }
X n->ti_next = n->ti_prev = 0;
X n->ti_x1 = 0;
X n->ti_pr = IPPROTO_TCP;
X n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
X n->ti_src = inp->inp_laddr;
X n->ti_dst = inp->inp_faddr;
X n->ti_sport = inp->inp_lport;
X n->ti_dport = inp->inp_fport;
X n->ti_seq = 0;
X n->ti_ack = 0;
X n->ti_x2 = 0;
X n->ti_off = 5;
X n->ti_flags = 0;
X n->ti_win = 0;
X n->ti_sum = 0;
X n->ti_urp = 0;
X return (n);
X}
X
X/*
X * Send a single message to the TCP at address specified by
X * the given TCP/IP header. If flags==0, then we make a copy
X * of the tcpiphdr at ti and send directly to the addressed host.
X * This is used to force keep alive messages out using the TCP
X * template for a connection tp->t_template. If flags are given
X * then we send a message back to the TCP which originated the
X * segment ti, and discard the mbuf containing it and any other
X * attached mbufs.
X *
X * In any case the ack and sequence number of the transmitted
X * segment are as specified by the parameters.
X */
Xtcp_respond(tp, ti, ack, seq, flags)
X struct tcpcb *tp;
X register struct tcpiphdr *ti;
X tcp_seq ack, seq;
X int flags;
X{
X register struct mbuf *m;
X int win = 0, tlen;
X struct route *ro = 0;
X
X if (tp) {
X win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
X ro = &tp->t_inpcb->inp_route;
X }
X if (flags == 0) {
X m = m_get(M_DONTWAIT, MT_HEADER);
X if (m == NULL)
X return;
X#ifdef TCP_COMPAT_42
X tlen = 1;
X#else
X tlen = 0;
X#endif
X m->m_len = sizeof (struct tcpiphdr) + tlen;
X *mtod(m, struct tcpiphdr *) = *ti;
X ti = mtod(m, struct tcpiphdr *);
X flags = TH_ACK;
X } else {
X m = dtom(ti);
X m_freem(m->m_next);
X m->m_next = 0;
X m->m_off = (int)ti - (int)m;
X tlen = 0;
X m->m_len = sizeof (struct tcpiphdr);
X#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
X xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
X xchg(ti->ti_dport, ti->ti_sport, u_short);
X#undef xchg
X }
X ti->ti_next = ti->ti_prev = 0;
X ti->ti_x1 = 0;
X ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
X ti->ti_seq = htonl(seq);
X ti->ti_ack = htonl(ack);
X ti->ti_x2 = 0;
X ti->ti_off = sizeof (struct tcphdr) >> 2;
X ti->ti_flags = flags;
X ti->ti_win = htons((u_short)win);
X ti->ti_urp = 0;
X ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen);
X ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen;
X ((struct ip *)ti)->ip_ttl = tcp_ttl;
X (void) ip_output(m, (struct mbuf *)0, ro, 0);
X}
X
X/*
X * Create a new TCP control block, making an
X * empty reassembly queue and hooking it to the argument
X * protocol control block.
X */
Xstruct tcpcb *
Xtcp_newtcpcb(inp)
X struct inpcb *inp;
X{
X struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
X register struct tcpcb *tp;
X
X if (m == NULL)
X return ((struct tcpcb *)0);
X tp = mtod(m, struct tcpcb *);
X tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
X tp->t_maxseg = TCP_MSS;
X tp->t_flags = 0; /* sends options! */
X tp->t_inpcb = inp;
X /*
X * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
X * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
X * reasonable initial retransmit time.
X */
X tp->t_srtt = TCPTV_SRTTBASE;
X tp->t_rttvar = TCPTV_SRTTDFLT << 2;
X TCPT_RANGESET(tp->t_rxtcur,
X ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
X TCPTV_MIN, TCPTV_REXMTMAX);
X tp->snd_cwnd = sbspace(&inp->inp_socket->so_snd);
X tp->snd_ssthresh = 65535; /* XXX */
X inp->inp_ppcb = (caddr_t)tp;
X return (tp);
X}
X
X/*
X * Drop a TCP connection, reporting
X * the specified error. If connection is synchronized,
X * then send a RST to peer.
X */
Xstruct tcpcb *
Xtcp_drop(tp, errno)
X register struct tcpcb *tp;
X int errno;
X{
X struct socket *so = tp->t_inpcb->inp_socket;
X
X if (TCPS_HAVERCVDSYN(tp->t_state)) {
X tp->t_state = TCPS_CLOSED;
X (void) tcp_output(tp);
X tcpstat.tcps_drops++;
X } else
X tcpstat.tcps_conndrops++;
X so->so_error = errno;
X return (tcp_close(tp));
X}
X
X/*
X * Close a TCP control block:
X * discard all space held by the tcp
X * discard internet protocol block
X * wake up any sleepers
X */
Xstruct tcpcb *
Xtcp_close(tp)
X register struct tcpcb *tp;
X{
X register struct tcpiphdr *t;
X struct inpcb *inp = tp->t_inpcb;
X struct socket *so = inp->inp_socket;
X register struct mbuf *m;
X
X t = tp->seg_next;
X while (t != (struct tcpiphdr *)tp) {
X t = (struct tcpiphdr *)t->ti_next;
X m = dtom(t->ti_prev);
X remque(t->ti_prev);
X m_freem(m);
X }
X if (tp->t_template)
X (void) m_free(dtom(tp->t_template));
X (void) m_free(dtom(tp));
X inp->inp_ppcb = 0;
X soisdisconnected(so);
X in_pcbdetach(inp);
X tcpstat.tcps_closed++;
X return ((struct tcpcb *)0);
X}
X
Xtcp_drain()
X{
X
X}
X
X/*
X * Notify a tcp user of an asynchronous error;
X * just wake up so that he can collect error status.
X */
Xtcp_notify(inp)
X register struct inpcb *inp;
X{
X
X wakeup((caddr_t) &inp->inp_socket->so_timeo);
X sorwakeup(inp->inp_socket);
X sowwakeup(inp->inp_socket);
X}
Xtcp_ctlinput(cmd, sa)
X int cmd;
X struct sockaddr *sa;
X{
X extern u_char inetctlerrmap[];
X struct sockaddr_in *sin;
X int tcp_quench(), in_rtchange();
X
X if ((unsigned)cmd > PRC_NCMDS)
X return;
X if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
X return;
X sin = (struct sockaddr_in *)sa;
X if (sin->sin_addr.s_addr == INADDR_ANY)
X return;
X
X switch (cmd) {
X
X case PRC_QUENCH:
X in_pcbnotify(&tcb, &sin->sin_addr, 0, tcp_quench);
X break;
X
X case PRC_ROUTEDEAD:
X case PRC_REDIRECT_NET:
X case PRC_REDIRECT_HOST:
X case PRC_REDIRECT_TOSNET:
X case PRC_REDIRECT_TOSHOST:
X#if BSD>=43
X in_pcbnotify(&tcb, &sin->sin_addr, 0, in_rtchange);
X#endif
X break;
X
X default:
X if (inetctlerrmap[cmd] == 0)
X return; /* XXX */
X in_pcbnotify(&tcb, &sin->sin_addr, (int)inetctlerrmap[cmd],
X tcp_notify);
X }
X}
X
X#if BSD<43
X/* XXX fake routine */
Xtcp_abort(inp)
X struct inpcb *inp;
X{
X return;
X}
X#endif
X
X/*
X * When a source quench is received, close congestion window
X * to one segment. We will gradually open it again as we proceed.
X */
Xtcp_quench(inp)
X struct inpcb *inp;
X{
X struct tcpcb *tp = intotcpcb(inp);
X
X if (tp)
X tp->snd_cwnd = tp->t_maxseg;
X}
END-of-netinet/tcp_subr.c
echo x - netinet/tcp_timer.c
sed 's/^X//' >netinet/tcp_timer.c << 'END-of-netinet/tcp_timer.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcp_timer.c 7.11.1.2 (Berkeley) 3/16/88
X */
X
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "protosw.h"
X#include "errno.h"
X
X#include "../net/if.h"
X#include "../net/route.h"
X
X#include "in.h"
X#include "in_pcb.h"
X#include "in_systm.h"
X#include "ip.h"
X#include "ip_var.h"
X#include "tcp.h"
X#include "tcp_fsm.h"
X#include "tcp_seq.h"
X#include "tcp_timer.h"
X#include "tcp_var.h"
X#include "tcpip.h"
X
Xint tcpnodelack = 0;
Xint tcp_keepidle = TCPTV_KEEP_IDLE;
Xint tcp_keepintvl = TCPTV_KEEPINTVL;
Xint tcp_maxidle;
X/*
X * Fast timeout routine for processing delayed acks
X */
Xtcp_fasttimo()
X{
X register struct inpcb *inp;
X register struct tcpcb *tp;
X int s = splnet();
X
X inp = tcb.inp_next;
X if (inp)
X for (; inp != &tcb; inp = inp->inp_next)
X if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
X (tp->t_flags & TF_DELACK)) {
X tp->t_flags &= ~TF_DELACK;
X tp->t_flags |= TF_ACKNOW;
X tcpstat.tcps_delack++;
X (void) tcp_output(tp);
X }
X splx(s);
X}
X
X/*
X * Tcp protocol timeout routine called every 500 ms.
X * Updates the timers in all active tcb's and
X * causes finite state machine actions if timers expire.
X */
Xtcp_slowtimo()
X{
X register struct inpcb *ip, *ipnxt;
X register struct tcpcb *tp;
X int s = splnet();
X register int i;
X
X tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
X /*
X * Search through tcb's and update active timers.
X */
X ip = tcb.inp_next;
X if (ip == 0) {
X splx(s);
X return;
X }
X for (; ip != &tcb; ip = ipnxt) {
X ipnxt = ip->inp_next;
X tp = intotcpcb(ip);
X if (tp == 0)
X continue;
X for (i = 0; i < TCPT_NTIMERS; i++) {
X if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
X (void) tcp_usrreq(tp->t_inpcb->inp_socket,
X PRU_SLOWTIMO, (struct mbuf *)0,
X (struct mbuf *)i, (struct mbuf *)0);
X if (ipnxt->inp_prev != ip)
X goto tpgone;
X }
X }
X tp->t_idle++;
X if (tp->t_rtt)
X tp->t_rtt++;
Xtpgone:
X ;
X }
X tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
X#ifdef TCP_COMPAT_42
X if ((int)tcp_iss < 0)
X tcp_iss = 0; /* XXX */
X#endif
X splx(s);
X}
X
X/*
X * Cancel all timers for TCP tp.
X */
Xtcp_canceltimers(tp)
X struct tcpcb *tp;
X{
X register int i;
X
X for (i = 0; i < TCPT_NTIMERS; i++)
X tp->t_timer[i] = 0;
X}
X
Xint tcp_backoff[TCP_MAXRXTSHIFT + 1] =
X { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
X
X/*
X * TCP timer processing.
X */
Xstruct tcpcb *
Xtcp_timers(tp, timer)
X register struct tcpcb *tp;
X int timer;
X{
X register int rexmt;
X
X switch (timer) {
X
X /*
X * 2 MSL timeout in shutdown went off. If we're closed but
X * still waiting for peer to close and connection has been idle
X * too long, or if 2MSL time is up from TIME_WAIT, delete connection
X * control block. Otherwise, check again in a bit.
X */
X case TCPT_2MSL:
X if (tp->t_state != TCPS_TIME_WAIT &&
X tp->t_idle <= tcp_maxidle)
X tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
X else
X tp = tcp_close(tp);
X break;
X
X /*
X * Retransmission timer went off. Message has not
X * been acked within retransmit interval. Back off
X * to a longer retransmit interval and retransmit one segment.
X */
X case TCPT_REXMT:
X if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
X tp->t_rxtshift = TCP_MAXRXTSHIFT;
X tcpstat.tcps_timeoutdrop++;
X tp = tcp_drop(tp, ETIMEDOUT);
X break;
X }
X tcpstat.tcps_rexmttimeo++;
X rexmt = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
X rexmt *= tcp_backoff[tp->t_rxtshift];
X TCPT_RANGESET(tp->t_rxtcur, rexmt, TCPTV_MIN, TCPTV_REXMTMAX);
X tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
X /*
X * If losing, let the lower level know and try for
X * a better route. Also, if we backed off this far,
X * our srtt estimate is probably bogus. Clobber it
X * so we'll take the next rtt measurement as our srtt;
X * move the current srtt into rttvar to keep the current
X * retransmit times until then.
X */
X if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
X#if BSD>=43
X in_losing(tp->t_inpcb);
X#endif
X tp->t_rttvar += (tp->t_srtt >> 2);
X tp->t_srtt = 0;
X }
X tp->snd_nxt = tp->snd_una;
X /*
X * If timing a segment in this window, stop the timer.
X */
X tp->t_rtt = 0;
X /*
X * Close the congestion window down to one segment
X * (we'll open it by one segment for each ack we get).
X * Since we probably have a window's worth of unacked
X * data accumulated, this "slow start" keeps us from
X * dumping all that data as back-to-back packets (which
X * might overwhelm an intermediate gateway).
X *
X * There are two phases to the opening: Initially we
X * open by one mss on each ack. This makes the window
X * size increase exponentially with time. If the
X * window is larger than the path can handle, this
X * exponential growth results in dropped packet(s)
X * almost immediately. To get more time between
X * drops but still "push" the network to take advantage
X * of improving conditions, we switch from exponential
X * to linear window opening at some threshhold size.
X * For a threshhold, we use half the current window
X * size, truncated to a multiple of the mss.
X *
X * (the minimum cwnd that will give us exponential
X * growth is 2 mss. We don't allow the threshhold
X * to go below this.)
X */
X {
X u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
X if (win < 2)
X win = 2;
X tp->snd_cwnd = tp->t_maxseg;
X tp->snd_ssthresh = win * tp->t_maxseg;
X }
X (void) tcp_output(tp);
X break;
X
X /*
X * Persistance timer into zero window.
X * Force a byte to be output, if possible.
X */
X case TCPT_PERSIST:
X tcpstat.tcps_persisttimeo++;
X tcp_setpersist(tp);
X tp->t_force = 1;
X (void) tcp_output(tp);
X tp->t_force = 0;
X break;
X
X /*
X * Keep-alive timer went off; send something
X * or drop connection if idle for too long.
X */
X case TCPT_KEEP:
X tcpstat.tcps_keeptimeo++;
X if (tp->t_state < TCPS_ESTABLISHED)
X goto dropit;
X if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
X tp->t_state <= TCPS_CLOSE_WAIT) {
X if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
X goto dropit;
X /*
X * Send a packet designed to force a response
X * if the peer is up and reachable:
X * either an ACK if the connection is still alive,
X * or an RST if the peer has closed the connection
X * due to timeout or reboot.
X * Using sequence number tp->snd_una-1
X * causes the transmitted zero-length segment
X * to lie outside the receive window;
X * by the protocol spec, this requires the
X * correspondent TCP to respond.
X */
X tcpstat.tcps_keepprobe++;
X#ifdef TCP_COMPAT_42
X /*
X * The keepalive packet must have nonzero length
X * to get a 4.2 host to respond.
X */
X tcp_respond(tp, tp->t_template,
X tp->rcv_nxt - 1, tp->snd_una - 1, 0);
X#else
X tcp_respond(tp, tp->t_template,
X tp->rcv_nxt, tp->snd_una - 1, 0);
X#endif
X tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
X } else
X tp->t_timer[TCPT_KEEP] = tcp_keepidle;
X break;
X dropit:
X tcpstat.tcps_keepdrops++;
X tp = tcp_drop(tp, ETIMEDOUT);
X break;
X }
X return (tp);
X}
END-of-netinet/tcp_timer.c
echo x - netinet/tcp_timer.h
sed 's/^X//' >netinet/tcp_timer.h << 'END-of-netinet/tcp_timer.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcp_timer.h 7.5 (Berkeley) 3/16/88
X */
X
X/*
X * Definitions of the TCP timers. These timers are counted
X * down PR_SLOWHZ times a second.
X */
X#define TCPT_NTIMERS 4
X
X#define TCPT_REXMT 0 /* retransmit */
X#define TCPT_PERSIST 1 /* retransmit persistance */
X#define TCPT_KEEP 2 /* keep alive */
X#define TCPT_2MSL 3 /* 2*msl quiet time timer */
X
X/*
X * The TCPT_REXMT timer is used to force retransmissions.
X * The TCP has the TCPT_REXMT timer set whenever segments
X * have been sent for which ACKs are expected but not yet
X * received. If an ACK is received which advances tp->snd_una,
X * then the retransmit timer is cleared (if there are no more
X * outstanding segments) or reset to the base value (if there
X * are more ACKs expected). Whenever the retransmit timer goes off,
X * we retransmit one unacknowledged segment, and do a backoff
X * on the retransmit timer.
X *
X * The TCPT_PERSIST timer is used to keep window size information
X * flowing even if the window goes shut. If all previous transmissions
X * have been acknowledged (so that there are no retransmissions in progress),
X * and the window is too small to bother sending anything, then we start
X * the TCPT_PERSIST timer. When it expires, if the window is nonzero,
X * we go to transmit state. Otherwise, at intervals send a single byte
X * into the peer's window to force him to update our window information.
X * We do this at most as often as TCPT_PERSMIN time intervals,
X * but no more frequently than the current estimate of round-trip
X * packet time. The TCPT_PERSIST timer is cleared whenever we receive
X * a window update from the peer.
X *
X * The TCPT_KEEP timer is used to keep connections alive. If an
X * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,
X * but not yet established, then we drop the connection. Once the connection
X * is established, if the connection is idle for TCPTV_KEEP_IDLE time
X * (and keepalives have been enabled on the socket), we begin to probe
X * the connection. We force the peer to send us a segment by sending:
X * <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
X * This segment is (deliberately) outside the window, and should elicit
X * an ack segment in response from the peer. If, despite the TCPT_KEEP
X * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
X * amount of time probing, then we drop the connection.
X */
X
X#define TCP_TTL 30 /* default time to live for TCP segs */
X/*
X * Time constants.
X */
X#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */
X#define TCPTV_SRTTBASE 0 /* base roundtrip time;
X if 0, no idea yet */
X#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
X
X#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistance */
X#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
X
X#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */
X#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */
X#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */
X#define TCPTV_KEEPCNT 8 /* max probes before drop */
X
X#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
X#define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */
X
X#define TCP_LINGERTIME 120 /* linger at most 2 minutes */
X
X#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */
X
X#ifdef TCPTIMERS
Xchar *tcptimers[] =
X { "REXMT", "PERSIST", "KEEP", "2MSL" };
X#endif
X
X/*
X * Force a time value to be in a certain range.
X */
X#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \
X (tv) = (value); \
X if ((tv) < (tvmin)) \
X (tv) = (tvmin); \
X else if ((tv) > (tvmax)) \
X (tv) = (tvmax); \
X}
X
X#ifdef KERNEL
Xextern int tcp_keepidle; /* time before keepalive probes begin */
Xextern int tcp_keepintvl; /* time between keepalive probes */
Xextern int tcp_maxidle; /* time to drop after starting probes */
Xextern int tcp_ttl; /* time to live for TCP segs */
Xextern int tcp_backoff[];
X#endif
END-of-netinet/tcp_timer.h
echo x - netinet/tcp_usrreq.c
sed 's/^X//' >netinet/tcp_usrreq.c << 'END-of-netinet/tcp_usrreq.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcp_usrreq.c 7.7.1.2 (Berkeley) 3/16/88
X */
X
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "protosw.h"
X#include "errno.h"
X#include "stat.h"
X
X#include "../net/if.h"
X#include "../net/route.h"
X
X#include "in.h"
X#include "in_pcb.h"
X#include "in_systm.h"
X#include "ip.h"
X#include "ip_var.h"
X#include "tcp.h"
X#include "tcp_fsm.h"
X#include "tcp_seq.h"
X#include "tcp_timer.h"
X#include "tcp_var.h"
X#include "tcpip.h"
X#include "tcp_debug.h"
X
X/*
X * TCP protocol interface to socket abstraction.
X */
Xextern char *tcpstates[];
Xstruct tcpcb *tcp_newtcpcb();
X
X/*
X * Process a TCP user request for TCP tb. If this is a send request
X * then m is the mbuf chain of send data. If this is a timer expiration
X * (called from the software clock routine), then timertype tells which timer.
X */
X/*ARGSUSED*/
Xtcp_usrreq(so, req, m, nam, rights)
X struct socket *so;
X int req;
X struct mbuf *m, *nam, *rights;
X{
X register struct inpcb *inp;
X register struct tcpcb *tp;
X int s;
X int error = 0;
X int ostate;
X
X#if BSD>=43
X if (req == PRU_CONTROL)
X return (in_control(so, (int)m, (caddr_t)nam,
X (struct ifnet *)rights));
X#else
X if (req == PRU_CONTROL)
X return(EOPNOTSUPP);
X#endif
X if (rights && rights->m_len)
X return (EINVAL);
X
X s = splnet();
X inp = sotoinpcb(so);
X /*
X * When a TCP is attached to a socket, then there will be
X * a (struct inpcb) pointed at by the socket, and this
X * structure will point at a subsidary (struct tcpcb).
X */
X if (inp == 0 && req != PRU_ATTACH) {
X splx(s);
X return (EINVAL); /* XXX */
X }
X if (inp) {
X tp = intotcpcb(inp);
X /* WHAT IF TP IS 0? */
X#ifdef KPROF
X tcp_acounts[tp->t_state][req]++;
X#endif
X ostate = tp->t_state;
X } else
X ostate = 0;
X switch (req) {
X
X /*
X * TCP attaches to socket via PRU_ATTACH, reserving space,
X * and an internet control block.
X */
X case PRU_ATTACH:
X if (inp) {
X error = EISCONN;
X break;
X }
X error = tcp_attach(so);
X if (error)
X break;
X if ((so->so_options & SO_LINGER) && so->so_linger == 0)
X so->so_linger = TCP_LINGERTIME;
X tp = sototcpcb(so);
X break;
X
X /*
X * PRU_DETACH detaches the TCP protocol from the socket.
X * If the protocol state is non-embryonic, then can't
X * do this directly: have to initiate a PRU_DISCONNECT,
X * which may finish later; embryonic TCB's can just
X * be discarded here.
X */
X case PRU_DETACH:
X if (tp->t_state > TCPS_LISTEN)
X tp = tcp_disconnect(tp);
X else
X tp = tcp_close(tp);
X break;
X
X /*
X * Give the socket an address.
X */
X case PRU_BIND:
X error = in_pcbbind(inp, nam);
X if (error)
X break;
X break;
X
X /*
X * Prepare to accept connections.
X */
X case PRU_LISTEN:
X if (inp->inp_lport == 0)
X error = in_pcbbind(inp, (struct mbuf *)0);
X if (error == 0)
X tp->t_state = TCPS_LISTEN;
X break;
X
X /*
X * Initiate connection to peer.
X * Create a template for use in transmissions on this connection.
X * Enter SYN_SENT state, and mark socket as connecting.
X * Start keep-alive timer, and seed output sequence space.
X * Send initial segment on connection.
X */
X case PRU_CONNECT:
X if (inp->inp_lport == 0) {
X error = in_pcbbind(inp, (struct mbuf *)0);
X if (error)
X break;
X }
X error = in_pcbconnect(inp, nam);
X if (error)
X break;
X tp->t_template = tcp_template(tp);
X if (tp->t_template == 0) {
X in_pcbdisconnect(inp);
X error = ENOBUFS;
X break;
X }
X soisconnecting(so);
X tcpstat.tcps_connattempt++;
X tp->t_state = TCPS_SYN_SENT;
X tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
X tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
X tcp_sendseqinit(tp);
X error = tcp_output(tp);
X break;
X
X /*
X * Create a TCP connection between two sockets.
X */
X case PRU_CONNECT2:
X error = EOPNOTSUPP;
X break;
X
X /*
X * Initiate disconnect from peer.
X * If connection never passed embryonic stage, just drop;
X * else if don't need to let data drain, then can just drop anyways,
X * else have to begin TCP shutdown process: mark socket disconnecting,
X * drain unread data, state switch to reflect user close, and
X * send segment (e.g. FIN) to peer. Socket will be really disconnected
X * when peer sends FIN and acks ours.
X *
X * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
X */
X case PRU_DISCONNECT:
X tp = tcp_disconnect(tp);
X break;
X
X /*
X * Accept a connection. Essentially all the work is
X * done at higher levels; just return the address
X * of the peer, storing through addr.
X */
X case PRU_ACCEPT: {
X struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
X
X nam->m_len = sizeof (struct sockaddr_in);
X sin->sin_family = AF_INET;
X sin->sin_port = inp->inp_fport;
X sin->sin_addr = inp->inp_faddr;
X break;
X }
X
X /*
X * Mark the connection as being incapable of further output.
X */
X case PRU_SHUTDOWN:
X socantsendmore(so);
X tp = tcp_usrclosed(tp);
X if (tp)
X error = tcp_output(tp);
X break;
X
X /*
X * After a receive, possibly send window update to peer.
X */
X case PRU_RCVD:
X (void) tcp_output(tp);
X break;
X
X /*
X * Do a send by putting data in output queue and updating urgent
X * marker if URG set. Possibly send more data.
X */
X case PRU_SEND:
X sbappend(&so->so_snd, m);
X error = tcp_output(tp);
X break;
X
X /*
X * Abort the TCP.
X */
X case PRU_ABORT:
X tp = tcp_drop(tp, ECONNABORTED);
X break;
X
X case PRU_SENSE:
X ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
X (void) splx(s);
X return (0);
X
X case PRU_RCVOOB:
X if ((so->so_oobmark == 0 &&
X (so->so_state & SS_RCVATMARK) == 0) ||
X#ifdef SO_OOBINLINE
X so->so_options & SO_OOBINLINE ||
X#endif
X tp->t_oobflags & TCPOOB_HADDATA) {
X error = EINVAL;
X break;
X }
X if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
X error = EWOULDBLOCK;
X break;
X }
X m->m_len = 1;
X *mtod(m, caddr_t) = tp->t_iobc;
X if (((int)nam & MSG_PEEK) == 0)
X tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
X break;
X
X case PRU_SENDOOB:
X if (sbspace(&so->so_snd) < -512) {
X m_freem(m);
X error = ENOBUFS;
X break;
X }
X /*
X * According to RFC961 (Assigned Protocols),
X * the urgent pointer points to the last octet
X * of urgent data. We continue, however,
X * to consider it to indicate the first octet
X * of data past the urgent section.
X * Otherwise, snd_up should be one lower.
X */
X sbappend(&so->so_snd, m);
X tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
X tp->t_force = 1;
X error = tcp_output(tp);
X tp->t_force = 0;
X break;
X
X case PRU_SOCKADDR:
X in_setsockaddr(inp, nam);
X break;
X
X case PRU_PEERADDR:
X in_setpeeraddr(inp, nam);
X break;
X
X /*
X * TCP slow timer went off; going through this
X * routine for tracing's sake.
X */
X case PRU_SLOWTIMO:
X tp = tcp_timers(tp, (int)nam);
X req |= (int)nam << 8; /* for debug's sake */
X break;
X
X default:
X panic("tcp_usrreq");
X }
X if (tp && (so->so_options & SO_DEBUG))
X tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req);
X splx(s);
X return (error);
X}
X
X#if BSD>=43
Xtcp_ctloutput(op, so, level, optname, mp)
X int op;
X struct socket *so;
X int level, optname;
X struct mbuf **mp;
X{
X int error = 0;
X struct inpcb *inp = sotoinpcb(so);
X register struct tcpcb *tp = intotcpcb(inp);
X register struct mbuf *m;
X
X if (level != IPPROTO_TCP)
X return (ip_ctloutput(op, so, level, optname, mp));
X
X switch (op) {
X
X case PRCO_SETOPT:
X m = *mp;
X switch (optname) {
X
X case TCP_NODELAY:
X if (m == NULL || m->m_len < sizeof (int))
X error = EINVAL;
X else if (*mtod(m, int *))
X tp->t_flags |= TF_NODELAY;
X else
X tp->t_flags &= ~TF_NODELAY;
X break;
X
X case TCP_MAXSEG: /* not yet */
X default:
X error = EINVAL;
X break;
X }
X if (m)
X (void) m_free(m);
X break;
X
X case PRCO_GETOPT:
X *mp = m = m_get(M_WAIT, MT_SOOPTS);
X m->m_len = sizeof(int);
X
X switch (optname) {
X case TCP_NODELAY:
X *mtod(m, int *) = tp->t_flags & TF_NODELAY;
X break;
X case TCP_MAXSEG:
X *mtod(m, int *) = tp->t_maxseg;
X break;
X default:
X error = EINVAL;
X break;
X }
X break;
X }
X return (error);
X}
X#endif
X
Xint tcp_sendspace = 1024*4;
Xint tcp_recvspace = 1024*4;
X/*
X * Attach TCP protocol to socket, allocating
X * internet protocol control block, tcp control block,
X * bufer space, and entering LISTEN state if to accept connections.
X */
Xtcp_attach(so)
X struct socket *so;
X{
X register struct tcpcb *tp;
X struct inpcb *inp;
X int error;
X
X error = soreserve(so, tcp_sendspace, tcp_recvspace);
X if (error)
X return (error);
X error = in_pcballoc(so, &tcb);
X if (error)
X return (error);
X inp = sotoinpcb(so);
X tp = tcp_newtcpcb(inp);
X if (tp == 0) {
X int nofd = so->so_state & SS_NOFDREF; /* XXX */
X
X so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
X in_pcbdetach(inp);
X so->so_state |= nofd;
X return (ENOBUFS);
X }
X tp->t_state = TCPS_CLOSED;
X return (0);
X}
X
X/*
X * Initiate (or continue) disconnect.
X * If embryonic state, just send reset (once).
X * If in ``let data drain'' option and linger null, just drop.
X * Otherwise (hard), mark socket disconnecting and drop
X * current input data; switch states based on user close, and
X * send segment to peer (with FIN).
X */
Xstruct tcpcb *
Xtcp_disconnect(tp)
X register struct tcpcb *tp;
X{
X struct socket *so = tp->t_inpcb->inp_socket;
X
X if (tp->t_state < TCPS_ESTABLISHED)
X tp = tcp_close(tp);
X else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
X tp = tcp_drop(tp, 0);
X else {
X soisdisconnecting(so);
X sbflush(&so->so_rcv);
X tp = tcp_usrclosed(tp);
X if (tp)
X (void) tcp_output(tp);
X }
X return (tp);
X}
X
X/*
X * User issued close, and wish to trail through shutdown states:
X * if never received SYN, just forget it. If got a SYN from peer,
X * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
X * If already got a FIN from peer, then almost done; go to LAST_ACK
X * state. In all other cases, have already sent FIN to peer (e.g.
X * after PRU_SHUTDOWN), and just have to play tedious game waiting
X * for peer to send FIN or not respond to keep-alives, etc.
X * We can let the user exit from the close as soon as the FIN is acked.
X */
Xstruct tcpcb *
Xtcp_usrclosed(tp)
X register struct tcpcb *tp;
X{
X
X switch (tp->t_state) {
X
X case TCPS_CLOSED:
X case TCPS_LISTEN:
X case TCPS_SYN_SENT:
X tp->t_state = TCPS_CLOSED;
X tp = tcp_close(tp);
X break;
X
X case TCPS_SYN_RECEIVED:
X case TCPS_ESTABLISHED:
X tp->t_state = TCPS_FIN_WAIT_1;
X break;
X
X case TCPS_CLOSE_WAIT:
X tp->t_state = TCPS_LAST_ACK;
X break;
X }
X if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
X soisdisconnected(tp->t_inpcb->inp_socket);
X return (tp);
X}
END-of-netinet/tcp_usrreq.c
echo x - netinet/tcp_var.h
sed 's/^X//' >netinet/tcp_var.h << 'END-of-netinet/tcp_var.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcp_var.h 7.7 (Berkeley) 2/27/88
X */
X
X/*
X * TCP configuration: This is a half-assed attempt to make TCP
X * self-configure for a few varieties of 4.2 and 4.3-based unixes.
X * If you don't have a) a 4.3bsd vax or b) a 3.x Sun (x<6), check
X * this carefully (it's probably not right). Please send me mail
X * if you run into configuration problems.
X * - Van Jacobson (van@lbl-csam.arpa)
X */
X
X#ifndef BSD
X#define BSD 42 /* if we're not 4.3, pretend we're 4.2 */
X#define OLDSTAT /* set if we have to use old netstat binaries */
X#endif
X
X/* #define OLDSTAT /* set if we have to use old netstat binaries */
X
X#if sun || BSD < 43
X#define TCP_COMPAT_42 /* set if we have to interop w/4.2 systems */
X#endif
X
X#ifndef SB_MAX
X#ifdef SB_MAXCOUNT
X#define SB_MAX SB_MAXCOUNT /* Sun has to be a little bit different... */
X#else
X#define SB_MAX 32767 /* XXX */
X#endif SB_MAXCOUNT
X#endif SB_MAX
X
X#ifndef IP_MAXPACKET
X#define IP_MAXPACKET 65535 /* maximum packet size */
X#endif
X
X/*
X * Bill Nowicki pointed out that the page size (CLBYTES) has
X * nothing to do with the mbuf cluster size. So, we followed
X * Sun's lead and made the new define MCLBYTES stand for the mbuf
X * cluster size. The following define makes up backwards compatible
X * with 4.3 and 4.2. If CLBYTES is >1024 on your machine, check
X * this against the mbuf cluster definitions in /usr/include/sys/mbuf.h.
X */
X#ifndef MCLBYTES
X#define MCLBYTES CLBYTES /* XXX */
X#endif
X
X/*
X * The routine in_localaddr is broken in Sun's 3.4. We redefine ours
X * (in tcp_input.c) so we use can it but won't have a name conflict.
X */
X#ifdef sun
X#define in_localaddr tcp_in_localaddr
X#endif
X
X/* --------------- end of TCP config ---------------- */
X
X/*
X * Kernel variables for tcp.
X */
X
X/*
X * Tcp control block, one per tcp; fields:
X */
Xstruct tcpcb {
X struct tcpiphdr *seg_next; /* sequencing queue */
X struct tcpiphdr *seg_prev;
X short t_state; /* state of this connection */
X short t_timer[TCPT_NTIMERS]; /* tcp timers */
X short t_rxtshift; /* log(2) of rexmt exp. backoff */
X short t_rxtcur; /* current retransmit value */
X short t_dupacks; /* consecutive dup acks recd */
X u_short t_maxseg; /* maximum segment size */
X char t_force; /* 1 if forcing out a byte */
X u_char t_flags;
X#define TF_ACKNOW 0x01 /* ack peer immediately */
X#define TF_DELACK 0x02 /* ack, but try to delay it */
X#define TF_NODELAY 0x04 /* don't delay packets to coalesce */
X#define TF_NOOPT 0x08 /* don't use tcp options */
X#define TF_SENTFIN 0x10 /* have sent FIN */
X struct tcpiphdr *t_template; /* skeletal packet for transmit */
X struct inpcb *t_inpcb; /* back pointer to internet pcb */
X/*
X * The following fields are used as in the protocol specification.
X * See RFC783, Dec. 1981, page 21.
X */
X/* send sequence variables */
X tcp_seq snd_una; /* send unacknowledged */
X tcp_seq snd_nxt; /* send next */
X tcp_seq snd_up; /* send urgent pointer */
X tcp_seq snd_wl1; /* window update seg seq number */
X tcp_seq snd_wl2; /* window update seg ack number */
X tcp_seq iss; /* initial send sequence number */
X u_short snd_wnd; /* send window */
X/* receive sequence variables */
X u_short rcv_wnd; /* receive window */
X tcp_seq rcv_nxt; /* receive next */
X tcp_seq rcv_up; /* receive urgent pointer */
X tcp_seq irs; /* initial receive sequence number */
X/*
X * Additional variables for this implementation.
X */
X/* receive variables */
X tcp_seq rcv_adv; /* advertised window */
X/* retransmit variables */
X tcp_seq snd_max; /* highest sequence number sent
X * used to recognize retransmits
X */
X/* congestion control (for slow start, source quench, retransmit after loss) */
X u_short snd_cwnd; /* congestion-controlled window */
X u_short snd_ssthresh; /* snd_cwnd size threshhold for
X * for slow start exponential to
X * linear switch */
X/*
X * transmit timing stuff.
X * srtt and rttvar are stored as fixed point; for convenience in smoothing,
X * srtt has 3 bits to the right of the binary point, rttvar has 2.
X * "Variance" is actually smoothed difference.
X */
X short t_idle; /* inactivity time */
X short t_rtt; /* round trip time */
X tcp_seq t_rtseq; /* sequence number being timed */
X short t_srtt; /* smoothed round-trip time */
X short t_rttvar; /* variance in round-trip time */
X u_short max_rcvd; /* most peer has sent into window */
X u_short max_sndwnd; /* largest window peer has offered */
X/* out-of-band data */
X char t_oobflags; /* have some */
X char t_iobc; /* input character */
X#define TCPOOB_HAVEDATA 0x01
X#define TCPOOB_HADDATA 0x02
X};
X
X#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb)
X#define sototcpcb(so) (intotcpcb(sotoinpcb(so)))
X
X/*
X * TCP statistics.
X * Many of these should be kept per connection,
X * but that's inconvenient at the moment.
X */
Xstruct tcpstat {
X#ifdef OLDSTAT
X /*
X * Declare statistics the same as in 4.3
X * at the start of tcpstat (same size and
X * position) for netstat.
X */
X int tcps_rcvbadsum;
X int tcps_rcvbadoff;
X int tcps_rcvshort;
X int tcps_badsegs;
X int tcps_unack;
X#define tcps_badsum tcps_rcvbadsum
X#define tcps_badoff tcps_rcvbadoff
X#define tcps_hdrops tcps_rcvshort
X
X#endif OLDSTAT
X u_long tcps_connattempt; /* connections initiated */
X u_long tcps_accepts; /* connections accepted */
X u_long tcps_connects; /* connections established */
X u_long tcps_drops; /* connections dropped */
X u_long tcps_conndrops; /* embryonic connections dropped */
X u_long tcps_closed; /* conn. closed (includes drops) */
X u_long tcps_segstimed; /* segs where we tried to get rtt */
X u_long tcps_rttupdated; /* times we succeeded */
X u_long tcps_delack; /* delayed acks sent */
X u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */
X u_long tcps_rexmttimeo; /* retransmit timeouts */
X u_long tcps_persisttimeo; /* persist timeouts */
X u_long tcps_keeptimeo; /* keepalive timeouts */
X u_long tcps_keepprobe; /* keepalive probes sent */
X u_long tcps_keepdrops; /* connections dropped in keepalive */
X
X u_long tcps_sndtotal; /* total packets sent */
X u_long tcps_sndpack; /* data packets sent */
X u_long tcps_sndbyte; /* data bytes sent */
X u_long tcps_sndrexmitpack; /* data packets retransmitted */
X u_long tcps_sndrexmitbyte; /* data bytes retransmitted */
X u_long tcps_sndacks; /* ack-only packets sent */
X u_long tcps_sndprobe; /* window probes sent */
X u_long tcps_sndurg; /* packets sent with URG only */
X u_long tcps_sndwinup; /* window update-only packets sent */
X u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */
X
X u_long tcps_rcvtotal; /* total packets received */
X u_long tcps_rcvpack; /* packets received in sequence */
X u_long tcps_rcvbyte; /* bytes received in sequence */
X#ifndef OLDSTAT
X u_long tcps_rcvbadsum; /* packets received with ccksum errs */
X u_long tcps_rcvbadoff; /* packets received with bad offset */
X u_long tcps_rcvshort; /* packets received too short */
X#endif
X u_long tcps_rcvduppack; /* duplicate-only packets received */
X u_long tcps_rcvdupbyte; /* duplicate-only bytes received */
X u_long tcps_rcvpartduppack; /* packets with some duplicate data */
X u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */
X u_long tcps_rcvoopack; /* out-of-order packets received */
X u_long tcps_rcvoobyte; /* out-of-order bytes received */
X u_long tcps_rcvpackafterwin; /* packets with data after window */
X u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */
X u_long tcps_rcvafterclose; /* packets rcvd after "close" */
X u_long tcps_rcvwinprobe; /* rcvd window probe packets */
X u_long tcps_rcvdupack; /* rcvd duplicate acks */
X u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */
X u_long tcps_rcvackpack; /* rcvd ack packets */
X u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */
X u_long tcps_rcvwinupd; /* rcvd window update packets */
X};
X
X#ifdef KERNEL
Xstruct inpcb tcb; /* head of queue of active tcpcb's */
Xstruct tcpstat tcpstat; /* tcp statistics */
Xstruct tcpiphdr *tcp_template();
Xstruct tcpcb *tcp_close(), *tcp_drop();
Xstruct tcpcb *tcp_timers(), *tcp_disconnect(), *tcp_usrclosed();
X#endif
END-of-netinet/tcp_var.h
echo x - netinet/tcpip.h
sed 's/^X//' >netinet/tcpip.h << 'END-of-netinet/tcpip.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)tcpip.h 7.2 (Berkeley) 12/7/87
X */
X
X/*
X * Tcp+ip header, after ip options removed.
X */
Xstruct tcpiphdr {
X struct ipovly ti_i; /* overlaid ip structure */
X struct tcphdr ti_t; /* tcp header */
X};
X#define ti_next ti_i.ih_next
X#define ti_prev ti_i.ih_prev
X#define ti_x1 ti_i.ih_x1
X#define ti_pr ti_i.ih_pr
X#define ti_len ti_i.ih_len
X#define ti_src ti_i.ih_src
X#define ti_dst ti_i.ih_dst
X#define ti_sport ti_t.th_sport
X#define ti_dport ti_t.th_dport
X#define ti_seq ti_t.th_seq
X#define ti_ack ti_t.th_ack
X#define ti_x2 ti_t.th_x2
X#define ti_off ti_t.th_off
X#define ti_flags ti_t.th_flags
X#define ti_win ti_t.th_win
X#define ti_sum ti_t.th_sum
X#define ti_urp ti_t.th_urp
END-of-netinet/tcpip.h
exit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads