File: | netinet/tcp_subr.c |
Warning: | line 525, column 2 Value stored to 'q' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: tcp_subr.c,v 1.194 2023/11/29 18:30:48 bluhm Exp $ */ |
2 | /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ |
3 | |
4 | /* |
5 | * Copyright (c) 1982, 1986, 1988, 1990, 1993 |
6 | * The Regents of the University of California. All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the name of the University nor the names of its contributors |
17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | * SUCH DAMAGE. |
31 | * |
32 | * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 |
33 | * |
34 | * NRL grants permission for redistribution and use in source and binary |
35 | * forms, with or without modification, of the software and documentation |
36 | * created at NRL provided that the following conditions are met: |
37 | * |
38 | * 1. Redistributions of source code must retain the above copyright |
39 | * notice, this list of conditions and the following disclaimer. |
40 | * 2. Redistributions in binary form must reproduce the above copyright |
41 | * notice, this list of conditions and the following disclaimer in the |
42 | * documentation and/or other materials provided with the distribution. |
43 | * 3. All advertising materials mentioning features or use of this software |
44 | * must display the following acknowledgements: |
45 | * This product includes software developed by the University of |
46 | * California, Berkeley and its contributors. |
47 | * This product includes software developed at the Information |
48 | * Technology Division, US Naval Research Laboratory. |
49 | * 4. Neither the name of the NRL nor the names of its contributors |
50 | * may be used to endorse or promote products derived from this software |
51 | * without specific prior written permission. |
52 | * |
53 | * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS |
54 | * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
55 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
56 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR |
57 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
58 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
59 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
60 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
61 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
62 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
63 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
64 | * |
65 | * The views and conclusions contained in the software and documentation |
66 | * are those of the authors and should not be interpreted as representing |
67 | * official policies, either expressed or implied, of the US Naval |
68 | * Research Laboratory (NRL). |
69 | */ |
70 | |
71 | #include <sys/param.h> |
72 | #include <sys/systm.h> |
73 | #include <sys/mbuf.h> |
74 | #include <sys/mutex.h> |
75 | #include <sys/socket.h> |
76 | #include <sys/socketvar.h> |
77 | #include <sys/timeout.h> |
78 | #include <sys/protosw.h> |
79 | #include <sys/kernel.h> |
80 | #include <sys/pool.h> |
81 | |
82 | #include <net/route.h> |
83 | |
84 | #include <netinet/in.h> |
85 | #include <netinet/ip.h> |
86 | #include <netinet/in_pcb.h> |
87 | #include <netinet/ip_var.h> |
88 | #include <netinet/ip_icmp.h> |
89 | #include <netinet/tcp.h> |
90 | #include <netinet/tcp_fsm.h> |
91 | #include <netinet/tcp_seq.h> |
92 | #include <netinet/tcp_timer.h> |
93 | #include <netinet/tcp_var.h> |
94 | |
95 | #ifdef INET61 |
96 | #include <netinet6/ip6protosw.h> |
97 | #endif /* INET6 */ |
98 | |
99 | #include <crypto/md5.h> |
100 | #include <crypto/sha2.h> |
101 | |
102 | /* |
103 | * Locks used to protect struct members in this file: |
104 | * I immutable after creation |
105 | * T tcp_timer_mtx global tcp timer data structures |
106 | */ |
107 | |
108 | struct mutex tcp_timer_mtx = MUTEX_INITIALIZER(IPL_SOFTNET){ ((void *)0), ((((0x2)) > 0x0 && ((0x2)) < 0x9 ) ? 0x9 : ((0x2))), 0x0 }; |
109 | |
110 | /* patchable/settable parameters for tcp */ |
111 | int tcp_mssdflt = TCP_MSS512; |
112 | int tcp_rttdflt = TCPTV_SRTTDFLT((3) * 1000); |
113 | |
114 | /* values controllable via sysctl */ |
115 | int tcp_do_rfc1323 = 1; |
116 | int tcp_do_sack = 1; /* RFC 2018 selective ACKs */ |
117 | int tcp_ack_on_push = 0; /* set to enable immediate ACK-on-PUSH */ |
118 | #ifdef TCP_ECN1 |
119 | int tcp_do_ecn = 0; /* RFC3168 ECN enabled/disabled? */ |
120 | #endif |
121 | int tcp_do_rfc3390 = 2; /* Increase TCP's Initial Window to 10*mss */ |
122 | int tcp_do_tso = 1; /* TCP segmentation offload for output */ |
123 | |
124 | #ifndef TCB_INITIAL_HASH_SIZE128 |
125 | #define TCB_INITIAL_HASH_SIZE128 128 |
126 | #endif |
127 | |
128 | int tcp_reass_limit = NMBCLUSTERS(256 * 1024) / 8; /* hardlimit for tcpqe_pool */ |
129 | int tcp_sackhole_limit = 32*1024; /* hardlimit for sackhl_pool */ |
130 | |
131 | struct pool tcpcb_pool; |
132 | struct pool tcpqe_pool; |
133 | struct pool sackhl_pool; |
134 | |
135 | struct cpumem *tcpcounters; /* tcp statistics */ |
136 | |
137 | u_char tcp_secret[16]; /* [I] */ |
138 | SHA2_CTX tcp_secret_ctx; /* [I] */ |
139 | tcp_seq tcp_iss; /* [T] updated by timer and connection */ |
140 | uint64_t tcp_starttime; /* [I] random offset for tcp_now() */ |
141 | |
142 | /* |
143 | * Tcp initialization |
144 | */ |
145 | void |
146 | tcp_init(void) |
147 | { |
148 | tcp_iss = 1; /* wrong */ |
149 | /* 0 is treated special so add 1, 63 bits to count is enough */ |
150 | arc4random_buf(&tcp_starttime, sizeof(tcp_starttime)); |
151 | tcp_starttime = 1ULL + (tcp_starttime / 2); |
152 | pool_init(&tcpcb_pool, sizeof(struct tcpcb), 0, IPL_SOFTNET0x2, 0, |
153 | "tcpcb", NULL((void *)0)); |
154 | pool_init(&tcpqe_pool, sizeof(struct tcpqent), 0, IPL_SOFTNET0x2, 0, |
155 | "tcpqe", NULL((void *)0)); |
156 | pool_sethardlimit(&tcpqe_pool, tcp_reass_limit, NULL((void *)0), 0); |
157 | pool_init(&sackhl_pool, sizeof(struct sackhole), 0, IPL_SOFTNET0x2, 0, |
158 | "sackhl", NULL((void *)0)); |
159 | pool_sethardlimit(&sackhl_pool, tcp_sackhole_limit, NULL((void *)0), 0); |
160 | in_pcbinit(&tcbtable, TCB_INITIAL_HASH_SIZE128); |
161 | tcpcounters = counters_alloc(tcps_ncounters); |
162 | |
163 | arc4random_buf(tcp_secret, sizeof(tcp_secret)); |
164 | SHA512Init(&tcp_secret_ctx); |
165 | SHA512Update(&tcp_secret_ctx, tcp_secret, sizeof(tcp_secret)); |
166 | |
167 | #ifdef INET61 |
168 | /* |
169 | * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we |
170 | * do max length checks/computations only on the former. |
171 | */ |
172 | if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))) |
173 | max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)); |
174 | if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) > |
175 | MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr))) |
176 | panic("tcp_init"); |
177 | |
178 | icmp6_mtudisc_callback_register(tcp6_mtudisc_callback); |
179 | #endif /* INET6 */ |
180 | |
181 | /* Initialize the compressed state engine. */ |
182 | syn_cache_init(); |
183 | |
184 | /* Initialize timer state. */ |
185 | tcp_timer_init(); |
186 | } |
187 | |
188 | /* |
189 | * Create template to be used to send tcp packets on a connection. |
190 | * Call after host entry created, allocates an mbuf and fills |
191 | * in a skeletal tcp/ip header, minimizing the amount of work |
192 | * necessary when the connection is used. |
193 | * |
194 | * To support IPv6 in addition to IPv4 and considering that the sizes of |
195 | * the IPv4 and IPv6 headers are not the same, we now use a separate pointer |
196 | * for the TCP header. Also, we made the former tcpiphdr header pointer |
197 | * into just an IP overlay pointer, with casting as appropriate for v6. rja |
198 | */ |
199 | struct mbuf * |
200 | tcp_template(struct tcpcb *tp) |
201 | { |
202 | struct inpcb *inp = tp->t_inpcb; |
203 | struct mbuf *m; |
204 | struct tcphdr *th; |
205 | |
206 | CTASSERT(sizeof(struct ip) + sizeof(struct tcphdr) <= MHLEN)extern char _ctassert[(sizeof(struct ip) + sizeof(struct tcphdr ) <= ((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr) )) ? 1 : -1 ] __attribute__((__unused__)); |
207 | CTASSERT(sizeof(struct ip6_hdr) + sizeof(struct tcphdr) <= MHLEN)extern char _ctassert[(sizeof(struct ip6_hdr) + sizeof(struct tcphdr) <= ((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr ))) ? 1 : -1 ] __attribute__((__unused__)); |
208 | |
209 | if ((m = tp->t_template) == 0) { |
210 | m = m_get(M_DONTWAIT0x0002, MT_HEADER2); |
211 | if (m == NULL((void *)0)) |
212 | return (0); |
213 | |
214 | switch (tp->pf) { |
215 | case 0: /*default to PF_INET*/ |
216 | case AF_INET2: |
217 | m->m_lenm_hdr.mh_len = sizeof(struct ip); |
218 | break; |
219 | #ifdef INET61 |
220 | case AF_INET624: |
221 | m->m_lenm_hdr.mh_len = sizeof(struct ip6_hdr); |
222 | break; |
223 | #endif /* INET6 */ |
224 | } |
225 | m->m_lenm_hdr.mh_len += sizeof (struct tcphdr); |
226 | } |
227 | |
228 | switch(tp->pf) { |
229 | case AF_INET2: |
230 | { |
231 | struct ipovly *ipovly; |
232 | |
233 | ipovly = mtod(m, struct ipovly *)((struct ipovly *)((m)->m_hdr.mh_data)); |
234 | |
235 | bzero(ipovly->ih_x1, sizeof ipovly->ih_x1)__builtin_bzero((ipovly->ih_x1), (sizeof ipovly->ih_x1) ); |
236 | ipovly->ih_pr = IPPROTO_TCP6; |
237 | ipovly->ih_len = htons(sizeof (struct tcphdr))(__uint16_t)(__builtin_constant_p(sizeof (struct tcphdr)) ? ( __uint16_t)(((__uint16_t)(sizeof (struct tcphdr)) & 0xffU ) << 8 | ((__uint16_t)(sizeof (struct tcphdr)) & 0xff00U ) >> 8) : __swap16md(sizeof (struct tcphdr))); |
238 | ipovly->ih_src = inp->inp_laddrinp_laddru.iau_a4u.inaddr; |
239 | ipovly->ih_dst = inp->inp_faddrinp_faddru.iau_a4u.inaddr; |
240 | |
241 | th = (struct tcphdr *)(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + |
242 | sizeof(struct ip)); |
243 | } |
244 | break; |
245 | #ifdef INET61 |
246 | case AF_INET624: |
247 | { |
248 | struct ip6_hdr *ip6; |
249 | |
250 | ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data)); |
251 | |
252 | ip6->ip6_src = inp->inp_laddr6inp_laddru.iau_addr6; |
253 | ip6->ip6_dst = inp->inp_faddr6inp_faddru.iau_addr6; |
254 | ip6->ip6_flowip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000)(__uint32_t)(__builtin_constant_p(0x60000000) ? (__uint32_t)( ((__uint32_t)(0x60000000) & 0xff) << 24 | ((__uint32_t )(0x60000000) & 0xff00) << 8 | ((__uint32_t)(0x60000000 ) & 0xff0000) >> 8 | ((__uint32_t)(0x60000000) & 0xff000000) >> 24) : __swap32md(0x60000000)) | |
255 | (inp->inp_flowinfoinp_hu.hu_ipv6.ip6_ctlun.ip6_un1.ip6_un1_flow & IPV6_FLOWLABEL_MASK0xffff0f00); |
256 | |
257 | ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_TCP6; |
258 | ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(struct tcphdr))(__uint16_t)(__builtin_constant_p(sizeof(struct tcphdr)) ? (__uint16_t )(((__uint16_t)(sizeof(struct tcphdr)) & 0xffU) << 8 | ((__uint16_t)(sizeof(struct tcphdr)) & 0xff00U) >> 8) : __swap16md(sizeof(struct tcphdr))); /*XXX*/ |
259 | ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = in6_selecthlim(inp); /*XXX*/ |
260 | |
261 | th = (struct tcphdr *)(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + |
262 | sizeof(struct ip6_hdr)); |
263 | } |
264 | break; |
265 | #endif /* INET6 */ |
266 | } |
267 | |
268 | th->th_sport = inp->inp_lport; |
269 | th->th_dport = inp->inp_fport; |
270 | th->th_seq = 0; |
271 | th->th_ack = 0; |
272 | th->th_x2 = 0; |
273 | th->th_off = 5; |
274 | th->th_flags = 0; |
275 | th->th_win = 0; |
276 | th->th_urp = 0; |
277 | th->th_sum = 0; |
278 | return (m); |
279 | } |
280 | |
281 | /* |
282 | * Send a single message to the TCP at address specified by |
283 | * the given TCP/IP header. If m == 0, then we make a copy |
284 | * of the tcpiphdr at ti and send directly to the addressed host. |
285 | * This is used to force keep alive messages out using the TCP |
286 | * template for a connection tp->t_template. If flags are given |
287 | * then we send a message back to the TCP which originated the |
288 | * segment ti, and discard the mbuf containing it and any other |
289 | * attached mbufs. |
290 | * |
291 | * In any case the ack and sequence number of the transmitted |
292 | * segment are as specified by the parameters. |
293 | */ |
294 | void |
295 | tcp_respond(struct tcpcb *tp, caddr_t template, struct tcphdr *th0, |
296 | tcp_seq ack, tcp_seq seq, int flags, u_int rtableid, uint64_t now) |
297 | { |
298 | int tlen; |
299 | int win = 0; |
300 | struct mbuf *m = NULL((void *)0); |
301 | struct tcphdr *th; |
302 | struct ip *ip; |
303 | #ifdef INET61 |
304 | struct ip6_hdr *ip6; |
305 | #endif |
306 | int af; /* af on wire */ |
307 | |
308 | if (tp) { |
309 | struct socket *so = tp->t_inpcb->inp_socket; |
310 | win = sbspace(so, &so->so_rcv); |
311 | /* |
312 | * If this is called with an unconnected |
313 | * socket/tp/pcb (tp->pf is 0), we lose. |
314 | */ |
315 | af = tp->pf; |
316 | } else |
317 | af = (((struct ip *)template)->ip_v == 6) ? AF_INET624 : AF_INET2; |
318 | |
319 | m = m_gethdr(M_DONTWAIT0x0002, MT_HEADER2); |
320 | if (m == NULL((void *)0)) |
321 | return; |
322 | m->m_datam_hdr.mh_data += max_linkhdr; |
323 | tlen = 0; |
324 | |
325 | #define xchg(a,b,type) do { type t; t=a; a=b; b=t; } while (0) |
326 | switch (af) { |
327 | #ifdef INET61 |
328 | case AF_INET624: |
329 | ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data)); |
330 | th = (struct tcphdr *)(ip6 + 1); |
331 | tlen = sizeof(*ip6) + sizeof(*th); |
332 | if (th0) { |
333 | bcopy(template, ip6, sizeof(*ip6)); |
334 | bcopy(th0, th, sizeof(*th)); |
335 | xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr); |
336 | } else { |
337 | bcopy(template, ip6, tlen); |
338 | } |
339 | break; |
340 | #endif /* INET6 */ |
341 | case AF_INET2: |
342 | ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data)); |
343 | th = (struct tcphdr *)(ip + 1); |
344 | tlen = sizeof(*ip) + sizeof(*th); |
345 | if (th0) { |
346 | bcopy(template, ip, sizeof(*ip)); |
347 | bcopy(th0, th, sizeof(*th)); |
348 | xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, u_int32_t); |
349 | } else { |
350 | bcopy(template, ip, tlen); |
351 | } |
352 | break; |
353 | } |
354 | if (th0) |
355 | xchg(th->th_dport, th->th_sport, u_int16_t); |
356 | else |
357 | flags = TH_ACK0x10; |
358 | #undef xchg |
359 | |
360 | th->th_seq = htonl(seq)(__uint32_t)(__builtin_constant_p(seq) ? (__uint32_t)(((__uint32_t )(seq) & 0xff) << 24 | ((__uint32_t)(seq) & 0xff00 ) << 8 | ((__uint32_t)(seq) & 0xff0000) >> 8 | ((__uint32_t)(seq) & 0xff000000) >> 24) : __swap32md (seq)); |
361 | th->th_ack = htonl(ack)(__uint32_t)(__builtin_constant_p(ack) ? (__uint32_t)(((__uint32_t )(ack) & 0xff) << 24 | ((__uint32_t)(ack) & 0xff00 ) << 8 | ((__uint32_t)(ack) & 0xff0000) >> 8 | ((__uint32_t)(ack) & 0xff000000) >> 24) : __swap32md (ack)); |
362 | th->th_x2 = 0; |
363 | th->th_off = sizeof (struct tcphdr) >> 2; |
364 | th->th_flags = flags; |
365 | if (tp) |
366 | win >>= tp->rcv_scale; |
367 | if (win > TCP_MAXWIN65535) |
368 | win = TCP_MAXWIN65535; |
369 | th->th_win = htons((u_int16_t)win)(__uint16_t)(__builtin_constant_p((u_int16_t)win) ? (__uint16_t )(((__uint16_t)((u_int16_t)win) & 0xffU) << 8 | ((__uint16_t )((u_int16_t)win) & 0xff00U) >> 8) : __swap16md((u_int16_t )win)); |
370 | th->th_urp = 0; |
371 | |
372 | if (tp && (tp->t_flags & (TF_REQ_TSTMP0x0080U|TF_NOOPT0x0008U)) == TF_REQ_TSTMP0x0080U && |
373 | (flags & TH_RST0x04) == 0 && (tp->t_flags & TF_RCVD_TSTMP0x0100U)) { |
374 | u_int32_t *lp = (u_int32_t *)(th + 1); |
375 | /* Form timestamp option as shown in appendix A of RFC 1323. */ |
376 | *lp++ = htonl(TCPOPT_TSTAMP_HDR)(__uint32_t)(__builtin_constant_p((1<<24|1<<16|8<< 8|10)) ? (__uint32_t)(((__uint32_t)((1<<24|1<<16| 8<<8|10)) & 0xff) << 24 | ((__uint32_t)((1<< 24|1<<16|8<<8|10)) & 0xff00) << 8 | ((__uint32_t )((1<<24|1<<16|8<<8|10)) & 0xff0000) >> 8 | ((__uint32_t)((1<<24|1<<16|8<<8|10)) & 0xff000000) >> 24) : __swap32md((1<<24|1<< 16|8<<8|10))); |
377 | *lp++ = htonl(now + tp->ts_modulate)(__uint32_t)(__builtin_constant_p(now + tp->ts_modulate) ? (__uint32_t)(((__uint32_t)(now + tp->ts_modulate) & 0xff ) << 24 | ((__uint32_t)(now + tp->ts_modulate) & 0xff00) << 8 | ((__uint32_t)(now + tp->ts_modulate) & 0xff0000) >> 8 | ((__uint32_t)(now + tp->ts_modulate ) & 0xff000000) >> 24) : __swap32md(now + tp->ts_modulate )); |
378 | *lp = htonl(tp->ts_recent)(__uint32_t)(__builtin_constant_p(tp->ts_recent) ? (__uint32_t )(((__uint32_t)(tp->ts_recent) & 0xff) << 24 | ( (__uint32_t)(tp->ts_recent) & 0xff00) << 8 | ((__uint32_t )(tp->ts_recent) & 0xff0000) >> 8 | ((__uint32_t )(tp->ts_recent) & 0xff000000) >> 24) : __swap32md (tp->ts_recent)); |
379 | tlen += TCPOLEN_TSTAMP_APPA(10 +2); |
380 | th->th_off = (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_APPA(10 +2)) >> 2; |
381 | } |
382 | |
383 | m->m_lenm_hdr.mh_len = tlen; |
384 | m->m_pkthdrM_dat.MH.MH_pkthdr.len = tlen; |
385 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = 0; |
386 | m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_OUT0x0002; |
387 | |
388 | /* force routing table */ |
389 | if (tp) |
390 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = tp->t_inpcb->inp_rtableid; |
391 | else |
392 | m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = rtableid; |
393 | |
394 | switch (af) { |
395 | #ifdef INET61 |
396 | case AF_INET624: |
397 | ip6->ip6_flowip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000)(__uint32_t)(__builtin_constant_p(0x60000000) ? (__uint32_t)( ((__uint32_t)(0x60000000) & 0xff) << 24 | ((__uint32_t )(0x60000000) & 0xff00) << 8 | ((__uint32_t)(0x60000000 ) & 0xff0000) >> 8 | ((__uint32_t)(0x60000000) & 0xff000000) >> 24) : __swap32md(0x60000000)); |
398 | ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_TCP6; |
399 | ip6->ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = in6_selecthlim(tp ? tp->t_inpcb : NULL((void *)0)); /*XXX*/ |
400 | ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = tlen - sizeof(struct ip6_hdr); |
401 | ip6->ip6_plenip6_ctlun.ip6_un1.ip6_un1_plen = htons(ip6->ip6_plen)(__uint16_t)(__builtin_constant_p(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen ) ? (__uint16_t)(((__uint16_t)(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen ) & 0xffU) << 8 | ((__uint16_t)(ip6->ip6_ctlun.ip6_un1 .ip6_un1_plen) & 0xff00U) >> 8) : __swap16md(ip6-> ip6_ctlun.ip6_un1.ip6_un1_plen)); |
402 | ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL((void *)0), |
403 | tp ? &tp->t_inpcb->inp_route6inp_ru.ru_route6 : NULL((void *)0), |
404 | 0, NULL((void *)0), |
405 | tp ? tp->t_inpcb->inp_seclevel : NULL((void *)0)); |
406 | break; |
407 | #endif /* INET6 */ |
408 | case AF_INET2: |
409 | ip->ip_len = htons(tlen)(__uint16_t)(__builtin_constant_p(tlen) ? (__uint16_t)(((__uint16_t )(tlen) & 0xffU) << 8 | ((__uint16_t)(tlen) & 0xff00U ) >> 8) : __swap16md(tlen)); |
410 | ip->ip_ttl = ip_defttl; |
411 | ip->ip_tos = 0; |
412 | ip_output(m, NULL((void *)0), |
413 | tp ? &tp->t_inpcb->inp_routeinp_ru.ru_route : NULL((void *)0), |
414 | ip_mtudisc ? IP_MTUDISC0x0800 : 0, NULL((void *)0), |
415 | tp ? tp->t_inpcb->inp_seclevel : NULL((void *)0), 0); |
416 | break; |
417 | } |
418 | } |
419 | |
420 | /* |
421 | * Create a new TCP control block, making an |
422 | * empty reassembly queue and hooking it to the argument |
423 | * protocol control block. |
424 | */ |
425 | struct tcpcb * |
426 | tcp_newtcpcb(struct inpcb *inp, int wait) |
427 | { |
428 | struct tcpcb *tp; |
429 | int i; |
430 | |
431 | tp = pool_get(&tcpcb_pool, (wait == M_WAIT0x0001 ? PR_WAITOK0x0001 : PR_NOWAIT0x0002) | |
432 | PR_ZERO0x0008); |
433 | if (tp == NULL((void *)0)) |
434 | return (NULL((void *)0)); |
435 | TAILQ_INIT(&tp->t_segq)do { (&tp->t_segq)->tqh_first = ((void *)0); (& tp->t_segq)->tqh_last = &(&tp->t_segq)->tqh_first ; } while (0); |
436 | tp->t_maxseg = tcp_mssdflt; |
437 | tp->t_maxopd = 0; |
438 | |
439 | for (i = 0; i < TCPT_NTIMERS6; i++) |
440 | TCP_TIMER_INIT(tp, i)timeout_set_proc(&(tp)->t_timer[(i)], tcp_timer_funcs[ (i)], tp); |
441 | |
442 | tp->sack_enable = tcp_do_sack; |
443 | tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE0x0020U|TF_REQ_TSTMP0x0080U) : 0; |
444 | tp->t_inpcb = inp; |
445 | /* |
446 | * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no |
447 | * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives |
448 | * reasonable initial retransmit time. |
449 | */ |
450 | tp->t_srtt = TCPTV_SRTTBASE0; |
451 | tp->t_rttvar = tcp_rttdflt << |
452 | (TCP_RTTVAR_SHIFT2 + TCP_RTT_BASE_SHIFT2 - 1); |
453 | tp->t_rttmin = TCPTV_MIN((1) * 1000); |
454 | TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),do { (tp->t_rxtcur) = (((((tp)->t_srtt >> 3) + (tp )->t_rttvar) >> 2)); if ((tp->t_rxtcur) < (((1 ) * 1000))) (tp->t_rxtcur) = (((1) * 1000)); else if ((tp-> t_rxtcur) > (((64) * 1000))) (tp->t_rxtcur) = (((64) * 1000 )); } while ( 0) |
455 | TCPTV_MIN, TCPTV_REXMTMAX)do { (tp->t_rxtcur) = (((((tp)->t_srtt >> 3) + (tp )->t_rttvar) >> 2)); if ((tp->t_rxtcur) < (((1 ) * 1000))) (tp->t_rxtcur) = (((1) * 1000)); else if ((tp-> t_rxtcur) > (((64) * 1000))) (tp->t_rxtcur) = (((64) * 1000 )); } while ( 0); |
456 | tp->snd_cwnd = TCP_MAXWIN65535 << TCP_MAX_WINSHIFT14; |
457 | tp->snd_ssthresh = TCP_MAXWIN65535 << TCP_MAX_WINSHIFT14; |
458 | |
459 | tp->t_pmtud_mtu_sent = 0; |
460 | tp->t_pmtud_mss_acked = 0; |
461 | |
462 | #ifdef INET61 |
463 | /* we disallow IPv4 mapped address completely. */ |
464 | if ((inp->inp_flags & INP_IPV60x100) == 0) |
465 | tp->pf = PF_INET2; |
466 | else |
467 | tp->pf = PF_INET624; |
468 | #else |
469 | tp->pf = PF_INET2; |
470 | #endif |
471 | |
472 | #ifdef INET61 |
473 | if (inp->inp_flags & INP_IPV60x100) |
474 | inp->inp_ipv6inp_hu.hu_ipv6.ip6_hlimip6_ctlun.ip6_un1.ip6_un1_hlim = ip6_defhlim; |
475 | else |
476 | #endif /* INET6 */ |
477 | inp->inp_ipinp_hu.hu_ip.ip_ttl = ip_defttl; |
478 | |
479 | inp->inp_ppcb = (caddr_t)tp; |
480 | return (tp); |
481 | } |
482 | |
483 | /* |
484 | * Drop a TCP connection, reporting |
485 | * the specified error. If connection is synchronized, |
486 | * then send a RST to peer. |
487 | */ |
488 | struct tcpcb * |
489 | tcp_drop(struct tcpcb *tp, int errno) |
490 | { |
491 | struct socket *so = tp->t_inpcb->inp_socket; |
492 | |
493 | if (TCPS_HAVERCVDSYN(tp->t_state)((tp->t_state) >= 3)) { |
494 | tp->t_state = TCPS_CLOSED0; |
495 | (void) tcp_output(tp); |
496 | tcpstat_inc(tcps_drops); |
497 | } else |
498 | tcpstat_inc(tcps_conndrops); |
499 | if (errno == ETIMEDOUT60 && tp->t_softerror) |
500 | errno = tp->t_softerror; |
501 | so->so_error = errno; |
502 | return (tcp_close(tp)); |
503 | } |
504 | |
505 | /* |
506 | * Close a TCP control block: |
507 | * discard all space held by the tcp |
508 | * discard internet protocol block |
509 | * wake up any sleepers |
510 | */ |
511 | struct tcpcb * |
512 | tcp_close(struct tcpcb *tp) |
513 | { |
514 | struct inpcb *inp = tp->t_inpcb; |
515 | struct socket *so = inp->inp_socket; |
516 | struct sackhole *p, *q; |
517 | |
518 | /* free the reassembly queue, if any */ |
519 | tcp_freeq(tp); |
520 | |
521 | tcp_canceltimers(tp); |
522 | syn_cache_cleanup(tp); |
523 | |
524 | /* Free SACK holes. */ |
525 | q = p = tp->snd_holes; |
Value stored to 'q' is never read | |
526 | while (p != 0) { |
527 | q = p->next; |
528 | pool_put(&sackhl_pool, p); |
529 | p = q; |
530 | } |
531 | |
532 | m_free(tp->t_template); |
533 | /* Free tcpcb after all pending timers have been run. */ |
534 | TCP_TIMER_ARM(tp, TCPT_REAPER, 1)do { (((tp)->t_flags) |= (0x04000000U << (4))); timeout_add_msec (&(tp)->t_timer[(4)], (1)); } while (0); |
535 | |
536 | inp->inp_ppcb = NULL((void *)0); |
537 | soisdisconnected(so); |
538 | in_pcbdetach(inp); |
539 | return (NULL((void *)0)); |
540 | } |
541 | |
542 | int |
543 | tcp_freeq(struct tcpcb *tp) |
544 | { |
545 | struct tcpqent *qe; |
546 | int rv = 0; |
547 | |
548 | while ((qe = TAILQ_FIRST(&tp->t_segq)((&tp->t_segq)->tqh_first)) != NULL((void *)0)) { |
549 | TAILQ_REMOVE(&tp->t_segq, qe, tcpqe_q)do { if (((qe)->tcpqe_q.tqe_next) != ((void *)0)) (qe)-> tcpqe_q.tqe_next->tcpqe_q.tqe_prev = (qe)->tcpqe_q.tqe_prev ; else (&tp->t_segq)->tqh_last = (qe)->tcpqe_q.tqe_prev ; *(qe)->tcpqe_q.tqe_prev = (qe)->tcpqe_q.tqe_next; ((qe )->tcpqe_q.tqe_prev) = ((void *)-1); ((qe)->tcpqe_q.tqe_next ) = ((void *)-1); } while (0); |
550 | m_freem(qe->tcpqe_m); |
551 | pool_put(&tcpqe_pool, qe); |
552 | rv = 1; |
553 | } |
554 | return (rv); |
555 | } |
556 | |
557 | /* |
558 | * Compute proper scaling value for receiver window from buffer space |
559 | */ |
560 | |
561 | void |
562 | tcp_rscale(struct tcpcb *tp, u_long hiwat) |
563 | { |
564 | tp->request_r_scale = 0; |
565 | while (tp->request_r_scale < TCP_MAX_WINSHIFT14 && |
566 | TCP_MAXWIN65535 << tp->request_r_scale < hiwat) |
567 | tp->request_r_scale++; |
568 | } |
569 | |
570 | /* |
571 | * Notify a tcp user of an asynchronous error; |
572 | * store error as soft error, but wake up user |
573 | * (for now, won't do anything until can select for soft error). |
574 | */ |
575 | void |
576 | tcp_notify(struct inpcb *inp, int error) |
577 | { |
578 | struct tcpcb *tp = intotcpcb(inp)((struct tcpcb *)(inp)->inp_ppcb); |
579 | struct socket *so = inp->inp_socket; |
580 | |
581 | /* |
582 | * Ignore some errors if we are hooked up. |
583 | * If connection hasn't completed, has retransmitted several times, |
584 | * and receives a second error, give up now. This is better |
585 | * than waiting a long time to establish a connection that |
586 | * can never complete. |
587 | */ |
588 | if (tp->t_state == TCPS_ESTABLISHED4 && |
589 | (error == EHOSTUNREACH65 || error == ENETUNREACH51 || |
590 | error == EHOSTDOWN64)) { |
591 | return; |
592 | } else if (TCPS_HAVEESTABLISHED(tp->t_state)((tp->t_state) >= 4) == 0 && |
593 | tp->t_rxtshift > 3 && tp->t_softerror) |
594 | so->so_error = error; |
595 | else |
596 | tp->t_softerror = error; |
597 | wakeup((caddr_t) &so->so_timeo); |
598 | sorwakeup(so); |
599 | sowwakeup(so); |
600 | } |
601 | |
602 | #ifdef INET61 |
603 | void |
604 | tcp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d) |
605 | { |
606 | struct tcphdr th; |
607 | struct tcpcb *tp; |
608 | void (*notify)(struct inpcb *, int) = tcp_notify; |
609 | struct ip6_hdr *ip6; |
610 | const struct sockaddr_in6 *sa6_src = NULL((void *)0); |
611 | struct sockaddr_in6 *sa6 = satosin6(sa); |
612 | struct inpcb *inp; |
613 | struct mbuf *m; |
614 | tcp_seq seq; |
615 | int off; |
616 | struct { |
617 | u_int16_t th_sport; |
618 | u_int16_t th_dport; |
619 | u_int32_t th_seq; |
620 | } *thp; |
621 | |
622 | CTASSERT(sizeof(*thp) <= sizeof(th))extern char _ctassert[(sizeof(*thp) <= sizeof(th)) ? 1 : - 1 ] __attribute__((__unused__)); |
623 | if (sa->sa_family != AF_INET624 || |
624 | sa->sa_len != sizeof(struct sockaddr_in6) || |
625 | IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sa6->sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&sa6->sin6_addr)->__u6_addr .__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void *)(&(&sa6->sin6_addr)->__u6_addr.__u6_addr8[8] ) == 0) && (*(const u_int32_t *)(const void *)(&( &sa6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0)) || |
626 | IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sa6->sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&sa6->sin6_addr)->__u6_addr .__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void *)(&(&sa6->sin6_addr)->__u6_addr.__u6_addr8[8] ) == (__uint32_t)(__builtin_constant_p(0x0000ffff) ? (__uint32_t )(((__uint32_t)(0x0000ffff) & 0xff) << 24 | ((__uint32_t )(0x0000ffff) & 0xff00) << 8 | ((__uint32_t)(0x0000ffff ) & 0xff0000) >> 8 | ((__uint32_t)(0x0000ffff) & 0xff000000) >> 24) : __swap32md(0x0000ffff))))) |
627 | return; |
628 | if ((unsigned)cmd >= PRC_NCMDS21) |
629 | return; |
630 | else if (cmd == PRC_QUENCH4) { |
631 | /* |
632 | * Don't honor ICMP Source Quench messages meant for |
633 | * TCP connections. |
634 | */ |
635 | /* XXX there's no PRC_QUENCH in IPv6 */ |
636 | return; |
637 | } else if (PRC_IS_REDIRECT(cmd)((cmd) >= 14 && (cmd) <= 17)) |
638 | notify = in_rtchange, d = NULL((void *)0); |
639 | else if (cmd == PRC_MSGSIZE5) |
640 | ; /* special code is present, see below */ |
641 | else if (cmd == PRC_HOSTDEAD6) |
642 | d = NULL((void *)0); |
643 | else if (inet6ctlerrmap[cmd] == 0) |
644 | return; |
645 | |
646 | /* if the parameter is from icmp6, decode it. */ |
647 | if (d != NULL((void *)0)) { |
648 | struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; |
649 | m = ip6cp->ip6c_m; |
650 | ip6 = ip6cp->ip6c_ip6; |
651 | off = ip6cp->ip6c_off; |
652 | sa6_src = ip6cp->ip6c_src; |
653 | } else { |
654 | m = NULL((void *)0); |
655 | ip6 = NULL((void *)0); |
656 | sa6_src = &sa6_any; |
657 | } |
658 | |
659 | if (ip6) { |
660 | /* |
661 | * XXX: We assume that when ip6 is non NULL, |
662 | * M and OFF are valid. |
663 | */ |
664 | |
665 | /* check if we can safely examine src and dst ports */ |
666 | if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < off + sizeof(*thp)) |
667 | return; |
668 | |
669 | bzero(&th, sizeof(th))__builtin_bzero((&th), (sizeof(th))); |
670 | m_copydata(m, off, sizeof(*thp), &th); |
671 | |
672 | /* |
673 | * Check to see if we have a valid TCP connection |
674 | * corresponding to the address in the ICMPv6 message |
675 | * payload. |
676 | */ |
677 | inp = in6_pcblookup(&tcbtable, &sa6->sin6_addr, |
678 | th.th_dport, &sa6_src->sin6_addr, th.th_sport, rdomain); |
679 | if (cmd == PRC_MSGSIZE5) { |
680 | /* |
681 | * Depending on the value of "valid" and routing table |
682 | * size (mtudisc_{hi,lo}wat), we will: |
683 | * - recalculate the new MTU and create the |
684 | * corresponding routing entry, or |
685 | * - ignore the MTU change notification. |
686 | */ |
687 | icmp6_mtudisc_update((struct ip6ctlparam *)d, |
688 | inp != NULL((void *)0)); |
689 | in_pcbunref(inp); |
690 | return; |
691 | } |
692 | if (inp) { |
693 | seq = ntohl(th.th_seq)(__uint32_t)(__builtin_constant_p(th.th_seq) ? (__uint32_t)(( (__uint32_t)(th.th_seq) & 0xff) << 24 | ((__uint32_t )(th.th_seq) & 0xff00) << 8 | ((__uint32_t)(th.th_seq ) & 0xff0000) >> 8 | ((__uint32_t)(th.th_seq) & 0xff000000) >> 24) : __swap32md(th.th_seq)); |
694 | if ((tp = intotcpcb(inp)((struct tcpcb *)(inp)->inp_ppcb)) && |
695 | SEQ_GEQ(seq, tp->snd_una)((int)((seq)-(tp->snd_una)) >= 0) && |
696 | SEQ_LT(seq, tp->snd_max)((int)((seq)-(tp->snd_max)) < 0)) |
697 | notify(inp, inet6ctlerrmap[cmd]); |
698 | } else if (inet6ctlerrmap[cmd] == EHOSTUNREACH65 || |
699 | inet6ctlerrmap[cmd] == ENETUNREACH51 || |
700 | inet6ctlerrmap[cmd] == EHOSTDOWN64) |
701 | syn_cache_unreach((struct sockaddr *)sa6_src, |
702 | sa, &th, rdomain); |
703 | in_pcbunref(inp); |
704 | } else { |
705 | in6_pcbnotify(&tcbtable, sa6, 0, |
706 | sa6_src, 0, rdomain, cmd, NULL((void *)0), notify); |
707 | } |
708 | } |
709 | #endif |
710 | |
711 | void |
712 | tcp_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *v) |
713 | { |
714 | struct ip *ip = v; |
715 | struct tcphdr *th; |
716 | struct tcpcb *tp; |
717 | struct inpcb *inp; |
718 | struct in_addr faddr; |
719 | tcp_seq seq; |
720 | u_int mtu; |
721 | void (*notify)(struct inpcb *, int) = tcp_notify; |
722 | int errno; |
723 | |
724 | if (sa->sa_family != AF_INET2) |
725 | return; |
726 | faddr = satosin(sa)->sin_addr; |
727 | if (faddr.s_addr == INADDR_ANY((u_int32_t) (__uint32_t)(__builtin_constant_p((u_int32_t)(0x00000000 )) ? (__uint32_t)(((__uint32_t)((u_int32_t)(0x00000000)) & 0xff) << 24 | ((__uint32_t)((u_int32_t)(0x00000000)) & 0xff00) << 8 | ((__uint32_t)((u_int32_t)(0x00000000)) & 0xff0000) >> 8 | ((__uint32_t)((u_int32_t)(0x00000000) ) & 0xff000000) >> 24) : __swap32md((u_int32_t)(0x00000000 ))))) |
728 | return; |
729 | |
730 | if ((unsigned)cmd >= PRC_NCMDS21) |
731 | return; |
732 | errno = inetctlerrmap[cmd]; |
733 | if (cmd == PRC_QUENCH4) |
734 | /* |
735 | * Don't honor ICMP Source Quench messages meant for |
736 | * TCP connections. |
737 | */ |
738 | return; |
739 | else if (PRC_IS_REDIRECT(cmd)((cmd) >= 14 && (cmd) <= 17)) |
740 | notify = in_rtchange, ip = 0; |
741 | else if (cmd == PRC_MSGSIZE5 && ip_mtudisc && ip) { |
742 | /* |
743 | * Verify that the packet in the icmp payload refers |
744 | * to an existing TCP connection. |
745 | */ |
746 | th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); |
747 | seq = ntohl(th->th_seq)(__uint32_t)(__builtin_constant_p(th->th_seq) ? (__uint32_t )(((__uint32_t)(th->th_seq) & 0xff) << 24 | ((__uint32_t )(th->th_seq) & 0xff00) << 8 | ((__uint32_t)(th-> th_seq) & 0xff0000) >> 8 | ((__uint32_t)(th->th_seq ) & 0xff000000) >> 24) : __swap32md(th->th_seq)); |
748 | inp = in_pcblookup(&tcbtable, |
749 | ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, |
750 | rdomain); |
751 | if (inp && (tp = intotcpcb(inp)((struct tcpcb *)(inp)->inp_ppcb)) && |
752 | SEQ_GEQ(seq, tp->snd_una)((int)((seq)-(tp->snd_una)) >= 0) && |
753 | SEQ_LT(seq, tp->snd_max)((int)((seq)-(tp->snd_max)) < 0)) { |
754 | struct icmp *icp; |
755 | icp = (struct icmp *)((caddr_t)ip - |
756 | offsetof(struct icmp, icmp_ip)__builtin_offsetof(struct icmp, icmp_dun.id_ip.idi_ip)); |
757 | |
758 | /* |
759 | * If the ICMP message advertises a Next-Hop MTU |
760 | * equal or larger than the maximum packet size we have |
761 | * ever sent, drop the message. |
762 | */ |
763 | mtu = (u_int)ntohs(icp->icmp_nextmtu)(__uint16_t)(__builtin_constant_p(icp->icmp_hun.ih_pmtu.ipm_nextmtu ) ? (__uint16_t)(((__uint16_t)(icp->icmp_hun.ih_pmtu.ipm_nextmtu ) & 0xffU) << 8 | ((__uint16_t)(icp->icmp_hun.ih_pmtu .ipm_nextmtu) & 0xff00U) >> 8) : __swap16md(icp-> icmp_hun.ih_pmtu.ipm_nextmtu)); |
764 | if (mtu >= tp->t_pmtud_mtu_sent) { |
765 | in_pcbunref(inp); |
766 | return; |
767 | } |
768 | if (mtu >= tcp_hdrsz(tp) + tp->t_pmtud_mss_acked) { |
769 | /* |
770 | * Calculate new MTU, and create corresponding |
771 | * route (traditional PMTUD). |
772 | */ |
773 | tp->t_flags &= ~TF_PMTUD_PEND0x00400000U; |
774 | icmp_mtudisc(icp, inp->inp_rtableid); |
775 | } else { |
776 | /* |
777 | * Record the information got in the ICMP |
778 | * message; act on it later. |
779 | * If we had already recorded an ICMP message, |
780 | * replace the old one only if the new message |
781 | * refers to an older TCP segment |
782 | */ |
783 | if (tp->t_flags & TF_PMTUD_PEND0x00400000U) { |
784 | if (SEQ_LT(tp->t_pmtud_th_seq, seq)((int)((tp->t_pmtud_th_seq)-(seq)) < 0)) { |
785 | in_pcbunref(inp); |
786 | return; |
787 | } |
788 | } else |
789 | tp->t_flags |= TF_PMTUD_PEND0x00400000U; |
790 | tp->t_pmtud_th_seq = seq; |
791 | tp->t_pmtud_nextmtu = icp->icmp_nextmtuicmp_hun.ih_pmtu.ipm_nextmtu; |
792 | tp->t_pmtud_ip_len = icp->icmp_ipicmp_dun.id_ip.idi_ip.ip_len; |
793 | tp->t_pmtud_ip_hl = icp->icmp_ipicmp_dun.id_ip.idi_ip.ip_hl; |
794 | in_pcbunref(inp); |
795 | return; |
796 | } |
797 | } else { |
798 | /* ignore if we don't have a matching connection */ |
799 | in_pcbunref(inp); |
800 | return; |
801 | } |
802 | in_pcbunref(inp); |
803 | notify = tcp_mtudisc, ip = 0; |
804 | } else if (cmd == PRC_MTUINC2) |
805 | notify = tcp_mtudisc_increase, ip = 0; |
806 | else if (cmd == PRC_HOSTDEAD6) |
807 | ip = 0; |
808 | else if (errno == 0) |
809 | return; |
810 | |
811 | if (ip) { |
812 | th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); |
813 | inp = in_pcblookup(&tcbtable, |
814 | ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, |
815 | rdomain); |
816 | if (inp) { |
817 | seq = ntohl(th->th_seq)(__uint32_t)(__builtin_constant_p(th->th_seq) ? (__uint32_t )(((__uint32_t)(th->th_seq) & 0xff) << 24 | ((__uint32_t )(th->th_seq) & 0xff00) << 8 | ((__uint32_t)(th-> th_seq) & 0xff0000) >> 8 | ((__uint32_t)(th->th_seq ) & 0xff000000) >> 24) : __swap32md(th->th_seq)); |
818 | if ((tp = intotcpcb(inp)((struct tcpcb *)(inp)->inp_ppcb)) && |
819 | SEQ_GEQ(seq, tp->snd_una)((int)((seq)-(tp->snd_una)) >= 0) && |
820 | SEQ_LT(seq, tp->snd_max)((int)((seq)-(tp->snd_max)) < 0)) |
821 | notify(inp, errno); |
822 | } else if (inetctlerrmap[cmd] == EHOSTUNREACH65 || |
823 | inetctlerrmap[cmd] == ENETUNREACH51 || |
824 | inetctlerrmap[cmd] == EHOSTDOWN64) { |
825 | struct sockaddr_in sin; |
826 | |
827 | bzero(&sin, sizeof(sin))__builtin_bzero((&sin), (sizeof(sin))); |
828 | sin.sin_len = sizeof(sin); |
829 | sin.sin_family = AF_INET2; |
830 | sin.sin_port = th->th_sport; |
831 | sin.sin_addr = ip->ip_src; |
832 | syn_cache_unreach(sintosa(&sin), sa, th, rdomain); |
833 | } |
834 | in_pcbunref(inp); |
835 | } else |
836 | in_pcbnotifyall(&tcbtable, sa, rdomain, errno, notify); |
837 | } |
838 | |
839 | |
840 | #ifdef INET61 |
841 | /* |
842 | * Path MTU Discovery handlers. |
843 | */ |
844 | void |
845 | tcp6_mtudisc_callback(struct sockaddr_in6 *sin6, u_int rdomain) |
846 | { |
847 | in6_pcbnotify(&tcbtable, sin6, 0, |
848 | &sa6_any, 0, rdomain, PRC_MSGSIZE5, NULL((void *)0), tcp_mtudisc); |
849 | } |
850 | #endif /* INET6 */ |
851 | |
852 | /* |
853 | * On receipt of path MTU corrections, flush old route and replace it |
854 | * with the new one. Retransmit all unacknowledged packets, to ensure |
855 | * that all packets will be received. |
856 | */ |
857 | void |
858 | tcp_mtudisc(struct inpcb *inp, int errno) |
859 | { |
860 | struct tcpcb *tp = intotcpcb(inp)((struct tcpcb *)(inp)->inp_ppcb); |
861 | struct rtentry *rt; |
862 | int orig_maxseg, change = 0; |
863 | |
864 | if (tp == NULL((void *)0)) |
865 | return; |
866 | orig_maxseg = tp->t_maxseg; |
867 | |
868 | rt = in_pcbrtentry(inp); |
869 | if (rt != NULL((void *)0)) { |
870 | unsigned int orig_mtulock = (rt->rt_locksrt_rmx.rmx_locks & RTV_MTU0x1); |
871 | |
872 | /* |
873 | * If this was not a host route, remove and realloc. |
874 | */ |
875 | if ((rt->rt_flags & RTF_HOST0x4) == 0) { |
876 | in_rtchange(inp, errno); |
877 | if ((rt = in_pcbrtentry(inp)) == NULL((void *)0)) |
878 | return; |
879 | } |
880 | if (orig_mtulock < (rt->rt_locksrt_rmx.rmx_locks & RTV_MTU0x1)) |
881 | change = 1; |
882 | } |
883 | tcp_mss(tp, -1); |
884 | if (orig_maxseg > tp->t_maxseg) |
885 | change = 1; |
886 | |
887 | /* |
888 | * Resend unacknowledged packets |
889 | */ |
890 | tp->snd_nxt = tp->snd_una; |
891 | if (change || errno > 0) |
892 | tcp_output(tp); |
893 | } |
894 | |
895 | void |
896 | tcp_mtudisc_increase(struct inpcb *inp, int errno) |
897 | { |
898 | struct tcpcb *tp = intotcpcb(inp)((struct tcpcb *)(inp)->inp_ppcb); |
899 | struct rtentry *rt = in_pcbrtentry(inp); |
900 | |
901 | if (tp != 0 && rt != 0) { |
902 | /* |
903 | * If this was a host route, remove and realloc. |
904 | */ |
905 | if (rt->rt_flags & RTF_HOST0x4) |
906 | in_rtchange(inp, errno); |
907 | |
908 | /* also takes care of congestion window */ |
909 | tcp_mss(tp, -1); |
910 | } |
911 | } |
912 | |
913 | /* |
914 | * Generate new ISNs with a method based on RFC1948 |
915 | */ |
916 | #define TCP_ISS_CONN_INC4096 4096 |
917 | |
918 | void |
919 | tcp_set_iss_tsm(struct tcpcb *tp) |
920 | { |
921 | SHA2_CTX ctx; |
922 | union { |
923 | uint8_t bytes[SHA512_DIGEST_LENGTH64]; |
924 | uint32_t words[2]; |
925 | } digest; |
926 | u_int rdomain = rtable_l2(tp->t_inpcb->inp_rtableid); |
927 | tcp_seq iss; |
928 | |
929 | mtx_enter(&tcp_timer_mtx); |
930 | tcp_iss += TCP_ISS_CONN_INC4096; |
931 | iss = tcp_iss; |
932 | mtx_leave(&tcp_timer_mtx); |
933 | |
934 | ctx = tcp_secret_ctx; |
935 | SHA512Update(&ctx, &rdomain, sizeof(rdomain)); |
936 | SHA512Update(&ctx, &tp->t_inpcb->inp_lport, sizeof(u_short)); |
937 | SHA512Update(&ctx, &tp->t_inpcb->inp_fport, sizeof(u_short)); |
938 | if (tp->pf == AF_INET624) { |
939 | SHA512Update(&ctx, &tp->t_inpcb->inp_laddr6inp_laddru.iau_addr6, |
940 | sizeof(struct in6_addr)); |
941 | SHA512Update(&ctx, &tp->t_inpcb->inp_faddr6inp_faddru.iau_addr6, |
942 | sizeof(struct in6_addr)); |
943 | } else { |
944 | SHA512Update(&ctx, &tp->t_inpcb->inp_laddrinp_laddru.iau_a4u.inaddr, |
945 | sizeof(struct in_addr)); |
946 | SHA512Update(&ctx, &tp->t_inpcb->inp_faddrinp_faddru.iau_a4u.inaddr, |
947 | sizeof(struct in_addr)); |
948 | } |
949 | SHA512Final(digest.bytes, &ctx); |
950 | tp->iss = digest.words[0] + iss; |
951 | tp->ts_modulate = digest.words[1]; |
952 | } |
953 | |
954 | #ifdef TCP_SIGNATURE1 |
955 | int |
956 | tcp_signature_tdb_attach(void) |
957 | { |
958 | return (0); |
959 | } |
960 | |
961 | int |
962 | tcp_signature_tdb_init(struct tdb *tdbp, const struct xformsw *xsp, |
963 | struct ipsecinit *ii) |
964 | { |
965 | if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80)) |
966 | return (EINVAL22); |
967 | |
968 | tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA76, M_NOWAIT0x0002); |
969 | if (tdbp->tdb_amxkey == NULL((void *)0)) |
970 | return (ENOMEM12); |
971 | memcpy(tdbp->tdb_amxkey, ii->ii_authkey, ii->ii_authkeylen)__builtin_memcpy((tdbp->tdb_amxkey), (ii->ii_authkey), ( ii->ii_authkeylen)); |
972 | tdbp->tdb_amxkeylen = ii->ii_authkeylen; |
973 | |
974 | return (0); |
975 | } |
976 | |
977 | int |
978 | tcp_signature_tdb_zeroize(struct tdb *tdbp) |
979 | { |
980 | if (tdbp->tdb_amxkey) { |
981 | explicit_bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen); |
982 | free(tdbp->tdb_amxkey, M_XDATA76, tdbp->tdb_amxkeylen); |
983 | tdbp->tdb_amxkey = NULL((void *)0); |
984 | } |
985 | |
986 | return (0); |
987 | } |
988 | |
989 | int |
990 | tcp_signature_tdb_input(struct mbuf **mp, struct tdb *tdbp, int skip, |
991 | int protoff) |
992 | { |
993 | m_freemp(mp); |
994 | return (IPPROTO_DONE257); |
995 | } |
996 | |
997 | int |
998 | tcp_signature_tdb_output(struct mbuf *m, struct tdb *tdbp, int skip, |
999 | int protoff) |
1000 | { |
1001 | m_freem(m); |
1002 | return (EINVAL22); |
1003 | } |
1004 | |
1005 | int |
1006 | tcp_signature_apply(caddr_t fstate, caddr_t data, unsigned int len) |
1007 | { |
1008 | MD5Update((MD5_CTX *)fstate, (char *)data, len); |
1009 | return 0; |
1010 | } |
1011 | |
1012 | int |
1013 | tcp_signature(struct tdb *tdb, int af, struct mbuf *m, struct tcphdr *th, |
1014 | int iphlen, int doswap, char *sig) |
1015 | { |
1016 | MD5_CTX ctx; |
1017 | int len; |
1018 | struct tcphdr th0; |
1019 | |
1020 | MD5Init(&ctx); |
1021 | |
1022 | switch(af) { |
1023 | case 0: |
1024 | case AF_INET2: { |
1025 | struct ippseudo ippseudo; |
1026 | struct ip *ip; |
1027 | |
1028 | ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data)); |
1029 | |
1030 | ippseudo.ippseudo_src = ip->ip_src; |
1031 | ippseudo.ippseudo_dst = ip->ip_dst; |
1032 | ippseudo.ippseudo_pad = 0; |
1033 | ippseudo.ippseudo_p = IPPROTO_TCP6; |
1034 | ippseudo.ippseudo_len = htons(m->m_pkthdr.len - iphlen)(__uint16_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len - iphlen) ? (__uint16_t)(((__uint16_t)(m->M_dat.MH.MH_pkthdr .len - iphlen) & 0xffU) << 8 | ((__uint16_t)(m-> M_dat.MH.MH_pkthdr.len - iphlen) & 0xff00U) >> 8) : __swap16md(m->M_dat.MH.MH_pkthdr.len - iphlen)); |
1035 | |
1036 | MD5Update(&ctx, (char *)&ippseudo, |
1037 | sizeof(struct ippseudo)); |
1038 | break; |
1039 | } |
1040 | #ifdef INET61 |
1041 | case AF_INET624: { |
1042 | struct ip6_hdr_pseudo ip6pseudo; |
1043 | struct ip6_hdr *ip6; |
1044 | |
1045 | ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data)); |
1046 | bzero(&ip6pseudo, sizeof(ip6pseudo))__builtin_bzero((&ip6pseudo), (sizeof(ip6pseudo))); |
1047 | ip6pseudo.ip6ph_src = ip6->ip6_src; |
1048 | ip6pseudo.ip6ph_dst = ip6->ip6_dst; |
1049 | in6_clearscope(&ip6pseudo.ip6ph_src); |
1050 | in6_clearscope(&ip6pseudo.ip6ph_dst); |
1051 | ip6pseudo.ip6ph_nxt = IPPROTO_TCP6; |
1052 | ip6pseudo.ip6ph_len = htonl(m->m_pkthdr.len - iphlen)(__uint32_t)(__builtin_constant_p(m->M_dat.MH.MH_pkthdr.len - iphlen) ? (__uint32_t)(((__uint32_t)(m->M_dat.MH.MH_pkthdr .len - iphlen) & 0xff) << 24 | ((__uint32_t)(m-> M_dat.MH.MH_pkthdr.len - iphlen) & 0xff00) << 8 | ( (__uint32_t)(m->M_dat.MH.MH_pkthdr.len - iphlen) & 0xff0000 ) >> 8 | ((__uint32_t)(m->M_dat.MH.MH_pkthdr.len - iphlen ) & 0xff000000) >> 24) : __swap32md(m->M_dat.MH. MH_pkthdr.len - iphlen)); |
1053 | |
1054 | MD5Update(&ctx, (char *)&ip6pseudo, |
1055 | sizeof(ip6pseudo)); |
1056 | break; |
1057 | } |
1058 | #endif |
1059 | } |
1060 | |
1061 | th0 = *th; |
1062 | th0.th_sum = 0; |
1063 | |
1064 | if (doswap) { |
1065 | th0.th_seq = htonl(th0.th_seq)(__uint32_t)(__builtin_constant_p(th0.th_seq) ? (__uint32_t)( ((__uint32_t)(th0.th_seq) & 0xff) << 24 | ((__uint32_t )(th0.th_seq) & 0xff00) << 8 | ((__uint32_t)(th0.th_seq ) & 0xff0000) >> 8 | ((__uint32_t)(th0.th_seq) & 0xff000000) >> 24) : __swap32md(th0.th_seq)); |
1066 | th0.th_ack = htonl(th0.th_ack)(__uint32_t)(__builtin_constant_p(th0.th_ack) ? (__uint32_t)( ((__uint32_t)(th0.th_ack) & 0xff) << 24 | ((__uint32_t )(th0.th_ack) & 0xff00) << 8 | ((__uint32_t)(th0.th_ack ) & 0xff0000) >> 8 | ((__uint32_t)(th0.th_ack) & 0xff000000) >> 24) : __swap32md(th0.th_ack)); |
1067 | th0.th_win = htons(th0.th_win)(__uint16_t)(__builtin_constant_p(th0.th_win) ? (__uint16_t)( ((__uint16_t)(th0.th_win) & 0xffU) << 8 | ((__uint16_t )(th0.th_win) & 0xff00U) >> 8) : __swap16md(th0.th_win )); |
1068 | th0.th_urp = htons(th0.th_urp)(__uint16_t)(__builtin_constant_p(th0.th_urp) ? (__uint16_t)( ((__uint16_t)(th0.th_urp) & 0xffU) << 8 | ((__uint16_t )(th0.th_urp) & 0xff00U) >> 8) : __swap16md(th0.th_urp )); |
1069 | } |
1070 | MD5Update(&ctx, (char *)&th0, sizeof(th0)); |
1071 | |
1072 | len = m->m_pkthdrM_dat.MH.MH_pkthdr.len - iphlen - th->th_off * sizeof(uint32_t); |
1073 | |
1074 | if (len > 0 && |
1075 | m_apply(m, iphlen + th->th_off * sizeof(uint32_t), len, |
1076 | tcp_signature_apply, (caddr_t)&ctx)) |
1077 | return (-1); |
1078 | |
1079 | MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen); |
1080 | MD5Final(sig, &ctx); |
1081 | |
1082 | return (0); |
1083 | } |
1084 | #endif /* TCP_SIGNATURE */ |