X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..e5568f75972dfc723778653c11cb6b4dc825716a:/bsd/netinet/tcp_subr.c diff --git a/bsd/netinet/tcp_subr.c b/bsd/netinet/tcp_subr.c index cee36d93b..cb7bda653 100644 --- a/bsd/netinet/tcp_subr.c +++ b/bsd/netinet/tcp_subr.c @@ -3,22 +3,19 @@ * * @APPLE_LICENSE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -140,6 +137,18 @@ SYSCTL_INT(_net_inet_tcp, TCPCTL_V6MSSDFLT, v6mssdflt, "Default TCP Maximum Segment Size for IPv6"); #endif +/* + * Minimum MSS we accept and use. This prevents DoS attacks where + * we are forced to a ridiculous low MSS like 20 and send hundreds + * of packets instead of one. The effect scales with the available + * bandwidth and quickly saturates the CPU and network interface + * with packet generation and sending. Set to zero to disable MINMSS + * checking. This setting prevents us from sending too small packets. + */ +int tcp_minmss = TCP_MINMSS; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, minmss, CTLFLAG_RW, + &tcp_minmss , 0, "Minmum TCP Maximum Segment Size"); + static int tcp_do_rfc1323 = 1; SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_RW, &tcp_do_rfc1323 , 0, "Enable rfc1323 (high performance TCP) extensions"); @@ -214,6 +223,7 @@ static struct tcpcb dummy_tcb; extern struct inpcbhead time_wait_slots[]; extern int cur_tw_slot; extern u_long *delack_bitmask; +extern u_long route_generation; int get_inpcb_str_size() @@ -274,6 +284,13 @@ tcp_init() tcbinfo.ipi_zone = zinit("tcpcb", sizeof(struct inp_tp), maxsockets, ZONE_INTERRUPT, 0); #endif + + tcp_reass_maxseg = nmbclusters / 16; +#ifndef __APPLE__ + TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments", + &tcp_reass_maxseg); +#endif + #if INET6 #define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) #else /* INET6 */ @@ -692,6 +709,9 @@ tcp_close(tp) register struct rtentry *rt; int dosavessthresh; + if ( inp->inp_ppcb == NULL) /* tcp_close was called previously, bail */ + return; + #ifndef __APPLE__ /* * Make sure that all of our timers are stopped before we @@ -702,7 +722,16 @@ tcp_close(tp) callout_stop(tp->tt_keep); callout_stop(tp->tt_2msl); callout_stop(tp->tt_delack); +#else + /* Clear the timers before we delete the PCB. */ + { + int i; + for (i = 0; i < TCPT_NTIMERS; i++) { + tp->t_timer[i] = 0; + } + } #endif + KERNEL_DEBUG(DBG_FNC_TCP_CLOSE | DBG_FUNC_START, tp,0,0,0,0); switch (tp->t_state) @@ -740,11 +769,16 @@ tcp_close(tp) goto no_valid_rt; } else -#endif /* INET6 */ - if ((rt = inp->inp_route.ro_rt) == NULL || +#endif /* INET6 */ + rt = inp->inp_route.ro_rt; + if (rt == NULL || ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr - == INADDR_ANY) + == INADDR_ANY || rt->generation_id != route_generation) { + if (tp->t_state >= TCPS_CLOSE_WAIT) + tp->t_state = TCPS_CLOSING; + goto no_valid_rt; + } if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) { i = tp->t_srtt * @@ -865,6 +899,7 @@ tcp_freeq(tp) LIST_REMOVE(q, tqe_q); m_freem(q->tqe_m); FREE(q, M_TSEGQ); + tcp_reass_qsize--; rv = 1; } return (rv); @@ -895,6 +930,7 @@ tcp_drain() LIST_REMOVE(te, tqe_q); m_freem(te->tqe_m); FREE(te, M_TSEGQ); + tcp_reass_qsize--; } } } @@ -915,7 +951,12 @@ tcp_notify(inp, error) struct inpcb *inp; int error; { - struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb; + struct tcpcb *tp; + + if (inp == NULL) + return; /* pcb is gone already */ + + tp = (struct tcpcb *)inp->inp_ppcb; /* * Ignore some errors if we are hooked up. @@ -1453,13 +1494,7 @@ tcp_mtudisc(inp, errno) if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC && (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC) mss -= TCPOLEN_CC_APPA; -#if (MCLBYTES & (MCLBYTES - 1)) == 0 - if (mss > MCLBYTES) - mss &= ~(MCLBYTES-1); -#else - if (mss > MCLBYTES) - mss = mss / MCLBYTES * MCLBYTES; -#endif + if (so->so_snd.sb_hiwat < mss) mss = so->so_snd.sb_hiwat; @@ -1489,7 +1524,7 @@ tcp_rtlookup(inp) if (ro == NULL) return (NULL); rt = ro->ro_rt; - if (rt == NULL || !(rt->rt_flags & RTF_UP)) { + if (rt == NULL || !(rt->rt_flags & RTF_UP) || rt->generation_id != route_generation) { /* No route yet, so try to acquire one */ if (inp->inp_faddr.s_addr != INADDR_ANY) { ro->ro_dst.sa_family = AF_INET;