Bug Summary

File:netinet/tcp_subr.c
Warning:line 268, column 15
Access to field 'th_sport' results in a dereference of an undefined pointer value (loaded from variable 'th')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tcp_subr.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/netinet/tcp_subr.c
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
108struct mutex tcp_timer_mtx = MUTEX_INITIALIZER(IPL_SOFTNET){ ((void *)0), ((((0x2)) > 0x0 && ((0x2)) < 0x9
) ? 0x9 : ((0x2))), 0x0 }
;
109
110/* patchable/settable parameters for tcp */
111int tcp_mssdflt = TCP_MSS512;
112int tcp_rttdflt = TCPTV_SRTTDFLT((3) * 1000);
113
114/* values controllable via sysctl */
115int tcp_do_rfc1323 = 1;
116int tcp_do_sack = 1; /* RFC 2018 selective ACKs */
117int tcp_ack_on_push = 0; /* set to enable immediate ACK-on-PUSH */
118#ifdef TCP_ECN1
119int tcp_do_ecn = 0; /* RFC3168 ECN enabled/disabled? */
120#endif
121int tcp_do_rfc3390 = 2; /* Increase TCP's Initial Window to 10*mss */
122int 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
128int tcp_reass_limit = NMBCLUSTERS(256 * 1024) / 8; /* hardlimit for tcpqe_pool */
129int tcp_sackhole_limit = 32*1024; /* hardlimit for sackhl_pool */
130
131struct pool tcpcb_pool;
132struct pool tcpqe_pool;
133struct pool sackhl_pool;
134
135struct cpumem *tcpcounters; /* tcp statistics */
136
137u_char tcp_secret[16]; /* [I] */
138SHA2_CTX tcp_secret_ctx; /* [I] */
139tcp_seq tcp_iss; /* [T] updated by timer and connection */
140uint64_t tcp_starttime; /* [I] random offset for tcp_now() */
141
142/*
143 * Tcp initialization
144 */
145void
146tcp_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 */
199struct mbuf *
200tcp_template(struct tcpcb *tp)
201{
202 struct inpcb *inp = tp->t_inpcb;
203 struct mbuf *m;
204 struct tcphdr *th;
1
'th' declared without an initial value
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) {
2
Assuming the condition is false
3
Taking false branch
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) {
4
'Default' branch taken. Execution continues on line 268
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;
5
Access to field 'th_sport' results in a dereference of an undefined pointer value (loaded from variable 'th')
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 */
294void
295tcp_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 */
425struct tcpcb *
426tcp_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 */
488struct tcpcb *
489tcp_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 */
511struct tcpcb *
512tcp_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;
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
542int
543tcp_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
561void
562tcp_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 */
575void
576tcp_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
603void
604tcp6_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
711void
712tcp_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 */
844void
845tcp6_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 */
857void
858tcp_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
895void
896tcp_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
918void
919tcp_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
955int
956tcp_signature_tdb_attach(void)
957{
958 return (0);
959}
960
961int
962tcp_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
977int
978tcp_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
989int
990tcp_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
997int
998tcp_signature_tdb_output(struct mbuf *m, struct tdb *tdbp, int skip,
999 int protoff)
1000{
1001 m_freem(m);
1002 return (EINVAL22);
1003}
1004
1005int
1006tcp_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
1012int
1013tcp_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 */