typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,
                               struct sk_buff *skb,
-                              const struct net_device *in,
-                              const struct net_device *out,
-                              int (*okfn)(struct sk_buff *));
+                              const struct nf_hook_state *state);
 
 struct nf_hook_ops {
        struct list_head list;
 
  * to ip6tables, which doesn't support NAT, so things are fairly simple. */
 static unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops,
                                           struct sk_buff *skb,
-                                          const struct net_device *in,
-                                          const struct net_device *out,
-                                          int (*okfn)(struct sk_buff *))
+                                          const struct nf_hook_state *state)
 {
        const struct ipv6hdr *hdr;
        u32 pkt_len;
  * address to be able to detect DNAT afterwards. */
 static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
                                      struct sk_buff *skb,
-                                     const struct net_device *in,
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
+                                     const struct nf_hook_state *state)
 {
        struct net_bridge_port *p;
        struct net_bridge *br;
        if (unlikely(!pskb_may_pull(skb, len)))
                return NF_DROP;
 
-       p = br_port_get_rcu(in);
+       p = br_port_get_rcu(state->in);
        if (p == NULL)
                return NF_DROP;
        br = p->br;
                        return NF_ACCEPT;
 
                nf_bridge_pull_encap_header_rcsum(skb);
-               return br_nf_pre_routing_ipv6(ops, skb, in, out, okfn);
+               return br_nf_pre_routing_ipv6(ops, skb, state);
        }
 
        if (!brnf_call_iptables && !br->nf_call_iptables)
  * prevent this from happening. */
 static unsigned int br_nf_local_in(const struct nf_hook_ops *ops,
                                   struct sk_buff *skb,
-                                  const struct net_device *in,
-                                  const struct net_device *out,
-                                  int (*okfn)(struct sk_buff *))
+                                  const struct nf_hook_state *state)
 {
        br_drop_fake_rtable(skb);
        return NF_ACCEPT;
  * bridge ports. */
 static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
                                     struct sk_buff *skb,
-                                    const struct net_device *in,
-                                    const struct net_device *out,
-                                    int (*okfn)(struct sk_buff *))
+                                    const struct nf_hook_state *state)
 {
        struct nf_bridge_info *nf_bridge;
        struct net_device *parent;
        if (!nf_bridge_unshare(skb))
                return NF_DROP;
 
-       parent = bridge_parent(out);
+       parent = bridge_parent(state->out);
        if (!parent)
                return NF_DROP;
 
        else
                skb->protocol = htons(ETH_P_IPV6);
 
-       NF_HOOK(pf, NF_INET_FORWARD, skb, brnf_get_logical_dev(skb, in), parent,
-               br_nf_forward_finish);
+       NF_HOOK(pf, NF_INET_FORWARD, skb, brnf_get_logical_dev(skb, state->in),
+               parent, br_nf_forward_finish);
 
        return NF_STOLEN;
 }
 
 static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
                                      struct sk_buff *skb,
-                                     const struct net_device *in,
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
+                                     const struct nf_hook_state *state)
 {
        struct net_bridge_port *p;
        struct net_bridge *br;
        struct net_device **d = (struct net_device **)(skb->cb);
 
-       p = br_port_get_rcu(out);
+       p = br_port_get_rcu(state->out);
        if (p == NULL)
                return NF_ACCEPT;
        br = p->br;
                        nf_bridge_push_encap_header(skb);
                return NF_ACCEPT;
        }
-       *d = (struct net_device *)in;
-       NF_HOOK(NFPROTO_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
-               (struct net_device *)out, br_nf_forward_finish);
+       *d = state->in;
+       NF_HOOK(NFPROTO_ARP, NF_ARP_FORWARD, skb, state->in,
+               state->out, br_nf_forward_finish);
 
        return NF_STOLEN;
 }
 /* PF_BRIDGE/POST_ROUTING ********************************************/
 static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
                                       struct sk_buff *skb,
-                                      const struct net_device *in,
-                                      const struct net_device *out,
-                                      int (*okfn)(struct sk_buff *))
+                                      const struct nf_hook_state *state)
 {
        struct nf_bridge_info *nf_bridge = skb->nf_bridge;
        struct net_device *realoutdev = bridge_parent(skb->dev);
  * for the second time. */
 static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops,
                                   struct sk_buff *skb,
-                                  const struct net_device *in,
-                                  const struct net_device *out,
-                                  int (*okfn)(struct sk_buff *))
+                                  const struct nf_hook_state *state)
 {
        if (skb->nf_bridge &&
            !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
 
 
 static unsigned int
 ebt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-           const struct net_device *in, const struct net_device *out,
-           int (*okfn)(struct sk_buff *))
+           const struct nf_hook_state *state)
 {
-       return ebt_do_table(ops->hooknum, skb, in, out,
-                           dev_net(in)->xt.frame_filter);
+       return ebt_do_table(ops->hooknum, skb, state->in, state->out,
+                           dev_net(state->in)->xt.frame_filter);
 }
 
 static unsigned int
 ebt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-            const struct net_device *in, const struct net_device *out,
-            int (*okfn)(struct sk_buff *))
+            const struct nf_hook_state *state)
 {
-       return ebt_do_table(ops->hooknum, skb, in, out,
-                           dev_net(out)->xt.frame_filter);
+       return ebt_do_table(ops->hooknum, skb, state->in, state->out,
+                           dev_net(state->out)->xt.frame_filter);
 }
 
 static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
 
 
 static unsigned int
 ebt_nat_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
-          const struct net_device *in, const struct net_device *out,
-          int (*okfn)(struct sk_buff *))
+          const struct nf_hook_state *state)
 {
-       return ebt_do_table(ops->hooknum, skb, in, out,
-                           dev_net(in)->xt.frame_nat);
+       return ebt_do_table(ops->hooknum, skb, state->in, state->out,
+                           dev_net(state->in)->xt.frame_nat);
 }
 
 static unsigned int
 ebt_nat_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
-           const struct net_device *in, const struct net_device *out,
-           int (*okfn)(struct sk_buff *))
+           const struct nf_hook_state *state)
 {
-       return ebt_do_table(ops->hooknum, skb, in, out,
-                           dev_net(out)->xt.frame_nat);
+       return ebt_do_table(ops->hooknum, skb, state->in, state->out,
+                           dev_net(state->out)->xt.frame_nat);
 }
 
 static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
 
 static unsigned int
 nft_do_chain_bridge(const struct nf_hook_ops *ops,
                    struct sk_buff *skb,
-                   const struct net_device *in,
-                   const struct net_device *out,
-                   int (*okfn)(struct sk_buff *))
+                   const struct nf_hook_state *state)
 {
        struct nft_pktinfo pkt;
 
        switch (eth_hdr(skb)->h_proto) {
        case htons(ETH_P_IP):
-               nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+               nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, state->in, state->out);
                break;
        case htons(ETH_P_IPV6):
-               nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
+               nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, state->in, state->out);
                break;
        default:
-               nft_set_pktinfo(&pkt, ops, skb, in, out);
+               nft_set_pktinfo(&pkt, ops, skb, state->in, state->out);
                break;
        }
 
 
 
 static unsigned int dnrmg_hook(const struct nf_hook_ops *ops,
                        struct sk_buff *skb,
-                       const struct net_device *in,
-                       const struct net_device *out,
-                       int (*okfn)(struct sk_buff *))
+                       const struct nf_hook_state *state)
 {
        dnrmg_send_peer(skb);
        return NF_ACCEPT;
 
 /* The work comes in here from netfilter.c */
 static unsigned int
 arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                    const struct net_device *in, const struct net_device *out,
-                    int (*okfn)(struct sk_buff *))
+                    const struct nf_hook_state *state)
 {
-       const struct net *net = dev_net((in != NULL) ? in : out);
+       const struct net *net = dev_net(state->in ? state->in : state->out);
 
-       return arpt_do_table(skb, ops->hooknum, in, out,
+       return arpt_do_table(skb, ops->hooknum, state->in, state->out,
                             net->ipv4.arptable_filter);
 }
 
 
 static unsigned int
 arp_mangle(const struct nf_hook_ops *ops,
           struct sk_buff *skb,
-          const struct net_device *in,
-          const struct net_device *out,
-          int (*okfn)(struct sk_buff *))
+          const struct nf_hook_state *state)
 {
        struct arphdr *arp = arp_hdr(skb);
        struct arp_payload *payload;
        struct clusterip_config *c;
-       struct net *net = dev_net(in ? in : out);
+       struct net *net = dev_net(state->in ? state->in : state->out);
 
        /* we don't care about non-ethernet and non-ipv4 ARP */
        if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
         * addresses on different interfacs.  However, in the CLUSTERIP case
         * this wouldn't work, since we didn't subscribe the mcast group on
         * other interfaces */
-       if (c->dev != out) {
+       if (c->dev != state->out) {
                pr_debug("not mangling arp reply on different "
                         "interface: cip'%s'-skb'%s'\n",
-                        c->dev->name, out->name);
+                        c->dev->name, state->out->name);
                clusterip_config_put(c);
                return NF_ACCEPT;
        }
 
 
 static unsigned int ipv4_synproxy_hook(const struct nf_hook_ops *ops,
                                       struct sk_buff *skb,
-                                      const struct net_device *in,
-                                      const struct net_device *out,
-                                      int (*okfn)(struct sk_buff *))
+                                      const struct nf_hook_state *nhs)
 {
-       struct synproxy_net *snet = synproxy_pernet(dev_net(in ? : out));
+       struct synproxy_net *snet = synproxy_pernet(dev_net(nhs->in ? : nhs->out));
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct;
        struct nf_conn_synproxy *synproxy;
 
 
 static unsigned int
 iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                   const struct net_device *in, const struct net_device *out,
-                   int (*okfn)(struct sk_buff *))
+                   const struct nf_hook_state *state)
 {
        const struct net *net;
 
                /* root is playing with raw sockets. */
                return NF_ACCEPT;
 
-       net = dev_net((in != NULL) ? in : out);
-       return ipt_do_table(skb, ops->hooknum, in, out,
+       net = dev_net(state->in ? state->in : state->out);
+       return ipt_do_table(skb, ops->hooknum, state->in, state->out,
                            net->ipv4.iptable_filter);
 }
 
 
 static unsigned int
 iptable_mangle_hook(const struct nf_hook_ops *ops,
                     struct sk_buff *skb,
-                    const struct net_device *in,
-                    const struct net_device *out,
-                    int (*okfn)(struct sk_buff *))
+                    const struct nf_hook_state *state)
 {
        if (ops->hooknum == NF_INET_LOCAL_OUT)
-               return ipt_mangle_out(skb, out);
+               return ipt_mangle_out(skb, state->out);
        if (ops->hooknum == NF_INET_POST_ROUTING)
-               return ipt_do_table(skb, ops->hooknum, in, out,
-                                   dev_net(out)->ipv4.iptable_mangle);
+               return ipt_do_table(skb, ops->hooknum, state->in, state->out,
+                                   dev_net(state->out)->ipv4.iptable_mangle);
        /* PREROUTING/INPUT/FORWARD: */
-       return ipt_do_table(skb, ops->hooknum, in, out,
-                           dev_net(in)->ipv4.iptable_mangle);
+       return ipt_do_table(skb, ops->hooknum, state->in, state->out,
+                           dev_net(state->in)->ipv4.iptable_mangle);
 }
 
 static struct nf_hook_ops *mangle_ops __read_mostly;
 
 
 static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_fn(ops, skb, in, out, iptable_nat_do_chain);
+       return nf_nat_ipv4_fn(ops, skb, state->in, state->out,
+                             iptable_nat_do_chain);
 }
 
 static unsigned int iptable_nat_ipv4_in(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_in(ops, skb, in, out, iptable_nat_do_chain);
+       return nf_nat_ipv4_in(ops, skb, state->in, state->out,
+                             iptable_nat_do_chain);
 }
 
 static unsigned int iptable_nat_ipv4_out(const struct nf_hook_ops *ops,
                                         struct sk_buff *skb,
-                                        const struct net_device *in,
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
+                                        const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_out(ops, skb, in, out, iptable_nat_do_chain);
+       return nf_nat_ipv4_out(ops, skb, state->in, state->out,
+                              iptable_nat_do_chain);
 }
 
 static unsigned int iptable_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
                                              struct sk_buff *skb,
-                                             const struct net_device *in,
-                                             const struct net_device *out,
-                                             int (*okfn)(struct sk_buff *))
+                                             const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_local_fn(ops, skb, in, out, iptable_nat_do_chain);
+       return nf_nat_ipv4_local_fn(ops, skb, state->in, state->out,
+                                   iptable_nat_do_chain);
 }
 
 static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
 iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                const struct net_device *in, const struct net_device *out,
-                int (*okfn)(struct sk_buff *))
+                const struct nf_hook_state *state)
 {
        const struct net *net;
 
                /* root is playing with raw sockets. */
                return NF_ACCEPT;
 
-       net = dev_net((in != NULL) ? in : out);
-       return ipt_do_table(skb, ops->hooknum, in, out, net->ipv4.iptable_raw);
+       net = dev_net(state->in ? state->in : state->out);
+       return ipt_do_table(skb, ops->hooknum, state->in, state->out,
+                           net->ipv4.iptable_raw);
 }
 
 static struct nf_hook_ops *rawtable_ops __read_mostly;
 
 
 static unsigned int
 iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                     const struct net_device *in,
-                     const struct net_device *out,
-                     int (*okfn)(struct sk_buff *))
+                     const struct nf_hook_state *state)
 {
        const struct net *net;
 
                /* Somebody is playing with raw sockets. */
                return NF_ACCEPT;
 
-       net = dev_net((in != NULL) ? in : out);
-       return ipt_do_table(skb, ops->hooknum, in, out,
+       net = dev_net(state->in ? state->in : state->out);
+       return ipt_do_table(skb, ops->hooknum, state->in, state->out,
                            net->ipv4.iptable_security);
 }
 
 
 
 static unsigned int ipv4_helper(const struct nf_hook_ops *ops,
                                struct sk_buff *skb,
-                               const struct net_device *in,
-                               const struct net_device *out,
-                               int (*okfn)(struct sk_buff *))
+                               const struct nf_hook_state *state)
 {
        struct nf_conn *ct;
        enum ip_conntrack_info ctinfo;
 
 static unsigned int ipv4_confirm(const struct nf_hook_ops *ops,
                                 struct sk_buff *skb,
-                                const struct net_device *in,
-                                const struct net_device *out,
-                                int (*okfn)(struct sk_buff *))
+                                const struct nf_hook_state *state)
 {
        struct nf_conn *ct;
        enum ip_conntrack_info ctinfo;
 
 static unsigned int ipv4_conntrack_in(const struct nf_hook_ops *ops,
                                      struct sk_buff *skb,
-                                     const struct net_device *in,
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
+                                     const struct nf_hook_state *state)
 {
-       return nf_conntrack_in(dev_net(in), PF_INET, ops->hooknum, skb);
+       return nf_conntrack_in(dev_net(state->in), PF_INET, ops->hooknum, skb);
 }
 
 static unsigned int ipv4_conntrack_local(const struct nf_hook_ops *ops,
                                         struct sk_buff *skb,
-                                        const struct net_device *in,
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
+                                        const struct nf_hook_state *state)
 {
        /* root is playing with raw sockets. */
        if (skb->len < sizeof(struct iphdr) ||
            ip_hdrlen(skb) < sizeof(struct iphdr))
                return NF_ACCEPT;
-       return nf_conntrack_in(dev_net(out), PF_INET, ops->hooknum, skb);
+       return nf_conntrack_in(dev_net(state->out), PF_INET, ops->hooknum, skb);
 }
 
 /* Connection tracking may drop packets, but never alters them, so
 
 
 static unsigned int ipv4_conntrack_defrag(const struct nf_hook_ops *ops,
                                          struct sk_buff *skb,
-                                         const struct net_device *in,
-                                         const struct net_device *out,
-                                         int (*okfn)(struct sk_buff *))
+                                         const struct nf_hook_state *state)
 {
        struct sock *sk = skb->sk;
        struct inet_sock *inet = inet_sk(skb->sk);
 
 static unsigned int
 nft_do_chain_arp(const struct nf_hook_ops *ops,
                  struct sk_buff *skb,
-                 const struct net_device *in,
-                 const struct net_device *out,
-                 int (*okfn)(struct sk_buff *))
+                 const struct nf_hook_state *state)
 {
        struct nft_pktinfo pkt;
 
-       nft_set_pktinfo(&pkt, ops, skb, in, out);
+       nft_set_pktinfo(&pkt, ops, skb, state->in, state->out);
 
        return nft_do_chain(&pkt, ops);
 }
 
 
 static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops,
                                      struct sk_buff *skb,
-                                     const struct net_device *in,
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
+                                     const struct nf_hook_state *state)
 {
        struct nft_pktinfo pkt;
 
-       nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+       nft_set_pktinfo_ipv4(&pkt, ops, skb, state->in, state->out);
 
        return nft_do_chain(&pkt, ops);
 }
 
 static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
        if (unlikely(skb->len < sizeof(struct iphdr) ||
                     ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
                return NF_ACCEPT;
        }
 
-       return nft_do_chain_ipv4(ops, skb, in, out, okfn);
+       return nft_do_chain_ipv4(ops, skb, state);
 }
 
 struct nft_af_info nft_af_ipv4 __read_mostly = {
 
 
 static unsigned int nft_nat_ipv4_fn(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_fn(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv4_fn(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static unsigned int nft_nat_ipv4_in(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_in(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv4_in(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static unsigned int nft_nat_ipv4_out(const struct nf_hook_ops *ops,
                                     struct sk_buff *skb,
-                                    const struct net_device *in,
-                                    const struct net_device *out,
-                                    int (*okfn)(struct sk_buff *))
+                                    const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_out(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv4_out(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static unsigned int nft_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
                                          struct sk_buff *skb,
-                                         const struct net_device *in,
-                                         const struct net_device *out,
-                                         int (*okfn)(struct sk_buff *))
+                                         const struct nf_hook_state *state)
 {
-       return nf_nat_ipv4_local_fn(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv4_local_fn(ops, skb, state->in, state->out,
+                                   nft_nat_do_chain);
 }
 
 static const struct nf_chain_type nft_chain_nat_ipv4 = {
 
 
 static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
        unsigned int ret;
        struct nft_pktinfo pkt;
            ip_hdrlen(skb) < sizeof(struct iphdr))
                return NF_ACCEPT;
 
-       nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+       nft_set_pktinfo_ipv4(&pkt, ops, skb, state->in, state->out);
 
        mark = skb->mark;
        iph = ip_hdr(skb);
 
 
 static unsigned int ipv6_synproxy_hook(const struct nf_hook_ops *ops,
                                       struct sk_buff *skb,
-                                      const struct net_device *in,
-                                      const struct net_device *out,
-                                      int (*okfn)(struct sk_buff *))
+                                      const struct nf_hook_state *nhs)
 {
-       struct synproxy_net *snet = synproxy_pernet(dev_net(in ? : out));
+       struct synproxy_net *snet = synproxy_pernet(dev_net(nhs->in ? : nhs->out));
        enum ip_conntrack_info ctinfo;
        struct nf_conn *ct;
        struct nf_conn_synproxy *synproxy;
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
 ip6table_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                    const struct net_device *in, const struct net_device *out,
-                    int (*okfn)(struct sk_buff *))
+                    const struct nf_hook_state *state)
 {
-       const struct net *net = dev_net((in != NULL) ? in : out);
+       const struct net *net = dev_net(state->in ? state->in : state->out);
 
-       return ip6t_do_table(skb, ops->hooknum, in, out,
+       return ip6t_do_table(skb, ops->hooknum, state->in, state->out,
                             net->ipv6.ip6table_filter);
 }
 
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
 ip6table_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                    const struct net_device *in, const struct net_device *out,
-                    int (*okfn)(struct sk_buff *))
+                    const struct nf_hook_state *state)
 {
        if (ops->hooknum == NF_INET_LOCAL_OUT)
-               return ip6t_mangle_out(skb, out);
+               return ip6t_mangle_out(skb, state->out);
        if (ops->hooknum == NF_INET_POST_ROUTING)
-               return ip6t_do_table(skb, ops->hooknum, in, out,
-                                    dev_net(out)->ipv6.ip6table_mangle);
+               return ip6t_do_table(skb, ops->hooknum, state->in, state->out,
+                                    dev_net(state->out)->ipv6.ip6table_mangle);
        /* INPUT/FORWARD */
-       return ip6t_do_table(skb, ops->hooknum, in, out,
-                            dev_net(in)->ipv6.ip6table_mangle);
+       return ip6t_do_table(skb, ops->hooknum, state->in, state->out,
+                            dev_net(state->in)->ipv6.ip6table_mangle);
 }
 
 static struct nf_hook_ops *mangle_ops __read_mostly;
 
 
 static unsigned int ip6table_nat_fn(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_fn(ops, skb, in, out, ip6table_nat_do_chain);
+       return nf_nat_ipv6_fn(ops, skb, state->in, state->out,
+                             ip6table_nat_do_chain);
 }
 
 static unsigned int ip6table_nat_in(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_in(ops, skb, in, out, ip6table_nat_do_chain);
+       return nf_nat_ipv6_in(ops, skb, state->in, state->out,
+                             ip6table_nat_do_chain);
 }
 
 static unsigned int ip6table_nat_out(const struct nf_hook_ops *ops,
                                     struct sk_buff *skb,
-                                    const struct net_device *in,
-                                    const struct net_device *out,
-                                    int (*okfn)(struct sk_buff *))
+                                    const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_out(ops, skb, in, out, ip6table_nat_do_chain);
+       return nf_nat_ipv6_out(ops, skb, state->in, state->out,
+                              ip6table_nat_do_chain);
 }
 
 static unsigned int ip6table_nat_local_fn(const struct nf_hook_ops *ops,
                                          struct sk_buff *skb,
-                                         const struct net_device *in,
-                                         const struct net_device *out,
-                                         int (*okfn)(struct sk_buff *))
+                                         const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_local_fn(ops, skb, in, out, ip6table_nat_do_chain);
+       return nf_nat_ipv6_local_fn(ops, skb, state->in, state->out,
+                                   ip6table_nat_do_chain);
 }
 
 static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
 
 /* The work comes in here from netfilter.c. */
 static unsigned int
 ip6table_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                 const struct net_device *in, const struct net_device *out,
-                 int (*okfn)(struct sk_buff *))
+                 const struct nf_hook_state *state)
 {
-       const struct net *net = dev_net((in != NULL) ? in : out);
+       const struct net *net = dev_net(state->in ? state->in : state->out);
 
-       return ip6t_do_table(skb, ops->hooknum, in, out,
+       return ip6t_do_table(skb, ops->hooknum, state->in, state->out,
                             net->ipv6.ip6table_raw);
 }
 
 
 
 static unsigned int
 ip6table_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                      const struct net_device *in,
-                      const struct net_device *out,
-                      int (*okfn)(struct sk_buff *))
+                      const struct nf_hook_state *state)
 {
-       const struct net *net = dev_net((in != NULL) ? in : out);
+       const struct net *net = dev_net(state->in ? state->in : state->out);
 
-       return ip6t_do_table(skb, ops->hooknum, in, out,
+       return ip6t_do_table(skb, ops->hooknum, state->in, state->out,
                             net->ipv6.ip6table_security);
 }
 
 
 
 static unsigned int ipv6_helper(const struct nf_hook_ops *ops,
                                struct sk_buff *skb,
-                               const struct net_device *in,
-                               const struct net_device *out,
-                               int (*okfn)(struct sk_buff *))
+                               const struct nf_hook_state *state)
 {
        struct nf_conn *ct;
        const struct nf_conn_help *help;
 
 static unsigned int ipv6_confirm(const struct nf_hook_ops *ops,
                                 struct sk_buff *skb,
-                                const struct net_device *in,
-                                const struct net_device *out,
-                                int (*okfn)(struct sk_buff *))
+                                const struct nf_hook_state *state)
 {
        struct nf_conn *ct;
        enum ip_conntrack_info ctinfo;
 
 static unsigned int ipv6_conntrack_in(const struct nf_hook_ops *ops,
                                      struct sk_buff *skb,
-                                     const struct net_device *in,
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
+                                     const struct nf_hook_state *state)
 {
-       return nf_conntrack_in(dev_net(in), PF_INET6, ops->hooknum, skb);
+       return nf_conntrack_in(dev_net(state->in), PF_INET6, ops->hooknum, skb);
 }
 
 static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops,
                                         struct sk_buff *skb,
-                                        const struct net_device *in,
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
+                                        const struct nf_hook_state *state)
 {
        /* root is playing with raw sockets. */
        if (skb->len < sizeof(struct ipv6hdr)) {
                net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
                return NF_ACCEPT;
        }
-       return nf_conntrack_in(dev_net(out), PF_INET6, ops->hooknum, skb);
+       return nf_conntrack_in(dev_net(state->out), PF_INET6, ops->hooknum, skb);
 }
 
 static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
 
 
 static unsigned int ipv6_defrag(const struct nf_hook_ops *ops,
                                struct sk_buff *skb,
-                               const struct net_device *in,
-                               const struct net_device *out,
-                               int (*okfn)(struct sk_buff *))
+                               const struct nf_hook_state *state)
 {
        struct sk_buff *reasm;
 
        nf_ct_frag6_consume_orig(reasm);
 
        NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, reasm,
-                      (struct net_device *) in, (struct net_device *) out,
-                      okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
+                      state->in, state->out,
+                      state->okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
 
        return NF_STOLEN;
 }
 
 
 static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops,
                                      struct sk_buff *skb,
-                                     const struct net_device *in,
-                                     const struct net_device *out,
-                                     int (*okfn)(struct sk_buff *))
+                                     const struct nf_hook_state *state)
 {
        struct nft_pktinfo pkt;
 
        /* malformed packet, drop it */
-       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
+       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, state->in, state->out) < 0)
                return NF_DROP;
 
        return nft_do_chain(&pkt, ops);
 
 static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
        if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
                if (net_ratelimit())
                return NF_ACCEPT;
        }
 
-       return nft_do_chain_ipv6(ops, skb, in, out, okfn);
+       return nft_do_chain_ipv6(ops, skb, state);
 }
 
 struct nft_af_info nft_af_ipv6 __read_mostly = {
 
 
 static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_fn(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv6_fn(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static unsigned int nft_nat_ipv6_in(const struct nf_hook_ops *ops,
                                    struct sk_buff *skb,
-                                   const struct net_device *in,
-                                   const struct net_device *out,
-                                   int (*okfn)(struct sk_buff *))
+                                   const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_in(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv6_in(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static unsigned int nft_nat_ipv6_out(const struct nf_hook_ops *ops,
                                     struct sk_buff *skb,
-                                    const struct net_device *in,
-                                    const struct net_device *out,
-                                    int (*okfn)(struct sk_buff *))
+                                    const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_out(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv6_out(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static unsigned int nft_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
                                          struct sk_buff *skb,
-                                         const struct net_device *in,
-                                         const struct net_device *out,
-                                         int (*okfn)(struct sk_buff *))
+                                         const struct nf_hook_state *state)
 {
-       return nf_nat_ipv6_local_fn(ops, skb, in, out, nft_nat_do_chain);
+       return nf_nat_ipv6_local_fn(ops, skb, state->in, state->out, nft_nat_do_chain);
 }
 
 static const struct nf_chain_type nft_chain_nat_ipv6 = {
 
 
 static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
        unsigned int ret;
        struct nft_pktinfo pkt;
        u32 mark, flowlabel;
 
        /* malformed packet, drop it */
-       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
+       if (nft_set_pktinfo_ipv6(&pkt, ops, skb, state->in, state->out) < 0)
                return NF_DROP;
 
        /* save source/dest address, mark, hoplimit, flowlabel, priority */
 
                /* Optimization: we don't need to hold module
                   reference here, since function can't sleep. --RR */
 repeat:
-               verdict = (*elemp)->hook(*elemp, skb, state->in, state->out,
-                                        state->okfn);
+               verdict = (*elemp)->hook(*elemp, skb, state);
                if (verdict != NF_ACCEPT) {
 #ifdef CONFIG_NETFILTER_DEBUG
                        if (unlikely((verdict & NF_VERDICT_MASK)
 
  */
 static unsigned int
 ip_vs_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb,
-            const struct net_device *in, const struct net_device *out,
-            int (*okfn)(struct sk_buff *))
+            const struct nf_hook_state *state)
 {
        return ip_vs_out(ops->hooknum, skb, AF_INET);
 }
  */
 static unsigned int
 ip_vs_local_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                  const struct net_device *in, const struct net_device *out,
-                  int (*okfn)(struct sk_buff *))
+                  const struct nf_hook_state *state)
 {
        return ip_vs_out(ops->hooknum, skb, AF_INET);
 }
  */
 static unsigned int
 ip_vs_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb,
-            const struct net_device *in, const struct net_device *out,
-            int (*okfn)(struct sk_buff *))
+            const struct nf_hook_state *state)
 {
        return ip_vs_out(ops->hooknum, skb, AF_INET6);
 }
  */
 static unsigned int
 ip_vs_local_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                  const struct net_device *in, const struct net_device *out,
-                  int (*okfn)(struct sk_buff *))
+                  const struct nf_hook_state *state)
 {
        return ip_vs_out(ops->hooknum, skb, AF_INET6);
 }
  */
 static unsigned int
 ip_vs_remote_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                     const struct net_device *in,
-                     const struct net_device *out,
-                     int (*okfn)(struct sk_buff *))
+                     const struct nf_hook_state *state)
 {
        return ip_vs_in(ops->hooknum, skb, AF_INET);
 }
  */
 static unsigned int
 ip_vs_local_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                    const struct net_device *in, const struct net_device *out,
-                    int (*okfn)(struct sk_buff *))
+                    const struct nf_hook_state *state)
 {
        return ip_vs_in(ops->hooknum, skb, AF_INET);
 }
  */
 static unsigned int
 ip_vs_remote_request6(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                     const struct net_device *in,
-                     const struct net_device *out,
-                     int (*okfn)(struct sk_buff *))
+                     const struct nf_hook_state *state)
 {
        return ip_vs_in(ops->hooknum, skb, AF_INET6);
 }
  */
 static unsigned int
 ip_vs_local_request6(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                    const struct net_device *in, const struct net_device *out,
-                    int (*okfn)(struct sk_buff *))
+                    const struct nf_hook_state *state)
 {
        return ip_vs_in(ops->hooknum, skb, AF_INET6);
 }
  */
 static unsigned int
 ip_vs_forward_icmp(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                  const struct net_device *in, const struct net_device *out,
-                  int (*okfn)(struct sk_buff *))
+                  const struct nf_hook_state *state)
 {
        int r;
        struct net *net;
 #ifdef CONFIG_IP_VS_IPV6
 static unsigned int
 ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb,
-                     const struct net_device *in, const struct net_device *out,
-                     int (*okfn)(struct sk_buff *))
+                     const struct nf_hook_state *state)
 {
        int r;
        struct net *net;
 
 
 static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
                                         struct sk_buff *skb,
-                                        const struct net_device *in,
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
+                                        const struct nf_hook_state *state)
 {
-       return selinux_ip_forward(skb, in, PF_INET);
+       return selinux_ip_forward(skb, state->in, PF_INET);
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
                                         struct sk_buff *skb,
-                                        const struct net_device *in,
-                                        const struct net_device *out,
-                                        int (*okfn)(struct sk_buff *))
+                                        const struct nf_hook_state *state)
 {
-       return selinux_ip_forward(skb, in, PF_INET6);
+       return selinux_ip_forward(skb, state->in, PF_INET6);
 }
 #endif /* IPV6 */
 
 
 static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
        return selinux_ip_output(skb, PF_INET);
 }
 
 static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
                                           struct sk_buff *skb,
-                                          const struct net_device *in,
-                                          const struct net_device *out,
-                                          int (*okfn)(struct sk_buff *))
+                                          const struct nf_hook_state *state)
 {
-       return selinux_ip_postroute(skb, out, PF_INET);
+       return selinux_ip_postroute(skb, state->out, PF_INET);
 }
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
                                           struct sk_buff *skb,
-                                          const struct net_device *in,
-                                          const struct net_device *out,
-                                          int (*okfn)(struct sk_buff *))
+                                          const struct nf_hook_state *state)
 {
-       return selinux_ip_postroute(skb, out, PF_INET6);
+       return selinux_ip_postroute(skb, state->out, PF_INET6);
 }
 #endif /* IPV6 */
 
 
 
 static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
        struct socket_smack *ssp;
        struct smack_known *skp;
 
 static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops,
                                        struct sk_buff *skb,
-                                       const struct net_device *in,
-                                       const struct net_device *out,
-                                       int (*okfn)(struct sk_buff *))
+                                       const struct nf_hook_state *state)
 {
        struct socket_smack *ssp;
        struct smack_known *skp;