X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/f3cdd7218787350474c0262a1e146f37f11b3767..0880b18ef40ee52f08a23527900e6354275bcc33:/usr/src/sys/netinet/tcp_subr.c diff --git a/usr/src/sys/netinet/tcp_subr.c b/usr/src/sys/netinet/tcp_subr.c index 22da4cce08..179353f875 100644 --- a/usr/src/sys/netinet/tcp_subr.c +++ b/usr/src/sys/netinet/tcp_subr.c @@ -1,24 +1,34 @@ -/* tcp_subr.c 4.19 82/03/24 */ - -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/mbuf.h" -#include "../h/socket.h" -#include "../h/socketvar.h" -#include "../h/protosw.h" -#include "../net/in.h" -#include "../net/in_pcb.h" -#include "../net/in_systm.h" +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)tcp_subr.c 7.1 (Berkeley) %G% + */ + +#include "param.h" +#include "systm.h" +#include "mbuf.h" +#include "socket.h" +#include "socketvar.h" +#include "protosw.h" +#include "errno.h" + +#include "../net/route.h" #include "../net/if.h" -#include "../net/ip.h" -#include "../net/ip_var.h" -#include "../net/tcp.h" -#include "../net/tcp_fsm.h" -#include "../net/tcp_seq.h" -#include "../net/tcp_timer.h" -#include "../net/tcp_var.h" -#include "../net/tcpip.h" -#include "../errno.h" + +#include "in.h" +#include "in_pcb.h" +#include "in_systm.h" +#include "ip.h" +#include "ip_var.h" +#include "ip_icmp.h" +#include "tcp.h" +#include "tcp_fsm.h" +#include "tcp_seq.h" +#include "tcp_timer.h" +#include "tcp_var.h" +#include "tcpip.h" /* * Tcp initialization @@ -26,7 +36,6 @@ tcp_init() { -COUNT(TCP_INIT); tcp_iss = 1; /* wrong */ tcb.inp_next = tcb.inp_prev = &tcb; tcp_alpha = TCP_ALPHA; @@ -47,13 +56,14 @@ tcp_template(tp) register struct mbuf *m; register struct tcpiphdr *n; -COUNT(TCP_TEMPLATE); - m = m_get(M_WAIT); - if (m == 0) - return (0); - m->m_off = MMAXOFF - sizeof (struct tcpiphdr); - m->m_len = sizeof (struct tcpiphdr); - n = mtod(m, struct tcpiphdr *); + if ((n = tp->t_template) == 0) { + m = m_get(M_WAIT, MT_HEADER); + if (m == NULL) + return (0); + m->m_off = MMAXOFF - sizeof (struct tcpiphdr); + m->m_len = sizeof (struct tcpiphdr); + n = mtod(m, struct tcpiphdr *); + } n->ti_next = n->ti_prev = 0; n->ti_x1 = 0; n->ti_pr = IPPROTO_TCP; @@ -94,15 +104,16 @@ tcp_respond(tp, ti, ack, seq, flags) { struct mbuf *m; int win = 0, tlen; + struct route *ro = 0; -COUNT(TCP_RESPOND); - if (tp) + if (tp) { win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); + ro = &tp->t_inpcb->inp_route; + } if (flags == 0) { - m = m_get(M_DONTWAIT); - if (m == 0) + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == NULL) return; - m->m_off = MMINOFF; m->m_len = sizeof (struct tcpiphdr) + 1; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); @@ -122,26 +133,18 @@ COUNT(TCP_RESPOND); } ti->ti_next = ti->ti_prev = 0; ti->ti_x1 = 0; - ti->ti_len = sizeof (struct tcphdr) + tlen; - ti->ti_seq = seq; - ti->ti_ack = ack; -#if vax - ti->ti_len = htons((u_short)ti->ti_len); - ti->ti_seq = htonl(ti->ti_seq); - ti->ti_ack = htonl(ti->ti_ack); -#endif + ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); + ti->ti_seq = htonl(seq); + ti->ti_ack = htonl(ack); ti->ti_x2 = 0; ti->ti_off = sizeof (struct tcphdr) >> 2; ti->ti_flags = flags; - ti->ti_win = win; -#if vax - ti->ti_win = htons(ti->ti_win); -#endif + ti->ti_win = htons((u_short)win); ti->ti_urp = 0; ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen); ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen; ((struct ip *)ti)->ip_ttl = TCP_TTL; - (void) ip_output(m, (struct mbuf *)0, 0); + (void) ip_output(m, (struct mbuf *)0, ro, 0); } /* @@ -153,17 +156,18 @@ struct tcpcb * tcp_newtcpcb(inp) struct inpcb *inp; { - struct mbuf *m = m_getclr(M_DONTWAIT); + struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB); register struct tcpcb *tp; -COUNT(TCP_NEWTCPCB); - if (m == 0) - return (0); + if (m == NULL) + return ((struct tcpcb *)0); tp = mtod(m, struct tcpcb *); tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; - tp->t_maxseg = 1024; - tp->t_flags = TF_NOOPT; /* until all TCP's take options */ + tp->t_maxseg = TCP_MSS; + tp->t_flags = 0; /* sends options! */ tp->t_inpcb = inp; + tp->t_srtt = TCPTV_SRTTBASE; + tp->snd_cwnd = sbspace(&inp->inp_socket->so_snd); inp->inp_ppcb = (caddr_t)tp; return (tp); } @@ -173,19 +177,19 @@ COUNT(TCP_NEWTCPCB); * the specified error. If connection is synchronized, * then send a RST to peer. */ +struct tcpcb * tcp_drop(tp, errno) - struct tcpcb *tp; + register struct tcpcb *tp; int errno; { struct socket *so = tp->t_inpcb->inp_socket; -COUNT(TCP_DROP); if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; - tcp_output(tp); + (void) tcp_output(tp); } so->so_error = errno; - tcp_close(tp); + return (tcp_close(tp)); } /* @@ -194,39 +198,86 @@ COUNT(TCP_DROP); * discard internet protocol block * wake up any sleepers */ +struct tcpcb * tcp_close(tp) register struct tcpcb *tp; { register struct tcpiphdr *t; struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; + register struct mbuf *m; -COUNT(TCP_CLOSE); t = tp->seg_next; - for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) - m_freem(dtom(t)); + while (t != (struct tcpiphdr *)tp) { + t = (struct tcpiphdr *)t->ti_next; + m = dtom(t->ti_prev); + remque(t->ti_prev); + m_freem(m); + } if (tp->t_template) (void) m_free(dtom(tp->t_template)); if (tp->t_tcpopt) (void) m_free(dtom(tp->t_tcpopt)); - if (tp->t_ipopt) - (void) m_free(dtom(tp->t_ipopt)); (void) m_free(dtom(tp)); inp->inp_ppcb = 0; - in_pcbdetach(inp); soisdisconnected(so); + in_pcbdetach(inp); + return ((struct tcpcb *)0); } tcp_drain() { -COUNT(TCP_DRAIN); } -tcp_ctlinput(m) - struct mbuf *m; +tcp_ctlinput(cmd, sa) + int cmd; + struct sockaddr *sa; +{ + extern u_char inetctlerrmap[]; + struct sockaddr_in *sin; + int tcp_quench(), in_rtchange(); + + if ((unsigned)cmd > PRC_NCMDS) + return; + if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) + return; + sin = (struct sockaddr_in *)sa; + if (sin->sin_addr.s_addr == INADDR_ANY) + return; + + switch (cmd) { + + case PRC_QUENCH: + in_pcbnotify(&tcb, &sin->sin_addr, 0, tcp_quench); + break; + + case PRC_ROUTEDEAD: + case PRC_REDIRECT_NET: + case PRC_REDIRECT_HOST: + case PRC_REDIRECT_TOSNET: + case PRC_REDIRECT_TOSHOST: + in_pcbnotify(&tcb, &sin->sin_addr, 0, in_rtchange); + break; + + default: + if (inetctlerrmap[cmd] == 0) + return; /* XXX */ + in_pcbnotify(&tcb, &sin->sin_addr, (int)inetctlerrmap[cmd], + (int (*)())0); + } +} + +/* + * When a source quench is received, close congestion window + * to 80% of the outstanding data (but not less than one segment). + */ +tcp_quench(inp) + struct inpcb *inp; { + struct tcpcb *tp = intotcpcb(inp); -COUNT(TCP_CTLINPUT); - m_freem(m); + if (tp) + tp->snd_cwnd = MAX(8 * (tp->snd_nxt - tp->snd_una) / 10, + tp->t_maxseg); }