return err;
 }
 
+/* Accept RST for rcv_nxt - 1 after a FIN.
+ * When tcp connections are abruptly terminated from Mac OSX (via ^C), a
+ * FIN is sent followed by a RST packet. The RST is sent with the same
+ * sequence number as the FIN, and thus according to RFC 5961 a challenge
+ * ACK should be sent. However, Mac OSX rate limits replies to challenge
+ * ACKs on the closed socket. In addition middleboxes can drop either the
+ * challenge ACK or a subsequent RST.
+ */
+static bool tcp_reset_check(const struct sock *sk, const struct sk_buff *skb)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+
+       return unlikely(TCP_SKB_CB(skb)->seq == (tp->rcv_nxt - 1) &&
+                       (1 << sk->sk_state) & (TCPF_CLOSE_WAIT | TCPF_LAST_ACK |
+                                              TCPF_CLOSING));
+}
+
 /* Does PAWS and seqno based validation of an incoming segment, flags will
  * play significant role here.
  */
                                                  LINUX_MIB_TCPACKSKIPPEDSEQ,
                                                  &tp->last_oow_ack_time))
                                tcp_send_dupack(sk, skb);
+               } else if (tcp_reset_check(sk, skb)) {
+                       tcp_reset(sk);
                }
                goto discard;
        }
 
        /* Step 2: check RST bit */
        if (th->rst) {
-               /* RFC 5961 3.2 (extend to match against SACK too if available):
-                * If seq num matches RCV.NXT or the right-most SACK block,
+               /* RFC 5961 3.2 (extend to match against (RCV.NXT - 1) after a
+                * FIN and SACK too if available):
+                * If seq num matches RCV.NXT or (RCV.NXT - 1) after a FIN, or
+                * the right-most SACK block,
                 * then
                 *     RESET the connection
                 * else
                 *     Send a challenge ACK
                 */
-               if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
+               if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt ||
+                   tcp_reset_check(sk, skb)) {
                        rst_seq_match = true;
                } else if (tcp_is_sack(tp) && tp->rx_opt.num_sacks > 0) {
                        struct tcp_sack_block *sp = &tp->selective_acks[0];