Commit | Line | Data |
---|---|---|
ee787340 | 1 | /* tcp_subr.c 4.20 82/03/28 */ |
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" | |
ecaa4e6f | 16 | #include "../net/tcp_fsm.h" |
0974b45c BJ |
17 | #include "../net/tcp_seq.h" |
18 | #include "../net/tcp_timer.h" | |
ecaa4e6f | 19 | #include "../net/tcp_var.h" |
0974b45c | 20 | #include "../net/tcpip.h" |
ee787340 | 21 | #include "../net/route.h" |
f1b2fa5b | 22 | #include "../errno.h" |
ecaa4e6f BJ |
23 | |
24 | /* | |
25 | * Tcp initialization | |
26 | */ | |
27 | tcp_init() | |
28 | { | |
29 | ||
0974b45c | 30 | COUNT(TCP_INIT); |
ecaa4e6f BJ |
31 | tcp_iss = 1; /* wrong */ |
32 | tcb.inp_next = tcb.inp_prev = &tcb; | |
405c9168 BJ |
33 | tcp_alpha = TCP_ALPHA; |
34 | tcp_beta = TCP_BETA; | |
ecaa4e6f BJ |
35 | } |
36 | ||
37 | /* | |
38 | * Create template to be used to send tcp packets on a connection. | |
39 | * Call after host entry created, allocates an mbuf and fills | |
40 | * in a skeletal tcp/ip header, minimizing the amount of work | |
41 | * necessary when the connection is used. | |
42 | */ | |
43 | struct tcpiphdr * | |
44 | tcp_template(tp) | |
45 | struct tcpcb *tp; | |
46 | { | |
47 | register struct inpcb *inp = tp->t_inpcb; | |
48 | register struct mbuf *m; | |
49 | register struct tcpiphdr *n; | |
50 | ||
51 | COUNT(TCP_TEMPLATE); | |
e6b33a03 | 52 | m = m_get(M_WAIT); |
ecaa4e6f BJ |
53 | if (m == 0) |
54 | return (0); | |
55 | m->m_off = MMAXOFF - sizeof (struct tcpiphdr); | |
56 | m->m_len = sizeof (struct tcpiphdr); | |
57 | n = mtod(m, struct tcpiphdr *); | |
58 | n->ti_next = n->ti_prev = 0; | |
59 | n->ti_x1 = 0; | |
60 | n->ti_pr = IPPROTO_TCP; | |
61 | n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); | |
62 | n->ti_src = inp->inp_laddr; | |
63 | n->ti_dst = inp->inp_faddr; | |
64 | n->ti_sport = inp->inp_lport; | |
65 | n->ti_dport = inp->inp_fport; | |
66 | n->ti_seq = 0; | |
0974b45c | 67 | n->ti_ack = 0; |
ecaa4e6f BJ |
68 | n->ti_x2 = 0; |
69 | n->ti_off = 5; | |
70 | n->ti_flags = 0; | |
71 | n->ti_win = 0; | |
72 | n->ti_sum = 0; | |
73 | n->ti_urp = 0; | |
74 | return (n); | |
75 | } | |
76 | ||
77 | /* | |
405c9168 BJ |
78 | * Send a single message to the TCP at address specified by |
79 | * the given TCP/IP header. If flags==0, then we make a copy | |
80 | * of the tcpiphdr at ti and send directly to the addressed host. | |
81 | * This is used to force keep alive messages out using the TCP | |
82 | * template for a connection tp->t_template. If flags are given | |
83 | * then we send a message back to the TCP which originated the | |
84 | * segment ti, and discard the mbuf containing it and any other | |
85 | * attached mbufs. | |
86 | * | |
87 | * In any case the ack and sequence number of the transmitted | |
88 | * segment are as specified by the parameters. | |
ecaa4e6f | 89 | */ |
8e65fd66 BJ |
90 | tcp_respond(tp, ti, ack, seq, flags) |
91 | struct tcpcb *tp; | |
ecaa4e6f | 92 | register struct tcpiphdr *ti; |
0974b45c | 93 | tcp_seq ack, seq; |
ecaa4e6f BJ |
94 | int flags; |
95 | { | |
405c9168 | 96 | struct mbuf *m; |
1e977657 | 97 | int win = 0, tlen; |
ecaa4e6f | 98 | |
0974b45c | 99 | COUNT(TCP_RESPOND); |
8e65fd66 BJ |
100 | if (tp) |
101 | win = sbspace(&tp->t_inpcb->inp_socket->so_rcv); | |
405c9168 | 102 | if (flags == 0) { |
ef9b4258 | 103 | m = m_get(M_DONTWAIT); |
405c9168 BJ |
104 | if (m == 0) |
105 | return; | |
106 | m->m_off = MMINOFF; | |
1e977657 | 107 | m->m_len = sizeof (struct tcpiphdr) + 1; |
405c9168 BJ |
108 | *mtod(m, struct tcpiphdr *) = *ti; |
109 | ti = mtod(m, struct tcpiphdr *); | |
110 | flags = TH_ACK; | |
1e977657 | 111 | tlen = 1; |
405c9168 | 112 | } else { |
4aed14e3 | 113 | m = dtom(ti); |
405c9168 BJ |
114 | m_freem(m->m_next); |
115 | m->m_next = 0; | |
1acff8ec | 116 | m->m_off = (int)ti - (int)m; |
405c9168 | 117 | m->m_len = sizeof (struct tcpiphdr); |
0974b45c | 118 | #define xchg(a,b,type) { type t; t=a; a=b; b=t; } |
405c9168 BJ |
119 | xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); |
120 | xchg(ti->ti_dport, ti->ti_sport, u_short); | |
ecaa4e6f | 121 | #undef xchg |
1e977657 | 122 | tlen = 0; |
405c9168 | 123 | } |
0974b45c BJ |
124 | ti->ti_next = ti->ti_prev = 0; |
125 | ti->ti_x1 = 0; | |
1e977657 | 126 | ti->ti_len = sizeof (struct tcphdr) + tlen; |
4aed14e3 BJ |
127 | ti->ti_seq = seq; |
128 | ti->ti_ack = ack; | |
129 | #if vax | |
668cc26d | 130 | ti->ti_len = htons((u_short)ti->ti_len); |
4aed14e3 BJ |
131 | ti->ti_seq = htonl(ti->ti_seq); |
132 | ti->ti_ack = htonl(ti->ti_ack); | |
133 | #endif | |
0974b45c BJ |
134 | ti->ti_x2 = 0; |
135 | ti->ti_off = sizeof (struct tcphdr) >> 2; | |
ecaa4e6f | 136 | ti->ti_flags = flags; |
8e65fd66 BJ |
137 | ti->ti_win = win; |
138 | #if vax | |
139 | ti->ti_win = htons(ti->ti_win); | |
140 | #endif | |
141 | ti->ti_urp = 0; | |
f3cdd721 | 142 | ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + tlen); |
1e977657 | 143 | ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + tlen; |
0974b45c | 144 | ((struct ip *)ti)->ip_ttl = TCP_TTL; |
ee787340 | 145 | (void) ip_output(m, (struct mbuf *)0, 0, 0); |
ecaa4e6f | 146 | } |
a6503abf | 147 | |
0974b45c BJ |
148 | /* |
149 | * Create a new TCP control block, making an | |
150 | * empty reassembly queue and hooking it to the argument | |
151 | * protocol control block. | |
152 | */ | |
a6503abf BJ |
153 | struct tcpcb * |
154 | tcp_newtcpcb(inp) | |
155 | struct inpcb *inp; | |
156 | { | |
e6b33a03 | 157 | struct mbuf *m = m_getclr(M_DONTWAIT); |
a6503abf BJ |
158 | register struct tcpcb *tp; |
159 | COUNT(TCP_NEWTCPCB); | |
160 | ||
161 | if (m == 0) | |
162 | return (0); | |
163 | tp = mtod(m, struct tcpcb *); | |
a6503abf | 164 | tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; |
0974b45c | 165 | tp->t_maxseg = 1024; |
8b5a83bb | 166 | tp->t_flags = TF_NOOPT; /* until all TCP's take options */ |
a6503abf BJ |
167 | tp->t_inpcb = inp; |
168 | inp->inp_ppcb = (caddr_t)tp; | |
169 | return (tp); | |
170 | } | |
171 | ||
0974b45c BJ |
172 | /* |
173 | * Drop a TCP connection, reporting | |
174 | * the specified error. If connection is synchronized, | |
175 | * then send a RST to peer. | |
176 | */ | |
a6503abf BJ |
177 | tcp_drop(tp, errno) |
178 | struct tcpcb *tp; | |
179 | int errno; | |
180 | { | |
181 | struct socket *so = tp->t_inpcb->inp_socket; | |
182 | ||
183 | COUNT(TCP_DROP); | |
d3504cc0 | 184 | if (TCPS_HAVERCVDSYN(tp->t_state)) { |
a6503abf BJ |
185 | tp->t_state = TCPS_CLOSED; |
186 | tcp_output(tp); | |
187 | } | |
188 | so->so_error = errno; | |
a6503abf BJ |
189 | tcp_close(tp); |
190 | } | |
191 | ||
0974b45c BJ |
192 | /* |
193 | * Close a TCP control block: | |
194 | * discard all space held by the tcp | |
195 | * discard internet protocol block | |
196 | * wake up any sleepers | |
197 | */ | |
a6503abf BJ |
198 | tcp_close(tp) |
199 | register struct tcpcb *tp; | |
200 | { | |
201 | register struct tcpiphdr *t; | |
364801f5 BJ |
202 | struct inpcb *inp = tp->t_inpcb; |
203 | struct socket *so = inp->inp_socket; | |
a6503abf BJ |
204 | |
205 | COUNT(TCP_CLOSE); | |
a6503abf BJ |
206 | t = tp->seg_next; |
207 | for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next) | |
208 | m_freem(dtom(t)); | |
0974b45c | 209 | if (tp->t_template) |
a6503abf | 210 | (void) m_free(dtom(tp->t_template)); |
0974b45c BJ |
211 | if (tp->t_tcpopt) |
212 | (void) m_free(dtom(tp->t_tcpopt)); | |
213 | if (tp->t_ipopt) | |
214 | (void) m_free(dtom(tp->t_ipopt)); | |
a6503abf | 215 | (void) m_free(dtom(tp)); |
364801f5 | 216 | inp->inp_ppcb = 0; |
252398a6 | 217 | in_pcbdetach(inp); |
4aed14e3 | 218 | soisdisconnected(so); |
a6503abf BJ |
219 | } |
220 | ||
a6503abf BJ |
221 | tcp_drain() |
222 | { | |
a6503abf BJ |
223 | |
224 | COUNT(TCP_DRAIN); | |
225 | } | |
226 | ||
227 | tcp_ctlinput(m) | |
228 | struct mbuf *m; | |
229 | { | |
230 | ||
231 | COUNT(TCP_CTLINPUT); | |
232 | m_freem(m); | |
233 | } |