]> Git Repo - linux.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
authorDavid S. Miller <[email protected]>
Sat, 21 Jul 2018 05:28:28 +0000 (22:28 -0700)
committerDavid S. Miller <[email protected]>
Sat, 21 Jul 2018 05:28:28 +0000 (22:28 -0700)
Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter/IPVS updates for your net-next
tree:

1) No need to set ttl from reject action for the bridge family, from
   Taehee Yoo.

2) Use a fixed timeout for flow that are passed up from the flowtable
   to conntrack, from Florian Westphal.

3) More preparation patches for tproxy support for nf_tables, from Mate
   Eckl.

4) Remove unnecessary indirection in core IPv6 checksum function, from
   Florian Westphal.

5) Use nf_ct_get_tuplepr() from openvswitch, instead of opencoding it.
   From Florian Westphal.

6) socket match now selects socket infrastructure, instead of depending
   on it. From Mate Eckl.

7) Patch series to simplify conntrack tuple building/parsing from packet
   path and ctnetlink, from Florian Westphal.

8) Fetch timeout policy from protocol helpers, instead of doing it from
   core, from Florian Westphal.

9) Merge IPv4 and IPv6 protocol trackers into conntrack core, from
   Florian Westphal.

10) Depend on CONFIG_NF_TABLES_IPV6 and CONFIG_IP6_NF_IPTABLES
    respectively, instead of IPV6. Patch from Mate Eckl.

11) Add specific function for garbage collection in conncount,
    from Yi-Hung Wei.

12) Catch number of elements in the connlimit list, from Yi-Hung Wei.

13) Move locking to nf_conncount, from Yi-Hung Wei.

14) Series of patches to add lockless tree traversal in nf_conncount,
    from Yi-Hung Wei.

15) Resolve clash in matching conntracks when race happens, from
    Martynas Pumputis.

16) If connection entry times out, remove template entry from the
    ip_vs_conn_tab table to improve behaviour under flood, from
    Julian Anastasov.

17) Remove useless parameter from nf_ct_helper_ext_add(), from Gao feng.

18) Call abort from 2-phase commit protocol before requesting modules,
    make sure this is done under the mutex, from Florian Westphal.

19) Grab module reference when starting transaction, also from Florian.

20) Dynamically allocate expression info array for pre-parsing, from
    Florian.

21) Add per netns mutex for nf_tables, from Florian Westphal.

22) A couple of patches to simplify and refactor nf_osf code to prepare
    for nft_osf support.

23) Break evaluation on missing socket, from Mate Eckl.

24) Allow to match socket mark from nft_socket, from Mate Eckl.

25) Remove dependency on nf_defrag_ipv6, now that IPv6 tracker is
    built-in into nf_conntrack. From Florian Westphal.
====================

Signed-off-by: David S. Miller <[email protected]>
1  2 
include/net/ipv6.h
include/net/netfilter/nf_tproxy.h
net/ipv6/netfilter/nf_conntrack_reasm.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/nf_conntrack_core.c
net/netfilter/xt_TPROXY.c

diff --combined include/net/ipv6.h
index 190015652168b06699fe68d1abfcd5f50b60e676,3720958cd4e166d40aeda8b0c309c20351a988c2..a44509f4e9852556b425f5f9b350a063d295d909
@@@ -375,7 -375,14 +375,7 @@@ struct ipv6_txoptions *ipv6_dup_options
  struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
                                          struct ipv6_txoptions *opt,
                                          int newtype,
 -                                        struct ipv6_opt_hdr __user *newopt,
 -                                        int newoptlen);
 -struct ipv6_txoptions *
 -ipv6_renew_options_kern(struct sock *sk,
 -                      struct ipv6_txoptions *opt,
 -                      int newtype,
 -                      struct ipv6_opt_hdr *newopt,
 -                      int newoptlen);
 +                                        struct ipv6_opt_hdr *newopt);
  struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
                                          struct ipv6_txoptions *opt);
  
@@@ -574,34 -581,6 +574,6 @@@ static inline bool ipv6_prefix_equal(co
  }
  #endif
  
- struct inet_frag_queue;
- enum ip6_defrag_users {
-       IP6_DEFRAG_LOCAL_DELIVER,
-       IP6_DEFRAG_CONNTRACK_IN,
-       __IP6_DEFRAG_CONNTRACK_IN       = IP6_DEFRAG_CONNTRACK_IN + USHRT_MAX,
-       IP6_DEFRAG_CONNTRACK_OUT,
-       __IP6_DEFRAG_CONNTRACK_OUT      = IP6_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
-       IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
-       __IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
- };
- void ip6_frag_init(struct inet_frag_queue *q, const void *a);
- extern const struct rhashtable_params ip6_rhash_params;
- /*
-  *    Equivalent of ipv4 struct ip
-  */
- struct frag_queue {
-       struct inet_frag_queue  q;
-       int                     iif;
-       __u16                   nhoffset;
-       u8                      ecn;
- };
- void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq);
  static inline bool ipv6_addr_any(const struct in6_addr *a)
  {
  #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
@@@ -843,7 -822,7 +815,7 @@@ static inline __be32 ip6_make_flowlabel
         * to minimize possbility that any useful information to an
         * attacker is leaked. Only lower 20 bits are relevant.
         */
 -      rol32(hash, 16);
 +      hash = rol32(hash, 16);
  
        flowlabel = (__force __be32)hash & IPV6_FLOWLABEL_MASK;
  
@@@ -1120,8 -1099,6 +1092,8 @@@ void ipv6_sysctl_unregister(void)
  
  int ipv6_sock_mc_join(struct sock *sk, int ifindex,
                      const struct in6_addr *addr);
 +int ipv6_sock_mc_join_ssm(struct sock *sk, int ifindex,
 +                        const struct in6_addr *addr, unsigned int mode);
  int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
                      const struct in6_addr *addr);
  #endif /* _NET_IPV6_H */
index 4cc64c8446eb94f1c122cf15d4bf74c7e3f2275d,d5a80888cbe4ee42550668a3a124cf57c889e111..82d0e41b76f224f02a5b8fb3fec6d4c64721066a
@@@ -17,6 -17,14 +17,14 @@@ static inline bool nf_tproxy_sk_is_tran
        return false;
  }
  
+ /* assign a socket to the skb -- consumes sk */
+ static inline void nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
+ {
+       skb_orphan(skb);
+       skb->sk = sk;
+       skb->destructor = sock_edemux;
+ }
  __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr);
  
  /**
@@@ -64,7 -72,7 +72,7 @@@ nf_tproxy_handle_time_wait4(struct net 
   * belonging to established connections going through that one.
   */
  struct sock *
 -nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp,
 +nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb,
                      const u8 protocol,
                      const __be32 saddr, const __be32 daddr,
                      const __be16 sport, const __be16 dport,
@@@ -103,7 -111,7 +111,7 @@@ nf_tproxy_handle_time_wait6(struct sk_b
                            struct sock *sk);
  
  struct sock *
 -nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
 +nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff,
                      const u8 protocol,
                      const struct in6_addr *saddr, const struct in6_addr *daddr,
                      const __be16 sport, const __be16 dport,
index e4d9e6976d3c295e68b13c0ceecd5fa76db4fbc1,333ee325696467da1ae0fdea1a102c73c64530df..0610bdab721cb9d6d69ac6cd7a5d21367efed23c
@@@ -33,9 -33,8 +33,8 @@@
  
  #include <net/sock.h>
  #include <net/snmp.h>
- #include <net/inet_frag.h>
+ #include <net/ipv6_frag.h>
  
- #include <net/ipv6.h>
  #include <net/protocol.h>
  #include <net/transp_v6.h>
  #include <net/rawv6.h>
@@@ -151,7 -150,7 +150,7 @@@ static void nf_ct_frag6_expire(struct t
        fq = container_of(frag, struct frag_queue, q);
        net = container_of(fq->q.net, struct net, nf_frag.frags);
  
-       ip6_expire_frag_queue(net, fq);
+       ip6frag_expire_frag_queue(net, fq);
  }
  
  /* Creation primitives. */
@@@ -585,8 -584,6 +584,8 @@@ int nf_ct_frag6_gather(struct net *net
            fq->q.meat == fq->q.len &&
            nf_ct_frag6_reasm(fq, skb, dev))
                ret = 0;
 +      else
 +              skb_dst_drop(skb);
  
  out_unlock:
        spin_unlock_bh(&fq->q.lock);
@@@ -624,16 -621,24 +623,24 @@@ static struct pernet_operations nf_ct_n
        .exit = nf_ct_net_exit,
  };
  
+ static const struct rhashtable_params nfct_rhash_params = {
+       .head_offset            = offsetof(struct inet_frag_queue, node),
+       .hashfn                 = ip6frag_key_hashfn,
+       .obj_hashfn             = ip6frag_obj_hashfn,
+       .obj_cmpfn              = ip6frag_obj_cmpfn,
+       .automatic_shrinking    = true,
+ };
  int nf_ct_frag6_init(void)
  {
        int ret = 0;
  
-       nf_frags.constructor = ip6_frag_init;
+       nf_frags.constructor = ip6frag_init;
        nf_frags.destructor = NULL;
        nf_frags.qsize = sizeof(struct frag_queue);
        nf_frags.frag_expire = nf_ct_frag6_expire;
        nf_frags.frags_cache_name = nf_frags_cache_name;
-       nf_frags.rhash_params = ip6_rhash_params;
+       nf_frags.rhash_params = nfct_rhash_params;
        ret = inet_frags_init(&nf_frags);
        if (ret)
                goto out;
diff --combined net/netfilter/Kconfig
index f0a1c536ef15a0d35a3078bf85b5f4bee704f894,e0ab50c58dc46fb4c3644f85785759fbb15f132f..6f6c959aeb8f97734e31bfd428d1c98652e56482
@@@ -49,6 -49,8 +49,8 @@@ config NETFILTER_NETLINK_LO
  config NF_CONNTRACK
        tristate "Netfilter connection tracking support"
        default m if NETFILTER_ADVANCED=n
+       select NF_DEFRAG_IPV4
+       select NF_DEFRAG_IPV6 if IPV6 != n
        help
          Connection tracking keeps a record of what packets have passed
          through your machine, in order to figure out how they are related
@@@ -460,13 -462,6 +462,13 @@@ config NF_TABLE
  
  if NF_TABLES
  
 +config NF_TABLES_SET
 +      tristate "Netfilter nf_tables set infrastructure"
 +      help
 +        This option enables the nf_tables set infrastructure that allows to
 +        look up for elements in a set and to build one-way mappings between
 +        matchings and actions.
 +
  config NF_TABLES_INET
        depends on IPV6
        select NF_TABLES_IPV4
@@@ -500,6 -495,24 +502,6 @@@ config NFT_FLOW_OFFLOA
          This option adds the "flow_offload" expression that you can use to
          choose what flows are placed into the hardware.
  
 -config NFT_SET_RBTREE
 -      tristate "Netfilter nf_tables rbtree set module"
 -      help
 -        This option adds the "rbtree" set type (Red Black tree) that is used
 -        to build interval-based sets.
 -
 -config NFT_SET_HASH
 -      tristate "Netfilter nf_tables hash set module"
 -      help
 -        This option adds the "hash" set type that is used to build one-way
 -        mappings between matchings and actions.
 -
 -config NFT_SET_BITMAP
 -      tristate "Netfilter nf_tables bitmap set module"
 -      help
 -        This option adds the "bitmap" set type that is used to build sets
 -        whose keys are smaller or equal to 16 bits.
 -
  config NFT_COUNTER
        tristate "Netfilter nf_tables counter module"
        help
@@@ -615,7 -628,7 +617,7 @@@ config NFT_SOCKE
        tristate "Netfilter nf_tables socket match support"
        depends on IPV6 || IPV6=n
        select NF_SOCKET_IPV4
-       select NF_SOCKET_IPV6 if IPV6
+       select NF_SOCKET_IPV6 if NF_TABLES_IPV6
        help
          This option allows matching for the presence or absence of a
          corresponding socket and its attributes.
@@@ -881,7 -894,7 +883,7 @@@ config NETFILTER_XT_TARGET_LO
        tristate "LOG target support"
        select NF_LOG_COMMON
        select NF_LOG_IPV4
-       select NF_LOG_IPV6 if IPV6
+       select NF_LOG_IPV6 if IP6_NF_IPTABLES
        default m if NETFILTER_ADVANCED=n
        help
          This option adds a `LOG' target, which allows you to create rules in
@@@ -973,7 -986,7 +975,7 @@@ config NETFILTER_XT_TARGET_TE
        depends on IPV6 || IPV6=n
        depends on !NF_CONNTRACK || NF_CONNTRACK
        select NF_DUP_IPV4
-       select NF_DUP_IPV6 if IPV6
+       select NF_DUP_IPV6 if IP6_NF_IPTABLES
        ---help---
        This option adds a "TEE" target with which a packet can be cloned and
        this clone be rerouted to another nexthop.
@@@ -1481,8 -1494,8 +1483,8 @@@ config NETFILTER_XT_MATCH_SOCKE
        depends on NETFILTER_ADVANCED
        depends on IPV6 || IPV6=n
        depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n
-       depends on NF_SOCKET_IPV4
-       depends on NF_SOCKET_IPV6
+       select NF_SOCKET_IPV4
+       select NF_SOCKET_IPV6 if IP6_NF_IPTABLES
        select NF_DEFRAG_IPV4
        select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n
        help
diff --combined net/netfilter/Makefile
index 8a76dced974d1c10eca35dca78cf2ab284cb2490,53bd1ed1228a1aeaefacd0831c49f32289b6c45d..dd26e4961f43048ca6495ff92c282a951d689706
@@@ -1,7 -1,12 +1,12 @@@
  # SPDX-License-Identifier: GPL-2.0
  netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o
  
- nf_conntrack-y        := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o
+ nf_conntrack-y        := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o \
+                  nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o \
+                  nf_conntrack_proto_icmp.o \
+                  nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o
+ nf_conntrack-$(subst m,y,$(CONFIG_IPV6)) += nf_conntrack_proto_icmpv6.o
  nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o
  nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o
  nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
@@@ -78,11 -83,7 +83,11 @@@ nf_tables-objs := nf_tables_core.o nf_t
                  nft_bitwise.o nft_byteorder.o nft_payload.o nft_lookup.o \
                  nft_dynset.o nft_meta.o nft_rt.o nft_exthdr.o
  
 +nf_tables_set-objs := nf_tables_set_core.o \
 +                    nft_set_hash.o nft_set_bitmap.o nft_set_rbtree.o
 +
  obj-$(CONFIG_NF_TABLES)               += nf_tables.o
 +obj-$(CONFIG_NF_TABLES_SET)   += nf_tables_set.o
  obj-$(CONFIG_NFT_COMPAT)      += nft_compat.o
  obj-$(CONFIG_NFT_CONNLIMIT)   += nft_connlimit.o
  obj-$(CONFIG_NFT_NUMGEN)      += nft_numgen.o
@@@ -95,6 -96,9 +100,6 @@@ obj-$(CONFIG_NFT_QUEUE)              += nft_queue.
  obj-$(CONFIG_NFT_QUOTA)               += nft_quota.o
  obj-$(CONFIG_NFT_REJECT)      += nft_reject.o
  obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o
 -obj-$(CONFIG_NFT_SET_RBTREE)  += nft_set_rbtree.o
 -obj-$(CONFIG_NFT_SET_HASH)    += nft_set_hash.o
 -obj-$(CONFIG_NFT_SET_BITMAP)  += nft_set_bitmap.o
  obj-$(CONFIG_NFT_COUNTER)     += nft_counter.o
  obj-$(CONFIG_NFT_LOG)         += nft_log.o
  obj-$(CONFIG_NFT_MASQ)                += nft_masq.o
index 805500197c2209de6da2e8b5937860aa83b78de2,d97d7e9a9ee7f853fa659bb0f86c0a01eeef9da2..8a113ca1eea22703b5f1c9ac19184231a18bd692
@@@ -37,7 -37,6 +37,6 @@@
  #include <linux/rculist_nulls.h>
  
  #include <net/netfilter/nf_conntrack.h>
- #include <net/netfilter/nf_conntrack_l3proto.h>
  #include <net/netfilter/nf_conntrack_l4proto.h>
  #include <net/netfilter/nf_conntrack_expect.h>
  #include <net/netfilter/nf_conntrack_helper.h>
@@@ -55,6 -54,7 +54,7 @@@
  #include <net/netfilter/nf_nat_core.h>
  #include <net/netfilter/nf_nat_helper.h>
  #include <net/netns/hash.h>
+ #include <net/ip.h>
  
  #include "nf_internals.h"
  
@@@ -222,7 -222,7 +222,7 @@@ static u32 hash_conntrack(const struct 
        return scale_hash(hash_conntrack_raw(tuple, net));
  }
  
- bool
static bool
  nf_ct_get_tuple(const struct sk_buff *skb,
                unsigned int nhoff,
                unsigned int dataoff,
                u_int8_t protonum,
                struct net *net,
                struct nf_conntrack_tuple *tuple,
-               const struct nf_conntrack_l3proto *l3proto,
                const struct nf_conntrack_l4proto *l4proto)
  {
+       unsigned int size;
+       const __be32 *ap;
+       __be32 _addrs[8];
+       struct {
+               __be16 sport;
+               __be16 dport;
+       } _inet_hdr, *inet_hdr;
        memset(tuple, 0, sizeof(*tuple));
  
        tuple->src.l3num = l3num;
-       if (l3proto->pkt_to_tuple(skb, nhoff, tuple) == 0)
+       switch (l3num) {
+       case NFPROTO_IPV4:
+               nhoff += offsetof(struct iphdr, saddr);
+               size = 2 * sizeof(__be32);
+               break;
+       case NFPROTO_IPV6:
+               nhoff += offsetof(struct ipv6hdr, saddr);
+               size = sizeof(_addrs);
+               break;
+       default:
+               return true;
+       }
+       ap = skb_header_pointer(skb, nhoff, size, _addrs);
+       if (!ap)
                return false;
  
+       switch (l3num) {
+       case NFPROTO_IPV4:
+               tuple->src.u3.ip = ap[0];
+               tuple->dst.u3.ip = ap[1];
+               break;
+       case NFPROTO_IPV6:
+               memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6));
+               memcpy(tuple->dst.u3.ip6, ap + 4, sizeof(tuple->dst.u3.ip6));
+               break;
+       }
        tuple->dst.protonum = protonum;
        tuple->dst.dir = IP_CT_DIR_ORIGINAL;
  
-       return l4proto->pkt_to_tuple(skb, dataoff, net, tuple);
+       if (unlikely(l4proto->pkt_to_tuple))
+               return l4proto->pkt_to_tuple(skb, dataoff, net, tuple);
+       /* Actually only need first 4 bytes to get ports. */
+       inet_hdr = skb_header_pointer(skb, dataoff, sizeof(_inet_hdr), &_inet_hdr);
+       if (!inet_hdr)
+               return false;
+       tuple->src.u.udp.port = inet_hdr->sport;
+       tuple->dst.u.udp.port = inet_hdr->dport;
+       return true;
+ }
+ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+                           u_int8_t *protonum)
+ {
+       int dataoff = -1;
+       const struct iphdr *iph;
+       struct iphdr _iph;
+       iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+       if (!iph)
+               return -1;
+       /* Conntrack defragments packets, we might still see fragments
+        * inside ICMP packets though.
+        */
+       if (iph->frag_off & htons(IP_OFFSET))
+               return -1;
+       dataoff = nhoff + (iph->ihl << 2);
+       *protonum = iph->protocol;
+       /* Check bogus IP headers */
+       if (dataoff > skb->len) {
+               pr_debug("bogus IPv4 packet: nhoff %u, ihl %u, skblen %u\n",
+                        nhoff, iph->ihl << 2, skb->len);
+               return -1;
+       }
+       return dataoff;
+ }
+ #if IS_ENABLED(CONFIG_IPV6)
+ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
+                           u8 *protonum)
+ {
+       int protoff = -1;
+       unsigned int extoff = nhoff + sizeof(struct ipv6hdr);
+       __be16 frag_off;
+       u8 nexthdr;
+       if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr),
+                         &nexthdr, sizeof(nexthdr)) != 0) {
+               pr_debug("can't get nexthdr\n");
+               return -1;
+       }
+       protoff = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_off);
+       /*
+        * (protoff == skb->len) means the packet has not data, just
+        * IPv6 and possibly extensions headers, but it is tracked anyway
+        */
+       if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
+               pr_debug("can't find proto in pkt\n");
+               return -1;
+       }
+       *protonum = nexthdr;
+       return protoff;
+ }
+ #endif
+ static int get_l4proto(const struct sk_buff *skb,
+                      unsigned int nhoff, u8 pf, u8 *l4num)
+ {
+       switch (pf) {
+       case NFPROTO_IPV4:
+               return ipv4_get_l4proto(skb, nhoff, l4num);
+ #if IS_ENABLED(CONFIG_IPV6)
+       case NFPROTO_IPV6:
+               return ipv6_get_l4proto(skb, nhoff, l4num);
+ #endif
+       default:
+               *l4num = 0;
+               break;
+       }
+       return -1;
  }
- EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
  
  bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
                       u_int16_t l3num,
                       struct net *net, struct nf_conntrack_tuple *tuple)
  {
-       const struct nf_conntrack_l3proto *l3proto;
        const struct nf_conntrack_l4proto *l4proto;
-       unsigned int protoff;
-       u_int8_t protonum;
+       u8 protonum;
+       int protoff;
        int ret;
  
        rcu_read_lock();
  
-       l3proto = __nf_ct_l3proto_find(l3num);
-       ret = l3proto->get_l4proto(skb, nhoff, &protoff, &protonum);
-       if (ret != NF_ACCEPT) {
+       protoff = get_l4proto(skb, nhoff, l3num, &protonum);
+       if (protoff <= 0) {
                rcu_read_unlock();
                return false;
        }
        l4proto = __nf_ct_l4proto_find(l3num, protonum);
  
        ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, net, tuple,
-                             l3proto, l4proto);
+                             l4proto);
  
        rcu_read_unlock();
        return ret;
@@@ -278,19 -392,35 +392,35 @@@ EXPORT_SYMBOL_GPL(nf_ct_get_tuplepr)
  bool
  nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
                   const struct nf_conntrack_tuple *orig,
-                  const struct nf_conntrack_l3proto *l3proto,
                   const struct nf_conntrack_l4proto *l4proto)
  {
        memset(inverse, 0, sizeof(*inverse));
  
        inverse->src.l3num = orig->src.l3num;
-       if (l3proto->invert_tuple(inverse, orig) == 0)
-               return false;
+       switch (orig->src.l3num) {
+       case NFPROTO_IPV4:
+               inverse->src.u3.ip = orig->dst.u3.ip;
+               inverse->dst.u3.ip = orig->src.u3.ip;
+               break;
+       case NFPROTO_IPV6:
+               inverse->src.u3.in6 = orig->dst.u3.in6;
+               inverse->dst.u3.in6 = orig->src.u3.in6;
+               break;
+       default:
+               break;
+       }
  
        inverse->dst.dir = !orig->dst.dir;
  
        inverse->dst.protonum = orig->dst.protonum;
-       return l4proto->invert_tuple(inverse, orig);
+       if (unlikely(l4proto->invert_tuple))
+               return l4proto->invert_tuple(inverse, orig);
+       inverse->src.u.all = orig->dst.u.all;
+       inverse->dst.u.all = orig->src.u.all;
+       return true;
  }
  EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
  
@@@ -502,6 -632,18 +632,18 @@@ nf_ct_key_equal(struct nf_conntrack_tup
               net_eq(net, nf_ct_net(ct));
  }
  
+ static inline bool
+ nf_ct_match(const struct nf_conn *ct1, const struct nf_conn *ct2)
+ {
+       return nf_ct_tuple_equal(&ct1->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                &ct2->tuplehash[IP_CT_DIR_ORIGINAL].tuple) &&
+              nf_ct_tuple_equal(&ct1->tuplehash[IP_CT_DIR_REPLY].tuple,
+                                &ct2->tuplehash[IP_CT_DIR_REPLY].tuple) &&
+              nf_ct_zone_equal(ct1, nf_ct_zone(ct2), IP_CT_DIR_ORIGINAL) &&
+              nf_ct_zone_equal(ct1, nf_ct_zone(ct2), IP_CT_DIR_REPLY) &&
+              net_eq(nf_ct_net(ct1), nf_ct_net(ct2));
+ }
  /* caller must hold rcu readlock and none of the nf_conntrack_locks */
  static void nf_ct_gc_expired(struct nf_conn *ct)
  {
@@@ -695,19 -837,21 +837,21 @@@ static int nf_ct_resolve_clash(struct n
        /* This is the conntrack entry already in hashes that won race. */
        struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
        const struct nf_conntrack_l4proto *l4proto;
+       enum ip_conntrack_info oldinfo;
+       struct nf_conn *loser_ct = nf_ct_get(skb, &oldinfo);
  
        l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
        if (l4proto->allow_clash &&
-           ((ct->status & IPS_NAT_DONE_MASK) == 0) &&
            !nf_ct_is_dying(ct) &&
            atomic_inc_not_zero(&ct->ct_general.use)) {
-               enum ip_conntrack_info oldinfo;
-               struct nf_conn *loser_ct = nf_ct_get(skb, &oldinfo);
-               nf_ct_acct_merge(ct, ctinfo, loser_ct);
-               nf_conntrack_put(&loser_ct->ct_general);
-               nf_ct_set(skb, ct, oldinfo);
-               return NF_ACCEPT;
+               if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
+                   nf_ct_match(ct, loser_ct)) {
+                       nf_ct_acct_merge(ct, ctinfo, loser_ct);
+                       nf_conntrack_put(&loser_ct->ct_general);
+                       nf_ct_set(skb, ct, oldinfo);
+                       return NF_ACCEPT;
+               }
+               nf_ct_put(ct);
        }
        NF_CT_STAT_INC(net, drop);
        return NF_DROP;
@@@ -1195,7 -1339,6 +1339,6 @@@ EXPORT_SYMBOL_GPL(nf_conntrack_free)
  static noinline struct nf_conntrack_tuple_hash *
  init_conntrack(struct net *net, struct nf_conn *tmpl,
               const struct nf_conntrack_tuple *tuple,
-              const struct nf_conntrack_l3proto *l3proto,
               const struct nf_conntrack_l4proto *l4proto,
               struct sk_buff *skb,
               unsigned int dataoff, u32 hash)
        const struct nf_conntrack_zone *zone;
        struct nf_conn_timeout *timeout_ext;
        struct nf_conntrack_zone tmp;
-       unsigned int *timeouts;
  
-       if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
+       if (!nf_ct_invert_tuple(&repl_tuple, tuple, l4proto)) {
                pr_debug("Can't invert tuple.\n");
                return NULL;
        }
        }
  
        timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL;
-       if (timeout_ext) {
-               timeouts = nf_ct_timeout_data(timeout_ext);
-               if (unlikely(!timeouts))
-                       timeouts = l4proto->get_timeouts(net);
-       } else {
-               timeouts = l4proto->get_timeouts(net);
-       }
  
-       if (!l4proto->new(ct, skb, dataoff, timeouts)) {
+       if (!l4proto->new(ct, skb, dataoff)) {
                nf_conntrack_free(ct);
                pr_debug("can't track with proto module\n");
                return NULL;
                        /* exp->master safe, refcnt bumped in nf_ct_find_expectation */
                        ct->master = exp->master;
                        if (exp->helper) {
-                               help = nf_ct_helper_ext_add(ct, exp->helper,
-                                                           GFP_ATOMIC);
+                               help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
                                if (help)
                                        rcu_assign_pointer(help->helper, exp->helper);
                        }
@@@ -1307,7 -1441,6 +1441,6 @@@ resolve_normal_ct(struct net *net, stru
                  unsigned int dataoff,
                  u_int16_t l3num,
                  u_int8_t protonum,
-                 const struct nf_conntrack_l3proto *l3proto,
                  const struct nf_conntrack_l4proto *l4proto)
  {
        const struct nf_conntrack_zone *zone;
        u32 hash;
  
        if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
-                            dataoff, l3num, protonum, net, &tuple, l3proto,
-                            l4proto)) {
+                            dataoff, l3num, protonum, net, &tuple, l4proto)) {
                pr_debug("Can't get tuple\n");
                return 0;
        }
        hash = hash_conntrack_raw(&tuple, net);
        h = __nf_conntrack_find_get(net, zone, &tuple, hash);
        if (!h) {
-               h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
+               h = init_conntrack(net, tmpl, &tuple, l4proto,
                                   skb, dataoff, hash);
                if (!h)
                        return 0;
@@@ -1363,14 -1495,11 +1495,11 @@@ unsigned in
  nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
                struct sk_buff *skb)
  {
-       const struct nf_conntrack_l3proto *l3proto;
        const struct nf_conntrack_l4proto *l4proto;
        struct nf_conn *ct, *tmpl;
        enum ip_conntrack_info ctinfo;
-       unsigned int *timeouts;
-       unsigned int dataoff;
        u_int8_t protonum;
-       int ret;
+       int dataoff, ret;
  
        tmpl = nf_ct_get(skb, &ctinfo);
        if (tmpl || ctinfo == IP_CT_UNTRACKED) {
        }
  
        /* rcu_read_lock()ed by nf_hook_thresh */
-       l3proto = __nf_ct_l3proto_find(pf);
-       ret = l3proto->get_l4proto(skb, skb_network_offset(skb),
-                                  &dataoff, &protonum);
-       if (ret <= 0) {
+       dataoff = get_l4proto(skb, skb_network_offset(skb), 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);
-               ret = -ret;
+               ret = NF_ACCEPT;
                goto out;
        }
  
                        goto out;
        }
  repeat:
-       ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
-                               l3proto, l4proto);
+       ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, l4proto);
        if (ret < 0) {
                /* Too stressed to deal. */
                NF_CT_STAT_INC_ATOMIC(net, drop);
                goto out;
        }
  
-       /* Decide what timeout policy we want to apply to this flow. */
-       timeouts = nf_ct_timeout_lookup(net, ct, l4proto);
-       ret = l4proto->packet(ct, skb, dataoff, ctinfo, timeouts);
+       ret = l4proto->packet(ct, skb, dataoff, ctinfo);
        if (ret <= 0) {
                /* Invalid: inverse of the return code tells
                 * the netfilter core what to do */
@@@ -1471,7 -1594,6 +1594,6 @@@ bool nf_ct_invert_tuplepr(struct nf_con
  
        rcu_read_lock();
        ret = nf_ct_invert_tuple(inverse, orig,
-                                __nf_ct_l3proto_find(orig->src.l3num),
                                 __nf_ct_l4proto_find(orig->src.l3num,
                                                      orig->dst.protonum));
        rcu_read_unlock();
@@@ -1609,14 -1731,14 +1731,14 @@@ static void nf_conntrack_attach(struct 
  
  static int nf_conntrack_update(struct net *net, struct sk_buff *skb)
  {
-       const struct nf_conntrack_l3proto *l3proto;
        const struct nf_conntrack_l4proto *l4proto;
        struct nf_conntrack_tuple_hash *h;
        struct nf_conntrack_tuple tuple;
        enum ip_conntrack_info ctinfo;
        struct nf_nat_hook *nat_hook;
-       unsigned int dataoff, status;
+       unsigned int status;
        struct nf_conn *ct;
+       int dataoff;
        u16 l3num;
        u8 l4num;
  
                return 0;
  
        l3num = nf_ct_l3num(ct);
-       l3proto = nf_ct_l3proto_find_get(l3num);
  
-       if (l3proto->get_l4proto(skb, skb_network_offset(skb), &dataoff,
-                                &l4num) <= 0)
+       dataoff = get_l4proto(skb, skb_network_offset(skb), l3num, &l4num);
+       if (dataoff <= 0)
                return -1;
  
        l4proto = nf_ct_l4proto_find_get(l3num, l4num);
  
        if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num,
-                            l4num, net, &tuple, l3proto, l4proto))
+                            l4num, net, &tuple, l4proto))
                return -1;
  
        if (ct->status & IPS_SRC_NAT) {
@@@ -2078,7 -2199,7 +2199,7 @@@ int nf_conntrack_set_hashsize(const cha
                return -EOPNOTSUPP;
  
        /* On boot, we can set this without any fancy locking. */
 -      if (!nf_conntrack_htable_size)
 +      if (!nf_conntrack_hash)
                return param_set_uint(val, kp);
  
        rc = kstrtouint(val, 0, &hashsize);
  }
  EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize);
  
- module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
-                 &nf_conntrack_htable_size, 0600);
  static __always_inline unsigned int total_extension_size(void)
  {
        /* remember to add new extensions below */
index d76550a8b642aafd96853332d18db898e43ff587,35df0827e2cae31458416b30c60e9985d70fcb9a..ad7420cdc4395c0852bf8ea0a215ebb7cbc0c053
  #include <net/netfilter/nf_tproxy.h>
  #include <linux/netfilter/xt_TPROXY.h>
  
- /* assign a socket to the skb -- consumes sk */
- static void
- nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
- {
-       skb_orphan(skb);
-       skb->sk = sk;
-       skb->destructor = sock_edemux;
- }
  static unsigned int
  tproxy_tg4(struct net *net, struct sk_buff *skb, __be32 laddr, __be16 lport,
           u_int32_t mark_mask, u_int32_t mark_value)
@@@ -61,7 -52,7 +52,7 @@@
         * addresses, this happens if the redirect already happened
         * and the current packet belongs to an already established
         * connection */
 -      sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol,
 +      sk = nf_tproxy_get_sock_v4(net, skb, iph->protocol,
                                   iph->saddr, iph->daddr,
                                   hp->source, hp->dest,
                                   skb->dev, NF_TPROXY_LOOKUP_ESTABLISHED);
@@@ -77,7 -68,7 +68,7 @@@
        else if (!sk)
                /* no, there's no established connection, check if
                 * there's a listener on the redirected addr/port */
 -              sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol,
 +              sk = nf_tproxy_get_sock_v4(net, skb, iph->protocol,
                                           iph->saddr, laddr,
                                           hp->source, lport,
                                           skb->dev, NF_TPROXY_LOOKUP_LISTENER);
@@@ -150,7 -141,7 +141,7 @@@ tproxy_tg6_v1(struct sk_buff *skb, cons
         * addresses, this happens if the redirect already happened
         * and the current packet belongs to an already established
         * connection */
 -      sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto,
 +      sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, tproto,
                                   &iph->saddr, &iph->daddr,
                                   hp->source, hp->dest,
                                   xt_in(par), NF_TPROXY_LOOKUP_ESTABLISHED);
        else if (!sk)
                /* no there's no established connection, check if
                 * there's a listener on the redirected addr/port */
 -              sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp,
 +              sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff,
                                           tproto, &iph->saddr, laddr,
                                           hp->source, lport,
                                           xt_in(par), NF_TPROXY_LOOKUP_LISTENER);
This page took 0.117512 seconds and 4 git commands to generate.