date and time created 81/11/29 22:20:02 by wnj
[unix-history] / usr / src / sys / netinet / tcp_subr.c
CommitLineData
f1b2fa5b 1/* tcp_subr.c 4.4 81/11/29 */
ecaa4e6f
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/mbuf.h"
6#include "../h/socket.h"
7#include "../h/socketvar.h"
8#include "../h/protosw.h"
0974b45c
BJ
9#include "../net/in.h"
10#include "../net/in_pcb.h"
11#include "../net/in_systm.h"
ecaa4e6f 12#include "../net/if.h"
ecaa4e6f
BJ
13#include "../net/ip.h"
14#include "../net/ip_var.h"
15#include "../net/tcp.h"
16#define TCPFSTAB
17#include "../net/tcp_fsm.h"
0974b45c
BJ
18#include "../net/tcp_seq.h"
19#include "../net/tcp_timer.h"
ecaa4e6f 20#include "../net/tcp_var.h"
0974b45c 21#include "../net/tcpip.h"
f1b2fa5b 22#include "../errno.h"
ecaa4e6f
BJ
23
24/*
25 * Tcp initialization
26 */
27tcp_init()
28{
29
0974b45c 30COUNT(TCP_INIT);
ecaa4e6f
BJ
31 tcp_iss = 1; /* wrong */
32 tcb.inp_next = tcb.inp_prev = &tcb;
33}
34
35/*
36 * Create template to be used to send tcp packets on a connection.
37 * Call after host entry created, allocates an mbuf and fills
38 * in a skeletal tcp/ip header, minimizing the amount of work
39 * necessary when the connection is used.
40 */
41struct tcpiphdr *
42tcp_template(tp)
43 struct tcpcb *tp;
44{
45 register struct inpcb *inp = tp->t_inpcb;
46 register struct mbuf *m;
47 register struct tcpiphdr *n;
48
49COUNT(TCP_TEMPLATE);
50 m = m_get(1);
51 if (m == 0)
52 return (0);
53 m->m_off = MMAXOFF - sizeof (struct tcpiphdr);
54 m->m_len = sizeof (struct tcpiphdr);
55 n = mtod(m, struct tcpiphdr *);
56 n->ti_next = n->ti_prev = 0;
57 n->ti_x1 = 0;
58 n->ti_pr = IPPROTO_TCP;
59 n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
60 n->ti_src = inp->inp_laddr;
61 n->ti_dst = inp->inp_faddr;
62 n->ti_sport = inp->inp_lport;
63 n->ti_dport = inp->inp_fport;
64 n->ti_seq = 0;
0974b45c 65 n->ti_ack = 0;
ecaa4e6f
BJ
66 n->ti_x2 = 0;
67 n->ti_off = 5;
68 n->ti_flags = 0;
69 n->ti_win = 0;
70 n->ti_sum = 0;
71 n->ti_urp = 0;
72 return (n);
73}
74
75/*
0974b45c 76 * Send a reset message back to send of TCP segment ti,
ecaa4e6f
BJ
77 * with ack, seq and flags fields as specified by parameters.
78 */
0974b45c 79tcp_respond(ti, ack, seq, flags)
ecaa4e6f 80 register struct tcpiphdr *ti;
0974b45c 81 tcp_seq ack, seq;
ecaa4e6f
BJ
82 int flags;
83{
0974b45c 84 struct mbuf *m = dtom(ti);
ecaa4e6f 85
0974b45c 86COUNT(TCP_RESPOND);
ecaa4e6f
BJ
87 m_freem(m->m_next);
88 m->m_next = 0;
89 m->m_len = sizeof(struct tcpiphdr);
0974b45c
BJ
90#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
91 xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
92 xchg(ti->ti_dport, ti->ti_sport, u_short);
ecaa4e6f 93#undef xchg
0974b45c
BJ
94 ti->ti_next = ti->ti_prev = 0;
95 ti->ti_x1 = 0;
96 ti->ti_len = htons(sizeof (struct tcphdr));
ecaa4e6f 97 ti->ti_seq = htonl(seq);
0974b45c
BJ
98 ti->ti_ack = htonl(ack);
99 ti->ti_x2 = 0;
100 ti->ti_off = sizeof (struct tcphdr) >> 2;
ecaa4e6f 101 ti->ti_flags = flags;
0974b45c
BJ
102 ti->ti_win = ti->ti_urp = 0;
103 ti->ti_sum = in_cksum(m, sizeof(struct tcpiphdr));
ecaa4e6f 104 ((struct ip *)ti)->ip_len = sizeof(struct tcpiphdr);
0974b45c 105 ((struct ip *)ti)->ip_ttl = TCP_TTL;
f1b2fa5b 106 (void) ip_output(m, (struct mbuf *)0);
ecaa4e6f 107}
a6503abf 108
0974b45c
BJ
109/*
110 * Create a new TCP control block, making an
111 * empty reassembly queue and hooking it to the argument
112 * protocol control block.
113 */
a6503abf
BJ
114struct tcpcb *
115tcp_newtcpcb(inp)
116 struct inpcb *inp;
117{
118 struct mbuf *m = m_getclr(0);
119 register struct tcpcb *tp;
120COUNT(TCP_NEWTCPCB);
121
122 if (m == 0)
123 return (0);
124 tp = mtod(m, struct tcpcb *);
a6503abf 125 tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
0974b45c 126 tp->t_maxseg = 1024;
a6503abf
BJ
127 tp->t_inpcb = inp;
128 inp->inp_ppcb = (caddr_t)tp;
129 return (tp);
130}
131
0974b45c
BJ
132/*
133 * Drop a TCP connection, reporting
134 * the specified error. If connection is synchronized,
135 * then send a RST to peer.
136 */
a6503abf
BJ
137tcp_drop(tp, errno)
138 struct tcpcb *tp;
139 int errno;
140{
141 struct socket *so = tp->t_inpcb->inp_socket;
142
143COUNT(TCP_DROP);
144 if (TCPS_HAVERCVDSYN(tp->t_state) &&
0974b45c 145 TCPS_OURFINNOTACKED(tp->t_state)) {
a6503abf
BJ
146 tp->t_state = TCPS_CLOSED;
147 tcp_output(tp);
148 }
149 so->so_error = errno;
a6503abf
BJ
150 tcp_close(tp);
151}
152
0974b45c
BJ
153/*
154 * Close a TCP control block:
155 * discard all space held by the tcp
156 * discard internet protocol block
157 * wake up any sleepers
158 */
a6503abf
BJ
159tcp_close(tp)
160 register struct tcpcb *tp;
161{
162 register struct tcpiphdr *t;
0974b45c 163 struct socket *so = tp->t_inpcb->inp_socket;
a6503abf
BJ
164
165COUNT(TCP_CLOSE);
a6503abf
BJ
166 t = tp->seg_next;
167 for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next)
168 m_freem(dtom(t));
0974b45c 169 if (tp->t_template)
a6503abf 170 (void) m_free(dtom(tp->t_template));
0974b45c
BJ
171 if (tp->t_tcpopt)
172 (void) m_free(dtom(tp->t_tcpopt));
173 if (tp->t_ipopt)
174 (void) m_free(dtom(tp->t_ipopt));
a6503abf
BJ
175 in_pcbfree(tp->t_inpcb);
176 (void) m_free(dtom(tp));
0974b45c
BJ
177 socantrcvmore(so);
178 socantsendmore(so);
a6503abf
BJ
179}
180
a6503abf
BJ
181tcp_drain()
182{
a6503abf
BJ
183
184COUNT(TCP_DRAIN);
185}
186
187tcp_ctlinput(m)
188 struct mbuf *m;
189{
190
191COUNT(TCP_CTLINPUT);
192 m_freem(m);
193}