+#if 1
+ lck_mtx_assert(((struct inpcb *)so->so_pcb)->inpcb_mtx, LCK_MTX_ASSERT_OWNED);
+#endif
+ /*
+ * Radar 3529618
+ * This is the second part of the MSS DoS prevention code (after
+ * minmss on the sending side) and it deals with too many too small
+ * tcp packets in a too short timeframe (1 second).
+ *
+ * For every full second we count the number of received packets
+ * and bytes. If we get a lot of packets per second for this connection
+ * (tcp_minmssoverload) we take a closer look at it and compute the
+ * average packet size for the past second. If that is less than
+ * tcp_minmss we get too many packets with very small payload which
+ * is not good and burdens our system (and every packet generates
+ * a wakeup to the process connected to our socket). We can reasonable
+ * expect this to be small packet DoS attack to exhaust our CPU
+ * cycles.
+ *
+ * Care has to be taken for the minimum packet overload value. This
+ * value defines the minimum number of packets per second before we
+ * start to worry. This must not be too low to avoid killing for
+ * example interactive connections with many small packets like
+ * telnet or SSH.
+ *
+ * Setting either tcp_minmssoverload or tcp_minmss to "0" disables
+ * this check.
+ *
+ * Account for packet if payload packet, skip over ACK, etc.
+ *
+ * The packet per second count is done all the time and is also used
+ * by "DELAY_ACK" to detect streaming situations.
+ *
+ */
+ if (tp->t_state == TCPS_ESTABLISHED && tlen > 0) {
+ if (tp->rcv_reset > tcp_now) {
+ tp->rcv_pps++;
+ tp->rcv_byps += tlen + off;
+ if (tp->rcv_byps > tp->rcv_maxbyps)
+ tp->rcv_maxbyps = tp->rcv_byps;
+ /*
+ * Setting either tcp_minmssoverload or tcp_minmss to "0" disables
+ * the check.
+ */
+ if (tcp_minmss && tcp_minmssoverload && tp->rcv_pps > tcp_minmssoverload) {
+ if ((tp->rcv_byps / tp->rcv_pps) < tcp_minmss) {
+ char ipstrbuf[MAX_IPv6_STR_LEN];
+ printf("too many small tcp packets from "
+ "%s:%u, av. %lubyte/packet, "
+ "dropping connection\n",
+#if INET6
+ isipv6 ?
+ inet_ntop(AF_INET6, &inp->in6p_faddr, ipstrbuf,
+ sizeof(ipstrbuf)) :
+#endif
+ inet_ntop(AF_INET, &inp->inp_faddr, ipstrbuf,
+ sizeof(ipstrbuf)),
+ inp->inp_fport,
+ tp->rcv_byps / tp->rcv_pps);
+ tp = tcp_drop(tp, ECONNRESET);
+/* tcpstat.tcps_minmssdrops++; */
+ goto drop;
+ }
+ }
+ } else {
+ tp->rcv_reset = tcp_now + TCP_RETRANSHZ;
+ tp->rcv_pps = 1;
+ tp->rcv_byps = tlen + off;
+ }
+ }
+
+#if TRAFFIC_MGT
+ if (so->so_traffic_mgt_flags & TRAFFIC_MGT_SO_BACKGROUND) {
+ tcpstat.tcps_bg_rcvtotal++;
+
+ /* Take snapshots of pkts recv;
+ * tcpcb should have been initialized to 0 when allocated,
+ * so if 0 then this is the first time we're doing this
+ */
+ if (!tp->tot_recv_snapshot) {
+ tp->tot_recv_snapshot = tcpstat.tcps_rcvtotal;
+ }
+ if (!tp->bg_recv_snapshot) {
+ tp->bg_recv_snapshot = tcpstat.tcps_bg_rcvtotal;
+ }
+ }
+#endif /* TRAFFIC_MGT */
+
+ /*
+ Explicit Congestion Notification - Flag that we need to send ECT if
+ + The IP Congestion experienced flag was set.
+ + Socket is in established state
+ + We negotiated ECN in the TCP setup
+ + This isn't a pure ack (tlen > 0)
+ + The data is in the valid window
+
+ TE_SENDECE will be cleared when we receive a packet with TH_CWR set.
+ */
+ if (ip_ecn == IPTOS_ECN_CE && tp->t_state == TCPS_ESTABLISHED &&
+ (tp->ecn_flags & (TE_SETUPSENT | TE_SETUPRECEIVED)) ==
+ (TE_SETUPSENT | TE_SETUPRECEIVED) && tlen > 0 &&
+ SEQ_GEQ(th->th_seq, tp->last_ack_sent) &&
+ SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) {
+ tp->ecn_flags |= TE_SENDECE;
+ }
+
+ /*
+ Clear TE_SENDECE if TH_CWR is set. This is harmless, so we don't
+ bother doing extensive checks for state and whatnot.
+ */
+ if ((thflags & TH_CWR) == TH_CWR) {
+ tp->ecn_flags &= ~TE_SENDECE;
+ }
+