/* This header is used to share core functionality between the
    standalone connection tracking module, and the compatibility layer's use
    of connection tracking. */
-unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
-                            struct sk_buff *skb);
+unsigned int nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state);
 
 int nf_conntrack_init_net(struct net *net);
 void nf_conntrack_cleanup_net(struct net *net);
 
        int (*packet)(struct nf_conn *ct,
                      const struct sk_buff *skb,
                      unsigned int dataoff,
-                     enum ip_conntrack_info ctinfo);
+                     enum ip_conntrack_info ctinfo,
+                     const struct nf_hook_state *state);
 
        /* Called when a new connection for this protocol found;
         * returns TRUE if it's OK.  If so, packet() called next. */
        /* Called when a conntrack entry is destroyed */
        void (*destroy)(struct nf_conn *ct);
 
-       int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
+       int (*error)(struct nf_conn *tmpl, struct sk_buff *skb,
                     unsigned int dataoff,
-                    u_int8_t pf, unsigned int hooknum);
+                    const struct nf_hook_state *state);
 
        /* called by gc worker if table is full */
        bool (*can_early_drop)(const struct nf_conn *ct);
 
 
 /* On success, returns 0, sets skb->_nfct | ctinfo */
 static int
-resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
+resolve_normal_ct(struct nf_conn *tmpl,
                  struct sk_buff *skb,
                  unsigned int dataoff,
-                 u_int16_t l3num,
                  u_int8_t protonum,
-                 const struct nf_conntrack_l4proto *l4proto)
+                 const struct nf_conntrack_l4proto *l4proto,
+                 const struct nf_hook_state *state)
 {
        const struct nf_conntrack_zone *zone;
        struct nf_conntrack_tuple tuple;
        u32 hash;
 
        if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
-                            dataoff, l3num, protonum, net, &tuple, l4proto)) {
+                            dataoff, state->pf, protonum, state->net,
+                            &tuple, l4proto)) {
                pr_debug("Can't get tuple\n");
                return 0;
        }
 
        /* look for tuple match */
        zone = nf_ct_zone_tmpl(tmpl, skb, &tmp);
-       hash = hash_conntrack_raw(&tuple, net);
-       h = __nf_conntrack_find_get(net, zone, &tuple, hash);
+       hash = hash_conntrack_raw(&tuple, state->net);
+       h = __nf_conntrack_find_get(state->net, zone, &tuple, hash);
        if (!h) {
-               h = init_conntrack(net, tmpl, &tuple, l4proto,
+               h = init_conntrack(state->net, tmpl, &tuple, l4proto,
                                   skb, dataoff, hash);
                if (!h)
                        return 0;
 }
 
 unsigned int
-nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
-               struct sk_buff *skb)
+nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
 {
        const struct nf_conntrack_l4proto *l4proto;
-       struct nf_conn *ct, *tmpl;
        enum ip_conntrack_info ctinfo;
+       struct nf_conn *ct, *tmpl;
        u_int8_t protonum;
        int dataoff, ret;
 
                /* Previously seen (loopback or untracked)?  Ignore. */
                if ((tmpl && !nf_ct_is_template(tmpl)) ||
                     ctinfo == IP_CT_UNTRACKED) {
-                       NF_CT_STAT_INC_ATOMIC(net, ignore);
+                       NF_CT_STAT_INC_ATOMIC(state->net, ignore);
                        return NF_ACCEPT;
                }
                skb->_nfct = 0;
        }
 
        /* rcu_read_lock()ed by nf_hook_thresh */
-       dataoff = get_l4proto(skb, skb_network_offset(skb), pf, &protonum);
+       dataoff = get_l4proto(skb, skb_network_offset(skb), state->pf, &protonum);
        if (dataoff <= 0) {
                pr_debug("not prepared to track yet or error occurred\n");
-               NF_CT_STAT_INC_ATOMIC(net, error);
-               NF_CT_STAT_INC_ATOMIC(net, invalid);
+               NF_CT_STAT_INC_ATOMIC(state->net, error);
+               NF_CT_STAT_INC_ATOMIC(state->net, invalid);
                ret = NF_ACCEPT;
                goto out;
        }
 
-       l4proto = __nf_ct_l4proto_find(pf, protonum);
+       l4proto = __nf_ct_l4proto_find(state->pf, protonum);
 
        /* It may be an special packet, error, unclean...
         * inverse of the return code tells to the netfilter
         * core what to do with the packet. */
        if (l4proto->error != NULL) {
-               ret = l4proto->error(net, tmpl, skb, dataoff, pf, hooknum);
+               ret = l4proto->error(tmpl, skb, dataoff, state);
                if (ret <= 0) {
-                       NF_CT_STAT_INC_ATOMIC(net, error);
-                       NF_CT_STAT_INC_ATOMIC(net, invalid);
+                       NF_CT_STAT_INC_ATOMIC(state->net, error);
+                       NF_CT_STAT_INC_ATOMIC(state->net, invalid);
                        ret = -ret;
                        goto out;
                }
                        goto out;
        }
 repeat:
-       ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, l4proto);
+       ret = resolve_normal_ct(tmpl, skb, dataoff,
+                               protonum, l4proto, state);
        if (ret < 0) {
                /* Too stressed to deal. */
-               NF_CT_STAT_INC_ATOMIC(net, drop);
+               NF_CT_STAT_INC_ATOMIC(state->net, drop);
                ret = NF_DROP;
                goto out;
        }
        ct = nf_ct_get(skb, &ctinfo);
        if (!ct) {
                /* Not valid part of a connection */
-               NF_CT_STAT_INC_ATOMIC(net, invalid);
+               NF_CT_STAT_INC_ATOMIC(state->net, invalid);
                ret = NF_ACCEPT;
                goto out;
        }
 
-       ret = l4proto->packet(ct, skb, dataoff, ctinfo);
+       ret = l4proto->packet(ct, skb, dataoff, ctinfo, state);
        if (ret <= 0) {
                /* Invalid: inverse of the return code tells
                 * the netfilter core what to do */
                pr_debug("nf_conntrack_in: Can't track with proto module\n");
                nf_conntrack_put(&ct->ct_general);
                skb->_nfct = 0;
-               NF_CT_STAT_INC_ATOMIC(net, invalid);
+               NF_CT_STAT_INC_ATOMIC(state->net, invalid);
                if (ret == -NF_DROP)
-                       NF_CT_STAT_INC_ATOMIC(net, drop);
+                       NF_CT_STAT_INC_ATOMIC(state->net, drop);
                /* Special case: TCP tracker reports an attempt to reopen a
                 * closed/aborted connection. We have to go back and create a
                 * fresh conntrack.
 
                                      struct sk_buff *skb,
                                      const struct nf_hook_state *state)
 {
-       return nf_conntrack_in(state->net, PF_INET, state->hook, skb);
+       return nf_conntrack_in(skb, state);
 }
 
 static unsigned int ipv4_conntrack_local(void *priv,
                return NF_ACCEPT;
        }
 
-       return nf_conntrack_in(state->net, PF_INET, state->hook, skb);
+       return nf_conntrack_in(skb, state);
 }
 
 /* Connection tracking may drop packets, but never alters them, so
                                      struct sk_buff *skb,
                                      const struct nf_hook_state *state)
 {
-       return nf_conntrack_in(state->net, PF_INET6, state->hook, skb);
+       return nf_conntrack_in(skb, state);
 }
 
 static unsigned int ipv6_conntrack_local(void *priv,
                                         struct sk_buff *skb,
                                         const struct nf_hook_state *state)
 {
-       return nf_conntrack_in(state->net, PF_INET6, state->hook, skb);
+       return nf_conntrack_in(skb, state);
 }
 
 static unsigned int ipv6_helper(void *priv,
 
 }
 
 static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
-                      unsigned int dataoff, enum ip_conntrack_info ctinfo)
+                      unsigned int dataoff, enum ip_conntrack_info ctinfo,
+                      const struct nf_hook_state *state)
 {
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
        struct dccp_hdr _dh, *dh;
        return NF_ACCEPT;
 }
 
-static int dccp_error(struct net *net, struct nf_conn *tmpl,
+static int dccp_error(struct nf_conn *tmpl,
                      struct sk_buff *skb, unsigned int dataoff,
-                     u_int8_t pf, unsigned int hooknum)
+                     const struct nf_hook_state *state)
 {
        struct dccp_hdr _dh, *dh;
        unsigned int dccp_len = skb->len - dataoff;
                }
        }
 
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
-           nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
-                               pf)) {
+       if (state->hook == NF_INET_PRE_ROUTING &&
+           state->net->ct.sysctl_checksum &&
+           nf_checksum_partial(skb, state->hook, dataoff, cscov,
+                               IPPROTO_DCCP, state->pf)) {
                msg = "nf_ct_dccp: bad checksum ";
                goto out_invalid;
        }
        return NF_ACCEPT;
 
 out_invalid:
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_DCCP, "%s", msg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf,
+                              IPPROTO_DCCP, "%s", msg);
        return -NF_ACCEPT;
 }
 
 
 static int generic_packet(struct nf_conn *ct,
                          const struct sk_buff *skb,
                          unsigned int dataoff,
-                         enum ip_conntrack_info ctinfo)
+                         enum ip_conntrack_info ctinfo,
+                         const struct nf_hook_state *state)
 {
        const unsigned int *timeout = nf_ct_timeout_lookup(ct);
 
 
 static int gre_packet(struct nf_conn *ct,
                      const struct sk_buff *skb,
                      unsigned int dataoff,
-                     enum ip_conntrack_info ctinfo)
+                     enum ip_conntrack_info ctinfo,
+                     const struct nf_hook_state *state)
 {
        /* If we've seen traffic both ways, this is a GRE connection.
         * Extend timeout. */
 
 static int icmp_packet(struct nf_conn *ct,
                       const struct sk_buff *skb,
                       unsigned int dataoff,
-                      enum ip_conntrack_info ctinfo)
+                      enum ip_conntrack_info ctinfo,
+                      const struct nf_hook_state *state)
 {
        /* Do not immediately delete the connection after the first
           successful reply to avoid excessive conntrackd traffic
 
 /* Returns conntrack if it dealt with ICMP, and filled in skb fields */
 static int
-icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
-                unsigned int hooknum)
+icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb,
+                  const struct nf_hook_state *state)
 {
        struct nf_conntrack_tuple innertuple, origtuple;
        const struct nf_conntrack_l4proto *innerproto;
        if (!nf_ct_get_tuplepr(skb,
                               skb_network_offset(skb) + ip_hdrlen(skb)
                                                       + sizeof(struct icmphdr),
-                              PF_INET, net, &origtuple)) {
+                              PF_INET, state->net, &origtuple)) {
                pr_debug("icmp_error_message: failed to get tuple\n");
                return -NF_ACCEPT;
        }
 
        ctinfo = IP_CT_RELATED;
 
-       h = nf_conntrack_find_get(net, zone, &innertuple);
+       h = nf_conntrack_find_get(state->net, zone, &innertuple);
        if (!h) {
                pr_debug("icmp_error_message: no match\n");
                return -NF_ACCEPT;
        return NF_ACCEPT;
 }
 
-static void icmp_error_log(const struct sk_buff *skb, struct net *net,
-                          u8 pf, const char *msg)
+static void icmp_error_log(const struct sk_buff *skb,
+                          const struct nf_hook_state *state,
+                          const char *msg)
 {
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMP, "%s", msg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf,
+                              IPPROTO_ICMP, "%s", msg);
 }
 
 /* Small and modified version of icmp_rcv */
 static int
-icmp_error(struct net *net, struct nf_conn *tmpl,
+icmp_error(struct nf_conn *tmpl,
           struct sk_buff *skb, unsigned int dataoff,
-          u8 pf, unsigned int hooknum)
+          const struct nf_hook_state *state)
 {
        const struct icmphdr *icmph;
        struct icmphdr _ih;
        /* Not enough header? */
        icmph = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_ih), &_ih);
        if (icmph == NULL) {
-               icmp_error_log(skb, net, pf, "short packet");
+               icmp_error_log(skb, state, "short packet");
                return -NF_ACCEPT;
        }
 
        /* See ip_conntrack_proto_tcp.c */
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
-           nf_ip_checksum(skb, hooknum, dataoff, 0)) {
-               icmp_error_log(skb, net, pf, "bad hw icmp checksum");
+       if (state->net->ct.sysctl_checksum &&
+           state->hook == NF_INET_PRE_ROUTING &&
+           nf_ip_checksum(skb, state->hook, dataoff, 0)) {
+               icmp_error_log(skb, state, "bad hw icmp checksum");
                return -NF_ACCEPT;
        }
 
         *                discarded.
         */
        if (icmph->type > NR_ICMP_TYPES) {
-               icmp_error_log(skb, net, pf, "invalid icmp type");
+               icmp_error_log(skb, state, "invalid icmp type");
                return -NF_ACCEPT;
        }
 
            icmph->type != ICMP_REDIRECT)
                return NF_ACCEPT;
 
-       return icmp_error_message(net, tmpl, skb, hooknum);
+       return icmp_error_message(tmpl, skb, state);
 }
 
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 
 static int icmpv6_packet(struct nf_conn *ct,
                       const struct sk_buff *skb,
                       unsigned int dataoff,
-                      enum ip_conntrack_info ctinfo)
+                      enum ip_conntrack_info ctinfo,
+                      const struct nf_hook_state *state)
 {
        unsigned int *timeout = nf_ct_timeout_lookup(ct);
 
        return NF_ACCEPT;
 }
 
-static void icmpv6_error_log(const struct sk_buff *skb, struct net *net,
-                            u8 pf, const char *msg)
+static void icmpv6_error_log(const struct sk_buff *skb,
+                            const struct nf_hook_state *state,
+                            const char *msg)
 {
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_ICMPV6, "%s", msg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf,
+                              IPPROTO_ICMPV6, "%s", msg);
 }
 
 static int
-icmpv6_error(struct net *net, struct nf_conn *tmpl,
-            struct sk_buff *skb, unsigned int dataoff,
-            u8 pf, unsigned int hooknum)
+icmpv6_error(struct nf_conn *tmpl,
+            struct sk_buff *skb,
+            unsigned int dataoff,
+            const struct nf_hook_state *state)
 {
        const struct icmp6hdr *icmp6h;
        struct icmp6hdr _ih;
 
        icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
        if (icmp6h == NULL) {
-               icmpv6_error_log(skb, net, pf, "short packet");
+               icmpv6_error_log(skb, state, "short packet");
                return -NF_ACCEPT;
        }
 
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
-           nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
-               icmpv6_error_log(skb, net, pf, "ICMPv6 checksum failed");
+       if (state->hook == NF_INET_PRE_ROUTING &&
+           state->net->ct.sysctl_checksum &&
+           nf_ip6_checksum(skb, state->hook, dataoff, IPPROTO_ICMPV6)) {
+               icmpv6_error_log(skb, state, "ICMPv6 checksum failed");
                return -NF_ACCEPT;
        }
 
        if (icmp6h->icmp6_type >= 128)
                return NF_ACCEPT;
 
-       return icmpv6_error_message(net, tmpl, skb, dataoff);
+       return icmpv6_error_message(state->net, tmpl, skb, dataoff);
 }
 
 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 
 static int sctp_packet(struct nf_conn *ct,
                       const struct sk_buff *skb,
                       unsigned int dataoff,
-                      enum ip_conntrack_info ctinfo)
+                      enum ip_conntrack_info ctinfo,
+                      const struct nf_hook_state *state)
 {
        enum sctp_conntrack new_state, old_state;
        enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
        return true;
 }
 
-static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb,
+static int sctp_error(struct nf_conn *tpl, struct sk_buff *skb,
                      unsigned int dataoff,
-                     u8 pf, unsigned int hooknum)
+                     const struct nf_hook_state *state)
 {
        const struct sctphdr *sh;
        const char *logmsg;
                logmsg = "nf_ct_sctp: short packet ";
                goto out_invalid;
        }
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
+       if (state->hook == NF_INET_PRE_ROUTING &&
+           state->net->ct.sysctl_checksum &&
            skb->ip_summed == CHECKSUM_NONE) {
                if (!skb_make_writable(skb, dataoff + sizeof(struct sctphdr))) {
                        logmsg = "nf_ct_sctp: failed to read header ";
        }
        return NF_ACCEPT;
 out_invalid:
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_SCTP, "%s", logmsg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf, IPPROTO_SCTP, "%s", logmsg);
        return -NF_ACCEPT;
 }
 
 
        [TCPHDR_ACK|TCPHDR_URG]                 = 1,
 };
 
-static void tcp_error_log(const struct sk_buff *skb, struct net *net,
-                         u8 pf, const char *msg)
+static void tcp_error_log(const struct sk_buff *skb,
+                         const struct nf_hook_state *state,
+                         const char *msg)
 {
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_TCP, "%s", msg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf, IPPROTO_TCP, "%s", msg);
 }
 
 /* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
-static int tcp_error(struct net *net, struct nf_conn *tmpl,
+static int tcp_error(struct nf_conn *tmpl,
                     struct sk_buff *skb,
                     unsigned int dataoff,
-                    u_int8_t pf,
-                    unsigned int hooknum)
+                    const struct nf_hook_state *state)
 {
        const struct tcphdr *th;
        struct tcphdr _tcph;
        /* Smaller that minimal TCP header? */
        th = skb_header_pointer(skb, dataoff, sizeof(_tcph), &_tcph);
        if (th == NULL) {
-               tcp_error_log(skb, net, pf, "short packet");
+               tcp_error_log(skb, state, "short packet");
                return -NF_ACCEPT;
        }
 
        /* Not whole TCP header or malformed packet */
        if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
-               tcp_error_log(skb, net, pf, "truncated packet");
+               tcp_error_log(skb, state, "truncated packet");
                return -NF_ACCEPT;
        }
 
         * because the checksum is assumed to be correct.
         */
        /* FIXME: Source route IP option packets --RR */
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
-           nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
-               tcp_error_log(skb, net, pf, "bad checksum");
+       if (state->net->ct.sysctl_checksum &&
+           state->hook == NF_INET_PRE_ROUTING &&
+           nf_checksum(skb, state->hook, dataoff, IPPROTO_TCP, state->pf)) {
+               tcp_error_log(skb, state, "bad checksum");
                return -NF_ACCEPT;
        }
 
        /* Check TCP flags. */
        tcpflags = (tcp_flag_byte(th) & ~(TCPHDR_ECE|TCPHDR_CWR|TCPHDR_PSH));
        if (!tcp_valid_flags[tcpflags]) {
-               tcp_error_log(skb, net, pf, "invalid tcp flag combination");
+               tcp_error_log(skb, state, "invalid tcp flag combination");
                return -NF_ACCEPT;
        }
 
 static int tcp_packet(struct nf_conn *ct,
                      const struct sk_buff *skb,
                      unsigned int dataoff,
-                     enum ip_conntrack_info ctinfo)
+                     enum ip_conntrack_info ctinfo,
+                     const struct nf_hook_state *state)
 {
        struct net *net = nf_ct_net(ct);
        struct nf_tcp_net *tn = tcp_pernet(net);
 
 static int udp_packet(struct nf_conn *ct,
                      const struct sk_buff *skb,
                      unsigned int dataoff,
-                     enum ip_conntrack_info ctinfo)
+                     enum ip_conntrack_info ctinfo,
+                     const struct nf_hook_state *state)
 {
        unsigned int *timeouts;
 
 }
 
 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
-static void udplite_error_log(const struct sk_buff *skb, struct net *net,
-                             u8 pf, const char *msg)
+static void udplite_error_log(const struct sk_buff *skb,
+                             const struct nf_hook_state *state,
+                             const char *msg)
 {
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDPLITE, "%s", msg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf,
+                              IPPROTO_UDPLITE, "%s", msg);
 }
 
-static int udplite_error(struct net *net, struct nf_conn *tmpl,
-                        struct sk_buff *skb,
+static int udplite_error(struct nf_conn *tmpl, struct sk_buff *skb,
                         unsigned int dataoff,
-                        u8 pf, unsigned int hooknum)
+                        const struct nf_hook_state *state)
 {
        unsigned int udplen = skb->len - dataoff;
        const struct udphdr *hdr;
        /* Header is too small? */
        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
        if (!hdr) {
-               udplite_error_log(skb, net, pf, "short packet");
+               udplite_error_log(skb, state, "short packet");
                return -NF_ACCEPT;
        }
 
        if (cscov == 0) {
                cscov = udplen;
        } else if (cscov < sizeof(*hdr) || cscov > udplen) {
-               udplite_error_log(skb, net, pf, "invalid checksum coverage");
+               udplite_error_log(skb, state, "invalid checksum coverage");
                return -NF_ACCEPT;
        }
 
        /* UDPLITE mandates checksums */
        if (!hdr->check) {
-               udplite_error_log(skb, net, pf, "checksum missing");
+               udplite_error_log(skb, state, "checksum missing");
                return -NF_ACCEPT;
        }
 
        /* Checksum invalid? Ignore. */
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
-           nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_UDP,
-                               pf)) {
-               udplite_error_log(skb, net, pf, "bad checksum");
+       if (state->hook == NF_INET_PRE_ROUTING &&
+           state->net->ct.sysctl_checksum &&
+           nf_checksum_partial(skb, state->hook, dataoff, cscov, IPPROTO_UDP,
+                               state->pf)) {
+               udplite_error_log(skb, state, "bad checksum");
                return -NF_ACCEPT;
        }
 
 }
 #endif
 
-static void udp_error_log(const struct sk_buff *skb, struct net *net,
-                         u8 pf, const char *msg)
+static void udp_error_log(const struct sk_buff *skb,
+                         const struct nf_hook_state *state,
+                         const char *msg)
 {
-       nf_l4proto_log_invalid(skb, net, pf, IPPROTO_UDP, "%s", msg);
+       nf_l4proto_log_invalid(skb, state->net, state->pf,
+                              IPPROTO_UDP, "%s", msg);
 }
 
-static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
+static int udp_error(struct nf_conn *tmpl, struct sk_buff *skb,
                     unsigned int dataoff,
-                    u_int8_t pf,
-                    unsigned int hooknum)
+                    const struct nf_hook_state *state)
 {
        unsigned int udplen = skb->len - dataoff;
        const struct udphdr *hdr;
        /* Header is too small? */
        hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
        if (hdr == NULL) {
-               udp_error_log(skb, net, pf, "short packet");
+               udp_error_log(skb, state, "short packet");
                return -NF_ACCEPT;
        }
 
        /* Truncated/malformed packets */
        if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
-               udp_error_log(skb, net, pf, "truncated/malformed packet");
+               udp_error_log(skb, state, "truncated/malformed packet");
                return -NF_ACCEPT;
        }
 
         * We skip checking packets on the outgoing path
         * because the checksum is assumed to be correct.
         * FIXME: Source route IP option packets --RR */
-       if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
-           nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
-               udp_error_log(skb, net, pf, "bad checksum");
+       if (state->net->ct.sysctl_checksum && state->hook == NF_INET_PRE_ROUTING &&
+           nf_checksum(skb, state->hook, dataoff, IPPROTO_UDP, state->pf)) {
+               udp_error_log(skb, state, "bad checksum");
                return -NF_ACCEPT;
        }
 
 
        struct nf_conn *ct;
 
        if (!cached) {
+               struct nf_hook_state state = {
+                       .hook = NF_INET_PRE_ROUTING,
+                       .pf = info->family,
+                       .net = net,
+               };
                struct nf_conn *tmpl = info->ct;
                int err;
 
                        nf_ct_set(skb, tmpl, IP_CT_NEW);
                }
 
-               err = nf_conntrack_in(net, info->family,
-                                     NF_INET_PRE_ROUTING, skb);
+               err = nf_conntrack_in(skb, &state);
                if (err != NF_ACCEPT)
                        return -ENOENT;