X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/de355530ae67247cbd0da700edb3a2a1dae884c2..5eebf7385fedb1517b66b53c28e5aa6bb0a2be50:/bsd/netinet/tcp_subr.c diff --git a/bsd/netinet/tcp_subr.c b/bsd/netinet/tcp_subr.c index 30377a449..cb7bda653 100644 --- a/bsd/netinet/tcp_subr.c +++ b/bsd/netinet/tcp_subr.c @@ -137,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"); @@ -211,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() @@ -271,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 */ @@ -689,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 @@ -699,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) @@ -737,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 * @@ -862,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); @@ -892,6 +930,7 @@ tcp_drain() LIST_REMOVE(te, tqe_q); m_freem(te->tqe_m); FREE(te, M_TSEGQ); + tcp_reass_qsize--; } } } @@ -912,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. @@ -1450,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; @@ -1486,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;