"SYN_SENT2",
 };
 
+enum nf_ct_tcp_action {
+       NFCT_TCP_INVALID,
+       NFCT_TCP_ACCEPT,
+};
+
 #define SECS * HZ
 #define MINS * 60 SECS
 #define HOURS * 60 MINS
        }
 }
 
-static bool tcp_in_window(struct nf_conn *ct,
-                         enum ip_conntrack_dir dir,
-                         unsigned int index,
-                         const struct sk_buff *skb,
-                         unsigned int dataoff,
-                         const struct tcphdr *tcph,
-                         const struct nf_hook_state *hook_state)
+__printf(6, 7)
+static enum nf_ct_tcp_action nf_tcp_log_invalid(const struct sk_buff *skb,
+                                               const struct nf_conn *ct,
+                                               const struct nf_hook_state *state,
+                                               const struct ip_ct_tcp_state *sender,
+                                               enum nf_ct_tcp_action ret,
+                                               const char *fmt, ...)
+{
+       const struct nf_tcp_net *tn = nf_tcp_pernet(nf_ct_net(ct));
+       struct va_format vaf;
+       va_list args;
+       bool be_liberal;
+
+       be_liberal = sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL || tn->tcp_be_liberal;
+       if (be_liberal)
+               return NFCT_TCP_ACCEPT;
+
+       va_start(args, fmt);
+       vaf.fmt = fmt;
+       vaf.va = &args;
+       nf_ct_l4proto_log_invalid(skb, ct, state, "%pV", &vaf);
+       va_end(args);
+
+       return ret;
+}
+
+static enum nf_ct_tcp_action
+tcp_in_window(struct nf_conn *ct, enum ip_conntrack_dir dir,
+             unsigned int index, const struct sk_buff *skb,
+             unsigned int dataoff, const struct tcphdr *tcph,
+             const struct nf_hook_state *hook_state)
 {
        struct ip_ct_tcp *state = &ct->proto.tcp;
        struct net *net = nf_ct_net(ct);
        struct ip_ct_tcp_state *sender = &state->seen[dir];
        struct ip_ct_tcp_state *receiver = &state->seen[!dir];
        __u32 seq, ack, sack, end, win, swin;
-       u16 win_raw;
+       bool in_recv_win, seq_ok;
        s32 receiver_offset;
-       bool res, in_recv_win;
+       u16 win_raw;
 
        /*
         * Get the required data from the packet.
                                        end, win);
                        if (!tcph->ack)
                                /* Simultaneous open */
-                               return true;
+                               return NFCT_TCP_ACCEPT;
                } else {
                        /*
                         * We are in the middle of a connection,
                                end, win);
 
                if (dir == IP_CT_DIR_REPLY && !tcph->ack)
-                       return true;
+                       return NFCT_TCP_ACCEPT;
        }
 
        if (!(tcph->ack)) {
                 */
                seq = end = sender->td_end;
 
+       seq_ok = before(seq, sender->td_maxend + 1);
+       if (!seq_ok) {
+               u32 overshot = end - sender->td_maxend + 1;
+               bool ack_ok;
+
+               ack_ok = after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1);
+               in_recv_win = receiver->td_maxwin &&
+                             after(end, sender->td_end - receiver->td_maxwin - 1);
+
+               if (in_recv_win &&
+                   ack_ok &&
+                   overshot <= receiver->td_maxwin &&
+                   before(sack, receiver->td_end + 1)) {
+                       /* Work around TCPs that send more bytes than allowed by
+                        * the receive window.
+                        *
+                        * If the (marked as invalid) packet is allowed to pass by
+                        * the ruleset and the peer acks this data, then its possible
+                        * all future packets will trigger 'ACK is over upper bound' check.
+                        *
+                        * Thus if only the sequence check fails then do update td_end so
+                        * possible ACK for this data can update internal state.
+                        */
+                       sender->td_end = end;
+                       sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
+
+                       nf_ct_l4proto_log_invalid(skb, ct, hook_state,
+                                                 "%u bytes more than expected", overshot);
+                       return NFCT_TCP_ACCEPT;
+               }
+
+               return nf_tcp_log_invalid(skb, ct, hook_state, sender, NFCT_TCP_INVALID,
+                                         "SEQ is over upper bound %u (over the window of the receiver)",
+                                         sender->td_maxend + 1);
+       }
+
+       if (!before(sack, receiver->td_end + 1))
+               return nf_tcp_log_invalid(skb, ct, hook_state, sender, NFCT_TCP_INVALID,
+                                         "ACK is over upper bound %u (ACKed data not seen yet)",
+                                         receiver->td_end + 1);
+
        /* Is the ending sequence in the receive window (if available)? */
        in_recv_win = !receiver->td_maxwin ||
                      after(end, sender->td_end - receiver->td_maxwin - 1);
 
-       if (before(seq, sender->td_maxend + 1) &&
-           in_recv_win &&
-           before(sack, receiver->td_end + 1) &&
+       if (in_recv_win &&
            after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) {
                /*
                 * Take into account window scaling (RFC 1323).
                                state->retrans = 0;
                        }
                }
-               res = true;
        } else {
-               res = false;
                if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
                    tn->tcp_be_liberal)
-                       res = true;
-               if (!res) {
-                       bool seq_ok = before(seq, sender->td_maxend + 1);
-
-                       if (!seq_ok) {
-                               u32 overshot = end - sender->td_maxend + 1;
-                               bool ack_ok;
-
-                               ack_ok = after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1);
-
-                               if (in_recv_win &&
-                                   ack_ok &&
-                                   overshot <= receiver->td_maxwin &&
-                                   before(sack, receiver->td_end + 1)) {
-                                       /* Work around TCPs that send more bytes than allowed by
-                                        * the receive window.
-                                        *
-                                        * If the (marked as invalid) packet is allowed to pass by
-                                        * the ruleset and the peer acks this data, then its possible
-                                        * all future packets will trigger 'ACK is over upper bound' check.
-                                        *
-                                        * Thus if only the sequence check fails then do update td_end so
-                                        * possible ACK for this data can update internal state.
-                                        */
-                                       sender->td_end = end;
-                                       sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
-
-                                       nf_ct_l4proto_log_invalid(skb, ct, hook_state,
-                                                                 "%u bytes more than expected", overshot);
-                                       return res;
-                               }
-                       }
+                       return NFCT_TCP_ACCEPT;
 
+               {
                        nf_ct_l4proto_log_invalid(skb, ct, hook_state,
                        "%s",
                        before(seq, sender->td_maxend + 1) ?
                        : "SEQ is under the lower bound (already ACKed data retransmitted)"
                        : "SEQ is over the upper bound (over the window of the receiver)");
                }
+
+               return NFCT_TCP_INVALID;
        }
 
-       return res;
+       return NFCT_TCP_ACCEPT;
 }
 
 /* table of valid flag combinations - PUSH, ECE and CWR are always valid */