Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

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

1) Get rid of nf_sk_is_transparent(), use inet_sk_transparent() instead.
From Máté Eckl.

2) Move shared tproxy infrastructure to nf_tproxy_ipv4 and nf_tproxy_ipv6.
Also from Máté.

3) Add hashtable to speed up chain lookups by name, from Florian Westphal.

4) Patch series to add connlimit support reusing part of the
nf_conncount infrastructure. This includes preparation changes such
passing context to the object and expression destroy interface;
garbage collection for expressions embedded into set elements, and
the introduction of the clone_destroy interface for expressions.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+978 -413
+11
include/net/netfilter/nf_conntrack_count.h
··· 13 13 const u32 *key, 14 14 const struct nf_conntrack_tuple *tuple, 15 15 const struct nf_conntrack_zone *zone); 16 + 17 + unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, 18 + const struct nf_conntrack_tuple *tuple, 19 + const struct nf_conntrack_zone *zone, 20 + bool *addit); 21 + 22 + bool nf_conncount_add(struct hlist_head *head, 23 + const struct nf_conntrack_tuple *tuple); 24 + 25 + void nf_conncount_cache_free(struct hlist_head *hhead); 26 + 16 27 #endif
-13
include/net/netfilter/nf_socket.h
··· 3 3 #define _NF_SOCK_H_ 4 4 5 5 #include <net/sock.h> 6 - #include <net/inet_timewait_sock.h> 7 - 8 - static inline bool nf_sk_is_transparent(struct sock *sk) 9 - { 10 - switch (sk->sk_state) { 11 - case TCP_TIME_WAIT: 12 - return inet_twsk(sk)->tw_transparent; 13 - case TCP_NEW_SYN_RECV: 14 - return inet_rsk(inet_reqsk(sk))->no_srccheck; 15 - default: 16 - return inet_sk(sk)->transparent; 17 - } 18 - } 19 6 20 7 struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb, 21 8 const struct net_device *indev);
+18 -2
include/net/netfilter/nf_tables.h
··· 9 9 #include <linux/netfilter/x_tables.h> 10 10 #include <linux/netfilter/nf_tables.h> 11 11 #include <linux/u64_stats_sync.h> 12 + #include <linux/rhashtable.h> 12 13 #include <net/netfilter/nf_flow_table.h> 13 14 #include <net/netlink.h> 14 15 ··· 343 342 const struct nft_set_desc *desc, 344 343 const struct nlattr * const nla[]); 345 344 void (*destroy)(const struct nft_set *set); 345 + void (*gc_init)(const struct nft_set *set); 346 346 347 347 unsigned int elemsize; 348 348 }; ··· 372 370 * 373 371 * @list: table set list node 374 372 * @bindings: list of set bindings 373 + * @table: table this set belongs to 374 + * @net: netnamespace this set belongs to 375 375 * @name: name of the set 376 376 * @handle: unique handle of the set 377 377 * @ktype: key type (numeric type defined by userspace, not used in the kernel) ··· 397 393 struct nft_set { 398 394 struct list_head list; 399 395 struct list_head bindings; 396 + struct nft_table *table; 397 + possible_net_t net; 400 398 char *name; 401 399 u64 handle; 402 400 u32 ktype; ··· 714 708 }; 715 709 716 710 #define NFT_EXPR_STATEFUL 0x1 711 + #define NFT_EXPR_GC 0x2 717 712 718 713 /** 719 714 * struct nft_expr_ops - nf_tables expression operations ··· 746 739 const struct nft_expr *expr); 747 740 void (*destroy)(const struct nft_ctx *ctx, 748 741 const struct nft_expr *expr); 742 + void (*destroy_clone)(const struct nft_ctx *ctx, 743 + const struct nft_expr *expr); 749 744 int (*dump)(struct sk_buff *skb, 750 745 const struct nft_expr *expr); 751 746 int (*validate)(const struct nft_ctx *ctx, 752 747 const struct nft_expr *expr, 753 748 const struct nft_data **data); 749 + bool (*gc)(struct net *net, 750 + const struct nft_expr *expr); 754 751 const struct nft_expr_type *type; 755 752 void *data; 756 753 }; ··· 861 850 * 862 851 * @rules: list of rules in the chain 863 852 * @list: used internally 853 + * @rhlhead: used internally 864 854 * @table: table that this chain belongs to 865 855 * @handle: chain handle 866 856 * @use: number of jump references to this chain ··· 874 862 struct nft_rule *__rcu *rules_gen_1; 875 863 struct list_head rules; 876 864 struct list_head list; 865 + struct rhlist_head rhlhead; 877 866 struct nft_table *table; 878 867 u64 handle; 879 868 u32 use; ··· 968 955 * struct nft_table - nf_tables table 969 956 * 970 957 * @list: used internally 971 - * @chains: chains in the table 958 + * @chains_ht: chains in the table 959 + * @chains: same, for stable walks 972 960 * @sets: sets in the table 973 961 * @objects: stateful objects in the table 974 962 * @flowtables: flow tables in the table ··· 983 969 */ 984 970 struct nft_table { 985 971 struct list_head list; 972 + struct rhltable chains_ht; 986 973 struct list_head chains; 987 974 struct list_head sets; 988 975 struct list_head objects; ··· 1085 1070 int (*init)(const struct nft_ctx *ctx, 1086 1071 const struct nlattr *const tb[], 1087 1072 struct nft_object *obj); 1088 - void (*destroy)(struct nft_object *obj); 1073 + void (*destroy)(const struct nft_ctx *ctx, 1074 + struct nft_object *obj); 1089 1075 int (*dump)(struct sk_buff *skb, 1090 1076 struct nft_object *obj, 1091 1077 bool reset);
+113
include/net/netfilter/nf_tproxy.h
··· 1 + #ifndef _NF_TPROXY_H_ 2 + #define _NF_TPROXY_H_ 3 + 4 + #include <net/tcp.h> 5 + 6 + enum nf_tproxy_lookup_t { 7 + NF_TPROXY_LOOKUP_LISTENER, 8 + NF_TPROXY_LOOKUP_ESTABLISHED, 9 + }; 10 + 11 + static inline bool nf_tproxy_sk_is_transparent(struct sock *sk) 12 + { 13 + if (inet_sk_transparent(sk)) 14 + return true; 15 + 16 + sock_gen_put(sk); 17 + return false; 18 + } 19 + 20 + __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr); 21 + 22 + /** 23 + * nf_tproxy_handle_time_wait4 - handle IPv4 TCP TIME_WAIT reopen redirections 24 + * @skb: The skb being processed. 25 + * @laddr: IPv4 address to redirect to or zero. 26 + * @lport: TCP port to redirect to or zero. 27 + * @sk: The TIME_WAIT TCP socket found by the lookup. 28 + * 29 + * We have to handle SYN packets arriving to TIME_WAIT sockets 30 + * differently: instead of reopening the connection we should rather 31 + * redirect the new connection to the proxy if there's a listener 32 + * socket present. 33 + * 34 + * nf_tproxy_handle_time_wait4() consumes the socket reference passed in. 35 + * 36 + * Returns the listener socket if there's one, the TIME_WAIT socket if 37 + * no such listener is found, or NULL if the TCP header is incomplete. 38 + */ 39 + struct sock * 40 + nf_tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb, 41 + __be32 laddr, __be16 lport, struct sock *sk); 42 + 43 + /* 44 + * This is used when the user wants to intercept a connection matching 45 + * an explicit iptables rule. In this case the sockets are assumed 46 + * matching in preference order: 47 + * 48 + * - match: if there's a fully established connection matching the 49 + * _packet_ tuple, it is returned, assuming the redirection 50 + * already took place and we process a packet belonging to an 51 + * established connection 52 + * 53 + * - match: if there's a listening socket matching the redirection 54 + * (e.g. on-port & on-ip of the connection), it is returned, 55 + * regardless if it was bound to 0.0.0.0 or an explicit 56 + * address. The reasoning is that if there's an explicit rule, it 57 + * does not really matter if the listener is bound to an interface 58 + * or to 0. The user already stated that he wants redirection 59 + * (since he added the rule). 60 + * 61 + * Please note that there's an overlap between what a TPROXY target 62 + * and a socket match will match. Normally if you have both rules the 63 + * "socket" match will be the first one, effectively all packets 64 + * belonging to established connections going through that one. 65 + */ 66 + struct sock * 67 + nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp, 68 + const u8 protocol, 69 + const __be32 saddr, const __be32 daddr, 70 + const __be16 sport, const __be16 dport, 71 + const struct net_device *in, 72 + const enum nf_tproxy_lookup_t lookup_type); 73 + 74 + const struct in6_addr * 75 + nf_tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, 76 + const struct in6_addr *daddr); 77 + 78 + /** 79 + * nf_tproxy_handle_time_wait6 - handle IPv6 TCP TIME_WAIT reopen redirections 80 + * @skb: The skb being processed. 81 + * @tproto: Transport protocol. 82 + * @thoff: Transport protocol header offset. 83 + * @net: Network namespace. 84 + * @laddr: IPv6 address to redirect to. 85 + * @lport: TCP port to redirect to or zero. 86 + * @sk: The TIME_WAIT TCP socket found by the lookup. 87 + * 88 + * We have to handle SYN packets arriving to TIME_WAIT sockets 89 + * differently: instead of reopening the connection we should rather 90 + * redirect the new connection to the proxy if there's a listener 91 + * socket present. 92 + * 93 + * nf_tproxy_handle_time_wait6() consumes the socket reference passed in. 94 + * 95 + * Returns the listener socket if there's one, the TIME_WAIT socket if 96 + * no such listener is found, or NULL if the TCP header is incomplete. 97 + */ 98 + struct sock * 99 + nf_tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff, 100 + struct net *net, 101 + const struct in6_addr *laddr, 102 + const __be16 lport, 103 + struct sock *sk); 104 + 105 + struct sock * 106 + nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp, 107 + const u8 protocol, 108 + const struct in6_addr *saddr, const struct in6_addr *daddr, 109 + const __be16 sport, const __be16 dport, 110 + const struct net_device *in, 111 + const enum nf_tproxy_lookup_t lookup_type); 112 + 113 + #endif /* _NF_TPROXY_H_ */
+20 -1
include/uapi/linux/netfilter/nf_tables.h
··· 1043 1043 }; 1044 1044 #define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1) 1045 1045 1046 + enum nft_connlimit_flags { 1047 + NFT_CONNLIMIT_F_INV = (1 << 0), 1048 + }; 1049 + 1050 + /** 1051 + * enum nft_connlimit_attributes - nf_tables connlimit expression netlink attributes 1052 + * 1053 + * @NFTA_CONNLIMIT_COUNT: number of connections (NLA_U32) 1054 + * @NFTA_CONNLIMIT_FLAGS: flags (NLA_U32: enum nft_connlimit_flags) 1055 + */ 1056 + enum nft_connlimit_attributes { 1057 + NFTA_CONNLIMIT_UNSPEC, 1058 + NFTA_CONNLIMIT_COUNT, 1059 + NFTA_CONNLIMIT_FLAGS, 1060 + __NFTA_CONNLIMIT_MAX 1061 + }; 1062 + #define NFTA_CONNLIMIT_MAX (__NFTA_CONNLIMIT_MAX - 1) 1063 + 1046 1064 /** 1047 1065 * enum nft_counter_attributes - nf_tables counter expression netlink attributes 1048 1066 * ··· 1375 1357 #define NFT_OBJECT_QUOTA 2 1376 1358 #define NFT_OBJECT_CT_HELPER 3 1377 1359 #define NFT_OBJECT_LIMIT 4 1378 - #define __NFT_OBJECT_MAX 5 1360 + #define NFT_OBJECT_CONNLIMIT 5 1361 + #define __NFT_OBJECT_MAX 6 1379 1362 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) 1380 1363 1381 1364 /**
+4 -1
net/ipv4/netfilter/Kconfig
··· 29 29 tristate "IPv4 socket lookup support" 30 30 help 31 31 This option enables the IPv4 socket lookup infrastructure. This is 32 - is required by the iptables socket match. 32 + is required by the {ip,nf}tables socket match. 33 + 34 + config NF_TPROXY_IPV4 35 + tristate "IPv4 tproxy support" 33 36 34 37 if NF_TABLES 35 38
+1
net/ipv4/netfilter/Makefile
··· 17 17 obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o 18 18 19 19 obj-$(CONFIG_NF_SOCKET_IPV4) += nf_socket_ipv4.o 20 + obj-$(CONFIG_NF_TPROXY_IPV4) += nf_tproxy_ipv4.o 20 21 21 22 # logging 22 23 obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o
+147
net/ipv4/netfilter/nf_tproxy_ipv4.c
··· 1 + /* 2 + * Copyright (C) 2007-2008 BalaBit IT Ltd. 3 + * Author: Krisztian Kovacs 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + */ 10 + 11 + #include <net/netfilter/nf_tproxy.h> 12 + #include <linux/module.h> 13 + #include <linux/skbuff.h> 14 + #include <net/sock.h> 15 + #include <net/inet_sock.h> 16 + #include <linux/ip.h> 17 + #include <net/checksum.h> 18 + #include <net/udp.h> 19 + #include <net/tcp.h> 20 + #include <linux/inetdevice.h> 21 + 22 + struct sock * 23 + nf_tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb, 24 + __be32 laddr, __be16 lport, struct sock *sk) 25 + { 26 + const struct iphdr *iph = ip_hdr(skb); 27 + struct tcphdr _hdr, *hp; 28 + 29 + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr); 30 + if (hp == NULL) { 31 + inet_twsk_put(inet_twsk(sk)); 32 + return NULL; 33 + } 34 + 35 + if (hp->syn && !hp->rst && !hp->ack && !hp->fin) { 36 + /* SYN to a TIME_WAIT socket, we'd rather redirect it 37 + * to a listener socket if there's one */ 38 + struct sock *sk2; 39 + 40 + sk2 = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, 41 + iph->saddr, laddr ? laddr : iph->daddr, 42 + hp->source, lport ? lport : hp->dest, 43 + skb->dev, NF_TPROXY_LOOKUP_LISTENER); 44 + if (sk2) { 45 + inet_twsk_deschedule_put(inet_twsk(sk)); 46 + sk = sk2; 47 + } 48 + } 49 + 50 + return sk; 51 + } 52 + EXPORT_SYMBOL_GPL(nf_tproxy_handle_time_wait4); 53 + 54 + __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) 55 + { 56 + struct in_device *indev; 57 + __be32 laddr; 58 + 59 + if (user_laddr) 60 + return user_laddr; 61 + 62 + laddr = 0; 63 + indev = __in_dev_get_rcu(skb->dev); 64 + for_primary_ifa(indev) { 65 + laddr = ifa->ifa_local; 66 + break; 67 + } endfor_ifa(indev); 68 + 69 + return laddr ? laddr : daddr; 70 + } 71 + EXPORT_SYMBOL_GPL(nf_tproxy_laddr4); 72 + 73 + struct sock * 74 + nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp, 75 + const u8 protocol, 76 + const __be32 saddr, const __be32 daddr, 77 + const __be16 sport, const __be16 dport, 78 + const struct net_device *in, 79 + const enum nf_tproxy_lookup_t lookup_type) 80 + { 81 + struct sock *sk; 82 + struct tcphdr *tcph; 83 + 84 + switch (protocol) { 85 + case IPPROTO_TCP: 86 + switch (lookup_type) { 87 + case NF_TPROXY_LOOKUP_LISTENER: 88 + tcph = hp; 89 + sk = inet_lookup_listener(net, &tcp_hashinfo, skb, 90 + ip_hdrlen(skb) + 91 + __tcp_hdrlen(tcph), 92 + saddr, sport, 93 + daddr, dport, 94 + in->ifindex, 0); 95 + 96 + if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 97 + sk = NULL; 98 + /* NOTE: we return listeners even if bound to 99 + * 0.0.0.0, those are filtered out in 100 + * xt_socket, since xt_TPROXY needs 0 bound 101 + * listeners too 102 + */ 103 + break; 104 + case NF_TPROXY_LOOKUP_ESTABLISHED: 105 + sk = inet_lookup_established(net, &tcp_hashinfo, 106 + saddr, sport, daddr, dport, 107 + in->ifindex); 108 + break; 109 + default: 110 + BUG(); 111 + } 112 + break; 113 + case IPPROTO_UDP: 114 + sk = udp4_lib_lookup(net, saddr, sport, daddr, dport, 115 + in->ifindex); 116 + if (sk) { 117 + int connected = (sk->sk_state == TCP_ESTABLISHED); 118 + int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0); 119 + 120 + /* NOTE: we return listeners even if bound to 121 + * 0.0.0.0, those are filtered out in 122 + * xt_socket, since xt_TPROXY needs 0 bound 123 + * listeners too 124 + */ 125 + if ((lookup_type == NF_TPROXY_LOOKUP_ESTABLISHED && 126 + (!connected || wildcard)) || 127 + (lookup_type == NF_TPROXY_LOOKUP_LISTENER && connected)) { 128 + sock_put(sk); 129 + sk = NULL; 130 + } 131 + } 132 + break; 133 + default: 134 + WARN_ON(1); 135 + sk = NULL; 136 + } 137 + 138 + pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n", 139 + protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk); 140 + 141 + return sk; 142 + } 143 + EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4); 144 + 145 + MODULE_LICENSE("GPL"); 146 + MODULE_AUTHOR("Balazs Scheidler, Krisztian Kovacs"); 147 + MODULE_DESCRIPTION("Netfilter IPv4 transparent proxy support");
+4 -1
net/ipv6/netfilter/Kconfig
··· 29 29 tristate "IPv6 socket lookup support" 30 30 help 31 31 This option enables the IPv6 socket lookup infrastructure. This 32 - is used by the ip6tables socket match. 32 + is used by the {ip6,nf}tables socket match. 33 + 34 + config NF_TPROXY_IPV6 35 + tristate "IPv6 tproxy support" 33 36 34 37 if NF_TABLES 35 38
+1
net/ipv6/netfilter/Makefile
··· 26 26 obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o 27 27 28 28 obj-$(CONFIG_NF_SOCKET_IPV6) += nf_socket_ipv6.o 29 + obj-$(CONFIG_NF_TPROXY_IPV6) += nf_tproxy_ipv6.o 29 30 30 31 # logging 31 32 obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o
+146
net/ipv6/netfilter/nf_tproxy_ipv6.c
··· 1 + #include <net/netfilter/nf_tproxy.h> 2 + #include <linux/module.h> 3 + #include <net/inet6_hashtables.h> 4 + #include <net/addrconf.h> 5 + #include <net/udp.h> 6 + #include <net/tcp.h> 7 + 8 + const struct in6_addr * 9 + nf_tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, 10 + const struct in6_addr *daddr) 11 + { 12 + struct inet6_dev *indev; 13 + struct inet6_ifaddr *ifa; 14 + struct in6_addr *laddr; 15 + 16 + if (!ipv6_addr_any(user_laddr)) 17 + return user_laddr; 18 + laddr = NULL; 19 + 20 + indev = __in6_dev_get(skb->dev); 21 + if (indev) { 22 + read_lock_bh(&indev->lock); 23 + list_for_each_entry(ifa, &indev->addr_list, if_list) { 24 + if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)) 25 + continue; 26 + 27 + laddr = &ifa->addr; 28 + break; 29 + } 30 + read_unlock_bh(&indev->lock); 31 + } 32 + 33 + return laddr ? laddr : daddr; 34 + } 35 + EXPORT_SYMBOL_GPL(nf_tproxy_laddr6); 36 + 37 + struct sock * 38 + nf_tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff, 39 + struct net *net, 40 + const struct in6_addr *laddr, 41 + const __be16 lport, 42 + struct sock *sk) 43 + { 44 + const struct ipv6hdr *iph = ipv6_hdr(skb); 45 + struct tcphdr _hdr, *hp; 46 + 47 + hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr); 48 + if (hp == NULL) { 49 + inet_twsk_put(inet_twsk(sk)); 50 + return NULL; 51 + } 52 + 53 + if (hp->syn && !hp->rst && !hp->ack && !hp->fin) { 54 + /* SYN to a TIME_WAIT socket, we'd rather redirect it 55 + * to a listener socket if there's one */ 56 + struct sock *sk2; 57 + 58 + sk2 = nf_tproxy_get_sock_v6(net, skb, thoff, hp, tproto, 59 + &iph->saddr, 60 + nf_tproxy_laddr6(skb, laddr, &iph->daddr), 61 + hp->source, 62 + lport ? lport : hp->dest, 63 + skb->dev, NF_TPROXY_LOOKUP_LISTENER); 64 + if (sk2) { 65 + inet_twsk_deschedule_put(inet_twsk(sk)); 66 + sk = sk2; 67 + } 68 + } 69 + 70 + return sk; 71 + } 72 + EXPORT_SYMBOL_GPL(nf_tproxy_handle_time_wait6); 73 + 74 + struct sock * 75 + nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp, 76 + const u8 protocol, 77 + const struct in6_addr *saddr, const struct in6_addr *daddr, 78 + const __be16 sport, const __be16 dport, 79 + const struct net_device *in, 80 + const enum nf_tproxy_lookup_t lookup_type) 81 + { 82 + struct sock *sk; 83 + struct tcphdr *tcph; 84 + 85 + switch (protocol) { 86 + case IPPROTO_TCP: 87 + switch (lookup_type) { 88 + case NF_TPROXY_LOOKUP_LISTENER: 89 + tcph = hp; 90 + sk = inet6_lookup_listener(net, &tcp_hashinfo, skb, 91 + thoff + __tcp_hdrlen(tcph), 92 + saddr, sport, 93 + daddr, ntohs(dport), 94 + in->ifindex, 0); 95 + 96 + if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 97 + sk = NULL; 98 + /* NOTE: we return listeners even if bound to 99 + * 0.0.0.0, those are filtered out in 100 + * xt_socket, since xt_TPROXY needs 0 bound 101 + * listeners too 102 + */ 103 + break; 104 + case NF_TPROXY_LOOKUP_ESTABLISHED: 105 + sk = __inet6_lookup_established(net, &tcp_hashinfo, 106 + saddr, sport, daddr, ntohs(dport), 107 + in->ifindex, 0); 108 + break; 109 + default: 110 + BUG(); 111 + } 112 + break; 113 + case IPPROTO_UDP: 114 + sk = udp6_lib_lookup(net, saddr, sport, daddr, dport, 115 + in->ifindex); 116 + if (sk) { 117 + int connected = (sk->sk_state == TCP_ESTABLISHED); 118 + int wildcard = ipv6_addr_any(&sk->sk_v6_rcv_saddr); 119 + 120 + /* NOTE: we return listeners even if bound to 121 + * 0.0.0.0, those are filtered out in 122 + * xt_socket, since xt_TPROXY needs 0 bound 123 + * listeners too 124 + */ 125 + if ((lookup_type == NF_TPROXY_LOOKUP_ESTABLISHED && (!connected || wildcard)) || 126 + (lookup_type == NF_TPROXY_LOOKUP_LISTENER && connected)) { 127 + sock_put(sk); 128 + sk = NULL; 129 + } 130 + } 131 + break; 132 + default: 133 + WARN_ON(1); 134 + sk = NULL; 135 + } 136 + 137 + pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n", 138 + protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk); 139 + 140 + return sk; 141 + } 142 + EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v6); 143 + 144 + MODULE_LICENSE("GPL"); 145 + MODULE_AUTHOR("Balazs Scheidler, Krisztian Kovacs"); 146 + MODULE_DESCRIPTION("Netfilter IPv4 transparent proxy support");
+11
net/netfilter/Kconfig
··· 517 517 This option adds the "counter" expression that you can use to 518 518 include packet and byte counters in a rule. 519 519 520 + config NFT_CONNLIMIT 521 + tristate "Netfilter nf_tables connlimit module" 522 + depends on NF_CONNTRACK 523 + depends on NETFILTER_ADVANCED 524 + select NETFILTER_CONNCOUNT 525 + help 526 + This option adds the "connlimit" expression that you can use to 527 + ratelimit rule matchings per connections. 528 + 520 529 config NFT_LOG 521 530 tristate "Netfilter nf_tables log module" 522 531 help ··· 998 989 depends on IP_NF_MANGLE 999 990 select NF_DEFRAG_IPV4 1000 991 select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n 992 + select NF_TPROXY_IPV4 993 + select NF_TPROXY_IPV6 if IP6_NF_IPTABLES 1001 994 help 1002 995 This option adds a `TPROXY' target, which is somewhat similar to 1003 996 REDIRECT. It can only be used in the mangle table and is useful
+1
net/netfilter/Makefile
··· 80 80 81 81 obj-$(CONFIG_NF_TABLES) += nf_tables.o 82 82 obj-$(CONFIG_NFT_COMPAT) += nft_compat.o 83 + obj-$(CONFIG_NFT_CONNLIMIT) += nft_connlimit.o 83 84 obj-$(CONFIG_NFT_NUMGEN) += nft_numgen.o 84 85 obj-$(CONFIG_NFT_CT) += nft_ct.o 85 86 obj-$(CONFIG_NFT_FLOW_OFFLOAD) += nft_flow_offload.o
+23 -13
net/netfilter/nf_conncount.c
··· 79 79 return memcmp(a, b, klen * sizeof(u32)); 80 80 } 81 81 82 - static bool add_hlist(struct hlist_head *head, 82 + bool nf_conncount_add(struct hlist_head *head, 83 83 const struct nf_conntrack_tuple *tuple) 84 84 { 85 85 struct nf_conncount_tuple *conn; ··· 91 91 hlist_add_head(&conn->node, head); 92 92 return true; 93 93 } 94 + EXPORT_SYMBOL_GPL(nf_conncount_add); 94 95 95 - static unsigned int check_hlist(struct net *net, 96 - struct hlist_head *head, 97 - const struct nf_conntrack_tuple *tuple, 98 - const struct nf_conntrack_zone *zone, 99 - bool *addit) 96 + unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, 97 + const struct nf_conntrack_tuple *tuple, 98 + const struct nf_conntrack_zone *zone, 99 + bool *addit) 100 100 { 101 101 const struct nf_conntrack_tuple_hash *found; 102 102 struct nf_conncount_tuple *conn; ··· 141 141 142 142 return length; 143 143 } 144 + EXPORT_SYMBOL_GPL(nf_conncount_lookup); 144 145 145 146 static void tree_nodes_free(struct rb_root *root, 146 147 struct nf_conncount_rb *gc_nodes[], ··· 188 187 } else { 189 188 /* same source network -> be counted! */ 190 189 unsigned int count; 191 - count = check_hlist(net, &rbconn->hhead, tuple, zone, &addit); 190 + 191 + count = nf_conncount_lookup(net, &rbconn->hhead, tuple, 192 + zone, &addit); 192 193 193 194 tree_nodes_free(root, gc_nodes, gc_count); 194 195 if (!addit) 195 196 return count; 196 197 197 - if (!add_hlist(&rbconn->hhead, tuple)) 198 + if (!nf_conncount_add(&rbconn->hhead, tuple)) 198 199 return 0; /* hotdrop */ 199 200 200 201 return count + 1; ··· 206 203 continue; 207 204 208 205 /* only used for GC on hhead, retval and 'addit' ignored */ 209 - check_hlist(net, &rbconn->hhead, tuple, zone, &addit); 206 + nf_conncount_lookup(net, &rbconn->hhead, tuple, zone, &addit); 210 207 if (hlist_empty(&rbconn->hhead)) 211 208 gc_nodes[gc_count++] = rbconn; 212 209 } ··· 306 303 } 307 304 EXPORT_SYMBOL_GPL(nf_conncount_init); 308 305 309 - static void destroy_tree(struct rb_root *r) 306 + void nf_conncount_cache_free(struct hlist_head *hhead) 310 307 { 311 308 struct nf_conncount_tuple *conn; 312 - struct nf_conncount_rb *rbconn; 313 309 struct hlist_node *n; 310 + 311 + hlist_for_each_entry_safe(conn, n, hhead, node) 312 + kmem_cache_free(conncount_conn_cachep, conn); 313 + } 314 + EXPORT_SYMBOL_GPL(nf_conncount_cache_free); 315 + 316 + static void destroy_tree(struct rb_root *r) 317 + { 318 + struct nf_conncount_rb *rbconn; 314 319 struct rb_node *node; 315 320 316 321 while ((node = rb_first(r)) != NULL) { ··· 326 315 327 316 rb_erase(node, r); 328 317 329 - hlist_for_each_entry_safe(conn, n, &rbconn->hhead, node) 330 - kmem_cache_free(conncount_conn_cachep, conn); 318 + nf_conncount_cache_free(&rbconn->hhead); 331 319 332 320 kmem_cache_free(conncount_rb_cachep, rbconn); 333 321 }
+126 -27
net/netfilter/nf_tables_api.c
··· 34 34 NFT_VALIDATE_DO, 35 35 }; 36 36 37 + static u32 nft_chain_hash(const void *data, u32 len, u32 seed); 38 + static u32 nft_chain_hash_obj(const void *data, u32 len, u32 seed); 39 + static int nft_chain_hash_cmp(struct rhashtable_compare_arg *, const void *); 40 + 41 + static const struct rhashtable_params nft_chain_ht_params = { 42 + .head_offset = offsetof(struct nft_chain, rhlhead), 43 + .key_offset = offsetof(struct nft_chain, name), 44 + .hashfn = nft_chain_hash, 45 + .obj_hashfn = nft_chain_hash_obj, 46 + .obj_cmpfn = nft_chain_hash_cmp, 47 + .locks_mul = 1, 48 + .automatic_shrinking = true, 49 + }; 50 + 37 51 static void nft_validate_state_update(struct net *net, u8 new_validate_state) 38 52 { 39 53 switch (net->nft.validate_state) { ··· 734 720 return ret; 735 721 } 736 722 723 + static u32 nft_chain_hash(const void *data, u32 len, u32 seed) 724 + { 725 + const char *name = data; 726 + 727 + return jhash(name, strlen(name), seed); 728 + } 729 + 730 + static u32 nft_chain_hash_obj(const void *data, u32 len, u32 seed) 731 + { 732 + const struct nft_chain *chain = data; 733 + 734 + return nft_chain_hash(chain->name, 0, seed); 735 + } 736 + 737 + static int nft_chain_hash_cmp(struct rhashtable_compare_arg *arg, 738 + const void *ptr) 739 + { 740 + const struct nft_chain *chain = ptr; 741 + const char *name = arg->key; 742 + 743 + return strcmp(chain->name, name); 744 + } 745 + 737 746 static int nf_tables_newtable(struct net *net, struct sock *nlsk, 738 747 struct sk_buff *skb, const struct nlmsghdr *nlh, 739 748 const struct nlattr * const nla[], ··· 803 766 if (table->name == NULL) 804 767 goto err_strdup; 805 768 769 + err = rhltable_init(&table->chains_ht, &nft_chain_ht_params); 770 + if (err) 771 + goto err_chain_ht; 772 + 806 773 INIT_LIST_HEAD(&table->chains); 807 774 INIT_LIST_HEAD(&table->sets); 808 775 INIT_LIST_HEAD(&table->objects); ··· 823 782 list_add_tail_rcu(&table->list, &net->nft.tables); 824 783 return 0; 825 784 err_trans: 785 + rhltable_destroy(&table->chains_ht); 786 + err_chain_ht: 826 787 kfree(table->name); 827 788 err_strdup: 828 789 kfree(table); ··· 965 922 { 966 923 BUG_ON(ctx->table->use > 0); 967 924 925 + rhltable_destroy(&ctx->table->chains_ht); 968 926 kfree(ctx->table->name); 969 927 kfree(ctx->table); 970 928 } ··· 1011 967 return ERR_PTR(-ENOENT); 1012 968 } 1013 969 1014 - static struct nft_chain *nft_chain_lookup(const struct nft_table *table, 970 + static struct nft_chain *nft_chain_lookup(struct nft_table *table, 1015 971 const struct nlattr *nla, u8 genmask) 1016 972 { 973 + char search[NFT_CHAIN_MAXNAMELEN + 1]; 974 + struct rhlist_head *tmp, *list; 1017 975 struct nft_chain *chain; 1018 976 1019 977 if (nla == NULL) 1020 978 return ERR_PTR(-EINVAL); 1021 979 1022 - list_for_each_entry_rcu(chain, &table->chains, list) { 1023 - if (!nla_strcmp(nla, chain->name) && 1024 - nft_active_genmask(chain, genmask)) 1025 - return chain; 1026 - } 980 + nla_strlcpy(search, nla, sizeof(search)); 1027 981 1028 - return ERR_PTR(-ENOENT); 982 + WARN_ON(!rcu_read_lock_held() && 983 + !lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES)); 984 + 985 + chain = ERR_PTR(-ENOENT); 986 + rcu_read_lock(); 987 + list = rhltable_lookup(&table->chains_ht, search, nft_chain_ht_params); 988 + if (!list) 989 + goto out_unlock; 990 + 991 + rhl_for_each_entry_rcu(chain, tmp, list, rhlhead) { 992 + if (nft_active_genmask(chain, genmask)) 993 + goto out_unlock; 994 + } 995 + chain = ERR_PTR(-ENOENT); 996 + out_unlock: 997 + rcu_read_unlock(); 998 + return chain; 1029 999 } 1030 1000 1031 1001 static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = { ··· 1243 1185 { 1244 1186 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1245 1187 u8 genmask = nft_genmask_cur(net); 1246 - const struct nft_table *table; 1247 1188 const struct nft_chain *chain; 1189 + struct nft_table *table; 1248 1190 struct sk_buff *skb2; 1249 1191 int family = nfmsg->nfgen_family; 1250 1192 int err; ··· 1562 1504 if (err < 0) 1563 1505 goto err1; 1564 1506 1565 - err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN); 1566 - if (err < 0) 1507 + err = rhltable_insert_key(&table->chains_ht, chain->name, 1508 + &chain->rhlhead, nft_chain_ht_params); 1509 + if (err) 1567 1510 goto err2; 1511 + 1512 + err = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN); 1513 + if (err < 0) { 1514 + rhltable_remove(&table->chains_ht, &chain->rhlhead, 1515 + nft_chain_ht_params); 1516 + goto err2; 1517 + } 1568 1518 1569 1519 table->use++; 1570 1520 list_add_tail_rcu(&chain->list, &table->chains); ··· 2272 2206 { 2273 2207 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2274 2208 u8 genmask = nft_genmask_cur(net); 2275 - const struct nft_table *table; 2276 2209 const struct nft_chain *chain; 2277 2210 const struct nft_rule *rule; 2211 + struct nft_table *table; 2278 2212 struct sk_buff *skb2; 2279 2213 int family = nfmsg->nfgen_family; 2280 2214 int err; ··· 3425 3359 } 3426 3360 3427 3361 INIT_LIST_HEAD(&set->bindings); 3362 + set->table = table; 3363 + write_pnet(&set->net, net); 3428 3364 set->ops = ops; 3429 3365 set->ktype = ktype; 3430 3366 set->klen = desc.klen; ··· 4104 4036 bool destroy_expr) 4105 4037 { 4106 4038 struct nft_set_ext *ext = nft_set_elem_ext(set, elem); 4039 + struct nft_ctx ctx = { 4040 + .net = read_pnet(&set->net), 4041 + .family = set->table->family, 4042 + }; 4107 4043 4108 4044 nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE); 4109 4045 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) 4110 4046 nft_data_release(nft_set_ext_data(ext), set->dtype); 4111 - if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) 4112 - nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext)); 4047 + if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) { 4048 + struct nft_expr *expr = nft_set_ext_expr(ext); 4049 + 4050 + if (expr->ops->destroy_clone) { 4051 + expr->ops->destroy_clone(&ctx, expr); 4052 + module_put(expr->ops->type->owner); 4053 + } else { 4054 + nf_tables_expr_destroy(&ctx, expr); 4055 + } 4056 + } 4113 4057 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF)) 4114 4058 (*nft_set_ext_obj(ext))->use--; 4115 4059 kfree(elem); ··· 4131 4051 /* Only called from commit path, nft_set_elem_deactivate() already deals with 4132 4052 * the refcounting from the preparation phase. 4133 4053 */ 4134 - static void nf_tables_set_elem_destroy(const struct nft_set *set, void *elem) 4054 + static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx, 4055 + const struct nft_set *set, void *elem) 4135 4056 { 4136 4057 struct nft_set_ext *ext = nft_set_elem_ext(set, elem); 4137 4058 4138 4059 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) 4139 - nf_tables_expr_destroy(NULL, nft_set_ext_expr(ext)); 4060 + nf_tables_expr_destroy(ctx, nft_set_ext_expr(ext)); 4140 4061 kfree(elem); 4141 4062 } 4142 4063 ··· 4868 4787 kfree(obj->name); 4869 4788 err2: 4870 4789 if (obj->ops->destroy) 4871 - obj->ops->destroy(obj); 4790 + obj->ops->destroy(&ctx, obj); 4872 4791 kfree(obj); 4873 4792 err1: 4874 4793 module_put(type->owner); ··· 5078 4997 return err; 5079 4998 } 5080 4999 5081 - static void nft_obj_destroy(struct nft_object *obj) 5000 + static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) 5082 5001 { 5083 5002 if (obj->ops->destroy) 5084 - obj->ops->destroy(obj); 5003 + obj->ops->destroy(ctx, obj); 5085 5004 5086 5005 module_put(obj->ops->type->owner); 5087 5006 kfree(obj->name); ··· 6047 5966 { 6048 5967 struct nft_base_chain *basechain; 6049 5968 6050 - if (nft_trans_chain_name(trans)) 5969 + if (nft_trans_chain_name(trans)) { 5970 + rhltable_remove(&trans->ctx.table->chains_ht, 5971 + &trans->ctx.chain->rhlhead, 5972 + nft_chain_ht_params); 6051 5973 swap(trans->ctx.chain->name, nft_trans_chain_name(trans)); 5974 + rhltable_insert_key(&trans->ctx.table->chains_ht, 5975 + trans->ctx.chain->name, 5976 + &trans->ctx.chain->rhlhead, 5977 + nft_chain_ht_params); 5978 + } 6052 5979 6053 5980 if (!nft_is_base_chain(trans->ctx.chain)) 6054 5981 return; ··· 6088 5999 nft_set_destroy(nft_trans_set(trans)); 6089 6000 break; 6090 6001 case NFT_MSG_DELSETELEM: 6091 - nf_tables_set_elem_destroy(nft_trans_elem_set(trans), 6002 + nf_tables_set_elem_destroy(&trans->ctx, 6003 + nft_trans_elem_set(trans), 6092 6004 nft_trans_elem(trans).priv); 6093 6005 break; 6094 6006 case NFT_MSG_DELOBJ: 6095 - nft_obj_destroy(nft_trans_obj(trans)); 6007 + nft_obj_destroy(&trans->ctx, nft_trans_obj(trans)); 6096 6008 break; 6097 6009 case NFT_MSG_DELFLOWTABLE: 6098 6010 nf_tables_flowtable_destroy(nft_trans_flowtable(trans)); ··· 6233 6143 nf_tables_commit_chain_free_rules_old(g0); 6234 6144 } 6235 6145 6146 + static void nft_chain_del(struct nft_chain *chain) 6147 + { 6148 + struct nft_table *table = chain->table; 6149 + 6150 + WARN_ON_ONCE(rhltable_remove(&table->chains_ht, &chain->rhlhead, 6151 + nft_chain_ht_params)); 6152 + list_del_rcu(&chain->list); 6153 + } 6154 + 6236 6155 static int nf_tables_commit(struct net *net, struct sk_buff *skb) 6237 6156 { 6238 6157 struct nft_trans *trans, *next; ··· 6316 6217 nft_trans_destroy(trans); 6317 6218 break; 6318 6219 case NFT_MSG_DELCHAIN: 6319 - list_del_rcu(&trans->ctx.chain->list); 6220 + nft_chain_del(trans->ctx.chain); 6320 6221 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN); 6321 6222 nf_tables_unregister_hook(trans->ctx.net, 6322 6223 trans->ctx.table, ··· 6427 6328 nft_trans_elem(trans).priv, true); 6428 6329 break; 6429 6330 case NFT_MSG_NEWOBJ: 6430 - nft_obj_destroy(nft_trans_obj(trans)); 6331 + nft_obj_destroy(&trans->ctx, nft_trans_obj(trans)); 6431 6332 break; 6432 6333 case NFT_MSG_NEWFLOWTABLE: 6433 6334 nf_tables_flowtable_destroy(nft_trans_flowtable(trans)); ··· 6467 6368 nft_trans_destroy(trans); 6468 6369 } else { 6469 6370 trans->ctx.table->use--; 6470 - list_del_rcu(&trans->ctx.chain->list); 6371 + nft_chain_del(trans->ctx.chain); 6471 6372 nf_tables_unregister_hook(trans->ctx.net, 6472 6373 trans->ctx.table, 6473 6374 trans->ctx.chain); ··· 7069 6970 ctx->chain->use--; 7070 6971 nf_tables_rule_release(ctx, rule); 7071 6972 } 7072 - list_del(&ctx->chain->list); 6973 + nft_chain_del(ctx->chain); 7073 6974 ctx->table->use--; 7074 6975 nf_tables_chain_destroy(ctx); 7075 6976 ··· 7121 7022 list_for_each_entry_safe(obj, ne, &table->objects, list) { 7122 7023 list_del(&obj->list); 7123 7024 table->use--; 7124 - nft_obj_destroy(obj); 7025 + nft_obj_destroy(&ctx, obj); 7125 7026 } 7126 7027 list_for_each_entry_safe(chain, nc, &table->chains, list) { 7127 7028 ctx.chain = chain; 7128 - list_del(&chain->list); 7029 + nft_chain_del(chain); 7129 7030 table->use--; 7130 7031 nf_tables_chain_destroy(&ctx); 7131 7032 }
+297
net/netfilter/nft_connlimit.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #include <linux/kernel.h> 3 + #include <linux/init.h> 4 + #include <linux/module.h> 5 + #include <linux/spinlock.h> 6 + #include <linux/netlink.h> 7 + #include <linux/netfilter.h> 8 + #include <linux/netfilter/nf_tables.h> 9 + #include <net/netfilter/nf_tables.h> 10 + #include <net/netfilter/nf_conntrack.h> 11 + #include <net/netfilter/nf_conntrack_count.h> 12 + #include <net/netfilter/nf_conntrack_core.h> 13 + #include <net/netfilter/nf_conntrack_tuple.h> 14 + #include <net/netfilter/nf_conntrack_zones.h> 15 + 16 + struct nft_connlimit { 17 + spinlock_t lock; 18 + struct hlist_head hhead; 19 + u32 limit; 20 + bool invert; 21 + }; 22 + 23 + static inline void nft_connlimit_do_eval(struct nft_connlimit *priv, 24 + struct nft_regs *regs, 25 + const struct nft_pktinfo *pkt, 26 + const struct nft_set_ext *ext) 27 + { 28 + const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt; 29 + const struct nf_conntrack_tuple *tuple_ptr; 30 + struct nf_conntrack_tuple tuple; 31 + enum ip_conntrack_info ctinfo; 32 + const struct nf_conn *ct; 33 + unsigned int count; 34 + bool addit; 35 + 36 + tuple_ptr = &tuple; 37 + 38 + ct = nf_ct_get(pkt->skb, &ctinfo); 39 + if (ct != NULL) { 40 + tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 41 + zone = nf_ct_zone(ct); 42 + } else if (!nf_ct_get_tuplepr(pkt->skb, skb_network_offset(pkt->skb), 43 + nft_pf(pkt), nft_net(pkt), &tuple)) { 44 + regs->verdict.code = NF_DROP; 45 + return; 46 + } 47 + 48 + spin_lock_bh(&priv->lock); 49 + count = nf_conncount_lookup(nft_net(pkt), &priv->hhead, tuple_ptr, zone, 50 + &addit); 51 + 52 + if (!addit) 53 + goto out; 54 + 55 + if (!nf_conncount_add(&priv->hhead, tuple_ptr)) { 56 + regs->verdict.code = NF_DROP; 57 + spin_unlock_bh(&priv->lock); 58 + return; 59 + } 60 + count++; 61 + out: 62 + spin_unlock_bh(&priv->lock); 63 + 64 + if ((count > priv->limit) ^ priv->invert) { 65 + regs->verdict.code = NFT_BREAK; 66 + return; 67 + } 68 + } 69 + 70 + static int nft_connlimit_do_init(const struct nft_ctx *ctx, 71 + const struct nlattr * const tb[], 72 + struct nft_connlimit *priv) 73 + { 74 + bool invert = false; 75 + u32 flags, limit; 76 + 77 + if (!tb[NFTA_CONNLIMIT_COUNT]) 78 + return -EINVAL; 79 + 80 + limit = ntohl(nla_get_be32(tb[NFTA_CONNLIMIT_COUNT])); 81 + 82 + if (tb[NFTA_CONNLIMIT_FLAGS]) { 83 + flags = ntohl(nla_get_be32(tb[NFTA_CONNLIMIT_FLAGS])); 84 + if (flags & ~NFT_CONNLIMIT_F_INV) 85 + return -EOPNOTSUPP; 86 + if (flags & NFT_CONNLIMIT_F_INV) 87 + invert = true; 88 + } 89 + 90 + spin_lock_init(&priv->lock); 91 + INIT_HLIST_HEAD(&priv->hhead); 92 + priv->limit = limit; 93 + priv->invert = invert; 94 + 95 + return nf_ct_netns_get(ctx->net, ctx->family); 96 + } 97 + 98 + static void nft_connlimit_do_destroy(const struct nft_ctx *ctx, 99 + struct nft_connlimit *priv) 100 + { 101 + nf_ct_netns_put(ctx->net, ctx->family); 102 + nf_conncount_cache_free(&priv->hhead); 103 + } 104 + 105 + static int nft_connlimit_do_dump(struct sk_buff *skb, 106 + struct nft_connlimit *priv) 107 + { 108 + if (nla_put_be32(skb, NFTA_CONNLIMIT_COUNT, htonl(priv->limit))) 109 + goto nla_put_failure; 110 + if (priv->invert && 111 + nla_put_be32(skb, NFTA_CONNLIMIT_FLAGS, htonl(NFT_CONNLIMIT_F_INV))) 112 + goto nla_put_failure; 113 + 114 + return 0; 115 + 116 + nla_put_failure: 117 + return -1; 118 + } 119 + 120 + static inline void nft_connlimit_obj_eval(struct nft_object *obj, 121 + struct nft_regs *regs, 122 + const struct nft_pktinfo *pkt) 123 + { 124 + struct nft_connlimit *priv = nft_obj_data(obj); 125 + 126 + nft_connlimit_do_eval(priv, regs, pkt, NULL); 127 + } 128 + 129 + static int nft_connlimit_obj_init(const struct nft_ctx *ctx, 130 + const struct nlattr * const tb[], 131 + struct nft_object *obj) 132 + { 133 + struct nft_connlimit *priv = nft_obj_data(obj); 134 + 135 + return nft_connlimit_do_init(ctx, tb, priv); 136 + } 137 + 138 + static void nft_connlimit_obj_destroy(const struct nft_ctx *ctx, 139 + struct nft_object *obj) 140 + { 141 + struct nft_connlimit *priv = nft_obj_data(obj); 142 + 143 + nft_connlimit_do_destroy(ctx, priv); 144 + } 145 + 146 + static int nft_connlimit_obj_dump(struct sk_buff *skb, 147 + struct nft_object *obj, bool reset) 148 + { 149 + struct nft_connlimit *priv = nft_obj_data(obj); 150 + 151 + return nft_connlimit_do_dump(skb, priv); 152 + } 153 + 154 + static const struct nla_policy nft_connlimit_policy[NFTA_CONNLIMIT_MAX + 1] = { 155 + [NFTA_CONNLIMIT_COUNT] = { .type = NLA_U32 }, 156 + [NFTA_CONNLIMIT_FLAGS] = { .type = NLA_U32 }, 157 + }; 158 + 159 + static struct nft_object_type nft_connlimit_obj_type; 160 + static const struct nft_object_ops nft_connlimit_obj_ops = { 161 + .type = &nft_connlimit_obj_type, 162 + .size = sizeof(struct nft_connlimit), 163 + .eval = nft_connlimit_obj_eval, 164 + .init = nft_connlimit_obj_init, 165 + .destroy = nft_connlimit_obj_destroy, 166 + .dump = nft_connlimit_obj_dump, 167 + }; 168 + 169 + static struct nft_object_type nft_connlimit_obj_type __read_mostly = { 170 + .type = NFT_OBJECT_CONNLIMIT, 171 + .ops = &nft_connlimit_obj_ops, 172 + .maxattr = NFTA_CONNLIMIT_MAX, 173 + .policy = nft_connlimit_policy, 174 + .owner = THIS_MODULE, 175 + }; 176 + 177 + static void nft_connlimit_eval(const struct nft_expr *expr, 178 + struct nft_regs *regs, 179 + const struct nft_pktinfo *pkt) 180 + { 181 + struct nft_connlimit *priv = nft_expr_priv(expr); 182 + 183 + nft_connlimit_do_eval(priv, regs, pkt, NULL); 184 + } 185 + 186 + static int nft_connlimit_dump(struct sk_buff *skb, const struct nft_expr *expr) 187 + { 188 + struct nft_connlimit *priv = nft_expr_priv(expr); 189 + 190 + return nft_connlimit_do_dump(skb, priv); 191 + } 192 + 193 + static int nft_connlimit_init(const struct nft_ctx *ctx, 194 + const struct nft_expr *expr, 195 + const struct nlattr * const tb[]) 196 + { 197 + struct nft_connlimit *priv = nft_expr_priv(expr); 198 + 199 + return nft_connlimit_do_init(ctx, tb, priv); 200 + } 201 + 202 + static void nft_connlimit_destroy(const struct nft_ctx *ctx, 203 + const struct nft_expr *expr) 204 + { 205 + struct nft_connlimit *priv = nft_expr_priv(expr); 206 + 207 + nft_connlimit_do_destroy(ctx, priv); 208 + } 209 + 210 + static int nft_connlimit_clone(struct nft_expr *dst, const struct nft_expr *src) 211 + { 212 + struct nft_connlimit *priv_dst = nft_expr_priv(dst); 213 + struct nft_connlimit *priv_src = nft_expr_priv(src); 214 + 215 + spin_lock_init(&priv_dst->lock); 216 + INIT_HLIST_HEAD(&priv_dst->hhead); 217 + priv_dst->limit = priv_src->limit; 218 + priv_dst->invert = priv_src->invert; 219 + 220 + return 0; 221 + } 222 + 223 + static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx, 224 + const struct nft_expr *expr) 225 + { 226 + struct nft_connlimit *priv = nft_expr_priv(expr); 227 + 228 + nf_conncount_cache_free(&priv->hhead); 229 + } 230 + 231 + static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr) 232 + { 233 + struct nft_connlimit *priv = nft_expr_priv(expr); 234 + bool addit, ret; 235 + 236 + spin_lock_bh(&priv->lock); 237 + nf_conncount_lookup(net, &priv->hhead, NULL, &nf_ct_zone_dflt, &addit); 238 + 239 + ret = hlist_empty(&priv->hhead); 240 + spin_unlock_bh(&priv->lock); 241 + 242 + return ret; 243 + } 244 + 245 + static struct nft_expr_type nft_connlimit_type; 246 + static const struct nft_expr_ops nft_connlimit_ops = { 247 + .type = &nft_connlimit_type, 248 + .size = NFT_EXPR_SIZE(sizeof(struct nft_connlimit)), 249 + .eval = nft_connlimit_eval, 250 + .init = nft_connlimit_init, 251 + .destroy = nft_connlimit_destroy, 252 + .clone = nft_connlimit_clone, 253 + .destroy_clone = nft_connlimit_destroy_clone, 254 + .dump = nft_connlimit_dump, 255 + .gc = nft_connlimit_gc, 256 + }; 257 + 258 + static struct nft_expr_type nft_connlimit_type __read_mostly = { 259 + .name = "connlimit", 260 + .ops = &nft_connlimit_ops, 261 + .policy = nft_connlimit_policy, 262 + .maxattr = NFTA_CONNLIMIT_MAX, 263 + .flags = NFT_EXPR_STATEFUL | NFT_EXPR_GC, 264 + .owner = THIS_MODULE, 265 + }; 266 + 267 + static int __init nft_connlimit_module_init(void) 268 + { 269 + int err; 270 + 271 + err = nft_register_obj(&nft_connlimit_obj_type); 272 + if (err < 0) 273 + return err; 274 + 275 + err = nft_register_expr(&nft_connlimit_type); 276 + if (err < 0) 277 + goto err1; 278 + 279 + return 0; 280 + err1: 281 + nft_unregister_obj(&nft_connlimit_obj_type); 282 + return err; 283 + } 284 + 285 + static void __exit nft_connlimit_module_exit(void) 286 + { 287 + nft_unregister_expr(&nft_connlimit_type); 288 + nft_unregister_obj(&nft_connlimit_obj_type); 289 + } 290 + 291 + module_init(nft_connlimit_module_init); 292 + module_exit(nft_connlimit_module_exit); 293 + 294 + MODULE_LICENSE("GPL"); 295 + MODULE_AUTHOR("Pablo Neira Ayuso"); 296 + MODULE_ALIAS_NFT_EXPR("connlimit"); 297 + MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CONNLIMIT);
+3 -1
net/netfilter/nft_counter.c
··· 96 96 free_percpu(priv->counter); 97 97 } 98 98 99 - static void nft_counter_obj_destroy(struct nft_object *obj) 99 + static void nft_counter_obj_destroy(const struct nft_ctx *ctx, 100 + struct nft_object *obj) 100 101 { 101 102 struct nft_counter_percpu_priv *priv = nft_obj_data(obj); 102 103 ··· 258 257 .eval = nft_counter_eval, 259 258 .init = nft_counter_init, 260 259 .destroy = nft_counter_destroy, 260 + .destroy_clone = nft_counter_destroy, 261 261 .dump = nft_counter_dump, 262 262 .clone = nft_counter_clone, 263 263 };
+2 -1
net/netfilter/nft_ct.c
··· 826 826 return 0; 827 827 } 828 828 829 - static void nft_ct_helper_obj_destroy(struct nft_object *obj) 829 + static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx, 830 + struct nft_object *obj) 830 831 { 831 832 struct nft_ct_helper_obj *priv = nft_obj_data(obj); 832 833
+9
net/netfilter/nft_dynset.c
··· 195 195 err = -EOPNOTSUPP; 196 196 if (!(priv->expr->ops->type->flags & NFT_EXPR_STATEFUL)) 197 197 goto err1; 198 + 199 + if (priv->expr->ops->type->flags & NFT_EXPR_GC) { 200 + if (set->flags & NFT_SET_TIMEOUT) 201 + goto err1; 202 + if (!set->ops->gc_init) 203 + goto err1; 204 + set->ops->gc_init(set); 205 + } 206 + 198 207 } else if (set->flags & NFT_SET_EVAL) 199 208 return -EINVAL; 200 209
+19 -2
net/netfilter/nft_set_hash.c
··· 311 311 continue; 312 312 } 313 313 314 + if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPR)) { 315 + struct nft_expr *expr = nft_set_ext_expr(&he->ext); 316 + 317 + if (expr->ops->gc && 318 + expr->ops->gc(read_pnet(&set->net), expr)) 319 + goto gc; 320 + } 314 321 if (!nft_set_elem_expired(&he->ext)) 315 322 continue; 323 + gc: 316 324 if (nft_set_elem_mark_busy(&he->ext)) 317 325 continue; 318 326 ··· 347 339 return sizeof(struct nft_rhash); 348 340 } 349 341 342 + static void nft_rhash_gc_init(const struct nft_set *set) 343 + { 344 + struct nft_rhash *priv = nft_set_priv(set); 345 + 346 + queue_delayed_work(system_power_efficient_wq, &priv->gc_work, 347 + nft_set_gc_interval(set)); 348 + } 349 + 350 350 static int nft_rhash_init(const struct nft_set *set, 351 351 const struct nft_set_desc *desc, 352 352 const struct nlattr * const tb[]) ··· 372 356 373 357 INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc); 374 358 if (set->flags & NFT_SET_TIMEOUT) 375 - queue_delayed_work(system_power_efficient_wq, &priv->gc_work, 376 - nft_set_gc_interval(set)); 359 + nft_rhash_gc_init(set); 360 + 377 361 return 0; 378 362 } 379 363 ··· 663 647 .elemsize = offsetof(struct nft_rhash_elem, ext), 664 648 .estimate = nft_rhash_estimate, 665 649 .init = nft_rhash_init, 650 + .gc_init = nft_rhash_gc_init, 666 651 .destroy = nft_rhash_destroy, 667 652 .insert = nft_rhash_insert, 668 653 .activate = nft_rhash_activate,
+2 -1
net/netfilter/nft_socket.c
··· 5 5 #include <net/netfilter/nf_tables_core.h> 6 6 #include <net/netfilter/nf_socket.h> 7 7 #include <net/inet_sock.h> 8 + #include <net/tcp.h> 8 9 9 10 struct nft_socket { 10 11 enum nft_socket_keys key:8; ··· 49 48 50 49 switch(priv->key) { 51 50 case NFT_SOCKET_TRANSPARENT: 52 - nft_reg_store8(dest, nf_sk_is_transparent(sk)); 51 + nft_reg_store8(dest, inet_sk_transparent(sk)); 53 52 break; 54 53 default: 55 54 WARN_ON(1);
+18 -348
net/netfilter/xt_TPROXY.c
··· 33 33 #include <net/netfilter/ipv6/nf_defrag_ipv6.h> 34 34 #endif 35 35 36 + #include <net/netfilter/nf_tproxy.h> 36 37 #include <linux/netfilter/xt_TPROXY.h> 37 - 38 - enum nf_tproxy_lookup_t { 39 - NFT_LOOKUP_LISTENER, 40 - NFT_LOOKUP_ESTABLISHED, 41 - }; 42 - 43 - static bool tproxy_sk_is_transparent(struct sock *sk) 44 - { 45 - switch (sk->sk_state) { 46 - case TCP_TIME_WAIT: 47 - if (inet_twsk(sk)->tw_transparent) 48 - return true; 49 - break; 50 - case TCP_NEW_SYN_RECV: 51 - if (inet_rsk(inet_reqsk(sk))->no_srccheck) 52 - return true; 53 - break; 54 - default: 55 - if (inet_sk(sk)->transparent) 56 - return true; 57 - } 58 - 59 - sock_gen_put(sk); 60 - return false; 61 - } 62 - 63 - static inline __be32 64 - tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) 65 - { 66 - struct in_device *indev; 67 - __be32 laddr; 68 - 69 - if (user_laddr) 70 - return user_laddr; 71 - 72 - laddr = 0; 73 - indev = __in_dev_get_rcu(skb->dev); 74 - for_primary_ifa(indev) { 75 - laddr = ifa->ifa_local; 76 - break; 77 - } endfor_ifa(indev); 78 - 79 - return laddr ? laddr : daddr; 80 - } 81 - 82 - /* 83 - * This is used when the user wants to intercept a connection matching 84 - * an explicit iptables rule. In this case the sockets are assumed 85 - * matching in preference order: 86 - * 87 - * - match: if there's a fully established connection matching the 88 - * _packet_ tuple, it is returned, assuming the redirection 89 - * already took place and we process a packet belonging to an 90 - * established connection 91 - * 92 - * - match: if there's a listening socket matching the redirection 93 - * (e.g. on-port & on-ip of the connection), it is returned, 94 - * regardless if it was bound to 0.0.0.0 or an explicit 95 - * address. The reasoning is that if there's an explicit rule, it 96 - * does not really matter if the listener is bound to an interface 97 - * or to 0. The user already stated that he wants redirection 98 - * (since he added the rule). 99 - * 100 - * Please note that there's an overlap between what a TPROXY target 101 - * and a socket match will match. Normally if you have both rules the 102 - * "socket" match will be the first one, effectively all packets 103 - * belonging to established connections going through that one. 104 - */ 105 - static inline struct sock * 106 - nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp, 107 - const u8 protocol, 108 - const __be32 saddr, const __be32 daddr, 109 - const __be16 sport, const __be16 dport, 110 - const struct net_device *in, 111 - const enum nf_tproxy_lookup_t lookup_type) 112 - { 113 - struct sock *sk; 114 - struct tcphdr *tcph; 115 - 116 - switch (protocol) { 117 - case IPPROTO_TCP: 118 - switch (lookup_type) { 119 - case NFT_LOOKUP_LISTENER: 120 - tcph = hp; 121 - sk = inet_lookup_listener(net, &tcp_hashinfo, skb, 122 - ip_hdrlen(skb) + 123 - __tcp_hdrlen(tcph), 124 - saddr, sport, 125 - daddr, dport, 126 - in->ifindex, 0); 127 - 128 - if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 129 - sk = NULL; 130 - /* NOTE: we return listeners even if bound to 131 - * 0.0.0.0, those are filtered out in 132 - * xt_socket, since xt_TPROXY needs 0 bound 133 - * listeners too 134 - */ 135 - break; 136 - case NFT_LOOKUP_ESTABLISHED: 137 - sk = inet_lookup_established(net, &tcp_hashinfo, 138 - saddr, sport, daddr, dport, 139 - in->ifindex); 140 - break; 141 - default: 142 - BUG(); 143 - } 144 - break; 145 - case IPPROTO_UDP: 146 - sk = udp4_lib_lookup(net, saddr, sport, daddr, dport, 147 - in->ifindex); 148 - if (sk) { 149 - int connected = (sk->sk_state == TCP_ESTABLISHED); 150 - int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0); 151 - 152 - /* NOTE: we return listeners even if bound to 153 - * 0.0.0.0, those are filtered out in 154 - * xt_socket, since xt_TPROXY needs 0 bound 155 - * listeners too 156 - */ 157 - if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) || 158 - (lookup_type == NFT_LOOKUP_LISTENER && connected)) { 159 - sock_put(sk); 160 - sk = NULL; 161 - } 162 - } 163 - break; 164 - default: 165 - WARN_ON(1); 166 - sk = NULL; 167 - } 168 - 169 - pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n", 170 - protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk); 171 - 172 - return sk; 173 - } 174 - 175 - #ifdef XT_TPROXY_HAVE_IPV6 176 - static inline struct sock * 177 - nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp, 178 - const u8 protocol, 179 - const struct in6_addr *saddr, const struct in6_addr *daddr, 180 - const __be16 sport, const __be16 dport, 181 - const struct net_device *in, 182 - const enum nf_tproxy_lookup_t lookup_type) 183 - { 184 - struct sock *sk; 185 - struct tcphdr *tcph; 186 - 187 - switch (protocol) { 188 - case IPPROTO_TCP: 189 - switch (lookup_type) { 190 - case NFT_LOOKUP_LISTENER: 191 - tcph = hp; 192 - sk = inet6_lookup_listener(net, &tcp_hashinfo, skb, 193 - thoff + __tcp_hdrlen(tcph), 194 - saddr, sport, 195 - daddr, ntohs(dport), 196 - in->ifindex, 0); 197 - 198 - if (sk && !refcount_inc_not_zero(&sk->sk_refcnt)) 199 - sk = NULL; 200 - /* NOTE: we return listeners even if bound to 201 - * 0.0.0.0, those are filtered out in 202 - * xt_socket, since xt_TPROXY needs 0 bound 203 - * listeners too 204 - */ 205 - break; 206 - case NFT_LOOKUP_ESTABLISHED: 207 - sk = __inet6_lookup_established(net, &tcp_hashinfo, 208 - saddr, sport, daddr, ntohs(dport), 209 - in->ifindex, 0); 210 - break; 211 - default: 212 - BUG(); 213 - } 214 - break; 215 - case IPPROTO_UDP: 216 - sk = udp6_lib_lookup(net, saddr, sport, daddr, dport, 217 - in->ifindex); 218 - if (sk) { 219 - int connected = (sk->sk_state == TCP_ESTABLISHED); 220 - int wildcard = ipv6_addr_any(&sk->sk_v6_rcv_saddr); 221 - 222 - /* NOTE: we return listeners even if bound to 223 - * 0.0.0.0, those are filtered out in 224 - * xt_socket, since xt_TPROXY needs 0 bound 225 - * listeners too 226 - */ 227 - if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) || 228 - (lookup_type == NFT_LOOKUP_LISTENER && connected)) { 229 - sock_put(sk); 230 - sk = NULL; 231 - } 232 - } 233 - break; 234 - default: 235 - WARN_ON(1); 236 - sk = NULL; 237 - } 238 - 239 - pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n", 240 - protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk); 241 - 242 - return sk; 243 - } 244 - #endif 245 - 246 - /** 247 - * tproxy_handle_time_wait4 - handle IPv4 TCP TIME_WAIT reopen redirections 248 - * @skb: The skb being processed. 249 - * @laddr: IPv4 address to redirect to or zero. 250 - * @lport: TCP port to redirect to or zero. 251 - * @sk: The TIME_WAIT TCP socket found by the lookup. 252 - * 253 - * We have to handle SYN packets arriving to TIME_WAIT sockets 254 - * differently: instead of reopening the connection we should rather 255 - * redirect the new connection to the proxy if there's a listener 256 - * socket present. 257 - * 258 - * tproxy_handle_time_wait4() consumes the socket reference passed in. 259 - * 260 - * Returns the listener socket if there's one, the TIME_WAIT socket if 261 - * no such listener is found, or NULL if the TCP header is incomplete. 262 - */ 263 - static struct sock * 264 - tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb, 265 - __be32 laddr, __be16 lport, struct sock *sk) 266 - { 267 - const struct iphdr *iph = ip_hdr(skb); 268 - struct tcphdr _hdr, *hp; 269 - 270 - hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr); 271 - if (hp == NULL) { 272 - inet_twsk_put(inet_twsk(sk)); 273 - return NULL; 274 - } 275 - 276 - if (hp->syn && !hp->rst && !hp->ack && !hp->fin) { 277 - /* SYN to a TIME_WAIT socket, we'd rather redirect it 278 - * to a listener socket if there's one */ 279 - struct sock *sk2; 280 - 281 - sk2 = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, 282 - iph->saddr, laddr ? laddr : iph->daddr, 283 - hp->source, lport ? lport : hp->dest, 284 - skb->dev, NFT_LOOKUP_LISTENER); 285 - if (sk2) { 286 - inet_twsk_deschedule_put(inet_twsk(sk)); 287 - sk = sk2; 288 - } 289 - } 290 - 291 - return sk; 292 - } 293 38 294 39 /* assign a socket to the skb -- consumes sk */ 295 40 static void ··· 64 319 sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, 65 320 iph->saddr, iph->daddr, 66 321 hp->source, hp->dest, 67 - skb->dev, NFT_LOOKUP_ESTABLISHED); 322 + skb->dev, NF_TPROXY_LOOKUP_ESTABLISHED); 68 323 69 - laddr = tproxy_laddr4(skb, laddr, iph->daddr); 324 + laddr = nf_tproxy_laddr4(skb, laddr, iph->daddr); 70 325 if (!lport) 71 326 lport = hp->dest; 72 327 73 328 /* UDP has no TCP_TIME_WAIT state, so we never enter here */ 74 329 if (sk && sk->sk_state == TCP_TIME_WAIT) 75 330 /* reopening a TIME_WAIT connection needs special handling */ 76 - sk = tproxy_handle_time_wait4(net, skb, laddr, lport, sk); 331 + sk = nf_tproxy_handle_time_wait4(net, skb, laddr, lport, sk); 77 332 else if (!sk) 78 333 /* no, there's no established connection, check if 79 334 * there's a listener on the redirected addr/port */ 80 335 sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, 81 336 iph->saddr, laddr, 82 337 hp->source, lport, 83 - skb->dev, NFT_LOOKUP_LISTENER); 338 + skb->dev, NF_TPROXY_LOOKUP_LISTENER); 84 339 85 340 /* NOTE: assign_sock consumes our sk reference */ 86 - if (sk && tproxy_sk_is_transparent(sk)) { 341 + if (sk && nf_tproxy_sk_is_transparent(sk)) { 87 342 /* This should be in a separate target, but we don't do multiple 88 343 targets on the same rule yet */ 89 344 skb->mark = (skb->mark & ~mark_mask) ^ mark_value; ··· 122 377 123 378 #ifdef XT_TPROXY_HAVE_IPV6 124 379 125 - static inline const struct in6_addr * 126 - tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr, 127 - const struct in6_addr *daddr) 128 - { 129 - struct inet6_dev *indev; 130 - struct inet6_ifaddr *ifa; 131 - struct in6_addr *laddr; 132 - 133 - if (!ipv6_addr_any(user_laddr)) 134 - return user_laddr; 135 - laddr = NULL; 136 - 137 - indev = __in6_dev_get(skb->dev); 138 - if (indev) { 139 - read_lock_bh(&indev->lock); 140 - list_for_each_entry(ifa, &indev->addr_list, if_list) { 141 - if (ifa->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)) 142 - continue; 143 - 144 - laddr = &ifa->addr; 145 - break; 146 - } 147 - read_unlock_bh(&indev->lock); 148 - } 149 - 150 - return laddr ? laddr : daddr; 151 - } 152 - 153 - /** 154 - * tproxy_handle_time_wait6 - handle IPv6 TCP TIME_WAIT reopen redirections 155 - * @skb: The skb being processed. 156 - * @tproto: Transport protocol. 157 - * @thoff: Transport protocol header offset. 158 - * @par: Iptables target parameters. 159 - * @sk: The TIME_WAIT TCP socket found by the lookup. 160 - * 161 - * We have to handle SYN packets arriving to TIME_WAIT sockets 162 - * differently: instead of reopening the connection we should rather 163 - * redirect the new connection to the proxy if there's a listener 164 - * socket present. 165 - * 166 - * tproxy_handle_time_wait6() consumes the socket reference passed in. 167 - * 168 - * Returns the listener socket if there's one, the TIME_WAIT socket if 169 - * no such listener is found, or NULL if the TCP header is incomplete. 170 - */ 171 - static struct sock * 172 - tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff, 173 - const struct xt_action_param *par, 174 - struct sock *sk) 175 - { 176 - const struct ipv6hdr *iph = ipv6_hdr(skb); 177 - struct tcphdr _hdr, *hp; 178 - const struct xt_tproxy_target_info_v1 *tgi = par->targinfo; 179 - 180 - hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr); 181 - if (hp == NULL) { 182 - inet_twsk_put(inet_twsk(sk)); 183 - return NULL; 184 - } 185 - 186 - if (hp->syn && !hp->rst && !hp->ack && !hp->fin) { 187 - /* SYN to a TIME_WAIT socket, we'd rather redirect it 188 - * to a listener socket if there's one */ 189 - struct sock *sk2; 190 - 191 - sk2 = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto, 192 - &iph->saddr, 193 - tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr), 194 - hp->source, 195 - tgi->lport ? tgi->lport : hp->dest, 196 - skb->dev, NFT_LOOKUP_LISTENER); 197 - if (sk2) { 198 - inet_twsk_deschedule_put(inet_twsk(sk)); 199 - sk = sk2; 200 - } 201 - } 202 - 203 - return sk; 204 - } 205 - 206 380 static unsigned int 207 381 tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par) 208 382 { ··· 153 489 sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, tproto, 154 490 &iph->saddr, &iph->daddr, 155 491 hp->source, hp->dest, 156 - xt_in(par), NFT_LOOKUP_ESTABLISHED); 492 + xt_in(par), NF_TPROXY_LOOKUP_ESTABLISHED); 157 493 158 - laddr = tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr); 494 + laddr = nf_tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr); 159 495 lport = tgi->lport ? tgi->lport : hp->dest; 160 496 161 497 /* UDP has no TCP_TIME_WAIT state, so we never enter here */ 162 - if (sk && sk->sk_state == TCP_TIME_WAIT) 498 + if (sk && sk->sk_state == TCP_TIME_WAIT) { 499 + const struct xt_tproxy_target_info_v1 *tgi = par->targinfo; 163 500 /* reopening a TIME_WAIT connection needs special handling */ 164 - sk = tproxy_handle_time_wait6(skb, tproto, thoff, par, sk); 501 + sk = nf_tproxy_handle_time_wait6(skb, tproto, thoff, 502 + xt_net(par), 503 + &tgi->laddr.in6, 504 + tgi->lport, 505 + sk); 506 + } 165 507 else if (!sk) 166 508 /* no there's no established connection, check if 167 509 * there's a listener on the redirected addr/port */ 168 510 sk = nf_tproxy_get_sock_v6(xt_net(par), skb, thoff, hp, 169 511 tproto, &iph->saddr, laddr, 170 512 hp->source, lport, 171 - xt_in(par), NFT_LOOKUP_LISTENER); 513 + xt_in(par), NF_TPROXY_LOOKUP_LISTENER); 172 514 173 515 /* NOTE: assign_sock consumes our sk reference */ 174 - if (sk && tproxy_sk_is_transparent(sk)) { 516 + if (sk && nf_tproxy_sk_is_transparent(sk)) { 175 517 /* This should be in a separate target, but we don't do multiple 176 518 targets on the same rule yet */ 177 519 skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
+2 -2
net/netfilter/xt_socket.c
··· 73 73 * if XT_SOCKET_TRANSPARENT is used 74 74 */ 75 75 if (info->flags & XT_SOCKET_TRANSPARENT) 76 - transparent = nf_sk_is_transparent(sk); 76 + transparent = inet_sk_transparent(sk); 77 77 78 78 if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && 79 79 transparent && sk_fullsock(sk)) ··· 130 130 * if XT_SOCKET_TRANSPARENT is used 131 131 */ 132 132 if (info->flags & XT_SOCKET_TRANSPARENT) 133 - transparent = nf_sk_is_transparent(sk); 133 + transparent = inet_sk_transparent(sk); 134 134 135 135 if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard && 136 136 transparent && sk_fullsock(sk))