/* protoinfo nlattr size, closes a hole */
        u16 nlattr_size;
 
-       /* Returns verdict for packet, or -1 for invalid. */
-       int (*packet)(struct nf_conn *ct,
-                     struct sk_buff *skb,
-                     unsigned int dataoff,
-                     enum ip_conntrack_info ctinfo,
-                     const struct nf_hook_state *state);
-
        /* Called when a conntrack entry is destroyed */
        void (*destroy)(struct nf_conn *ct);
 
                             unsigned int dataoff,
                             enum ip_conntrack_info ctinfo,
                             const struct nf_hook_state *state);
+int nf_conntrack_gre_packet(struct nf_conn *ct,
+                           struct sk_buff *skb,
+                           unsigned int dataoff,
+                           enum ip_conntrack_info ctinfo,
+                           const struct nf_hook_state *state);
 
 /* Existing built-in generic protocol */
 extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
 
        return ret;
 }
 
+static int generic_packet(struct nf_conn *ct, struct sk_buff *skb,
+                         enum ip_conntrack_info ctinfo)
+{
+       const unsigned int *timeout = nf_ct_timeout_lookup(ct);
+
+       if (!timeout)
+               timeout = &nf_generic_pernet(nf_ct_net(ct))->timeout;
+
+       nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
+       return NF_ACCEPT;
+}
+
 /* Returns verdict for packet, or -1 for invalid. */
 static int nf_conntrack_handle_packet(struct nf_conn *ct,
                                      struct sk_buff *skb,
        case IPPROTO_DCCP:
                return nf_conntrack_dccp_packet(ct, skb, dataoff,
                                                ctinfo, state);
+#endif
+#ifdef CONFIG_NF_CT_PROTO_GRE
+       case IPPROTO_GRE:
+               return nf_conntrack_gre_packet(ct, skb, dataoff,
+                                              ctinfo, state);
 #endif
        }
 
-       WARN_ON_ONCE(1);
-       return -NF_ACCEPT;
+       return generic_packet(ct, skb, ctinfo);
 }
 
 unsigned int
                goto out;
        }
 
-       if (l4proto->packet)
-               ret = l4proto->packet(ct, skb, dataoff, ctinfo, state);
-       else
-               ret = nf_conntrack_handle_packet(ct, skb, dataoff, ctinfo, state);
-
+       ret = nf_conntrack_handle_packet(ct, skb, dataoff, ctinfo, state);
        if (ret <= 0) {
                /* Invalid: inverse of the return code tells
                 * the netfilter core what to do */
 
 
 static const unsigned int nf_ct_generic_timeout = 600*HZ;
 
-static bool nf_generic_should_process(u8 proto)
-{
-       switch (proto) {
-#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
-       case IPPROTO_GRE:
-               return false;
-#endif
-       default:
-               return true;
-       }
-}
-
-/* Returns verdict for packet, or -1 for invalid. */
-static int generic_packet(struct nf_conn *ct,
-                         struct sk_buff *skb,
-                         unsigned int dataoff,
-                         enum ip_conntrack_info ctinfo,
-                         const struct nf_hook_state *state)
-{
-       const unsigned int *timeout = nf_ct_timeout_lookup(ct);
-
-       if (!nf_generic_should_process(nf_ct_protonum(ct))) {
-               pr_warn_once("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n",
-                            nf_ct_protonum(ct));
-               return -NF_ACCEPT;
-       }
-
-       if (!timeout)
-               timeout = &nf_generic_pernet(nf_ct_net(ct))->timeout;
-
-       nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
-       return NF_ACCEPT;
-}
-
 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 
 #include <linux/netfilter/nfnetlink.h>
 const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
 {
        .l4proto                = 255,
-       .packet                 = generic_packet,
 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
        .ctnl_timeout           = {
                .nlattr_to_obj  = generic_timeout_nlattr_to_obj,
 
 }
 
 /* Returns verdict for packet, and may modify conntrack */
-static int gre_packet(struct nf_conn *ct,
-                     struct sk_buff *skb,
-                     unsigned int dataoff,
-                     enum ip_conntrack_info ctinfo,
-                     const struct nf_hook_state *state)
+int nf_conntrack_gre_packet(struct nf_conn *ct,
+                           struct sk_buff *skb,
+                           unsigned int dataoff,
+                           enum ip_conntrack_info ctinfo,
+                           const struct nf_hook_state *state)
 {
        if (state->pf != NFPROTO_IPV4)
                return -NF_ACCEPT;
 #ifdef CONFIG_NF_CONNTRACK_PROCFS
        .print_conntrack = gre_print_conntrack,
 #endif
-       .packet          = gre_packet,
        .destroy         = gre_destroy,
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
        .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,