]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/tcp_subr.c
f51febfc1af45998e510d576213555feb73c2418
[apple/xnu.git] / bsd / netinet / tcp_subr.c
1 /*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
61 * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.73.2.22 2001/08/22 00:59:12 silby Exp $
62 */
63 /*
64 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
65 * support for mandatory and extensible security protections. This notice
66 * is included in support of clause 2.2 (b) of the Apple Public License,
67 * Version 2.0.
68 */
69
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/callout.h>
73 #include <sys/kernel.h>
74 #include <sys/sysctl.h>
75 #include <sys/malloc.h>
76 #include <sys/mbuf.h>
77 #include <sys/domain.h>
78 #include <sys/proc.h>
79 #include <sys/kauth.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
82 #include <sys/protosw.h>
83 #include <sys/random.h>
84 #include <sys/syslog.h>
85 #include <kern/locks.h>
86 #include <kern/zalloc.h>
87
88 #include <net/route.h>
89 #include <net/if.h>
90
91 #define _IP_VHL
92 #include <netinet/in.h>
93 #include <netinet/in_systm.h>
94 #include <netinet/ip.h>
95 #if INET6
96 #include <netinet/ip6.h>
97 #endif
98 #include <netinet/in_pcb.h>
99 #if INET6
100 #include <netinet6/in6_pcb.h>
101 #endif
102 #include <netinet/in_var.h>
103 #include <netinet/ip_var.h>
104 #if INET6
105 #include <netinet6/ip6_var.h>
106 #endif
107 #include <netinet/tcp.h>
108 #include <netinet/tcp_fsm.h>
109 #include <netinet/tcp_seq.h>
110 #include <netinet/tcp_timer.h>
111 #include <netinet/tcp_var.h>
112 #if INET6
113 #include <netinet6/tcp6_var.h>
114 #endif
115 #include <netinet/tcpip.h>
116 #if TCPDEBUG
117 #include <netinet/tcp_debug.h>
118 #endif
119 #include <netinet6/ip6protosw.h>
120
121 #if IPSEC
122 #include <netinet6/ipsec.h>
123 #if INET6
124 #include <netinet6/ipsec6.h>
125 #endif
126 #endif /*IPSEC*/
127
128 #if CONFIG_MACF_NET
129 #include <security/mac_framework.h>
130 #endif /* MAC_NET */
131
132 #include <libkern/crypto/md5.h>
133 #include <sys/kdebug.h>
134
135 #define DBG_FNC_TCP_CLOSE NETDBG_CODE(DBG_NETTCP, ((5 << 8) | 2))
136
137 extern int tcp_lq_overflow;
138
139 /* temporary: for testing */
140 #if IPSEC
141 extern int ipsec_bypass;
142 #endif
143
144 int tcp_mssdflt = TCP_MSS;
145 SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt, CTLFLAG_RW,
146 &tcp_mssdflt , 0, "Default TCP Maximum Segment Size");
147
148 #if INET6
149 int tcp_v6mssdflt = TCP6_MSS;
150 SYSCTL_INT(_net_inet_tcp, TCPCTL_V6MSSDFLT, v6mssdflt,
151 CTLFLAG_RW, &tcp_v6mssdflt , 0,
152 "Default TCP Maximum Segment Size for IPv6");
153 #endif
154
155 /*
156 * Minimum MSS we accept and use. This prevents DoS attacks where
157 * we are forced to a ridiculous low MSS like 20 and send hundreds
158 * of packets instead of one. The effect scales with the available
159 * bandwidth and quickly saturates the CPU and network interface
160 * with packet generation and sending. Set to zero to disable MINMSS
161 * checking. This setting prevents us from sending too small packets.
162 */
163 int tcp_minmss = TCP_MINMSS;
164 SYSCTL_INT(_net_inet_tcp, OID_AUTO, minmss, CTLFLAG_RW,
165 &tcp_minmss , 0, "Minmum TCP Maximum Segment Size");
166
167 /*
168 * Number of TCP segments per second we accept from remote host
169 * before we start to calculate average segment size. If average
170 * segment size drops below the minimum TCP MSS we assume a DoS
171 * attack and reset+drop the connection. Care has to be taken not to
172 * set this value too small to not kill interactive type connections
173 * (telnet, SSH) which send many small packets.
174 */
175 #ifdef FIX_WORKAROUND_FOR_3894301
176 __private_extern__ int tcp_minmssoverload = TCP_MINMSSOVERLOAD;
177 #else
178 __private_extern__ int tcp_minmssoverload = 0;
179 #endif
180 SYSCTL_INT(_net_inet_tcp, OID_AUTO, minmssoverload, CTLFLAG_RW,
181 &tcp_minmssoverload , 0, "Number of TCP Segments per Second allowed to"
182 "be under the MINMSS Size");
183
184 static int tcp_do_rfc1323 = 1;
185 SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_RW,
186 &tcp_do_rfc1323 , 0, "Enable rfc1323 (high performance TCP) extensions");
187
188 static int tcp_do_rfc1644 = 0;
189 SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1644, rfc1644, CTLFLAG_RW,
190 &tcp_do_rfc1644 , 0, "Enable rfc1644 (TTCP) extensions");
191
192 static int tcp_tcbhashsize = 0;
193 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcbhashsize, CTLFLAG_RD,
194 &tcp_tcbhashsize, 0, "Size of TCP control-block hashtable");
195
196 static int do_tcpdrain = 0;
197 SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0,
198 "Enable tcp_drain routine for extra help when low on mbufs");
199
200 SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD,
201 &tcbinfo.ipi_count, 0, "Number of active PCBs");
202
203 static int icmp_may_rst = 1;
204 SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0,
205 "Certain ICMP unreachable messages may abort connections in SYN_SENT");
206
207 static int tcp_strict_rfc1948 = 0;
208 SYSCTL_INT(_net_inet_tcp, OID_AUTO, strict_rfc1948, CTLFLAG_RW,
209 &tcp_strict_rfc1948, 0, "Determines if RFC1948 is followed exactly");
210
211 static int tcp_isn_reseed_interval = 0;
212 SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW,
213 &tcp_isn_reseed_interval, 0, "Seconds between reseeding of ISN secret");
214 static int tcp_background_io_enabled = 1;
215 SYSCTL_INT(_net_inet_tcp, OID_AUTO, background_io_enabled, CTLFLAG_RW,
216 &tcp_background_io_enabled, 0, "Background IO Enabled");
217
218 int tcp_TCPTV_MIN = 1;
219 SYSCTL_INT(_net_inet_tcp, OID_AUTO, rtt_min, CTLFLAG_RW,
220 &tcp_TCPTV_MIN, 0, "min rtt value allowed");
221
222 static void tcp_cleartaocache(void);
223 static void tcp_notify(struct inpcb *, int);
224 struct zone *sack_hole_zone;
225
226 extern unsigned int total_mb_cnt;
227 extern unsigned int total_cl_cnt;
228 extern int sbspace_factor;
229 extern int tcp_sockthreshold;
230 extern int slowlink_wsize; /* window correction for slow links */
231 extern int path_mtu_discovery;
232
233
234 /*
235 * Target size of TCP PCB hash tables. Must be a power of two.
236 *
237 * Note that this can be overridden by the kernel environment
238 * variable net.inet.tcp.tcbhashsize
239 */
240 #ifndef TCBHASHSIZE
241 #define TCBHASHSIZE CONFIG_TCBHASHSIZE
242 #endif
243
244 /*
245 * This is the actual shape of what we allocate using the zone
246 * allocator. Doing it this way allows us to protect both structures
247 * using the same generation count, and also eliminates the overhead
248 * of allocating tcpcbs separately. By hiding the structure here,
249 * we avoid changing most of the rest of the code (although it needs
250 * to be changed, eventually, for greater efficiency).
251 */
252 #define ALIGNMENT 32
253 #define ALIGNM1 (ALIGNMENT - 1)
254 struct inp_tp {
255 union {
256 struct inpcb inp;
257 char align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1];
258 } inp_tp_u;
259 struct tcpcb tcb;
260 };
261 #undef ALIGNMENT
262 #undef ALIGNM1
263
264 static struct tcpcb dummy_tcb;
265
266
267 extern struct inpcbhead time_wait_slots[];
268 extern int cur_tw_slot;
269 extern u_long *delack_bitmask;
270 extern u_long route_generation;
271
272 int get_inpcb_str_size(void);
273 int get_tcp_str_size(void);
274
275
276 int get_inpcb_str_size(void)
277 {
278 return sizeof(struct inpcb);
279 }
280
281
282 int get_tcp_str_size(void)
283 {
284 return sizeof(struct tcpcb);
285 }
286
287 int tcp_freeq(struct tcpcb *tp);
288
289
290 /*
291 * Tcp initialization
292 */
293 void
294 tcp_init()
295 {
296 int hashsize = TCBHASHSIZE;
297 vm_size_t str_size;
298 int i;
299 struct inpcbinfo *pcbinfo;
300
301 tcp_ccgen = 1;
302 tcp_cleartaocache();
303
304 tcp_keepinit = TCPTV_KEEP_INIT;
305 tcp_keepidle = TCPTV_KEEP_IDLE;
306 tcp_keepintvl = TCPTV_KEEPINTVL;
307 tcp_maxpersistidle = TCPTV_KEEP_IDLE;
308 tcp_msl = TCPTV_MSL;
309 read_random(&tcp_now, sizeof(tcp_now));
310 tcp_now = tcp_now & 0x3fffffff; /* Starts tcp internal 100ms clock at a random value */
311
312
313 LIST_INIT(&tcb);
314 tcbinfo.listhead = &tcb;
315 pcbinfo = &tcbinfo;
316 if (!powerof2(hashsize)) {
317 printf("WARNING: TCB hash size not a power of 2\n");
318 hashsize = 512; /* safe default */
319 }
320 tcp_tcbhashsize = hashsize;
321 tcbinfo.hashsize = hashsize;
322 tcbinfo.hashbase = hashinit(hashsize, M_PCB, &tcbinfo.hashmask);
323 tcbinfo.porthashbase = hashinit(hashsize, M_PCB,
324 &tcbinfo.porthashmask);
325 str_size = (vm_size_t) sizeof(struct inp_tp);
326 tcbinfo.ipi_zone = (void *) zinit(str_size, 120000*str_size, 8192, "tcpcb");
327 sack_hole_zone = zinit(str_size, 120000*str_size, 8192, "sack_hole zone");
328 tcp_reass_maxseg = nmbclusters / 16;
329
330 #if INET6
331 #define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
332 #else /* INET6 */
333 #define TCP_MINPROTOHDR (sizeof(struct tcpiphdr))
334 #endif /* INET6 */
335 if (max_protohdr < TCP_MINPROTOHDR)
336 max_protohdr = TCP_MINPROTOHDR;
337 if (max_linkhdr + TCP_MINPROTOHDR > MHLEN)
338 panic("tcp_init");
339 #undef TCP_MINPROTOHDR
340 dummy_tcb.t_state = TCP_NSTATES;
341 dummy_tcb.t_flags = 0;
342 tcbinfo.dummy_cb = (caddr_t) &dummy_tcb;
343
344 /*
345 * allocate lock group attribute and group for tcp pcb mutexes
346 */
347 pcbinfo->mtx_grp_attr = lck_grp_attr_alloc_init();
348 pcbinfo->mtx_grp = lck_grp_alloc_init("tcppcb", pcbinfo->mtx_grp_attr);
349
350 /*
351 * allocate the lock attribute for tcp pcb mutexes
352 */
353 pcbinfo->mtx_attr = lck_attr_alloc_init();
354
355 if ((pcbinfo->mtx = lck_rw_alloc_init(pcbinfo->mtx_grp, pcbinfo->mtx_attr)) == NULL) {
356 printf("tcp_init: mutex not alloced!\n");
357 return; /* pretty much dead if this fails... */
358 }
359
360
361 in_pcb_nat_init(&tcbinfo, AF_INET, IPPROTO_TCP, SOCK_STREAM);
362
363 delack_bitmask = _MALLOC((4 * hashsize)/32, M_PCB, M_WAITOK);
364 if (delack_bitmask == 0)
365 panic("Delack Memory");
366
367 for (i=0; i < (tcbinfo.hashsize / 32); i++)
368 delack_bitmask[i] = 0;
369
370 for (i=0; i < N_TIME_WAIT_SLOTS; i++) {
371 LIST_INIT(&time_wait_slots[i]);
372 }
373
374 timeout(tcp_fasttimo, NULL, hz/TCP_RETRANSHZ);
375 }
376
377 /*
378 * Fill in the IP and TCP headers for an outgoing packet, given the tcpcb.
379 * tcp_template used to store this data in mbufs, but we now recopy it out
380 * of the tcpcb each time to conserve mbufs.
381 */
382 void
383 tcp_fillheaders(tp, ip_ptr, tcp_ptr)
384 struct tcpcb *tp;
385 void *ip_ptr;
386 void *tcp_ptr;
387 {
388 struct inpcb *inp = tp->t_inpcb;
389 struct tcphdr *tcp_hdr = (struct tcphdr *)tcp_ptr;
390
391 #if INET6
392 if ((inp->inp_vflag & INP_IPV6) != 0) {
393 struct ip6_hdr *ip6;
394
395 ip6 = (struct ip6_hdr *)ip_ptr;
396 ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
397 (inp->in6p_flowinfo & IPV6_FLOWINFO_MASK);
398 ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
399 (IPV6_VERSION & IPV6_VERSION_MASK);
400 ip6->ip6_nxt = IPPROTO_TCP;
401 ip6->ip6_plen = sizeof(struct tcphdr);
402 ip6->ip6_src = inp->in6p_laddr;
403 ip6->ip6_dst = inp->in6p_faddr;
404 tcp_hdr->th_sum = 0;
405 } else
406 #endif
407 {
408 struct ip *ip = (struct ip *) ip_ptr;
409
410 ip->ip_vhl = IP_VHL_BORING;
411 ip->ip_tos = 0;
412 ip->ip_len = 0;
413 ip->ip_id = 0;
414 ip->ip_off = 0;
415 ip->ip_ttl = 0;
416 ip->ip_sum = 0;
417 ip->ip_p = IPPROTO_TCP;
418 ip->ip_src = inp->inp_laddr;
419 ip->ip_dst = inp->inp_faddr;
420 tcp_hdr->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
421 htons(sizeof(struct tcphdr) + IPPROTO_TCP));
422 }
423
424 tcp_hdr->th_sport = inp->inp_lport;
425 tcp_hdr->th_dport = inp->inp_fport;
426 tcp_hdr->th_seq = 0;
427 tcp_hdr->th_ack = 0;
428 tcp_hdr->th_x2 = 0;
429 tcp_hdr->th_off = 5;
430 tcp_hdr->th_flags = 0;
431 tcp_hdr->th_win = 0;
432 tcp_hdr->th_urp = 0;
433 }
434
435 /*
436 * Create template to be used to send tcp packets on a connection.
437 * Allocates an mbuf and fills in a skeletal tcp/ip header. The only
438 * use for this function is in keepalives, which use tcp_respond.
439 */
440 struct tcptemp *
441 tcp_maketemplate(tp)
442 struct tcpcb *tp;
443 {
444 struct mbuf *m;
445 struct tcptemp *n;
446
447 m = m_get(M_DONTWAIT, MT_HEADER);
448 if (m == NULL)
449 return (0);
450 m->m_len = sizeof(struct tcptemp);
451 n = mtod(m, struct tcptemp *);
452
453 tcp_fillheaders(tp, (void *)&n->tt_ipgen, (void *)&n->tt_t);
454 return (n);
455 }
456
457 /*
458 * Send a single message to the TCP at address specified by
459 * the given TCP/IP header. If m == 0, then we make a copy
460 * of the tcpiphdr at ti and send directly to the addressed host.
461 * This is used to force keep alive messages out using the TCP
462 * template for a connection. If flags are given then we send
463 * a message back to the TCP which originated the * segment ti,
464 * and discard the mbuf containing it and any other attached mbufs.
465 *
466 * In any case the ack and sequence number of the transmitted
467 * segment are as specified by the parameters.
468 *
469 * NOTE: If m != NULL, then ti must point to *inside* the mbuf.
470 */
471 void
472 tcp_respond(
473 struct tcpcb *tp,
474 void *ipgen,
475 register struct tcphdr *th,
476 register struct mbuf *m,
477 tcp_seq ack,
478 tcp_seq seq,
479 int flags,
480 #if CONFIG_FORCE_OUT_IFP
481 ifnet_t ifp
482 #else
483 __unused ifnet_t ifp
484 #endif
485 )
486 {
487 register int tlen;
488 int win = 0;
489 struct route *ro = 0;
490 struct route sro;
491 struct ip *ip;
492 struct tcphdr *nth;
493 #if INET6
494 struct route_in6 *ro6 = 0;
495 struct route_in6 sro6;
496 struct ip6_hdr *ip6;
497 int isipv6;
498 #endif /* INET6 */
499 int ipflags = 0;
500
501 #if INET6
502 isipv6 = IP_VHL_V(((struct ip *)ipgen)->ip_vhl) == 6;
503 ip6 = ipgen;
504 #endif /* INET6 */
505 ip = ipgen;
506
507 if (tp) {
508 if (!(flags & TH_RST)) {
509 win = tcp_sbspace(tp);
510 if (win > (long)TCP_MAXWIN << tp->rcv_scale)
511 win = (long)TCP_MAXWIN << tp->rcv_scale;
512 }
513 #if INET6
514 if (isipv6)
515 ro6 = &tp->t_inpcb->in6p_route;
516 else
517 #endif /* INET6 */
518 ro = &tp->t_inpcb->inp_route;
519 } else {
520 #if INET6
521 if (isipv6) {
522 ro6 = &sro6;
523 bzero(ro6, sizeof *ro6);
524 } else
525 #endif /* INET6 */
526 {
527 ro = &sro;
528 bzero(ro, sizeof *ro);
529 }
530 }
531 if (m == 0) {
532 m = m_gethdr(M_DONTWAIT, MT_HEADER); /* MAC-OK */
533 if (m == NULL)
534 return;
535 tlen = 0;
536 m->m_data += max_linkhdr;
537 #if INET6
538 if (isipv6) {
539 bcopy((caddr_t)ip6, mtod(m, caddr_t),
540 sizeof(struct ip6_hdr));
541 ip6 = mtod(m, struct ip6_hdr *);
542 nth = (struct tcphdr *)(ip6 + 1);
543 } else
544 #endif /* INET6 */
545 {
546 bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
547 ip = mtod(m, struct ip *);
548 nth = (struct tcphdr *)(ip + 1);
549 }
550 bcopy((caddr_t)th, (caddr_t)nth, sizeof(struct tcphdr));
551 flags = TH_ACK;
552 } else {
553 m_freem(m->m_next);
554 m->m_next = 0;
555 m->m_data = (caddr_t)ipgen;
556 /* m_len is set later */
557 tlen = 0;
558 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
559 #if INET6
560 if (isipv6) {
561 xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr);
562 nth = (struct tcphdr *)(ip6 + 1);
563 } else
564 #endif /* INET6 */
565 {
566 xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, n_long);
567 nth = (struct tcphdr *)(ip + 1);
568 }
569 if (th != nth) {
570 /*
571 * this is usually a case when an extension header
572 * exists between the IPv6 header and the
573 * TCP header.
574 */
575 nth->th_sport = th->th_sport;
576 nth->th_dport = th->th_dport;
577 }
578 xchg(nth->th_dport, nth->th_sport, n_short);
579 #undef xchg
580 }
581 #if INET6
582 if (isipv6) {
583 ip6->ip6_plen = htons((u_short)(sizeof (struct tcphdr) +
584 tlen));
585 tlen += sizeof (struct ip6_hdr) + sizeof (struct tcphdr);
586 } else
587 #endif
588 {
589 tlen += sizeof (struct tcpiphdr);
590 ip->ip_len = tlen;
591 ip->ip_ttl = ip_defttl;
592 }
593 m->m_len = tlen;
594 m->m_pkthdr.len = tlen;
595 m->m_pkthdr.rcvif = 0;
596 #if CONFIG_MACF_NET
597 if (tp != NULL && tp->t_inpcb != NULL) {
598 /*
599 * Packet is associated with a socket, so allow the
600 * label of the response to reflect the socket label.
601 */
602 mac_mbuf_label_associate_inpcb(tp->t_inpcb, m);
603 } else {
604 /*
605 * Packet is not associated with a socket, so possibly
606 * update the label in place.
607 */
608 mac_netinet_tcp_reply(m);
609 }
610 #endif
611 nth->th_seq = htonl(seq);
612 nth->th_ack = htonl(ack);
613 nth->th_x2 = 0;
614 nth->th_off = sizeof (struct tcphdr) >> 2;
615 nth->th_flags = flags;
616 if (tp)
617 nth->th_win = htons((u_short) (win >> tp->rcv_scale));
618 else
619 nth->th_win = htons((u_short)win);
620 nth->th_urp = 0;
621 #if INET6
622 if (isipv6) {
623 nth->th_sum = 0;
624 nth->th_sum = in6_cksum(m, IPPROTO_TCP,
625 sizeof(struct ip6_hdr),
626 tlen - sizeof(struct ip6_hdr));
627 ip6->ip6_hlim = in6_selecthlim(tp ? tp->t_inpcb : NULL,
628 ro6 && ro6->ro_rt ?
629 ro6->ro_rt->rt_ifp :
630 NULL);
631 } else
632 #endif /* INET6 */
633 {
634 nth->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
635 htons((u_short)(tlen - sizeof(struct ip) + ip->ip_p)));
636 m->m_pkthdr.csum_flags = CSUM_TCP;
637 m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
638 }
639 #if TCPDEBUG
640 if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
641 tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
642 #endif
643 #if IPSEC
644 if (ipsec_bypass == 0 && ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
645 m_freem(m);
646 return;
647 }
648 #endif
649 #if INET6
650 if (isipv6) {
651 (void)ip6_output(m, NULL, ro6, ipflags, NULL, NULL, 0);
652 if (ro6 == &sro6 && ro6->ro_rt) {
653 rtfree(ro6->ro_rt);
654 ro6->ro_rt = NULL;
655 }
656 } else
657 #endif /* INET6 */
658 {
659 #if CONFIG_FORCE_OUT_IFP
660 ifp = (tp && tp->t_inpcb) ? tp->t_inpcb->pdp_ifp :
661 (ifp && (ifp->if_flags & IFF_POINTOPOINT) != 0) ? ifp : NULL;
662 #endif
663 (void) ip_output_list(m, 0, NULL, ro, ipflags, NULL, ifp);
664 if (ro == &sro && ro->ro_rt) {
665 rtfree(ro->ro_rt);
666 ro->ro_rt = NULL;
667 }
668 }
669 }
670
671 /*
672 * Create a new TCP control block, making an
673 * empty reassembly queue and hooking it to the argument
674 * protocol control block. The `inp' parameter must have
675 * come from the zone allocator set up in tcp_init().
676 */
677 struct tcpcb *
678 tcp_newtcpcb(inp)
679 struct inpcb *inp;
680 {
681 struct inp_tp *it;
682 register struct tcpcb *tp;
683 register struct socket *so = inp->inp_socket;
684 #if INET6
685 int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
686 #endif /* INET6 */
687
688 if (so->cached_in_sock_layer == 0) {
689 it = (struct inp_tp *)inp;
690 tp = &it->tcb;
691 }
692 else
693 tp = (struct tcpcb *) inp->inp_saved_ppcb;
694
695 bzero((char *) tp, sizeof(struct tcpcb));
696 LIST_INIT(&tp->t_segq);
697 tp->t_maxseg = tp->t_maxopd =
698 #if INET6
699 isipv6 ? tcp_v6mssdflt :
700 #endif /* INET6 */
701 tcp_mssdflt;
702
703 if (tcp_do_rfc1323)
704 tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
705 tp->sack_enable = tcp_do_sack;
706 TAILQ_INIT(&tp->snd_holes);
707 tp->t_inpcb = inp; /* XXX */
708 /*
709 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
710 * rtt estimate. Set rttvar so that srtt + 4 * rttvar gives
711 * reasonable initial retransmit time.
712 */
713 tp->t_srtt = TCPTV_SRTTBASE;
714 tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
715 tp->t_rttmin = tcp_TCPTV_MIN;
716 tp->t_rxtcur = TCPTV_RTOBASE;
717 tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
718 tp->snd_bwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
719 tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
720 tp->snd_ssthresh_prev = TCP_MAXWIN << TCP_MAX_WINSHIFT;
721 tp->t_rcvtime = 0;
722 tp->t_bw_rtttime = 0;
723 /*
724 * IPv4 TTL initialization is necessary for an IPv6 socket as well,
725 * because the socket may be bound to an IPv6 wildcard address,
726 * which may match an IPv4-mapped IPv6 address.
727 */
728 inp->inp_ip_ttl = ip_defttl;
729 inp->inp_ppcb = (caddr_t)tp;
730 return (tp); /* XXX */
731 }
732
733 /*
734 * Drop a TCP connection, reporting
735 * the specified error. If connection is synchronized,
736 * then send a RST to peer.
737 */
738 struct tcpcb *
739 tcp_drop(tp, errno)
740 register struct tcpcb *tp;
741 int errno;
742 {
743 struct socket *so = tp->t_inpcb->inp_socket;
744
745 if (TCPS_HAVERCVDSYN(tp->t_state)) {
746 tp->t_state = TCPS_CLOSED;
747 (void) tcp_output(tp);
748 tcpstat.tcps_drops++;
749 } else
750 tcpstat.tcps_conndrops++;
751 if (errno == ETIMEDOUT && tp->t_softerror)
752 errno = tp->t_softerror;
753 so->so_error = errno;
754 return (tcp_close(tp));
755 }
756
757 /*
758 * Close a TCP control block:
759 * discard all space held by the tcp
760 * discard internet protocol block
761 * wake up any sleepers
762 */
763 struct tcpcb *
764 tcp_close(tp)
765 register struct tcpcb *tp;
766 {
767 struct inpcb *inp = tp->t_inpcb;
768 struct socket *so = inp->inp_socket;
769 #if INET6
770 int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
771 #endif /* INET6 */
772 register struct rtentry *rt;
773 int dosavessthresh;
774
775 if ( inp->inp_ppcb == NULL) /* tcp_close was called previously, bail */
776 return NULL;
777
778 /* Clear the timers before we delete the PCB. */
779 {
780 int i;
781 for (i = 0; i < TCPT_NTIMERS; i++) {
782 tp->t_timer[i] = 0;
783 }
784 }
785
786 KERNEL_DEBUG(DBG_FNC_TCP_CLOSE | DBG_FUNC_START, tp,0,0,0,0);
787 switch (tp->t_state)
788 {
789 case TCPS_ESTABLISHED:
790 case TCPS_FIN_WAIT_1:
791 case TCPS_CLOSING:
792 case TCPS_CLOSE_WAIT:
793 case TCPS_LAST_ACK:
794 break;
795 }
796
797 /*
798 * If another thread for this tcp is currently in ip (indicated by
799 * the TF_SENDINPROG flag), defer the cleanup until after it returns
800 * back to tcp. This is done to serialize the close until after all
801 * pending output is finished, in order to avoid having the PCB be
802 * detached and the cached route cleaned, only for ip to cache the
803 * route back into the PCB again. Note that we've cleared all the
804 * timers at this point. Set TF_CLOSING to indicate to tcp_output()
805 * that is should call us again once it returns from ip; at that
806 * point both flags should be cleared and we can proceed further
807 * with the cleanup.
808 */
809 if (tp->t_flags & (TF_CLOSING|TF_SENDINPROG)) {
810 tp->t_flags |= TF_CLOSING;
811 return (NULL);
812 }
813
814 lck_mtx_lock(rt_mtx);
815 /*
816 * If we got enough samples through the srtt filter,
817 * save the rtt and rttvar in the routing entry.
818 * 'Enough' is arbitrarily defined as the 16 samples.
819 * 16 samples is enough for the srtt filter to converge
820 * to within 5% of the correct value; fewer samples and
821 * we could save a very bogus rtt.
822 *
823 * Don't update the default route's characteristics and don't
824 * update anything that the user "locked".
825 */
826 if (tp->t_rttupdated >= 16) {
827 register u_long i = 0;
828
829 #if INET6
830 if (isipv6) {
831 struct sockaddr_in6 *sin6;
832
833 if ((rt = inp->in6p_route.ro_rt) == NULL)
834 goto no_valid_rt;
835 sin6 = (struct sockaddr_in6 *)rt_key(rt);
836 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
837 goto no_valid_rt;
838 }
839 else
840 #endif /* INET6 */
841 rt = inp->inp_route.ro_rt;
842 if (rt == NULL ||
843 ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr
844 == INADDR_ANY || rt->generation_id != route_generation) {
845 if (tp->t_state >= TCPS_CLOSE_WAIT)
846 tp->t_state = TCPS_CLOSING;
847
848 goto no_valid_rt;
849 }
850
851 if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
852 i = tp->t_srtt *
853 (RTM_RTTUNIT / (TCP_RETRANSHZ * TCP_RTT_SCALE));
854 if (rt->rt_rmx.rmx_rtt && i)
855 /*
856 * filter this update to half the old & half
857 * the new values, converting scale.
858 * See route.h and tcp_var.h for a
859 * description of the scaling constants.
860 */
861 rt->rt_rmx.rmx_rtt =
862 (rt->rt_rmx.rmx_rtt + i) / 2;
863 else
864 rt->rt_rmx.rmx_rtt = i;
865 tcpstat.tcps_cachedrtt++;
866 }
867 if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
868 i = tp->t_rttvar *
869 (RTM_RTTUNIT / (TCP_RETRANSHZ * TCP_RTTVAR_SCALE));
870 if (rt->rt_rmx.rmx_rttvar && i)
871 rt->rt_rmx.rmx_rttvar =
872 (rt->rt_rmx.rmx_rttvar + i) / 2;
873 else
874 rt->rt_rmx.rmx_rttvar = i;
875 tcpstat.tcps_cachedrttvar++;
876 }
877 /*
878 * The old comment here said:
879 * update the pipelimit (ssthresh) if it has been updated
880 * already or if a pipesize was specified & the threshhold
881 * got below half the pipesize. I.e., wait for bad news
882 * before we start updating, then update on both good
883 * and bad news.
884 *
885 * But we want to save the ssthresh even if no pipesize is
886 * specified explicitly in the route, because such
887 * connections still have an implicit pipesize specified
888 * by the global tcp_sendspace. In the absence of a reliable
889 * way to calculate the pipesize, it will have to do.
890 */
891 i = tp->snd_ssthresh;
892 if (rt->rt_rmx.rmx_sendpipe != 0)
893 dosavessthresh = (i < rt->rt_rmx.rmx_sendpipe / 2);
894 else
895 dosavessthresh = (i < so->so_snd.sb_hiwat / 2);
896 if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
897 i != 0 && rt->rt_rmx.rmx_ssthresh != 0)
898 || dosavessthresh) {
899 /*
900 * convert the limit from user data bytes to
901 * packets then to packet data bytes.
902 */
903 i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
904 if (i < 2)
905 i = 2;
906 i *= (u_long)(tp->t_maxseg +
907 #if INET6
908 (isipv6 ? sizeof (struct ip6_hdr) +
909 sizeof (struct tcphdr) :
910 #endif
911 sizeof (struct tcpiphdr)
912 #if INET6
913 )
914 #endif
915 );
916 if (rt->rt_rmx.rmx_ssthresh)
917 rt->rt_rmx.rmx_ssthresh =
918 (rt->rt_rmx.rmx_ssthresh + i) / 2;
919 else
920 rt->rt_rmx.rmx_ssthresh = i;
921 tcpstat.tcps_cachedssthresh++;
922 }
923 }
924 rt = inp->inp_route.ro_rt;
925 if (rt) {
926 /*
927 * mark route for deletion if no information is
928 * cached.
929 */
930 if ((so->so_flags & SOF_OVERFLOW) && tcp_lq_overflow &&
931 ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0)){
932 if (rt->rt_rmx.rmx_rtt == 0)
933 rt->rt_flags |= RTF_DELCLONE;
934 }
935 }
936 no_valid_rt:
937 /* free the reassembly queue, if any */
938 lck_mtx_unlock(rt_mtx);
939
940 (void) tcp_freeq(tp);
941
942 tcp_free_sackholes(tp);
943
944 /* Free the packet list */
945 if (tp->t_pktlist_head != NULL)
946 m_freem_list(tp->t_pktlist_head);
947 TCP_PKTLIST_CLEAR(tp);
948
949 #ifdef __APPLE__
950 if (so->cached_in_sock_layer)
951 inp->inp_saved_ppcb = (caddr_t) tp;
952 #endif
953
954 soisdisconnected(so);
955 #if INET6
956 if (INP_CHECK_SOCKAF(so, AF_INET6))
957 in6_pcbdetach(inp);
958 else
959 #endif /* INET6 */
960 in_pcbdetach(inp);
961 tcpstat.tcps_closed++;
962 KERNEL_DEBUG(DBG_FNC_TCP_CLOSE | DBG_FUNC_END, tcpstat.tcps_closed,0,0,0,0);
963 return ((struct tcpcb *)0);
964 }
965
966 int
967 tcp_freeq(tp)
968 struct tcpcb *tp;
969 {
970
971 register struct tseg_qent *q;
972 int rv = 0;
973
974 while((q = LIST_FIRST(&tp->t_segq)) != NULL) {
975 LIST_REMOVE(q, tqe_q);
976 m_freem(q->tqe_m);
977 FREE(q, M_TSEGQ);
978 tcp_reass_qsize--;
979 rv = 1;
980 }
981 return (rv);
982 }
983
984 void
985 tcp_drain()
986 {
987 if (do_tcpdrain)
988 {
989 struct inpcb *inpb;
990 struct tcpcb *tcpb;
991 struct tseg_qent *te;
992
993 /*
994 * Walk the tcpbs, if existing, and flush the reassembly queue,
995 * if there is one...
996 * XXX: The "Net/3" implementation doesn't imply that the TCP
997 * reassembly queue should be flushed, but in a situation
998 * where we're really low on mbufs, this is potentially
999 * usefull.
1000 */
1001 if (!lck_rw_try_lock_exclusive(tcbinfo.mtx)) /* do it next time if the lock is in use */
1002 return;
1003
1004 for (inpb = LIST_FIRST(tcbinfo.listhead); inpb;
1005 inpb = LIST_NEXT(inpb, inp_list)) {
1006 if ((tcpb = intotcpcb(inpb))) {
1007 while ((te = LIST_FIRST(&tcpb->t_segq))
1008 != NULL) {
1009 LIST_REMOVE(te, tqe_q);
1010 m_freem(te->tqe_m);
1011 FREE(te, M_TSEGQ);
1012 tcp_reass_qsize--;
1013 }
1014 }
1015 }
1016 lck_rw_done(tcbinfo.mtx);
1017
1018 }
1019 }
1020
1021 /*
1022 * Notify a tcp user of an asynchronous error;
1023 * store error as soft error, but wake up user
1024 * (for now, won't do anything until can select for soft error).
1025 *
1026 * Do not wake up user since there currently is no mechanism for
1027 * reporting soft errors (yet - a kqueue filter may be added).
1028 */
1029 static void
1030 tcp_notify(inp, error)
1031 struct inpcb *inp;
1032 int error;
1033 {
1034 struct tcpcb *tp;
1035
1036 if (inp == NULL || (inp->inp_state == INPCB_STATE_DEAD))
1037 return; /* pcb is gone already */
1038
1039 tp = (struct tcpcb *)inp->inp_ppcb;
1040
1041 /*
1042 * Ignore some errors if we are hooked up.
1043 * If connection hasn't completed, has retransmitted several times,
1044 * and receives a second error, give up now. This is better
1045 * than waiting a long time to establish a connection that
1046 * can never complete.
1047 */
1048 if (tp->t_state == TCPS_ESTABLISHED &&
1049 (error == EHOSTUNREACH || error == ENETUNREACH ||
1050 error == EHOSTDOWN)) {
1051 return;
1052 } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
1053 tp->t_softerror)
1054 tcp_drop(tp, error);
1055 else
1056 tp->t_softerror = error;
1057 #if 0
1058 wakeup((caddr_t) &so->so_timeo);
1059 sorwakeup(so);
1060 sowwakeup(so);
1061 #endif
1062 }
1063
1064 static int
1065 tcp_pcblist SYSCTL_HANDLER_ARGS
1066 {
1067 #pragma unused(oidp, arg1, arg2)
1068 int error, i, n;
1069 struct inpcb *inp, **inp_list;
1070 inp_gen_t gencnt;
1071 struct xinpgen xig;
1072 int slot;
1073
1074 /*
1075 * The process of preparing the TCB list is too time-consuming and
1076 * resource-intensive to repeat twice on every request.
1077 */
1078 lck_rw_lock_shared(tcbinfo.mtx);
1079 if (req->oldptr == USER_ADDR_NULL) {
1080 n = tcbinfo.ipi_count;
1081 req->oldidx = 2 * (sizeof xig)
1082 + (n + n/8) * sizeof(struct xtcpcb);
1083 lck_rw_done(tcbinfo.mtx);
1084 return 0;
1085 }
1086
1087 if (req->newptr != USER_ADDR_NULL) {
1088 lck_rw_done(tcbinfo.mtx);
1089 return EPERM;
1090 }
1091
1092 /*
1093 * OK, now we're committed to doing something.
1094 */
1095 gencnt = tcbinfo.ipi_gencnt;
1096 n = tcbinfo.ipi_count;
1097
1098 bzero(&xig, sizeof(xig));
1099 xig.xig_len = sizeof xig;
1100 xig.xig_count = n;
1101 xig.xig_gen = gencnt;
1102 xig.xig_sogen = so_gencnt;
1103 error = SYSCTL_OUT(req, &xig, sizeof xig);
1104 if (error) {
1105 lck_rw_done(tcbinfo.mtx);
1106 return error;
1107 }
1108 /*
1109 * We are done if there is no pcb
1110 */
1111 if (n == 0) {
1112 lck_rw_done(tcbinfo.mtx);
1113 return 0;
1114 }
1115
1116 inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
1117 if (inp_list == 0) {
1118 lck_rw_done(tcbinfo.mtx);
1119 return ENOMEM;
1120 }
1121
1122 for (inp = LIST_FIRST(tcbinfo.listhead), i = 0; inp && i < n;
1123 inp = LIST_NEXT(inp, inp_list)) {
1124 #ifdef __APPLE__
1125 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD)
1126 #else
1127 if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp))
1128 #endif
1129 inp_list[i++] = inp;
1130 }
1131
1132 for (slot = 0; slot < N_TIME_WAIT_SLOTS; slot++) {
1133 struct inpcb *inpnxt;
1134
1135 for (inp = time_wait_slots[slot].lh_first; inp && i < n; inp = inpnxt) {
1136 inpnxt = inp->inp_list.le_next;
1137 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD)
1138 inp_list[i++] = inp;
1139 }
1140 }
1141
1142 n = i;
1143
1144 error = 0;
1145 for (i = 0; i < n; i++) {
1146 inp = inp_list[i];
1147 if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD) {
1148 struct xtcpcb xt;
1149 caddr_t inp_ppcb;
1150
1151 bzero(&xt, sizeof(xt));
1152 xt.xt_len = sizeof xt;
1153 /* XXX should avoid extra copy */
1154 inpcb_to_compat(inp, &xt.xt_inp);
1155 inp_ppcb = inp->inp_ppcb;
1156 if (inp_ppcb != NULL) {
1157 bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
1158 }
1159 else
1160 bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
1161 if (inp->inp_socket)
1162 sotoxsocket(inp->inp_socket, &xt.xt_socket);
1163 error = SYSCTL_OUT(req, &xt, sizeof xt);
1164 }
1165 }
1166 if (!error) {
1167 /*
1168 * Give the user an updated idea of our state.
1169 * If the generation differs from what we told
1170 * her before, she knows that something happened
1171 * while we were processing this request, and it
1172 * might be necessary to retry.
1173 */
1174 bzero(&xig, sizeof(xig));
1175 xig.xig_len = sizeof xig;
1176 xig.xig_gen = tcbinfo.ipi_gencnt;
1177 xig.xig_sogen = so_gencnt;
1178 xig.xig_count = tcbinfo.ipi_count;
1179 error = SYSCTL_OUT(req, &xig, sizeof xig);
1180 }
1181 FREE(inp_list, M_TEMP);
1182 lck_rw_done(tcbinfo.mtx);
1183 return error;
1184 }
1185
1186 SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
1187 tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
1188
1189 #ifndef __APPLE__
1190 static int
1191 tcp_getcred(SYSCTL_HANDLER_ARGS)
1192 {
1193 struct sockaddr_in addrs[2];
1194 struct inpcb *inp;
1195 int error, s;
1196
1197 error = suser(req->p);
1198 if (error)
1199 return (error);
1200 error = SYSCTL_IN(req, addrs, sizeof(addrs));
1201 if (error)
1202 return (error);
1203 s = splnet();
1204 inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
1205 addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
1206 if (inp == NULL || inp->inp_socket == NULL) {
1207 error = ENOENT;
1208 goto out;
1209 }
1210 error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(*(kauth_cred_t)0);
1211 out:
1212 splx(s);
1213 return (error);
1214 }
1215
1216 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
1217 0, 0, tcp_getcred, "S,ucred", "Get the ucred of a TCP connection");
1218
1219 #if INET6
1220 static int
1221 tcp6_getcred(SYSCTL_HANDLER_ARGS)
1222 {
1223 struct sockaddr_in6 addrs[2];
1224 struct inpcb *inp;
1225 int error, s, mapped = 0;
1226
1227 error = suser(req->p);
1228 if (error)
1229 return (error);
1230 error = SYSCTL_IN(req, addrs, sizeof(addrs));
1231 if (error)
1232 return (error);
1233 if (IN6_IS_ADDR_V4MAPPED(&addrs[0].sin6_addr)) {
1234 if (IN6_IS_ADDR_V4MAPPED(&addrs[1].sin6_addr))
1235 mapped = 1;
1236 else
1237 return (EINVAL);
1238 }
1239 s = splnet();
1240 if (mapped == 1)
1241 inp = in_pcblookup_hash(&tcbinfo,
1242 *(struct in_addr *)&addrs[1].sin6_addr.s6_addr[12],
1243 addrs[1].sin6_port,
1244 *(struct in_addr *)&addrs[0].sin6_addr.s6_addr[12],
1245 addrs[0].sin6_port,
1246 0, NULL);
1247 else
1248 inp = in6_pcblookup_hash(&tcbinfo, &addrs[1].sin6_addr,
1249 addrs[1].sin6_port,
1250 &addrs[0].sin6_addr, addrs[0].sin6_port,
1251 0, NULL);
1252 if (inp == NULL || inp->inp_socket == NULL) {
1253 error = ENOENT;
1254 goto out;
1255 }
1256 error = SYSCTL_OUT(req, inp->inp_socket->so_cred,
1257 sizeof(*(kauth_cred_t)0);
1258 out:
1259 splx(s);
1260 return (error);
1261 }
1262
1263 SYSCTL_PROC(_net_inet6_tcp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
1264 0, 0,
1265 tcp6_getcred, "S,ucred", "Get the ucred of a TCP6 connection");
1266 #endif
1267 #endif /* __APPLE__*/
1268
1269 void
1270 tcp_ctlinput(cmd, sa, vip)
1271 int cmd;
1272 struct sockaddr *sa;
1273 void *vip;
1274 {
1275 struct ip *ip = vip;
1276 struct tcphdr *th;
1277 struct in_addr faddr;
1278 struct inpcb *inp;
1279 struct tcpcb *tp;
1280 void (*notify)(struct inpcb *, int) = tcp_notify;
1281 tcp_seq icmp_seq;
1282
1283 faddr = ((struct sockaddr_in *)sa)->sin_addr;
1284 if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
1285 return;
1286
1287 if (cmd == PRC_QUENCH)
1288 notify = tcp_quench;
1289 else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
1290 cmd == PRC_UNREACH_PORT) && ip)
1291 notify = tcp_drop_syn_sent;
1292 else if (cmd == PRC_MSGSIZE)
1293 notify = tcp_mtudisc;
1294 else if (PRC_IS_REDIRECT(cmd)) {
1295 ip = 0;
1296 notify = in_rtchange;
1297 } else if (cmd == PRC_HOSTDEAD)
1298 ip = 0;
1299 else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
1300 return;
1301 if (ip) {
1302 th = (struct tcphdr *)((caddr_t)ip
1303 + (IP_VHL_HL(ip->ip_vhl) << 2));
1304 inp = in_pcblookup_hash(&tcbinfo, faddr, th->th_dport,
1305 ip->ip_src, th->th_sport, 0, NULL);
1306 if (inp != NULL && inp->inp_socket != NULL) {
1307 tcp_lock(inp->inp_socket, 1, 0);
1308 if (in_pcb_checkstate(inp, WNT_RELEASE, 1) == WNT_STOPUSING) {
1309 tcp_unlock(inp->inp_socket, 1, 0);
1310 return;
1311 }
1312 icmp_seq = htonl(th->th_seq);
1313 tp = intotcpcb(inp);
1314 if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
1315 SEQ_LT(icmp_seq, tp->snd_max))
1316 (*notify)(inp, inetctlerrmap[cmd]);
1317 tcp_unlock(inp->inp_socket, 1, 0);
1318 }
1319 } else
1320 in_pcbnotifyall(&tcbinfo, faddr, inetctlerrmap[cmd], notify);
1321 }
1322
1323 #if INET6
1324 void
1325 tcp6_ctlinput(cmd, sa, d)
1326 int cmd;
1327 struct sockaddr *sa;
1328 void *d;
1329 {
1330 struct tcphdr th;
1331 void (*notify)(struct inpcb *, int) = tcp_notify;
1332 struct ip6_hdr *ip6;
1333 struct mbuf *m;
1334 struct ip6ctlparam *ip6cp = NULL;
1335 const struct sockaddr_in6 *sa6_src = NULL;
1336 int off;
1337 struct tcp_portonly {
1338 u_int16_t th_sport;
1339 u_int16_t th_dport;
1340 } *thp;
1341
1342 if (sa->sa_family != AF_INET6 ||
1343 sa->sa_len != sizeof(struct sockaddr_in6))
1344 return;
1345
1346 if (cmd == PRC_QUENCH)
1347 notify = tcp_quench;
1348 else if (cmd == PRC_MSGSIZE)
1349 notify = tcp_mtudisc;
1350 else if (!PRC_IS_REDIRECT(cmd) &&
1351 ((unsigned)cmd > PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
1352 return;
1353
1354 /* if the parameter is from icmp6, decode it. */
1355 if (d != NULL) {
1356 ip6cp = (struct ip6ctlparam *)d;
1357 m = ip6cp->ip6c_m;
1358 ip6 = ip6cp->ip6c_ip6;
1359 off = ip6cp->ip6c_off;
1360 sa6_src = ip6cp->ip6c_src;
1361 } else {
1362 m = NULL;
1363 ip6 = NULL;
1364 off = 0; /* fool gcc */
1365 sa6_src = &sa6_any;
1366 }
1367
1368 if (ip6) {
1369 /*
1370 * XXX: We assume that when IPV6 is non NULL,
1371 * M and OFF are valid.
1372 */
1373
1374 /* check if we can safely examine src and dst ports */
1375 if (m->m_pkthdr.len < off + sizeof(*thp))
1376 return;
1377
1378 bzero(&th, sizeof(th));
1379 m_copydata(m, off, sizeof(*thp), (caddr_t)&th);
1380
1381 in6_pcbnotify(&tcbinfo, sa, th.th_dport,
1382 (struct sockaddr *)ip6cp->ip6c_src,
1383 th.th_sport, cmd, notify);
1384 } else
1385 in6_pcbnotify(&tcbinfo, sa, 0, (struct sockaddr *)sa6_src,
1386 0, cmd, notify);
1387 }
1388 #endif /* INET6 */
1389
1390
1391 /*
1392 * Following is where TCP initial sequence number generation occurs.
1393 *
1394 * There are two places where we must use initial sequence numbers:
1395 * 1. In SYN-ACK packets.
1396 * 2. In SYN packets.
1397 *
1398 * The ISNs in SYN-ACK packets have no monotonicity requirement,
1399 * and should be as unpredictable as possible to avoid the possibility
1400 * of spoofing and/or connection hijacking. To satisfy this
1401 * requirement, SYN-ACK ISNs are generated via the arc4random()
1402 * function. If exact RFC 1948 compliance is requested via sysctl,
1403 * these ISNs will be generated just like those in SYN packets.
1404 *
1405 * The ISNs in SYN packets must be monotonic; TIME_WAIT recycling
1406 * depends on this property. In addition, these ISNs should be
1407 * unguessable so as to prevent connection hijacking. To satisfy
1408 * the requirements of this situation, the algorithm outlined in
1409 * RFC 1948 is used to generate sequence numbers.
1410 *
1411 * For more information on the theory of operation, please see
1412 * RFC 1948.
1413 *
1414 * Implementation details:
1415 *
1416 * Time is based off the system timer, and is corrected so that it
1417 * increases by one megabyte per second. This allows for proper
1418 * recycling on high speed LANs while still leaving over an hour
1419 * before rollover.
1420 *
1421 * Two sysctls control the generation of ISNs:
1422 *
1423 * net.inet.tcp.isn_reseed_interval controls the number of seconds
1424 * between seeding of isn_secret. This is normally set to zero,
1425 * as reseeding should not be necessary.
1426 *
1427 * net.inet.tcp.strict_rfc1948 controls whether RFC 1948 is followed
1428 * strictly. When strict compliance is requested, reseeding is
1429 * disabled and SYN-ACKs will be generated in the same manner as
1430 * SYNs. Strict mode is disabled by default.
1431 *
1432 */
1433
1434 #define ISN_BYTES_PER_SECOND 1048576
1435
1436 //PWC - md5 routines cause alignment exceptions. Need to figure out why. For now use lame incremental
1437 // isn. how's that for not easily guessable!?
1438
1439 int pwc_bogus;
1440
1441 tcp_seq
1442 tcp_new_isn(tp)
1443 struct tcpcb *tp;
1444 {
1445 u_int32_t md5_buffer[4];
1446 tcp_seq new_isn;
1447 struct timeval timenow;
1448 u_char isn_secret[32];
1449 int isn_last_reseed = 0;
1450 MD5_CTX isn_ctx;
1451
1452 /* Use arc4random for SYN-ACKs when not in exact RFC1948 mode. */
1453 if (((tp->t_state == TCPS_LISTEN) || (tp->t_state == TCPS_TIME_WAIT))
1454 && tcp_strict_rfc1948 == 0)
1455 #ifdef __APPLE__
1456 return random();
1457 #else
1458 return arc4random();
1459 #endif
1460 getmicrotime(&timenow);
1461
1462 /* Seed if this is the first use, reseed if requested. */
1463 if ((isn_last_reseed == 0) ||
1464 ((tcp_strict_rfc1948 == 0) && (tcp_isn_reseed_interval > 0) &&
1465 (((u_int)isn_last_reseed + (u_int)tcp_isn_reseed_interval*hz)
1466 < (u_int)timenow.tv_sec))) {
1467 #ifdef __APPLE__
1468 read_random(&isn_secret, sizeof(isn_secret));
1469 #else
1470 read_random_unlimited(&isn_secret, sizeof(isn_secret));
1471 #endif
1472 isn_last_reseed = timenow.tv_sec;
1473 }
1474
1475 /* Compute the md5 hash and return the ISN. */
1476 MD5Init(&isn_ctx);
1477 MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
1478 MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
1479 #if INET6
1480 if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) {
1481 MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
1482 sizeof(struct in6_addr));
1483 MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
1484 sizeof(struct in6_addr));
1485 } else
1486 #endif
1487 {
1488 MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
1489 sizeof(struct in_addr));
1490 MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
1491 sizeof(struct in_addr));
1492 }
1493 MD5Update(&isn_ctx, (u_char *) &isn_secret, sizeof(isn_secret));
1494 MD5Final((u_char *) &md5_buffer, &isn_ctx);
1495 new_isn = (tcp_seq) md5_buffer[0];
1496 new_isn += timenow.tv_sec * (ISN_BYTES_PER_SECOND / hz);
1497 return new_isn;
1498 }
1499
1500 /*
1501 * When a source quench is received, close congestion window
1502 * to one segment. We will gradually open it again as we proceed.
1503 */
1504 void
1505 tcp_quench(
1506 struct inpcb *inp,
1507 __unused int errno
1508 )
1509 {
1510 struct tcpcb *tp = intotcpcb(inp);
1511
1512 if (tp) {
1513 tp->snd_cwnd = tp->t_maxseg;
1514 tp->t_bytes_acked = 0;
1515 }
1516 }
1517
1518 /*
1519 * When a specific ICMP unreachable message is received and the
1520 * connection state is SYN-SENT, drop the connection. This behavior
1521 * is controlled by the icmp_may_rst sysctl.
1522 */
1523 void
1524 tcp_drop_syn_sent(inp, errno)
1525 struct inpcb *inp;
1526 int errno;
1527 {
1528 struct tcpcb *tp = intotcpcb(inp);
1529
1530 if (tp && tp->t_state == TCPS_SYN_SENT)
1531 tcp_drop(tp, errno);
1532 }
1533
1534 /*
1535 * When `need fragmentation' ICMP is received, update our idea of the MSS
1536 * based on the new value in the route. Also nudge TCP to send something,
1537 * since we know the packet we just sent was dropped.
1538 * This duplicates some code in the tcp_mss() function in tcp_input.c.
1539 */
1540 void
1541 tcp_mtudisc(
1542 struct inpcb *inp,
1543 __unused int errno
1544 )
1545 {
1546 struct tcpcb *tp = intotcpcb(inp);
1547 struct rtentry *rt;
1548 struct rmxp_tao *taop;
1549 struct socket *so = inp->inp_socket;
1550 int offered;
1551 int mss;
1552 #if INET6
1553 int isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
1554 #endif /* INET6 */
1555
1556 if (tp) {
1557 lck_mtx_lock(rt_mtx);
1558 #if INET6
1559 if (isipv6)
1560 rt = tcp_rtlookup6(inp);
1561 else
1562 #endif /* INET6 */
1563 rt = tcp_rtlookup(inp);
1564 if (!rt || !rt->rt_rmx.rmx_mtu) {
1565 tp->t_maxopd = tp->t_maxseg =
1566 #if INET6
1567 isipv6 ? tcp_v6mssdflt :
1568 #endif /* INET6 */
1569 tcp_mssdflt;
1570 lck_mtx_unlock(rt_mtx);
1571 return;
1572 }
1573 taop = rmx_taop(rt->rt_rmx);
1574 offered = taop->tao_mssopt;
1575 mss = rt->rt_rmx.rmx_mtu -
1576 #if INET6
1577 (isipv6 ?
1578 sizeof(struct ip6_hdr) + sizeof(struct tcphdr) :
1579 #endif /* INET6 */
1580 sizeof(struct tcpiphdr)
1581 #if INET6
1582 )
1583 #endif /* INET6 */
1584 ;
1585
1586 lck_mtx_unlock(rt_mtx);
1587 if (offered)
1588 mss = min(mss, offered);
1589 /*
1590 * XXX - The above conditional probably violates the TCP
1591 * spec. The problem is that, since we don't know the
1592 * other end's MSS, we are supposed to use a conservative
1593 * default. But, if we do that, then MTU discovery will
1594 * never actually take place, because the conservative
1595 * default is much less than the MTUs typically seen
1596 * on the Internet today. For the moment, we'll sweep
1597 * this under the carpet.
1598 *
1599 * The conservative default might not actually be a problem
1600 * if the only case this occurs is when sending an initial
1601 * SYN with options and data to a host we've never talked
1602 * to before. Then, they will reply with an MSS value which
1603 * will get recorded and the new parameters should get
1604 * recomputed. For Further Study.
1605 */
1606 if (tp->t_maxopd <= mss)
1607 return;
1608 tp->t_maxopd = mss;
1609
1610 if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
1611 (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
1612 mss -= TCPOLEN_TSTAMP_APPA;
1613
1614 if (so->so_snd.sb_hiwat < mss)
1615 mss = so->so_snd.sb_hiwat;
1616
1617 tp->t_maxseg = mss;
1618
1619 tcpstat.tcps_mturesent++;
1620 tp->t_rtttime = 0;
1621 tp->snd_nxt = tp->snd_una;
1622 tcp_output(tp);
1623 }
1624 }
1625
1626 /*
1627 * Look-up the routing entry to the peer of this inpcb. If no route
1628 * is found and it cannot be allocated the return NULL. This routine
1629 * is called by TCP routines that access the rmx structure and by tcp_mss
1630 * to get the interface MTU.
1631 */
1632 struct rtentry *
1633 tcp_rtlookup(inp)
1634 struct inpcb *inp;
1635 {
1636 struct route *ro;
1637 struct rtentry *rt;
1638 struct tcpcb *tp;
1639
1640 ro = &inp->inp_route;
1641 if (ro == NULL)
1642 return (NULL);
1643 rt = ro->ro_rt;
1644
1645 lck_mtx_assert(rt_mtx, LCK_MTX_ASSERT_OWNED);
1646
1647 if (rt == NULL || !(rt->rt_flags & RTF_UP) || rt->generation_id != route_generation) {
1648 /* No route yet, so try to acquire one */
1649 if (inp->inp_faddr.s_addr != INADDR_ANY) {
1650 ro->ro_dst.sa_family = AF_INET;
1651 ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
1652 ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
1653 inp->inp_faddr;
1654 rtalloc_ign_locked(ro, 0UL);
1655 rt = ro->ro_rt;
1656 }
1657 }
1658 if (rt != NULL && rt->rt_ifp != NULL)
1659 somultipages(inp->inp_socket,
1660 (rt->rt_ifp->if_hwassist & IFNET_MULTIPAGES));
1661
1662 /*
1663 * Update MTU discovery determination. Don't do it if:
1664 * 1) it is disabled via the sysctl
1665 * 2) the route isn't up
1666 * 3) the MTU is locked (if it is, then discovery has been
1667 * disabled)
1668 */
1669
1670 tp = intotcpcb(inp);
1671
1672 if (!path_mtu_discovery || ((rt != NULL) &&
1673 (!(rt->rt_flags & RTF_UP) || (rt->rt_rmx.rmx_locks & RTV_MTU))))
1674 tp->t_flags &= ~TF_PMTUD;
1675 else
1676 tp->t_flags |= TF_PMTUD;
1677
1678 return rt;
1679 }
1680
1681 #if INET6
1682 struct rtentry *
1683 tcp_rtlookup6(inp)
1684 struct inpcb *inp;
1685 {
1686 struct route_in6 *ro6;
1687 struct rtentry *rt;
1688 struct tcpcb *tp;
1689
1690 lck_mtx_assert(rt_mtx, LCK_MTX_ASSERT_OWNED);
1691
1692 ro6 = &inp->in6p_route;
1693 rt = ro6->ro_rt;
1694 if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
1695 /* No route yet, so try to acquire one */
1696 if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
1697 struct sockaddr_in6 *dst6;
1698
1699 dst6 = (struct sockaddr_in6 *)&ro6->ro_dst;
1700 dst6->sin6_family = AF_INET6;
1701 dst6->sin6_len = sizeof(*dst6);
1702 dst6->sin6_addr = inp->in6p_faddr;
1703 rtalloc_ign_locked((struct route *)ro6, 0UL);
1704 rt = ro6->ro_rt;
1705 }
1706 }
1707 if (rt != NULL && rt->rt_ifp != NULL)
1708 somultipages(inp->inp_socket,
1709 (rt->rt_ifp->if_hwassist & IFNET_MULTIPAGES));
1710 /*
1711 * Update path MTU Discovery determination
1712 * while looking up the route:
1713 * 1) we have a valid route to the destination
1714 * 2) the MTU is not locked (if it is, then discovery has been
1715 * disabled)
1716 */
1717
1718
1719 tp = intotcpcb(inp);
1720
1721 /*
1722 * Update MTU discovery determination. Don't do it if:
1723 * 1) it is disabled via the sysctl
1724 * 2) the route isn't up
1725 * 3) the MTU is locked (if it is, then discovery has been
1726 * disabled)
1727 */
1728
1729 if (!path_mtu_discovery || ((rt != NULL) &&
1730 (!(rt->rt_flags & RTF_UP) || (rt->rt_rmx.rmx_locks & RTV_MTU))))
1731 tp->t_flags &= ~TF_PMTUD;
1732 else
1733 tp->t_flags |= TF_PMTUD;
1734
1735 return rt;
1736 }
1737 #endif /* INET6 */
1738
1739 #if IPSEC
1740 /* compute ESP/AH header size for TCP, including outer IP header. */
1741 size_t
1742 ipsec_hdrsiz_tcp(tp)
1743 struct tcpcb *tp;
1744 {
1745 struct inpcb *inp;
1746 struct mbuf *m;
1747 size_t hdrsiz;
1748 struct ip *ip;
1749 #if INET6
1750 struct ip6_hdr *ip6 = NULL;
1751 #endif /* INET6 */
1752 struct tcphdr *th;
1753
1754 if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL))
1755 return 0;
1756 MGETHDR(m, M_DONTWAIT, MT_DATA); /* MAC-OK */
1757 if (!m)
1758 return 0;
1759
1760 #if INET6
1761 if ((inp->inp_vflag & INP_IPV6) != 0) {
1762 ip6 = mtod(m, struct ip6_hdr *);
1763 th = (struct tcphdr *)(ip6 + 1);
1764 m->m_pkthdr.len = m->m_len =
1765 sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
1766 tcp_fillheaders(tp, ip6, th);
1767 hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
1768 } else
1769 #endif /* INET6 */
1770 {
1771 ip = mtod(m, struct ip *);
1772 th = (struct tcphdr *)(ip + 1);
1773 m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr);
1774 tcp_fillheaders(tp, ip, th);
1775 hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
1776 }
1777 m_free(m);
1778 return hdrsiz;
1779 }
1780 #endif /*IPSEC*/
1781
1782 /*
1783 * Return a pointer to the cached information about the remote host.
1784 * The cached information is stored in the protocol specific part of
1785 * the route metrics.
1786 */
1787 struct rmxp_tao *
1788 tcp_gettaocache(inp)
1789 struct inpcb *inp;
1790 {
1791 struct rtentry *rt;
1792 struct rmxp_tao *taop;
1793
1794 lck_mtx_lock(rt_mtx);
1795 #if INET6
1796 if ((inp->inp_vflag & INP_IPV6) != 0)
1797 rt = tcp_rtlookup6(inp);
1798 else
1799 #endif /* INET6 */
1800 rt = tcp_rtlookup(inp);
1801
1802 /* Make sure this is a host route and is up. */
1803 if (rt == NULL ||
1804 (rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST)) {
1805 lck_mtx_unlock(rt_mtx);
1806 return NULL;
1807 }
1808
1809 taop = rmx_taop(rt->rt_rmx);
1810 lck_mtx_unlock(rt_mtx);
1811 return (taop);
1812 }
1813
1814 /*
1815 * Clear all the TAO cache entries, called from tcp_init.
1816 *
1817 * XXX
1818 * This routine is just an empty one, because we assume that the routing
1819 * routing tables are initialized at the same time when TCP, so there is
1820 * nothing in the cache left over.
1821 */
1822 static void
1823 tcp_cleartaocache()
1824 {
1825 }
1826
1827 int
1828 tcp_lock(so, refcount, lr)
1829 struct socket *so;
1830 int refcount;
1831 int lr;
1832 {
1833 int lr_saved;
1834 if (lr == 0)
1835 lr_saved = (unsigned int) __builtin_return_address(0);
1836 else lr_saved = lr;
1837
1838 if (so->so_pcb) {
1839 lck_mtx_lock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
1840 }
1841 else {
1842 panic("tcp_lock: so=%p NO PCB! lr=%x\n", so, lr_saved);
1843 lck_mtx_lock(so->so_proto->pr_domain->dom_mtx);
1844 }
1845
1846 if (so->so_usecount < 0)
1847 panic("tcp_lock: so=%p so_pcb=%p lr=%x ref=%x\n",
1848 so, so->so_pcb, lr_saved, so->so_usecount);
1849
1850 if (refcount)
1851 so->so_usecount++;
1852 so->lock_lr[so->next_lock_lr] = (u_int32_t)lr_saved;
1853 so->next_lock_lr = (so->next_lock_lr+1) % SO_LCKDBG_MAX;
1854 return (0);
1855 }
1856
1857 int
1858 tcp_unlock(so, refcount, lr)
1859 struct socket *so;
1860 int refcount;
1861 int lr;
1862 {
1863 int lr_saved;
1864 if (lr == 0)
1865 lr_saved = (unsigned int) __builtin_return_address(0);
1866 else lr_saved = lr;
1867
1868 #ifdef MORE_TCPLOCK_DEBUG
1869 printf("tcp_unlock: so=%p sopcb=%x lock=%x ref=%x lr=%x\n",
1870 so, so->so_pcb, ((struct inpcb *)so->so_pcb)->inpcb_mtx, so->so_usecount, lr_saved);
1871 #endif
1872 if (refcount)
1873 so->so_usecount--;
1874
1875 if (so->so_usecount < 0)
1876 panic("tcp_unlock: so=%p usecount=%x\n", so, so->so_usecount);
1877 if (so->so_pcb == NULL)
1878 panic("tcp_unlock: so=%p NO PCB usecount=%x lr=%x\n", so, so->so_usecount, lr_saved);
1879 else {
1880 lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
1881 so->unlock_lr[so->next_unlock_lr] = (u_int32_t)lr_saved;
1882 so->next_unlock_lr = (so->next_unlock_lr+1) % SO_LCKDBG_MAX;
1883 lck_mtx_unlock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
1884 }
1885 return (0);
1886 }
1887
1888 lck_mtx_t *
1889 tcp_getlock(
1890 struct socket *so,
1891 __unused int locktype)
1892 {
1893 struct inpcb *inp = sotoinpcb(so);
1894
1895 if (so->so_pcb) {
1896 if (so->so_usecount < 0)
1897 panic("tcp_getlock: so=%p usecount=%x\n", so, so->so_usecount);
1898 return(inp->inpcb_mtx);
1899 }
1900 else {
1901 panic("tcp_getlock: so=%p NULL so_pcb\n", so);
1902 return (so->so_proto->pr_domain->dom_mtx);
1903 }
1904 }
1905 long
1906 tcp_sbspace(struct tcpcb *tp)
1907 {
1908 struct sockbuf *sb = &tp->t_inpcb->inp_socket->so_rcv;
1909 long space, newspace;
1910
1911 space = ((long) lmin((sb->sb_hiwat - sb->sb_cc),
1912 (sb->sb_mbmax - sb->sb_mbcnt)));
1913
1914 #if TRAFFIC_MGT
1915 if (tp->t_inpcb->inp_socket->so_traffic_mgt_flags & TRAFFIC_MGT_SO_BACKGROUND) {
1916 if (tcp_background_io_enabled &&
1917 tp->t_inpcb->inp_socket->so_traffic_mgt_flags & TRAFFIC_MGT_SO_BG_SUPPRESSED) {
1918 tp->t_flags |= TF_RXWIN0SENT;
1919 return 0; /* Triggers TCP window closing by responding there is no space */
1920 }
1921 }
1922 #endif /* TRAFFIC_MGT */
1923
1924 /* Avoid inscreasing window size if the current window
1925 * is already very low, we could be in "persist" mode and
1926 * we could break some apps (see rdar://5409343)
1927 */
1928
1929 if (space < tp->t_maxseg)
1930 return space;
1931
1932 /* Clip window size for slower link */
1933
1934 if (((tp->t_flags & TF_SLOWLINK) != 0) && slowlink_wsize > 0 )
1935 return lmin(space, slowlink_wsize);
1936
1937 /*
1938 * Check for ressources constraints before over-ajusting the amount of space we can
1939 * advertise in the TCP window size updates.
1940 */
1941
1942 if (sbspace_factor && (tp->t_inpcb->inp_pcbinfo->ipi_count < tcp_sockthreshold) &&
1943 (total_mb_cnt / 8) < (mbstat.m_clusters / sbspace_factor)) {
1944 if (space < (long)(sb->sb_maxused - sb->sb_cc)) {/* make sure we don't constrain the window if we have enough ressources */
1945 space = (long) lmax((sb->sb_maxused - sb->sb_cc), tp->rcv_maxbyps);
1946 }
1947 newspace = (long) lmax(((long)sb->sb_maxused - sb->sb_cc), (long)tp->rcv_maxbyps);
1948
1949 if (newspace > space)
1950 space = newspace;
1951 }
1952 return space;
1953 }
1954 /* DSEP Review Done pl-20051213-v02 @3253,@3391,@3400 */