aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-04-09 14:46:04 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-09 14:46:04 -0400
commitca69d7102fde3e22b09536867ba14ace84ea80e1 (patch)
tree6cfba19b3885c0ce11df838cdda53cb556e2c46f
parent3ab1a30fbded99936956442d8cf8f379064e4a26 (diff)
parentaadd51aa71f8d013c818a312bb2a0c5714830dbc (diff)
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. They are: * nf_tables set timeout infrastructure from Patrick Mchardy. 1) Add support for set timeout support. 2) Add support for set element timeouts using the new set extension infrastructure. 4) Add garbage collection helper functions to get rid of stale elements. Elements are accumulated in a batch that are asynchronously released via RCU when the batch is full. 5) Add garbage collection synchronization helpers. This introduces a new element busy bit to address concurrent access from the netlink API and the garbage collector. 5) Add timeout support for the nft_hash set implementation. The garbage collector peridically checks for stale elements from the workqueue. * iptables/nftables cgroup fixes: 6) Ignore non full-socket objects from the input path, otherwise cgroup match may crash, from Daniel Borkmann. 7) Fix cgroup in nf_tables. 8) Save some cycles from xt_socket by skipping packet header parsing when skb->sk is already set because of early demux. Also from Daniel. * br_netfilter updates from Florian Westphal. 9) Save frag_max_size and restore it from the forward path too. 10) Use a per-cpu area to restore the original source MAC address when traffic is DNAT'ed. 11) Add helper functions to access physical devices. 12) Use these new physdev helper function from xt_physdev. 13) Add another nf_bridge_info_get() helper function to fetch the br_netfilter state information. 14) Annotate original layer 2 protocol number in nf_bridge info, instead of using kludgy flags. 15) Also annotate the pkttype mangling when the packet travels back and forth from the IP to the bridge layer, instead of using a flag. * More nf_tables set enhancement from Patrick: 16) Fix possible usage of set variant that doesn't support timeouts. 17) Avoid spurious "set is full" errors from Netlink API when there are pending stale elements scheduled to be released. 18) Restrict loop checks to set maps. 19) Add support for dynamic set updates from the packet path. 20) Add support to store optional user data (eg. comments) per set element. BTW, I have also pulled net-next into nf-next to anticipate the conflict resolution between your okfn() signature changes and Florian's br_netfilter updates. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter_bridge.h28
-rw-r--r--include/linux/skbuff.h8
-rw-r--r--include/net/netfilter/nf_tables.h155
-rw-r--r--include/net/netfilter/nf_tables_core.h3
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h39
-rw-r--r--net/bridge/br_netfilter.c144
-rw-r--r--net/ipv4/netfilter/nf_reject_ipv4.c4
-rw-r--r--net/ipv6/netfilter/nf_reject_ipv6.c4
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c32
-rw-r--r--net/netfilter/nf_log_common.c5
-rw-r--r--net/netfilter/nf_queue.c18
-rw-r--r--net/netfilter/nf_tables_api.c186
-rw-r--r--net/netfilter/nf_tables_core.c7
-rw-r--r--net/netfilter/nfnetlink_log.c17
-rw-r--r--net/netfilter/nfnetlink_queue_core.c28
-rw-r--r--net/netfilter/nft_dynset.c218
-rw-r--r--net/netfilter/nft_hash.c117
-rw-r--r--net/netfilter/nft_lookup.c2
-rw-r--r--net/netfilter/nft_meta.c5
-rw-r--r--net/netfilter/xt_cgroup.c2
-rw-r--r--net/netfilter/xt_physdev.c34
-rw-r--r--net/netfilter/xt_socket.c95
23 files changed, 973 insertions, 180 deletions
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 5fc0a0fe244b..ab8f76dba668 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -2,7 +2,7 @@
2#define __LINUX_BRIDGE_NETFILTER_H 2#define __LINUX_BRIDGE_NETFILTER_H
3 3
4#include <uapi/linux/netfilter_bridge.h> 4#include <uapi/linux/netfilter_bridge.h>
5 5#include <linux/skbuff.h>
6 6
7enum nf_br_hook_priorities { 7enum nf_br_hook_priorities {
8 NF_BR_PRI_FIRST = INT_MIN, 8 NF_BR_PRI_FIRST = INT_MIN,
@@ -17,15 +17,12 @@ enum nf_br_hook_priorities {
17 17
18#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 18#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
19 19
20#define BRNF_PKT_TYPE 0x01
21#define BRNF_BRIDGED_DNAT 0x02 20#define BRNF_BRIDGED_DNAT 0x02
22#define BRNF_NF_BRIDGE_PREROUTING 0x08 21#define BRNF_NF_BRIDGE_PREROUTING 0x08
23#define BRNF_8021Q 0x10
24#define BRNF_PPPoE 0x20
25 22
26static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) 23static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
27{ 24{
28 if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE)) 25 if (skb->nf_bridge->orig_proto == BRNF_PROTO_PPPOE)
29 return PPPOE_SES_HLEN; 26 return PPPOE_SES_HLEN;
30 return 0; 27 return 0;
31} 28}
@@ -40,6 +37,27 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
40 skb_dst_drop(skb); 37 skb_dst_drop(skb);
41} 38}
42 39
40static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
41{
42 return skb->nf_bridge ? skb->nf_bridge->physindev->ifindex : 0;
43}
44
45static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
46{
47 return skb->nf_bridge ? skb->nf_bridge->physoutdev->ifindex : 0;
48}
49
50static inline struct net_device *
51nf_bridge_get_physindev(const struct sk_buff *skb)
52{
53 return skb->nf_bridge ? skb->nf_bridge->physindev : NULL;
54}
55
56static inline struct net_device *
57nf_bridge_get_physoutdev(const struct sk_buff *skb)
58{
59 return skb->nf_bridge ? skb->nf_bridge->physoutdev : NULL;
60}
43#else 61#else
44#define br_drop_fake_rtable(skb) do { } while (0) 62#define br_drop_fake_rtable(skb) do { } while (0)
45#endif /* CONFIG_BRIDGE_NETFILTER */ 63#endif /* CONFIG_BRIDGE_NETFILTER */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 36f3f43c0117..0991259643d6 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -166,10 +166,16 @@ struct nf_conntrack {
166#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 166#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
167struct nf_bridge_info { 167struct nf_bridge_info {
168 atomic_t use; 168 atomic_t use;
169 enum {
170 BRNF_PROTO_UNCHANGED,
171 BRNF_PROTO_8021Q,
172 BRNF_PROTO_PPPOE
173 } orig_proto;
174 bool pkt_otherhost;
169 unsigned int mask; 175 unsigned int mask;
170 struct net_device *physindev; 176 struct net_device *physindev;
171 struct net_device *physoutdev; 177 struct net_device *physoutdev;
172 unsigned long data[32 / sizeof(unsigned long)]; 178 char neigh_header[8];
173}; 179};
174#endif 180#endif
175 181
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 804981980393..d6a2f0ed5130 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -195,6 +195,7 @@ struct nft_set_estimate {
195}; 195};
196 196
197struct nft_set_ext; 197struct nft_set_ext;
198struct nft_expr;
198 199
199/** 200/**
200 * struct nft_set_ops - nf_tables set operations 201 * struct nft_set_ops - nf_tables set operations
@@ -217,6 +218,15 @@ struct nft_set_ops {
217 bool (*lookup)(const struct nft_set *set, 218 bool (*lookup)(const struct nft_set *set,
218 const struct nft_data *key, 219 const struct nft_data *key,
219 const struct nft_set_ext **ext); 220 const struct nft_set_ext **ext);
221 bool (*update)(struct nft_set *set,
222 const struct nft_data *key,
223 void *(*new)(struct nft_set *,
224 const struct nft_expr *,
225 struct nft_data []),
226 const struct nft_expr *expr,
227 struct nft_data data[],
228 const struct nft_set_ext **ext);
229
220 int (*insert)(const struct nft_set *set, 230 int (*insert)(const struct nft_set *set,
221 const struct nft_set_elem *elem); 231 const struct nft_set_elem *elem);
222 void (*activate)(const struct nft_set *set, 232 void (*activate)(const struct nft_set *set,
@@ -257,6 +267,9 @@ void nft_unregister_set(struct nft_set_ops *ops);
257 * @dtype: data type (verdict or numeric type defined by userspace) 267 * @dtype: data type (verdict or numeric type defined by userspace)
258 * @size: maximum set size 268 * @size: maximum set size
259 * @nelems: number of elements 269 * @nelems: number of elements
270 * @ndeact: number of deactivated elements queued for removal
271 * @timeout: default timeout value in msecs
272 * @gc_int: garbage collection interval in msecs
260 * @policy: set parameterization (see enum nft_set_policies) 273 * @policy: set parameterization (see enum nft_set_policies)
261 * @ops: set ops 274 * @ops: set ops
262 * @pnet: network namespace 275 * @pnet: network namespace
@@ -272,7 +285,10 @@ struct nft_set {
272 u32 ktype; 285 u32 ktype;
273 u32 dtype; 286 u32 dtype;
274 u32 size; 287 u32 size;
275 u32 nelems; 288 atomic_t nelems;
289 u32 ndeact;
290 u64 timeout;
291 u32 gc_int;
276 u16 policy; 292 u16 policy;
277 /* runtime data below here */ 293 /* runtime data below here */
278 const struct nft_set_ops *ops ____cacheline_aligned; 294 const struct nft_set_ops *ops ____cacheline_aligned;
@@ -289,16 +305,27 @@ static inline void *nft_set_priv(const struct nft_set *set)
289 return (void *)set->data; 305 return (void *)set->data;
290} 306}
291 307
308static inline struct nft_set *nft_set_container_of(const void *priv)
309{
310 return (void *)priv - offsetof(struct nft_set, data);
311}
312
292struct nft_set *nf_tables_set_lookup(const struct nft_table *table, 313struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
293 const struct nlattr *nla); 314 const struct nlattr *nla);
294struct nft_set *nf_tables_set_lookup_byid(const struct net *net, 315struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
295 const struct nlattr *nla); 316 const struct nlattr *nla);
296 317
318static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
319{
320 return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ;
321}
322
297/** 323/**
298 * struct nft_set_binding - nf_tables set binding 324 * struct nft_set_binding - nf_tables set binding
299 * 325 *
300 * @list: set bindings list node 326 * @list: set bindings list node
301 * @chain: chain containing the rule bound to the set 327 * @chain: chain containing the rule bound to the set
328 * @flags: set action flags
302 * 329 *
303 * A set binding contains all information necessary for validation 330 * A set binding contains all information necessary for validation
304 * of new elements added to a bound set. 331 * of new elements added to a bound set.
@@ -306,6 +333,7 @@ struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
306struct nft_set_binding { 333struct nft_set_binding {
307 struct list_head list; 334 struct list_head list;
308 const struct nft_chain *chain; 335 const struct nft_chain *chain;
336 u32 flags;
309}; 337};
310 338
311int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, 339int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
@@ -319,12 +347,18 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
319 * @NFT_SET_EXT_KEY: element key 347 * @NFT_SET_EXT_KEY: element key
320 * @NFT_SET_EXT_DATA: mapping data 348 * @NFT_SET_EXT_DATA: mapping data
321 * @NFT_SET_EXT_FLAGS: element flags 349 * @NFT_SET_EXT_FLAGS: element flags
350 * @NFT_SET_EXT_TIMEOUT: element timeout
351 * @NFT_SET_EXT_EXPIRATION: element expiration time
352 * @NFT_SET_EXT_USERDATA: user data associated with the element
322 * @NFT_SET_EXT_NUM: number of extension types 353 * @NFT_SET_EXT_NUM: number of extension types
323 */ 354 */
324enum nft_set_extensions { 355enum nft_set_extensions {
325 NFT_SET_EXT_KEY, 356 NFT_SET_EXT_KEY,
326 NFT_SET_EXT_DATA, 357 NFT_SET_EXT_DATA,
327 NFT_SET_EXT_FLAGS, 358 NFT_SET_EXT_FLAGS,
359 NFT_SET_EXT_TIMEOUT,
360 NFT_SET_EXT_EXPIRATION,
361 NFT_SET_EXT_USERDATA,
328 NFT_SET_EXT_NUM 362 NFT_SET_EXT_NUM
329}; 363};
330 364
@@ -421,15 +455,97 @@ static inline u8 *nft_set_ext_flags(const struct nft_set_ext *ext)
421 return nft_set_ext(ext, NFT_SET_EXT_FLAGS); 455 return nft_set_ext(ext, NFT_SET_EXT_FLAGS);
422} 456}
423 457
458static inline u64 *nft_set_ext_timeout(const struct nft_set_ext *ext)
459{
460 return nft_set_ext(ext, NFT_SET_EXT_TIMEOUT);
461}
462
463static inline unsigned long *nft_set_ext_expiration(const struct nft_set_ext *ext)
464{
465 return nft_set_ext(ext, NFT_SET_EXT_EXPIRATION);
466}
467
468static inline struct nft_userdata *nft_set_ext_userdata(const struct nft_set_ext *ext)
469{
470 return nft_set_ext(ext, NFT_SET_EXT_USERDATA);
471}
472
473static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
474{
475 return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
476 time_is_before_eq_jiffies(*nft_set_ext_expiration(ext));
477}
478
424static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set, 479static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
425 void *elem) 480 void *elem)
426{ 481{
427 return elem + set->ops->elemsize; 482 return elem + set->ops->elemsize;
428} 483}
429 484
485void *nft_set_elem_init(const struct nft_set *set,
486 const struct nft_set_ext_tmpl *tmpl,
487 const struct nft_data *key,
488 const struct nft_data *data,
489 u64 timeout, gfp_t gfp);
430void nft_set_elem_destroy(const struct nft_set *set, void *elem); 490void nft_set_elem_destroy(const struct nft_set *set, void *elem);
431 491
432/** 492/**
493 * struct nft_set_gc_batch_head - nf_tables set garbage collection batch
494 *
495 * @rcu: rcu head
496 * @set: set the elements belong to
497 * @cnt: count of elements
498 */
499struct nft_set_gc_batch_head {
500 struct rcu_head rcu;
501 const struct nft_set *set;
502 unsigned int cnt;
503};
504
505#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE - \
506 sizeof(struct nft_set_gc_batch_head)) / \
507 sizeof(void *))
508
509/**
510 * struct nft_set_gc_batch - nf_tables set garbage collection batch
511 *
512 * @head: GC batch head
513 * @elems: garbage collection elements
514 */
515struct nft_set_gc_batch {
516 struct nft_set_gc_batch_head head;
517 void *elems[NFT_SET_GC_BATCH_SIZE];
518};
519
520struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
521 gfp_t gfp);
522void nft_set_gc_batch_release(struct rcu_head *rcu);
523
524static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
525{
526 if (gcb != NULL)
527 call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
528}
529
530static inline struct nft_set_gc_batch *
531nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
532 gfp_t gfp)
533{
534 if (gcb != NULL) {
535 if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
536 return gcb;
537 nft_set_gc_batch_complete(gcb);
538 }
539 return nft_set_gc_batch_alloc(set, gfp);
540}
541
542static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
543 void *elem)
544{
545 gcb->elems[gcb->head.cnt++] = elem;
546}
547
548/**
433 * struct nft_expr_type - nf_tables expression type 549 * struct nft_expr_type - nf_tables expression type
434 * 550 *
435 * @select_ops: function to select nft_expr_ops 551 * @select_ops: function to select nft_expr_ops
@@ -750,6 +866,8 @@ static inline u8 nft_genmask_cur(const struct net *net)
750 return 1 << ACCESS_ONCE(net->nft.gencursor); 866 return 1 << ACCESS_ONCE(net->nft.gencursor);
751} 867}
752 868
869#define NFT_GENMASK_ANY ((1 << 0) | (1 << 1))
870
753/* 871/*
754 * Set element transaction helpers 872 * Set element transaction helpers
755 */ 873 */
@@ -766,6 +884,41 @@ static inline void nft_set_elem_change_active(const struct nft_set *set,
766 ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet)); 884 ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet));
767} 885}
768 886
887/*
888 * We use a free bit in the genmask field to indicate the element
889 * is busy, meaning it is currently being processed either by
890 * the netlink API or GC.
891 *
892 * Even though the genmask is only a single byte wide, this works
893 * because the extension structure if fully constant once initialized,
894 * so there are no non-atomic write accesses unless it is already
895 * marked busy.
896 */
897#define NFT_SET_ELEM_BUSY_MASK (1 << 2)
898
899#if defined(__LITTLE_ENDIAN_BITFIELD)
900#define NFT_SET_ELEM_BUSY_BIT 2
901#elif defined(__BIG_ENDIAN_BITFIELD)
902#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
903#else
904#error
905#endif
906
907static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
908{
909 unsigned long *word = (unsigned long *)ext;
910
911 BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
912 return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
913}
914
915static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
916{
917 unsigned long *word = (unsigned long *)ext;
918
919 clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
920}
921
769/** 922/**
770 * struct nft_trans - nf_tables object update in transaction 923 * struct nft_trans - nf_tables object update in transaction
771 * 924 *
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index a75fc8e27cd6..c6f400cfaac8 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -31,6 +31,9 @@ void nft_cmp_module_exit(void);
31int nft_lookup_module_init(void); 31int nft_lookup_module_init(void);
32void nft_lookup_module_exit(void); 32void nft_lookup_module_exit(void);
33 33
34int nft_dynset_module_init(void);
35void nft_dynset_module_exit(void);
36
34int nft_bitwise_module_init(void); 37int nft_bitwise_module_init(void);
35void nft_bitwise_module_exit(void); 38void nft_bitwise_module_exit(void);
36 39
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index b9783931503b..05ee1e0804a3 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -208,12 +208,14 @@ enum nft_rule_compat_attributes {
208 * @NFT_SET_CONSTANT: set contents may not change while bound 208 * @NFT_SET_CONSTANT: set contents may not change while bound
209 * @NFT_SET_INTERVAL: set contains intervals 209 * @NFT_SET_INTERVAL: set contains intervals
210 * @NFT_SET_MAP: set is used as a dictionary 210 * @NFT_SET_MAP: set is used as a dictionary
211 * @NFT_SET_TIMEOUT: set uses timeouts
211 */ 212 */
212enum nft_set_flags { 213enum nft_set_flags {
213 NFT_SET_ANONYMOUS = 0x1, 214 NFT_SET_ANONYMOUS = 0x1,
214 NFT_SET_CONSTANT = 0x2, 215 NFT_SET_CONSTANT = 0x2,
215 NFT_SET_INTERVAL = 0x4, 216 NFT_SET_INTERVAL = 0x4,
216 NFT_SET_MAP = 0x8, 217 NFT_SET_MAP = 0x8,
218 NFT_SET_TIMEOUT = 0x10,
217}; 219};
218 220
219/** 221/**
@@ -252,6 +254,8 @@ enum nft_set_desc_attributes {
252 * @NFTA_SET_POLICY: selection policy (NLA_U32) 254 * @NFTA_SET_POLICY: selection policy (NLA_U32)
253 * @NFTA_SET_DESC: set description (NLA_NESTED) 255 * @NFTA_SET_DESC: set description (NLA_NESTED)
254 * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32) 256 * @NFTA_SET_ID: uniquely identifies a set in a transaction (NLA_U32)
257 * @NFTA_SET_TIMEOUT: default timeout value (NLA_U64)
258 * @NFTA_SET_GC_INTERVAL: garbage collection interval (NLA_U32)
255 */ 259 */
256enum nft_set_attributes { 260enum nft_set_attributes {
257 NFTA_SET_UNSPEC, 261 NFTA_SET_UNSPEC,
@@ -265,6 +269,8 @@ enum nft_set_attributes {
265 NFTA_SET_POLICY, 269 NFTA_SET_POLICY,
266 NFTA_SET_DESC, 270 NFTA_SET_DESC,
267 NFTA_SET_ID, 271 NFTA_SET_ID,
272 NFTA_SET_TIMEOUT,
273 NFTA_SET_GC_INTERVAL,
268 __NFTA_SET_MAX 274 __NFTA_SET_MAX
269}; 275};
270#define NFTA_SET_MAX (__NFTA_SET_MAX - 1) 276#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -284,12 +290,18 @@ enum nft_set_elem_flags {
284 * @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data) 290 * @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data)
285 * @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes) 291 * @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes)
286 * @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32) 292 * @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32)
293 * @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64)
294 * @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)
295 * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
287 */ 296 */
288enum nft_set_elem_attributes { 297enum nft_set_elem_attributes {
289 NFTA_SET_ELEM_UNSPEC, 298 NFTA_SET_ELEM_UNSPEC,
290 NFTA_SET_ELEM_KEY, 299 NFTA_SET_ELEM_KEY,
291 NFTA_SET_ELEM_DATA, 300 NFTA_SET_ELEM_DATA,
292 NFTA_SET_ELEM_FLAGS, 301 NFTA_SET_ELEM_FLAGS,
302 NFTA_SET_ELEM_TIMEOUT,
303 NFTA_SET_ELEM_EXPIRATION,
304 NFTA_SET_ELEM_USERDATA,
293 __NFTA_SET_ELEM_MAX 305 __NFTA_SET_ELEM_MAX
294}; 306};
295#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) 307#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
@@ -505,6 +517,33 @@ enum nft_lookup_attributes {
505}; 517};
506#define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1) 518#define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1)
507 519
520enum nft_dynset_ops {
521 NFT_DYNSET_OP_ADD,
522 NFT_DYNSET_OP_UPDATE,
523};
524
525/**
526 * enum nft_dynset_attributes - dynset expression attributes
527 *
528 * @NFTA_DYNSET_SET_NAME: name of set the to add data to (NLA_STRING)
529 * @NFTA_DYNSET_SET_ID: uniquely identifier of the set in the transaction (NLA_U32)
530 * @NFTA_DYNSET_OP: operation (NLA_U32)
531 * @NFTA_DYNSET_SREG_KEY: source register of the key (NLA_U32)
532 * @NFTA_DYNSET_SREG_DATA: source register of the data (NLA_U32)
533 * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64)
534 */
535enum nft_dynset_attributes {
536 NFTA_DYNSET_UNSPEC,
537 NFTA_DYNSET_SET_NAME,
538 NFTA_DYNSET_SET_ID,
539 NFTA_DYNSET_OP,
540 NFTA_DYNSET_SREG_KEY,
541 NFTA_DYNSET_SREG_DATA,
542 NFTA_DYNSET_TIMEOUT,
543 __NFTA_DYNSET_MAX,
544};
545#define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1)
546
508/** 547/**
509 * enum nft_payload_bases - nf_tables payload expression offset bases 548 * enum nft_payload_bases - nf_tables payload expression offset bases
510 * 549 *
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index acd31c9f2116..ab55e2472beb 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -111,6 +111,24 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
111 pppoe_proto(skb) == htons(PPP_IPV6) && \ 111 pppoe_proto(skb) == htons(PPP_IPV6) && \
112 brnf_filter_pppoe_tagged) 112 brnf_filter_pppoe_tagged)
113 113
114/* largest possible L2 header, see br_nf_dev_queue_xmit() */
115#define NF_BRIDGE_MAX_MAC_HEADER_LENGTH (PPPOE_SES_HLEN + ETH_HLEN)
116
117#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
118struct brnf_frag_data {
119 char mac[NF_BRIDGE_MAX_MAC_HEADER_LENGTH];
120 u8 encap_size;
121 u8 size;
122};
123
124static DEFINE_PER_CPU(struct brnf_frag_data, brnf_frag_data_storage);
125#endif
126
127static struct nf_bridge_info *nf_bridge_info_get(const struct sk_buff *skb)
128{
129 return skb->nf_bridge;
130}
131
114static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) 132static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
115{ 133{
116 struct net_bridge_port *port; 134 struct net_bridge_port *port;
@@ -189,14 +207,6 @@ static inline void nf_bridge_pull_encap_header_rcsum(struct sk_buff *skb)
189 skb->network_header += len; 207 skb->network_header += len;
190} 208}
191 209
192static inline void nf_bridge_save_header(struct sk_buff *skb)
193{
194 int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
195
196 skb_copy_from_linear_data_offset(skb, -header_size,
197 skb->nf_bridge->data, header_size);
198}
199
200/* When handing a packet over to the IP layer 210/* When handing a packet over to the IP layer
201 * check whether we have a skb that is in the 211 * check whether we have a skb that is in the
202 * expected format 212 * expected format
@@ -252,10 +262,16 @@ drop:
252 262
253static void nf_bridge_update_protocol(struct sk_buff *skb) 263static void nf_bridge_update_protocol(struct sk_buff *skb)
254{ 264{
255 if (skb->nf_bridge->mask & BRNF_8021Q) 265 switch (skb->nf_bridge->orig_proto) {
266 case BRNF_PROTO_8021Q:
256 skb->protocol = htons(ETH_P_8021Q); 267 skb->protocol = htons(ETH_P_8021Q);
257 else if (skb->nf_bridge->mask & BRNF_PPPoE) 268 break;
269 case BRNF_PROTO_PPPOE:
258 skb->protocol = htons(ETH_P_PPP_SES); 270 skb->protocol = htons(ETH_P_PPP_SES);
271 break;
272 case BRNF_PROTO_UNCHANGED:
273 break;
274 }
259} 275}
260 276
261/* PF_BRIDGE/PRE_ROUTING *********************************************/ 277/* PF_BRIDGE/PRE_ROUTING *********************************************/
@@ -263,12 +279,12 @@ static void nf_bridge_update_protocol(struct sk_buff *skb)
263 * bridge PRE_ROUTING hook. */ 279 * bridge PRE_ROUTING hook. */
264static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb) 280static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb)
265{ 281{
266 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 282 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
267 struct rtable *rt; 283 struct rtable *rt;
268 284
269 if (nf_bridge->mask & BRNF_PKT_TYPE) { 285 if (nf_bridge->pkt_otherhost) {
270 skb->pkt_type = PACKET_OTHERHOST; 286 skb->pkt_type = PACKET_OTHERHOST;
271 nf_bridge->mask ^= BRNF_PKT_TYPE; 287 nf_bridge->pkt_otherhost = false;
272 } 288 }
273 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; 289 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
274 290
@@ -296,7 +312,6 @@ static int br_nf_pre_routing_finish_ipv6(struct sock *sk, struct sk_buff *skb)
296 */ 312 */
297static int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb) 313static int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb)
298{ 314{
299 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
300 struct neighbour *neigh; 315 struct neighbour *neigh;
301 struct dst_entry *dst; 316 struct dst_entry *dst;
302 317
@@ -306,6 +321,7 @@ static int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb)
306 dst = skb_dst(skb); 321 dst = skb_dst(skb);
307 neigh = dst_neigh_lookup_skb(dst, skb); 322 neigh = dst_neigh_lookup_skb(dst, skb);
308 if (neigh) { 323 if (neigh) {
324 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
309 int ret; 325 int ret;
310 326
311 if (neigh->hh.hh_len) { 327 if (neigh->hh.hh_len) {
@@ -319,7 +335,7 @@ static int br_nf_pre_routing_finish_bridge(struct sock *sk, struct sk_buff *skb)
319 */ 335 */
320 skb_copy_from_linear_data_offset(skb, 336 skb_copy_from_linear_data_offset(skb,
321 -(ETH_HLEN-ETH_ALEN), 337 -(ETH_HLEN-ETH_ALEN),
322 skb->nf_bridge->data, 338 nf_bridge->neigh_header,
323 ETH_HLEN-ETH_ALEN); 339 ETH_HLEN-ETH_ALEN);
324 /* tell br_dev_xmit to continue with forwarding */ 340 /* tell br_dev_xmit to continue with forwarding */
325 nf_bridge->mask |= BRNF_BRIDGED_DNAT; 341 nf_bridge->mask |= BRNF_BRIDGED_DNAT;
@@ -392,7 +408,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb)
392{ 408{
393 struct net_device *dev = skb->dev; 409 struct net_device *dev = skb->dev;
394 struct iphdr *iph = ip_hdr(skb); 410 struct iphdr *iph = ip_hdr(skb);
395 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 411 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
396 struct rtable *rt; 412 struct rtable *rt;
397 int err; 413 int err;
398 int frag_max_size; 414 int frag_max_size;
@@ -400,9 +416,9 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb)
400 frag_max_size = IPCB(skb)->frag_max_size; 416 frag_max_size = IPCB(skb)->frag_max_size;
401 BR_INPUT_SKB_CB(skb)->frag_max_size = frag_max_size; 417 BR_INPUT_SKB_CB(skb)->frag_max_size = frag_max_size;
402 418
403 if (nf_bridge->mask & BRNF_PKT_TYPE) { 419 if (nf_bridge->pkt_otherhost) {
404 skb->pkt_type = PACKET_OTHERHOST; 420 skb->pkt_type = PACKET_OTHERHOST;
405 nf_bridge->mask ^= BRNF_PKT_TYPE; 421 nf_bridge->pkt_otherhost = false;
406 } 422 }
407 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; 423 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
408 if (dnat_took_place(skb)) { 424 if (dnat_took_place(skb)) {
@@ -485,20 +501,21 @@ static struct net_device *brnf_get_logical_dev(struct sk_buff *skb, const struct
485/* Some common code for IPv4/IPv6 */ 501/* Some common code for IPv4/IPv6 */
486static struct net_device *setup_pre_routing(struct sk_buff *skb) 502static struct net_device *setup_pre_routing(struct sk_buff *skb)
487{ 503{
488 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 504 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
489 505
490 if (skb->pkt_type == PACKET_OTHERHOST) { 506 if (skb->pkt_type == PACKET_OTHERHOST) {
491 skb->pkt_type = PACKET_HOST; 507 skb->pkt_type = PACKET_HOST;
492 nf_bridge->mask |= BRNF_PKT_TYPE; 508 nf_bridge->pkt_otherhost = true;
493 } 509 }
494 510
495 nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; 511 nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
496 nf_bridge->physindev = skb->dev; 512 nf_bridge->physindev = skb->dev;
497 skb->dev = brnf_get_logical_dev(skb, skb->dev); 513 skb->dev = brnf_get_logical_dev(skb, skb->dev);
514
498 if (skb->protocol == htons(ETH_P_8021Q)) 515 if (skb->protocol == htons(ETH_P_8021Q))
499 nf_bridge->mask |= BRNF_8021Q; 516 nf_bridge->orig_proto = BRNF_PROTO_8021Q;
500 else if (skb->protocol == htons(ETH_P_PPP_SES)) 517 else if (skb->protocol == htons(ETH_P_PPP_SES))
501 nf_bridge->mask |= BRNF_PPPoE; 518 nf_bridge->orig_proto = BRNF_PROTO_PPPOE;
502 519
503 /* Must drop socket now because of tproxy. */ 520 /* Must drop socket now because of tproxy. */
504 skb_orphan(skb); 521 skb_orphan(skb);
@@ -680,14 +697,21 @@ static unsigned int br_nf_local_in(const struct nf_hook_ops *ops,
680/* PF_BRIDGE/FORWARD *************************************************/ 697/* PF_BRIDGE/FORWARD *************************************************/
681static int br_nf_forward_finish(struct sock *sk, struct sk_buff *skb) 698static int br_nf_forward_finish(struct sock *sk, struct sk_buff *skb)
682{ 699{
683 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 700 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
684 struct net_device *in; 701 struct net_device *in;
685 702
686 if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) { 703 if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) {
704 int frag_max_size;
705
706 if (skb->protocol == htons(ETH_P_IP)) {
707 frag_max_size = IPCB(skb)->frag_max_size;
708 BR_INPUT_SKB_CB(skb)->frag_max_size = frag_max_size;
709 }
710
687 in = nf_bridge->physindev; 711 in = nf_bridge->physindev;
688 if (nf_bridge->mask & BRNF_PKT_TYPE) { 712 if (nf_bridge->pkt_otherhost) {
689 skb->pkt_type = PACKET_OTHERHOST; 713 skb->pkt_type = PACKET_OTHERHOST;
690 nf_bridge->mask ^= BRNF_PKT_TYPE; 714 nf_bridge->pkt_otherhost = false;
691 } 715 }
692 nf_bridge_update_protocol(skb); 716 nf_bridge_update_protocol(skb);
693 } else { 717 } else {
@@ -722,6 +746,10 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
722 if (!nf_bridge_unshare(skb)) 746 if (!nf_bridge_unshare(skb))
723 return NF_DROP; 747 return NF_DROP;
724 748
749 nf_bridge = nf_bridge_info_get(skb);
750 if (!nf_bridge)
751 return NF_DROP;
752
725 parent = bridge_parent(state->out); 753 parent = bridge_parent(state->out);
726 if (!parent) 754 if (!parent)
727 return NF_DROP; 755 return NF_DROP;
@@ -735,14 +763,19 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
735 763
736 nf_bridge_pull_encap_header(skb); 764 nf_bridge_pull_encap_header(skb);
737 765
738 nf_bridge = skb->nf_bridge;
739 if (skb->pkt_type == PACKET_OTHERHOST) { 766 if (skb->pkt_type == PACKET_OTHERHOST) {
740 skb->pkt_type = PACKET_HOST; 767 skb->pkt_type = PACKET_HOST;
741 nf_bridge->mask |= BRNF_PKT_TYPE; 768 nf_bridge->pkt_otherhost = true;
742 } 769 }
743 770
744 if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb)) 771 if (pf == NFPROTO_IPV4) {
745 return NF_DROP; 772 int frag_max = BR_INPUT_SKB_CB(skb)->frag_max_size;
773
774 if (br_parse_ip_options(skb))
775 return NF_DROP;
776
777 IPCB(skb)->frag_max_size = frag_max;
778 }
746 779
747 nf_bridge->physoutdev = skb->dev; 780 nf_bridge->physoutdev = skb->dev;
748 if (pf == NFPROTO_IPV4) 781 if (pf == NFPROTO_IPV4)
@@ -792,30 +825,22 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
792} 825}
793 826
794#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) 827#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
795static bool nf_bridge_copy_header(struct sk_buff *skb) 828static int br_nf_push_frag_xmit(struct sock *sk, struct sk_buff *skb)
796{ 829{
830 struct brnf_frag_data *data;
797 int err; 831 int err;
798 unsigned int header_size;
799 832
800 nf_bridge_update_protocol(skb); 833 data = this_cpu_ptr(&brnf_frag_data_storage);
801 header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); 834 err = skb_cow_head(skb, data->size);
802 err = skb_cow_head(skb, header_size);
803 if (err)
804 return false;
805
806 skb_copy_to_linear_data_offset(skb, -header_size,
807 skb->nf_bridge->data, header_size);
808 __skb_push(skb, nf_bridge_encap_header_len(skb));
809 return true;
810}
811 835
812static int br_nf_push_frag_xmit(struct sock *sk, struct sk_buff *skb) 836 if (err) {
813{
814 if (!nf_bridge_copy_header(skb)) {
815 kfree_skb(skb); 837 kfree_skb(skb);
816 return 0; 838 return 0;
817 } 839 }
818 840
841 skb_copy_to_linear_data_offset(skb, -data->size, data->mac, data->size);
842 __skb_push(skb, data->encap_size);
843
819 return br_dev_queue_push_xmit(sk, skb); 844 return br_dev_queue_push_xmit(sk, skb);
820} 845}
821 846
@@ -833,14 +858,27 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb)
833 * boundaries by preserving frag_list rather than refragmenting. 858 * boundaries by preserving frag_list rather than refragmenting.
834 */ 859 */
835 if (skb->len + mtu_reserved > skb->dev->mtu) { 860 if (skb->len + mtu_reserved > skb->dev->mtu) {
861 struct brnf_frag_data *data;
862
836 frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; 863 frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
837 if (br_parse_ip_options(skb)) 864 if (br_parse_ip_options(skb))
838 /* Drop invalid packet */ 865 /* Drop invalid packet */
839 return NF_DROP; 866 return NF_DROP;
840 IPCB(skb)->frag_max_size = frag_max_size; 867 IPCB(skb)->frag_max_size = frag_max_size;
868
869 nf_bridge_update_protocol(skb);
870
871 data = this_cpu_ptr(&brnf_frag_data_storage);
872 data->encap_size = nf_bridge_encap_header_len(skb);
873 data->size = ETH_HLEN + data->encap_size;
874
875 skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
876 data->size);
877
841 ret = ip_fragment(sk, skb, br_nf_push_frag_xmit); 878 ret = ip_fragment(sk, skb, br_nf_push_frag_xmit);
842 } else 879 } else {
843 ret = br_dev_queue_push_xmit(sk, skb); 880 ret = br_dev_queue_push_xmit(sk, skb);
881 }
844 882
845 return ret; 883 return ret;
846} 884}
@@ -856,7 +894,7 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
856 struct sk_buff *skb, 894 struct sk_buff *skb,
857 const struct nf_hook_state *state) 895 const struct nf_hook_state *state)
858{ 896{
859 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 897 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
860 struct net_device *realoutdev = bridge_parent(skb->dev); 898 struct net_device *realoutdev = bridge_parent(skb->dev);
861 u_int8_t pf; 899 u_int8_t pf;
862 900
@@ -882,11 +920,10 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
882 * about the value of skb->pkt_type. */ 920 * about the value of skb->pkt_type. */
883 if (skb->pkt_type == PACKET_OTHERHOST) { 921 if (skb->pkt_type == PACKET_OTHERHOST) {
884 skb->pkt_type = PACKET_HOST; 922 skb->pkt_type = PACKET_HOST;
885 nf_bridge->mask |= BRNF_PKT_TYPE; 923 nf_bridge->pkt_otherhost = true;
886 } 924 }
887 925
888 nf_bridge_pull_encap_header(skb); 926 nf_bridge_pull_encap_header(skb);
889 nf_bridge_save_header(skb);
890 if (pf == NFPROTO_IPV4) 927 if (pf == NFPROTO_IPV4)
891 skb->protocol = htons(ETH_P_IP); 928 skb->protocol = htons(ETH_P_IP);
892 else 929 else
@@ -925,13 +962,16 @@ static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops,
925 */ 962 */
926static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) 963static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb)
927{ 964{
928 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 965 struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
929 966
930 skb_pull(skb, ETH_HLEN); 967 skb_pull(skb, ETH_HLEN);
931 nf_bridge->mask &= ~BRNF_BRIDGED_DNAT; 968 nf_bridge->mask &= ~BRNF_BRIDGED_DNAT;
932 969
933 skb_copy_to_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), 970 BUILD_BUG_ON(sizeof(nf_bridge->neigh_header) != (ETH_HLEN - ETH_ALEN));
934 skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); 971
972 skb_copy_to_linear_data_offset(skb, -(ETH_HLEN - ETH_ALEN),
973 nf_bridge->neigh_header,
974 ETH_HLEN - ETH_ALEN);
935 skb->dev = nf_bridge->physindev; 975 skb->dev = nf_bridge->physindev;
936 br_handle_frame_finish(NULL, skb); 976 br_handle_frame_finish(NULL, skb);
937} 977}
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index c5b794da51a9..3262e41ff76f 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -13,6 +13,7 @@
13#include <net/dst.h> 13#include <net/dst.h>
14#include <net/netfilter/ipv4/nf_reject.h> 14#include <net/netfilter/ipv4/nf_reject.h>
15#include <linux/netfilter_ipv4.h> 15#include <linux/netfilter_ipv4.h>
16#include <linux/netfilter_bridge.h>
16#include <net/netfilter/ipv4/nf_reject.h> 17#include <net/netfilter/ipv4/nf_reject.h>
17 18
18const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, 19const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
@@ -146,7 +147,8 @@ void nf_send_reset(struct sk_buff *oldskb, int hook)
146 */ 147 */
147 if (oldskb->nf_bridge) { 148 if (oldskb->nf_bridge) {
148 struct ethhdr *oeth = eth_hdr(oldskb); 149 struct ethhdr *oeth = eth_hdr(oldskb);
149 nskb->dev = oldskb->nf_bridge->physindev; 150
151 nskb->dev = nf_bridge_get_physindev(oldskb);
150 niph->tot_len = htons(nskb->len); 152 niph->tot_len = htons(nskb->len);
151 ip_send_check(niph); 153 ip_send_check(niph);
152 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), 154 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 3afdce03d94e..94b4c6dfb400 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -13,6 +13,7 @@
13#include <net/ip6_checksum.h> 13#include <net/ip6_checksum.h>
14#include <net/netfilter/ipv6/nf_reject.h> 14#include <net/netfilter/ipv6/nf_reject.h>
15#include <linux/netfilter_ipv6.h> 15#include <linux/netfilter_ipv6.h>
16#include <linux/netfilter_bridge.h>
16#include <net/netfilter/ipv6/nf_reject.h> 17#include <net/netfilter/ipv6/nf_reject.h>
17 18
18const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, 19const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
@@ -195,7 +196,8 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
195 */ 196 */
196 if (oldskb->nf_bridge) { 197 if (oldskb->nf_bridge) {
197 struct ethhdr *oeth = eth_hdr(oldskb); 198 struct ethhdr *oeth = eth_hdr(oldskb);
198 nskb->dev = oldskb->nf_bridge->physindev; 199
200 nskb->dev = nf_bridge_get_physindev(oldskb);
199 nskb->protocol = htons(ETH_P_IPV6); 201 nskb->protocol = htons(ETH_P_IPV6);
200 ip6h->payload_len = htons(sizeof(struct tcphdr)); 202 ip6h->payload_len = htons(sizeof(struct tcphdr));
201 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol), 203 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 89f73a9e9874..a87d8b8ec730 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -70,7 +70,7 @@ obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o
70 70
71# nf_tables 71# nf_tables
72nf_tables-objs += nf_tables_core.o nf_tables_api.o 72nf_tables-objs += nf_tables_core.o nf_tables_api.o
73nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o 73nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o nft_dynset.o
74nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o 74nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o
75 75
76obj-$(CONFIG_NF_TABLES) += nf_tables.o 76obj-$(CONFIG_NF_TABLES) += nf_tables.o
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 758b002130d9..380ef5148ea1 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -19,6 +19,7 @@
19#include <net/netlink.h> 19#include <net/netlink.h>
20 20
21#include <linux/netfilter.h> 21#include <linux/netfilter.h>
22#include <linux/netfilter_bridge.h>
22#include <linux/netfilter/ipset/pfxlen.h> 23#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.h> 24#include <linux/netfilter/ipset/ip_set.h>
24#include <linux/netfilter/ipset/ip_set_hash.h> 25#include <linux/netfilter/ipset/ip_set_hash.h>
@@ -211,6 +212,22 @@ hash_netiface4_data_next(struct hash_netiface4_elem *next,
211#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) 212#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
212#include "ip_set_hash_gen.h" 213#include "ip_set_hash_gen.h"
213 214
215#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
216static const char *get_physindev_name(const struct sk_buff *skb)
217{
218 struct net_device *dev = nf_bridge_get_physindev(skb);
219
220 return dev ? dev->name : NULL;
221}
222
223static const char *get_phyoutdev_name(const struct sk_buff *skb)
224{
225 struct net_device *dev = nf_bridge_get_physoutdev(skb);
226
227 return dev ? dev->name : NULL;
228}
229#endif
230
214static int 231static int
215hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, 232hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
216 const struct xt_action_param *par, 233 const struct xt_action_param *par,
@@ -234,16 +251,15 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
234 e.ip &= ip_set_netmask(e.cidr); 251 e.ip &= ip_set_netmask(e.cidr);
235 252
236#define IFACE(dir) (par->dir ? par->dir->name : NULL) 253#define IFACE(dir) (par->dir ? par->dir->name : NULL)
237#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
238#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC) 254#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
239 255
240 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 256 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
241#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 257#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
242 const struct nf_bridge_info *nf_bridge = skb->nf_bridge; 258 e.iface = SRCDIR ? get_physindev_name(skb) :
259 get_phyoutdev_name(skb);
243 260
244 if (!nf_bridge) 261 if (!e.iface)
245 return -EINVAL; 262 return -EINVAL;
246 e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
247 e.physdev = 1; 263 e.physdev = 1;
248#else 264#else
249 e.iface = NULL; 265 e.iface = NULL;
@@ -476,11 +492,11 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
476 492
477 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 493 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
478#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 494#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
479 const struct nf_bridge_info *nf_bridge = skb->nf_bridge; 495 e.iface = SRCDIR ? get_physindev_name(skb) :
480 496 get_phyoutdev_name(skb);
481 if (!nf_bridge) 497 if (!e.iface)
482 return -EINVAL; 498 return -EINVAL;
483 e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev); 499
484 e.physdev = 1; 500 e.physdev = 1;
485#else 501#else
486 e.iface = NULL; 502 e.iface = NULL;
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c
index 2631876ac55b..a5aa5967b8e1 100644
--- a/net/netfilter/nf_log_common.c
+++ b/net/netfilter/nf_log_common.c
@@ -17,6 +17,7 @@
17#include <net/route.h> 17#include <net/route.h>
18 18
19#include <linux/netfilter.h> 19#include <linux/netfilter.h>
20#include <linux/netfilter_bridge.h>
20#include <linux/netfilter/xt_LOG.h> 21#include <linux/netfilter/xt_LOG.h>
21#include <net/netfilter/nf_log.h> 22#include <net/netfilter/nf_log.h>
22 23
@@ -163,10 +164,10 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
163 const struct net_device *physindev; 164 const struct net_device *physindev;
164 const struct net_device *physoutdev; 165 const struct net_device *physoutdev;
165 166
166 physindev = skb->nf_bridge->physindev; 167 physindev = nf_bridge_get_physindev(skb);
167 if (physindev && in != physindev) 168 if (physindev && in != physindev)
168 nf_log_buf_add(m, "PHYSIN=%s ", physindev->name); 169 nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
169 physoutdev = skb->nf_bridge->physoutdev; 170 physoutdev = nf_bridge_get_physoutdev(skb);
170 if (physoutdev && out != physoutdev) 171 if (physoutdev && out != physoutdev)
171 nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name); 172 nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
172 } 173 }
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 3f3ac57b2998..2e88032cd5ad 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -10,6 +10,7 @@
10#include <linux/proc_fs.h> 10#include <linux/proc_fs.h>
11#include <linux/skbuff.h> 11#include <linux/skbuff.h>
12#include <linux/netfilter.h> 12#include <linux/netfilter.h>
13#include <linux/netfilter_bridge.h>
13#include <linux/seq_file.h> 14#include <linux/seq_file.h>
14#include <linux/rcupdate.h> 15#include <linux/rcupdate.h>
15#include <net/protocol.h> 16#include <net/protocol.h>
@@ -58,12 +59,14 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
58 sock_put(state->sk); 59 sock_put(state->sk);
59#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 60#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
60 if (entry->skb->nf_bridge) { 61 if (entry->skb->nf_bridge) {
61 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; 62 struct net_device *physdev;
62 63
63 if (nf_bridge->physindev) 64 physdev = nf_bridge_get_physindev(entry->skb);
64 dev_put(nf_bridge->physindev); 65 if (physdev)
65 if (nf_bridge->physoutdev) 66 dev_put(physdev);
66 dev_put(nf_bridge->physoutdev); 67 physdev = nf_bridge_get_physoutdev(entry->skb);
68 if (physdev)
69 dev_put(physdev);
67 } 70 }
68#endif 71#endif
69 /* Drop reference to owner of hook which queued us. */ 72 /* Drop reference to owner of hook which queued us. */
@@ -87,13 +90,12 @@ bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
87 sock_hold(state->sk); 90 sock_hold(state->sk);
88#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 91#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
89 if (entry->skb->nf_bridge) { 92 if (entry->skb->nf_bridge) {
90 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
91 struct net_device *physdev; 93 struct net_device *physdev;
92 94
93 physdev = nf_bridge->physindev; 95 physdev = nf_bridge_get_physindev(entry->skb);
94 if (physdev) 96 if (physdev)
95 dev_hold(physdev); 97 dev_hold(physdev);
96 physdev = nf_bridge->physoutdev; 98 physdev = nf_bridge_get_physoutdev(entry->skb);
97 if (physdev) 99 if (physdev)
98 dev_hold(physdev); 100 dev_hold(physdev);
99 } 101 }
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 5604c2df05d1..0b96fa0d64b2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2159,7 +2159,7 @@ nft_select_set_ops(const struct nlattr * const nla[],
2159 features = 0; 2159 features = 0;
2160 if (nla[NFTA_SET_FLAGS] != NULL) { 2160 if (nla[NFTA_SET_FLAGS] != NULL) {
2161 features = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); 2161 features = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
2162 features &= NFT_SET_INTERVAL | NFT_SET_MAP; 2162 features &= NFT_SET_INTERVAL | NFT_SET_MAP | NFT_SET_TIMEOUT;
2163 } 2163 }
2164 2164
2165 bops = NULL; 2165 bops = NULL;
@@ -2216,6 +2216,8 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
2216 [NFTA_SET_POLICY] = { .type = NLA_U32 }, 2216 [NFTA_SET_POLICY] = { .type = NLA_U32 },
2217 [NFTA_SET_DESC] = { .type = NLA_NESTED }, 2217 [NFTA_SET_DESC] = { .type = NLA_NESTED },
2218 [NFTA_SET_ID] = { .type = NLA_U32 }, 2218 [NFTA_SET_ID] = { .type = NLA_U32 },
2219 [NFTA_SET_TIMEOUT] = { .type = NLA_U64 },
2220 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
2219}; 2221};
2220 2222
2221static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { 2223static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
@@ -2366,6 +2368,13 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2366 goto nla_put_failure; 2368 goto nla_put_failure;
2367 } 2369 }
2368 2370
2371 if (set->timeout &&
2372 nla_put_be64(skb, NFTA_SET_TIMEOUT, cpu_to_be64(set->timeout)))
2373 goto nla_put_failure;
2374 if (set->gc_int &&
2375 nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int)))
2376 goto nla_put_failure;
2377
2369 if (set->policy != NFT_SET_POL_PERFORMANCE) { 2378 if (set->policy != NFT_SET_POL_PERFORMANCE) {
2370 if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy))) 2379 if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
2371 goto nla_put_failure; 2380 goto nla_put_failure;
@@ -2578,7 +2587,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2578 char name[IFNAMSIZ]; 2587 char name[IFNAMSIZ];
2579 unsigned int size; 2588 unsigned int size;
2580 bool create; 2589 bool create;
2581 u32 ktype, dtype, flags, policy; 2590 u64 timeout;
2591 u32 ktype, dtype, flags, policy, gc_int;
2582 struct nft_set_desc desc; 2592 struct nft_set_desc desc;
2583 int err; 2593 int err;
2584 2594
@@ -2605,7 +2615,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2605 if (nla[NFTA_SET_FLAGS] != NULL) { 2615 if (nla[NFTA_SET_FLAGS] != NULL) {
2606 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS])); 2616 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
2607 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | 2617 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
2608 NFT_SET_INTERVAL | NFT_SET_MAP)) 2618 NFT_SET_INTERVAL | NFT_SET_MAP |
2619 NFT_SET_TIMEOUT))
2609 return -EINVAL; 2620 return -EINVAL;
2610 } 2621 }
2611 2622
@@ -2631,6 +2642,19 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2631 } else if (flags & NFT_SET_MAP) 2642 } else if (flags & NFT_SET_MAP)
2632 return -EINVAL; 2643 return -EINVAL;
2633 2644
2645 timeout = 0;
2646 if (nla[NFTA_SET_TIMEOUT] != NULL) {
2647 if (!(flags & NFT_SET_TIMEOUT))
2648 return -EINVAL;
2649 timeout = be64_to_cpu(nla_get_be64(nla[NFTA_SET_TIMEOUT]));
2650 }
2651 gc_int = 0;
2652 if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
2653 if (!(flags & NFT_SET_TIMEOUT))
2654 return -EINVAL;
2655 gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
2656 }
2657
2634 policy = NFT_SET_POL_PERFORMANCE; 2658 policy = NFT_SET_POL_PERFORMANCE;
2635 if (nla[NFTA_SET_POLICY] != NULL) 2659 if (nla[NFTA_SET_POLICY] != NULL)
2636 policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY])); 2660 policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
@@ -2699,6 +2723,8 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2699 set->flags = flags; 2723 set->flags = flags;
2700 set->size = desc.size; 2724 set->size = desc.size;
2701 set->policy = policy; 2725 set->policy = policy;
2726 set->timeout = timeout;
2727 set->gc_int = gc_int;
2702 2728
2703 err = ops->init(set, &desc, nla); 2729 err = ops->init(set, &desc, nla);
2704 if (err < 0) 2730 if (err < 0)
@@ -2785,12 +2811,13 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
2785 if (!list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS) 2811 if (!list_empty(&set->bindings) && set->flags & NFT_SET_ANONYMOUS)
2786 return -EBUSY; 2812 return -EBUSY;
2787 2813
2788 if (set->flags & NFT_SET_MAP) { 2814 if (binding->flags & NFT_SET_MAP) {
2789 /* If the set is already bound to the same chain all 2815 /* If the set is already bound to the same chain all
2790 * jumps are already validated for that chain. 2816 * jumps are already validated for that chain.
2791 */ 2817 */
2792 list_for_each_entry(i, &set->bindings, list) { 2818 list_for_each_entry(i, &set->bindings, list) {
2793 if (i->chain == binding->chain) 2819 if (binding->flags & NFT_SET_MAP &&
2820 i->chain == binding->chain)
2794 goto bind; 2821 goto bind;
2795 } 2822 }
2796 2823
@@ -2837,6 +2864,18 @@ const struct nft_set_ext_type nft_set_ext_types[] = {
2837 .len = sizeof(u8), 2864 .len = sizeof(u8),
2838 .align = __alignof__(u8), 2865 .align = __alignof__(u8),
2839 }, 2866 },
2867 [NFT_SET_EXT_TIMEOUT] = {
2868 .len = sizeof(u64),
2869 .align = __alignof__(u64),
2870 },
2871 [NFT_SET_EXT_EXPIRATION] = {
2872 .len = sizeof(unsigned long),
2873 .align = __alignof__(unsigned long),
2874 },
2875 [NFT_SET_EXT_USERDATA] = {
2876 .len = sizeof(struct nft_userdata),
2877 .align = __alignof__(struct nft_userdata),
2878 },
2840}; 2879};
2841EXPORT_SYMBOL_GPL(nft_set_ext_types); 2880EXPORT_SYMBOL_GPL(nft_set_ext_types);
2842 2881
@@ -2848,6 +2887,9 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
2848 [NFTA_SET_ELEM_KEY] = { .type = NLA_NESTED }, 2887 [NFTA_SET_ELEM_KEY] = { .type = NLA_NESTED },
2849 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED }, 2888 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED },
2850 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 }, 2889 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 },
2890 [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 },
2891 [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY,
2892 .len = NFT_USERDATA_MAXLEN },
2851}; 2893};
2852 2894
2853static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = { 2895static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
@@ -2909,6 +2951,34 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
2909 htonl(*nft_set_ext_flags(ext)))) 2951 htonl(*nft_set_ext_flags(ext))))
2910 goto nla_put_failure; 2952 goto nla_put_failure;
2911 2953
2954 if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
2955 nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
2956 cpu_to_be64(*nft_set_ext_timeout(ext))))
2957 goto nla_put_failure;
2958
2959 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
2960 unsigned long expires, now = jiffies;
2961
2962 expires = *nft_set_ext_expiration(ext);
2963 if (time_before(now, expires))
2964 expires -= now;
2965 else
2966 expires = 0;
2967
2968 if (nla_put_be64(skb, NFTA_SET_ELEM_EXPIRATION,
2969 cpu_to_be64(jiffies_to_msecs(expires))))
2970 goto nla_put_failure;
2971 }
2972
2973 if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) {
2974 struct nft_userdata *udata;
2975
2976 udata = nft_set_ext_userdata(ext);
2977 if (nla_put(skb, NFTA_SET_ELEM_USERDATA,
2978 udata->len + 1, udata->data))
2979 goto nla_put_failure;
2980 }
2981
2912 nla_nest_end(skb, nest); 2982 nla_nest_end(skb, nest);
2913 return 0; 2983 return 0;
2914 2984
@@ -3128,11 +3198,11 @@ static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
3128 return trans; 3198 return trans;
3129} 3199}
3130 3200
3131static void *nft_set_elem_init(const struct nft_set *set, 3201void *nft_set_elem_init(const struct nft_set *set,
3132 const struct nft_set_ext_tmpl *tmpl, 3202 const struct nft_set_ext_tmpl *tmpl,
3133 const struct nft_data *key, 3203 const struct nft_data *key,
3134 const struct nft_data *data, 3204 const struct nft_data *data,
3135 gfp_t gfp) 3205 u64 timeout, gfp_t gfp)
3136{ 3206{
3137 struct nft_set_ext *ext; 3207 struct nft_set_ext *ext;
3138 void *elem; 3208 void *elem;
@@ -3147,6 +3217,11 @@ static void *nft_set_elem_init(const struct nft_set *set,
3147 memcpy(nft_set_ext_key(ext), key, set->klen); 3217 memcpy(nft_set_ext_key(ext), key, set->klen);
3148 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA)) 3218 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
3149 memcpy(nft_set_ext_data(ext), data, set->dlen); 3219 memcpy(nft_set_ext_data(ext), data, set->dlen);
3220 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION))
3221 *nft_set_ext_expiration(ext) =
3222 jiffies + msecs_to_jiffies(timeout);
3223 if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT))
3224 *nft_set_ext_timeout(ext) = timeout;
3150 3225
3151 return elem; 3226 return elem;
3152} 3227}
@@ -3172,15 +3247,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3172 struct nft_set_ext *ext; 3247 struct nft_set_ext *ext;
3173 struct nft_set_elem elem; 3248 struct nft_set_elem elem;
3174 struct nft_set_binding *binding; 3249 struct nft_set_binding *binding;
3250 struct nft_userdata *udata;
3175 struct nft_data data; 3251 struct nft_data data;
3176 enum nft_registers dreg; 3252 enum nft_registers dreg;
3177 struct nft_trans *trans; 3253 struct nft_trans *trans;
3254 u64 timeout;
3178 u32 flags; 3255 u32 flags;
3256 u8 ulen;
3179 int err; 3257 int err;
3180 3258
3181 if (set->size && set->nelems == set->size)
3182 return -ENFILE;
3183
3184 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr, 3259 err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
3185 nft_set_elem_policy); 3260 nft_set_elem_policy);
3186 if (err < 0) 3261 if (err < 0)
@@ -3215,6 +3290,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3215 return -EINVAL; 3290 return -EINVAL;
3216 } 3291 }
3217 3292
3293 timeout = 0;
3294 if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
3295 if (!(set->flags & NFT_SET_TIMEOUT))
3296 return -EINVAL;
3297 timeout = be64_to_cpu(nla_get_be64(nla[NFTA_SET_ELEM_TIMEOUT]));
3298 } else if (set->flags & NFT_SET_TIMEOUT) {
3299 timeout = set->timeout;
3300 }
3301
3218 err = nft_data_init(ctx, &elem.key, &d1, nla[NFTA_SET_ELEM_KEY]); 3302 err = nft_data_init(ctx, &elem.key, &d1, nla[NFTA_SET_ELEM_KEY]);
3219 if (err < 0) 3303 if (err < 0)
3220 goto err1; 3304 goto err1;
@@ -3223,6 +3307,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3223 goto err2; 3307 goto err2;
3224 3308
3225 nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY); 3309 nft_set_ext_add(&tmpl, NFT_SET_EXT_KEY);
3310 if (timeout > 0) {
3311 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
3312 if (timeout != set->timeout)
3313 nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
3314 }
3226 3315
3227 if (nla[NFTA_SET_ELEM_DATA] != NULL) { 3316 if (nla[NFTA_SET_ELEM_DATA] != NULL) {
3228 err = nft_data_init(ctx, &data, &d2, nla[NFTA_SET_ELEM_DATA]); 3317 err = nft_data_init(ctx, &data, &d2, nla[NFTA_SET_ELEM_DATA]);
@@ -3241,6 +3330,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3241 .chain = (struct nft_chain *)binding->chain, 3330 .chain = (struct nft_chain *)binding->chain,
3242 }; 3331 };
3243 3332
3333 if (!(binding->flags & NFT_SET_MAP))
3334 continue;
3335
3244 err = nft_validate_data_load(&bind_ctx, dreg, 3336 err = nft_validate_data_load(&bind_ctx, dreg,
3245 &data, d2.type); 3337 &data, d2.type);
3246 if (err < 0) 3338 if (err < 0)
@@ -3250,20 +3342,38 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
3250 nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA); 3342 nft_set_ext_add(&tmpl, NFT_SET_EXT_DATA);
3251 } 3343 }
3252 3344
3345 /* The full maximum length of userdata can exceed the maximum
3346 * offset value (U8_MAX) for following extensions, therefor it
3347 * must be the last extension added.
3348 */
3349 ulen = 0;
3350 if (nla[NFTA_SET_ELEM_USERDATA] != NULL) {
3351 ulen = nla_len(nla[NFTA_SET_ELEM_USERDATA]);
3352 if (ulen > 0)
3353 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_USERDATA,
3354 ulen);
3355 }
3356
3253 err = -ENOMEM; 3357 err = -ENOMEM;
3254 elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data, GFP_KERNEL); 3358 elem.priv = nft_set_elem_init(set, &tmpl, &elem.key, &data,
3359 timeout, GFP_KERNEL);
3255 if (elem.priv == NULL) 3360 if (elem.priv == NULL)
3256 goto err3; 3361 goto err3;
3257 3362
3258 ext = nft_set_elem_ext(set, elem.priv); 3363 ext = nft_set_elem_ext(set, elem.priv);
3259 if (flags) 3364 if (flags)
3260 *nft_set_ext_flags(ext) = flags; 3365 *nft_set_ext_flags(ext) = flags;
3366 if (ulen > 0) {
3367 udata = nft_set_ext_userdata(ext);
3368 udata->len = ulen - 1;
3369 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
3370 }
3261 3371
3262 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set); 3372 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
3263 if (trans == NULL) 3373 if (trans == NULL)
3264 goto err4; 3374 goto err4;
3265 3375
3266 ext->genmask = nft_genmask_cur(ctx->net); 3376 ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
3267 err = set->ops->insert(set, &elem); 3377 err = set->ops->insert(set, &elem);
3268 if (err < 0) 3378 if (err < 0)
3269 goto err5; 3379 goto err5;
@@ -3316,11 +3426,15 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
3316 return -EBUSY; 3426 return -EBUSY;
3317 3427
3318 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { 3428 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
3429 if (set->size &&
3430 !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact))
3431 return -ENFILE;
3432
3319 err = nft_add_set_elem(&ctx, set, attr); 3433 err = nft_add_set_elem(&ctx, set, attr);
3320 if (err < 0) 3434 if (err < 0) {
3435 atomic_dec(&set->nelems);
3321 break; 3436 break;
3322 3437 }
3323 set->nelems++;
3324 } 3438 }
3325 return err; 3439 return err;
3326} 3440}
@@ -3402,11 +3516,36 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
3402 if (err < 0) 3516 if (err < 0)
3403 break; 3517 break;
3404 3518
3405 set->nelems--; 3519 set->ndeact++;
3406 } 3520 }
3407 return err; 3521 return err;
3408} 3522}
3409 3523
3524void nft_set_gc_batch_release(struct rcu_head *rcu)
3525{
3526 struct nft_set_gc_batch *gcb;
3527 unsigned int i;
3528
3529 gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu);
3530 for (i = 0; i < gcb->head.cnt; i++)
3531 nft_set_elem_destroy(gcb->head.set, gcb->elems[i]);
3532 kfree(gcb);
3533}
3534EXPORT_SYMBOL_GPL(nft_set_gc_batch_release);
3535
3536struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
3537 gfp_t gfp)
3538{
3539 struct nft_set_gc_batch *gcb;
3540
3541 gcb = kzalloc(sizeof(*gcb), gfp);
3542 if (gcb == NULL)
3543 return gcb;
3544 gcb->head.set = set;
3545 return gcb;
3546}
3547EXPORT_SYMBOL_GPL(nft_set_gc_batch_alloc);
3548
3410static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, 3549static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
3411 u32 portid, u32 seq) 3550 u32 portid, u32 seq)
3412{ 3551{
@@ -3710,6 +3849,8 @@ static int nf_tables_commit(struct sk_buff *skb)
3710 &te->elem, 3849 &te->elem,
3711 NFT_MSG_DELSETELEM, 0); 3850 NFT_MSG_DELSETELEM, 0);
3712 te->set->ops->remove(te->set, &te->elem); 3851 te->set->ops->remove(te->set, &te->elem);
3852 atomic_dec(&te->set->nelems);
3853 te->set->ndeact--;
3713 break; 3854 break;
3714 } 3855 }
3715 } 3856 }
@@ -3813,16 +3954,16 @@ static int nf_tables_abort(struct sk_buff *skb)
3813 nft_trans_destroy(trans); 3954 nft_trans_destroy(trans);
3814 break; 3955 break;
3815 case NFT_MSG_NEWSETELEM: 3956 case NFT_MSG_NEWSETELEM:
3816 nft_trans_elem_set(trans)->nelems--;
3817 te = (struct nft_trans_elem *)trans->data; 3957 te = (struct nft_trans_elem *)trans->data;
3818 3958
3819 te->set->ops->remove(te->set, &te->elem); 3959 te->set->ops->remove(te->set, &te->elem);
3960 atomic_dec(&te->set->nelems);
3820 break; 3961 break;
3821 case NFT_MSG_DELSETELEM: 3962 case NFT_MSG_DELSETELEM:
3822 te = (struct nft_trans_elem *)trans->data; 3963 te = (struct nft_trans_elem *)trans->data;
3823 3964
3824 nft_trans_elem_set(trans)->nelems++;
3825 te->set->ops->activate(te->set, &te->elem); 3965 te->set->ops->activate(te->set, &te->elem);
3966 te->set->ndeact--;
3826 3967
3827 nft_trans_destroy(trans); 3968 nft_trans_destroy(trans);
3828 break; 3969 break;
@@ -3960,7 +4101,8 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
3960 continue; 4101 continue;
3961 4102
3962 list_for_each_entry(binding, &set->bindings, list) { 4103 list_for_each_entry(binding, &set->bindings, list) {
3963 if (binding->chain != chain) 4104 if (!(binding->flags & NFT_SET_MAP) ||
4105 binding->chain != chain)
3964 continue; 4106 continue;
3965 4107
3966 iter.skip = 0; 4108 iter.skip = 0;
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index ef4dfcbaf149..7caf08a9225d 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -239,8 +239,14 @@ int __init nf_tables_core_module_init(void)
239 if (err < 0) 239 if (err < 0)
240 goto err6; 240 goto err6;
241 241
242 err = nft_dynset_module_init();
243 if (err < 0)
244 goto err7;
245
242 return 0; 246 return 0;
243 247
248err7:
249 nft_payload_module_exit();
244err6: 250err6:
245 nft_byteorder_module_exit(); 251 nft_byteorder_module_exit();
246err5: 252err5:
@@ -257,6 +263,7 @@ err1:
257 263
258void nf_tables_core_module_exit(void) 264void nf_tables_core_module_exit(void)
259{ 265{
266 nft_dynset_module_exit();
260 nft_payload_module_exit(); 267 nft_payload_module_exit();
261 nft_byteorder_module_exit(); 268 nft_byteorder_module_exit();
262 nft_bitwise_module_exit(); 269 nft_bitwise_module_exit();
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 957b83a0223b..51afea4b0af7 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -23,6 +23,7 @@
23#include <linux/ipv6.h> 23#include <linux/ipv6.h>
24#include <linux/netdevice.h> 24#include <linux/netdevice.h>
25#include <linux/netfilter.h> 25#include <linux/netfilter.h>
26#include <linux/netfilter_bridge.h>
26#include <net/netlink.h> 27#include <net/netlink.h>
27#include <linux/netfilter/nfnetlink.h> 28#include <linux/netfilter/nfnetlink.h>
28#include <linux/netfilter/nfnetlink_log.h> 29#include <linux/netfilter/nfnetlink_log.h>
@@ -448,14 +449,18 @@ __build_packet_message(struct nfnl_log_net *log,
448 htonl(br_port_get_rcu(indev)->br->dev->ifindex))) 449 htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
449 goto nla_put_failure; 450 goto nla_put_failure;
450 } else { 451 } else {
452 struct net_device *physindev;
453
451 /* Case 2: indev is bridge group, we need to look for 454 /* Case 2: indev is bridge group, we need to look for
452 * physical device (when called from ipv4) */ 455 * physical device (when called from ipv4) */
453 if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, 456 if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
454 htonl(indev->ifindex))) 457 htonl(indev->ifindex)))
455 goto nla_put_failure; 458 goto nla_put_failure;
456 if (skb->nf_bridge && skb->nf_bridge->physindev && 459
460 physindev = nf_bridge_get_physindev(skb);
461 if (physindev &&
457 nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, 462 nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
458 htonl(skb->nf_bridge->physindev->ifindex))) 463 htonl(physindev->ifindex)))
459 goto nla_put_failure; 464 goto nla_put_failure;
460 } 465 }
461#endif 466#endif
@@ -479,14 +484,18 @@ __build_packet_message(struct nfnl_log_net *log,
479 htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) 484 htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
480 goto nla_put_failure; 485 goto nla_put_failure;
481 } else { 486 } else {
487 struct net_device *physoutdev;
488
482 /* Case 2: indev is a bridge group, we need to look 489 /* Case 2: indev is a bridge group, we need to look
483 * for physical device (when called from ipv4) */ 490 * for physical device (when called from ipv4) */
484 if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, 491 if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
485 htonl(outdev->ifindex))) 492 htonl(outdev->ifindex)))
486 goto nla_put_failure; 493 goto nla_put_failure;
487 if (skb->nf_bridge && skb->nf_bridge->physoutdev && 494
495 physoutdev = nf_bridge_get_physoutdev(skb);
496 if (physoutdev &&
488 nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, 497 nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
489 htonl(skb->nf_bridge->physoutdev->ifindex))) 498 htonl(physoutdev->ifindex)))
490 goto nla_put_failure; 499 goto nla_put_failure;
491 } 500 }
492#endif 501#endif
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 6e74655a8d4f..628afc350c02 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -25,6 +25,7 @@
25#include <linux/proc_fs.h> 25#include <linux/proc_fs.h>
26#include <linux/netfilter_ipv4.h> 26#include <linux/netfilter_ipv4.h>
27#include <linux/netfilter_ipv6.h> 27#include <linux/netfilter_ipv6.h>
28#include <linux/netfilter_bridge.h>
28#include <linux/netfilter/nfnetlink.h> 29#include <linux/netfilter/nfnetlink.h>
29#include <linux/netfilter/nfnetlink_queue.h> 30#include <linux/netfilter/nfnetlink_queue.h>
30#include <linux/list.h> 31#include <linux/list.h>
@@ -396,14 +397,18 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
396 htonl(br_port_get_rcu(indev)->br->dev->ifindex))) 397 htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
397 goto nla_put_failure; 398 goto nla_put_failure;
398 } else { 399 } else {
400 int physinif;
401
399 /* Case 2: indev is bridge group, we need to look for 402 /* Case 2: indev is bridge group, we need to look for
400 * physical device (when called from ipv4) */ 403 * physical device (when called from ipv4) */
401 if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, 404 if (nla_put_be32(skb, NFQA_IFINDEX_INDEV,
402 htonl(indev->ifindex))) 405 htonl(indev->ifindex)))
403 goto nla_put_failure; 406 goto nla_put_failure;
404 if (entskb->nf_bridge && entskb->nf_bridge->physindev && 407
408 physinif = nf_bridge_get_physinif(entskb);
409 if (physinif &&
405 nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV, 410 nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV,
406 htonl(entskb->nf_bridge->physindev->ifindex))) 411 htonl(physinif)))
407 goto nla_put_failure; 412 goto nla_put_failure;
408 } 413 }
409#endif 414#endif
@@ -426,14 +431,18 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
426 htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) 431 htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
427 goto nla_put_failure; 432 goto nla_put_failure;
428 } else { 433 } else {
434 int physoutif;
435
429 /* Case 2: outdev is bridge group, we need to look for 436 /* Case 2: outdev is bridge group, we need to look for
430 * physical output device (when called from ipv4) */ 437 * physical output device (when called from ipv4) */
431 if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, 438 if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV,
432 htonl(outdev->ifindex))) 439 htonl(outdev->ifindex)))
433 goto nla_put_failure; 440 goto nla_put_failure;
434 if (entskb->nf_bridge && entskb->nf_bridge->physoutdev && 441
442 physoutif = nf_bridge_get_physoutif(entskb);
443 if (physoutif &&
435 nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV, 444 nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV,
436 htonl(entskb->nf_bridge->physoutdev->ifindex))) 445 htonl(physoutif)))
437 goto nla_put_failure; 446 goto nla_put_failure;
438 } 447 }
439#endif 448#endif
@@ -765,11 +774,12 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
765 return 1; 774 return 1;
766#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 775#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
767 if (entry->skb->nf_bridge) { 776 if (entry->skb->nf_bridge) {
768 if (entry->skb->nf_bridge->physindev && 777 int physinif, physoutif;
769 entry->skb->nf_bridge->physindev->ifindex == ifindex) 778
770 return 1; 779 physinif = nf_bridge_get_physinif(entry->skb);
771 if (entry->skb->nf_bridge->physoutdev && 780 physoutif = nf_bridge_get_physoutif(entry->skb);
772 entry->skb->nf_bridge->physoutdev->ifindex == ifindex) 781
782 if (physinif == ifindex || physoutif == ifindex)
773 return 1; 783 return 1;
774 } 784 }
775#endif 785#endif
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
new file mode 100644
index 000000000000..eeb72dee78ef
--- /dev/null
+++ b/net/netfilter/nft_dynset.c
@@ -0,0 +1,218 @@
1/*
2 * Copyright (c) 2015 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/netlink.h>
14#include <linux/netfilter.h>
15#include <linux/netfilter/nf_tables.h>
16#include <net/netfilter/nf_tables.h>
17#include <net/netfilter/nf_tables_core.h>
18
19struct nft_dynset {
20 struct nft_set *set;
21 struct nft_set_ext_tmpl tmpl;
22 enum nft_dynset_ops op:8;
23 enum nft_registers sreg_key:8;
24 enum nft_registers sreg_data:8;
25 u64 timeout;
26 struct nft_set_binding binding;
27};
28
29static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr,
30 struct nft_data data[NFT_REG_MAX + 1])
31{
32 const struct nft_dynset *priv = nft_expr_priv(expr);
33 u64 timeout;
34 void *elem;
35
36 if (set->size && !atomic_add_unless(&set->nelems, 1, set->size))
37 return NULL;
38
39 timeout = priv->timeout ? : set->timeout;
40 elem = nft_set_elem_init(set, &priv->tmpl,
41 &data[priv->sreg_key], &data[priv->sreg_data],
42 timeout, GFP_ATOMIC);
43 if (elem == NULL) {
44 if (set->size)
45 atomic_dec(&set->nelems);
46 }
47 return elem;
48}
49
50static void nft_dynset_eval(const struct nft_expr *expr,
51 struct nft_data data[NFT_REG_MAX + 1],
52 const struct nft_pktinfo *pkt)
53{
54 const struct nft_dynset *priv = nft_expr_priv(expr);
55 struct nft_set *set = priv->set;
56 const struct nft_set_ext *ext;
57 u64 timeout;
58
59 if (set->ops->update(set, &data[priv->sreg_key], nft_dynset_new,
60 expr, data, &ext)) {
61 if (priv->op == NFT_DYNSET_OP_UPDATE &&
62 nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
63 timeout = priv->timeout ? : set->timeout;
64 *nft_set_ext_expiration(ext) = jiffies + timeout;
65 return;
66 }
67 }
68
69 data[NFT_REG_VERDICT].verdict = NFT_BREAK;
70}
71
72static const struct nla_policy nft_dynset_policy[NFTA_DYNSET_MAX + 1] = {
73 [NFTA_DYNSET_SET_NAME] = { .type = NLA_STRING },
74 [NFTA_DYNSET_SET_ID] = { .type = NLA_U32 },
75 [NFTA_DYNSET_OP] = { .type = NLA_U32 },
76 [NFTA_DYNSET_SREG_KEY] = { .type = NLA_U32 },
77 [NFTA_DYNSET_SREG_DATA] = { .type = NLA_U32 },
78 [NFTA_DYNSET_TIMEOUT] = { .type = NLA_U64 },
79};
80
81static int nft_dynset_init(const struct nft_ctx *ctx,
82 const struct nft_expr *expr,
83 const struct nlattr * const tb[])
84{
85 struct nft_dynset *priv = nft_expr_priv(expr);
86 struct nft_set *set;
87 u64 timeout;
88 int err;
89
90 if (tb[NFTA_DYNSET_SET_NAME] == NULL ||
91 tb[NFTA_DYNSET_OP] == NULL ||
92 tb[NFTA_DYNSET_SREG_KEY] == NULL)
93 return -EINVAL;
94
95 set = nf_tables_set_lookup(ctx->table, tb[NFTA_DYNSET_SET_NAME]);
96 if (IS_ERR(set)) {
97 if (tb[NFTA_DYNSET_SET_ID])
98 set = nf_tables_set_lookup_byid(ctx->net,
99 tb[NFTA_DYNSET_SET_ID]);
100 if (IS_ERR(set))
101 return PTR_ERR(set);
102 }
103
104 if (set->flags & NFT_SET_CONSTANT)
105 return -EBUSY;
106
107 priv->op = ntohl(nla_get_be32(tb[NFTA_DYNSET_OP]));
108 switch (priv->op) {
109 case NFT_DYNSET_OP_ADD:
110 break;
111 case NFT_DYNSET_OP_UPDATE:
112 if (!(set->flags & NFT_SET_TIMEOUT))
113 return -EOPNOTSUPP;
114 break;
115 default:
116 return -EOPNOTSUPP;
117 }
118
119 timeout = 0;
120 if (tb[NFTA_DYNSET_TIMEOUT] != NULL) {
121 if (!(set->flags & NFT_SET_TIMEOUT))
122 return -EINVAL;
123 timeout = be64_to_cpu(nla_get_be64(tb[NFTA_DYNSET_TIMEOUT]));
124 }
125
126 priv->sreg_key = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_KEY]));
127 err = nft_validate_input_register(priv->sreg_key);
128 if (err < 0)
129 return err;
130
131 if (tb[NFTA_DYNSET_SREG_DATA] != NULL) {
132 if (!(set->flags & NFT_SET_MAP))
133 return -EINVAL;
134 if (set->dtype == NFT_DATA_VERDICT)
135 return -EOPNOTSUPP;
136
137 priv->sreg_data = ntohl(nla_get_be32(tb[NFTA_DYNSET_SREG_DATA]));
138 err = nft_validate_input_register(priv->sreg_data);
139 if (err < 0)
140 return err;
141 } else if (set->flags & NFT_SET_MAP)
142 return -EINVAL;
143
144 nft_set_ext_prepare(&priv->tmpl);
145 nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen);
146 if (set->flags & NFT_SET_MAP)
147 nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_DATA, set->dlen);
148 if (set->flags & NFT_SET_TIMEOUT) {
149 if (timeout || set->timeout)
150 nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION);
151 }
152
153 priv->timeout = timeout;
154
155 err = nf_tables_bind_set(ctx, set, &priv->binding);
156 if (err < 0)
157 return err;
158
159 priv->set = set;
160 return 0;
161}
162
163static void nft_dynset_destroy(const struct nft_ctx *ctx,
164 const struct nft_expr *expr)
165{
166 struct nft_dynset *priv = nft_expr_priv(expr);
167
168 nf_tables_unbind_set(ctx, priv->set, &priv->binding);
169}
170
171static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr)
172{
173 const struct nft_dynset *priv = nft_expr_priv(expr);
174
175 if (nla_put_be32(skb, NFTA_DYNSET_SREG_KEY, htonl(priv->sreg_key)))
176 goto nla_put_failure;
177 if (priv->set->flags & NFT_SET_MAP &&
178 nla_put_be32(skb, NFTA_DYNSET_SREG_DATA, htonl(priv->sreg_data)))
179 goto nla_put_failure;
180 if (nla_put_be32(skb, NFTA_DYNSET_OP, htonl(priv->op)))
181 goto nla_put_failure;
182 if (nla_put_string(skb, NFTA_DYNSET_SET_NAME, priv->set->name))
183 goto nla_put_failure;
184 if (nla_put_be64(skb, NFTA_DYNSET_TIMEOUT, cpu_to_be64(priv->timeout)))
185 goto nla_put_failure;
186 return 0;
187
188nla_put_failure:
189 return -1;
190}
191
192static struct nft_expr_type nft_dynset_type;
193static const struct nft_expr_ops nft_dynset_ops = {
194 .type = &nft_dynset_type,
195 .size = NFT_EXPR_SIZE(sizeof(struct nft_dynset)),
196 .eval = nft_dynset_eval,
197 .init = nft_dynset_init,
198 .destroy = nft_dynset_destroy,
199 .dump = nft_dynset_dump,
200};
201
202static struct nft_expr_type nft_dynset_type __read_mostly = {
203 .name = "dynset",
204 .ops = &nft_dynset_ops,
205 .policy = nft_dynset_policy,
206 .maxattr = NFTA_DYNSET_MAX,
207 .owner = THIS_MODULE,
208};
209
210int __init nft_dynset_module_init(void)
211{
212 return nft_register_expr(&nft_dynset_type);
213}
214
215void nft_dynset_module_exit(void)
216{
217 nft_unregister_expr(&nft_dynset_type);
218}
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index c7e1a9d7d46f..bc23806b7fbe 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -15,6 +15,7 @@
15#include <linux/log2.h> 15#include <linux/log2.h>
16#include <linux/jhash.h> 16#include <linux/jhash.h>
17#include <linux/netlink.h> 17#include <linux/netlink.h>
18#include <linux/workqueue.h>
18#include <linux/rhashtable.h> 19#include <linux/rhashtable.h>
19#include <linux/netfilter.h> 20#include <linux/netfilter.h>
20#include <linux/netfilter/nf_tables.h> 21#include <linux/netfilter/nf_tables.h>
@@ -25,6 +26,7 @@
25 26
26struct nft_hash { 27struct nft_hash {
27 struct rhashtable ht; 28 struct rhashtable ht;
29 struct delayed_work gc_work;
28}; 30};
29 31
30struct nft_hash_elem { 32struct nft_hash_elem {
@@ -62,6 +64,8 @@ static inline int nft_hash_cmp(struct rhashtable_compare_arg *arg,
62 64
63 if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) 65 if (nft_data_cmp(nft_set_ext_key(&he->ext), x->key, x->set->klen))
64 return 1; 66 return 1;
67 if (nft_set_elem_expired(&he->ext))
68 return 1;
65 if (!nft_set_elem_active(&he->ext, x->genmask)) 69 if (!nft_set_elem_active(&he->ext, x->genmask))
66 return 1; 70 return 1;
67 return 0; 71 return 0;
@@ -86,6 +90,42 @@ static bool nft_hash_lookup(const struct nft_set *set,
86 return !!he; 90 return !!he;
87} 91}
88 92
93static bool nft_hash_update(struct nft_set *set, const struct nft_data *key,
94 void *(*new)(struct nft_set *,
95 const struct nft_expr *,
96 struct nft_data []),
97 const struct nft_expr *expr,
98 struct nft_data data[],
99 const struct nft_set_ext **ext)
100{
101 struct nft_hash *priv = nft_set_priv(set);
102 struct nft_hash_elem *he;
103 struct nft_hash_cmp_arg arg = {
104 .genmask = NFT_GENMASK_ANY,
105 .set = set,
106 .key = key,
107 };
108
109 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);
110 if (he != NULL)
111 goto out;
112
113 he = new(set, expr, data);
114 if (he == NULL)
115 goto err1;
116 if (rhashtable_lookup_insert_key(&priv->ht, &arg, &he->node,
117 nft_hash_params))
118 goto err2;
119out:
120 *ext = &he->ext;
121 return true;
122
123err2:
124 nft_set_elem_destroy(set, he);
125err1:
126 return false;
127}
128
89static int nft_hash_insert(const struct nft_set *set, 129static int nft_hash_insert(const struct nft_set *set,
90 const struct nft_set_elem *elem) 130 const struct nft_set_elem *elem)
91{ 131{
@@ -107,6 +147,7 @@ static void nft_hash_activate(const struct nft_set *set,
107 struct nft_hash_elem *he = elem->priv; 147 struct nft_hash_elem *he = elem->priv;
108 148
109 nft_set_elem_change_active(set, &he->ext); 149 nft_set_elem_change_active(set, &he->ext);
150 nft_set_elem_clear_busy(&he->ext);
110} 151}
111 152
112static void *nft_hash_deactivate(const struct nft_set *set, 153static void *nft_hash_deactivate(const struct nft_set *set,
@@ -120,9 +161,15 @@ static void *nft_hash_deactivate(const struct nft_set *set,
120 .key = &elem->key, 161 .key = &elem->key,
121 }; 162 };
122 163
164 rcu_read_lock();
123 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params); 165 he = rhashtable_lookup_fast(&priv->ht, &arg, nft_hash_params);
124 if (he != NULL) 166 if (he != NULL) {
125 nft_set_elem_change_active(set, &he->ext); 167 if (!nft_set_elem_mark_busy(&he->ext))
168 nft_set_elem_change_active(set, &he->ext);
169 else
170 he = NULL;
171 }
172 rcu_read_unlock();
126 173
127 return he; 174 return he;
128} 175}
@@ -170,6 +217,8 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
170 217
171 if (iter->count < iter->skip) 218 if (iter->count < iter->skip)
172 goto cont; 219 goto cont;
220 if (nft_set_elem_expired(&he->ext))
221 goto cont;
173 if (!nft_set_elem_active(&he->ext, genmask)) 222 if (!nft_set_elem_active(&he->ext, genmask))
174 goto cont; 223 goto cont;
175 224
@@ -188,6 +237,55 @@ out:
188 rhashtable_walk_exit(&hti); 237 rhashtable_walk_exit(&hti);
189} 238}
190 239
240static void nft_hash_gc(struct work_struct *work)
241{
242 struct nft_set *set;
243 struct nft_hash_elem *he;
244 struct nft_hash *priv;
245 struct nft_set_gc_batch *gcb = NULL;
246 struct rhashtable_iter hti;
247 int err;
248
249 priv = container_of(work, struct nft_hash, gc_work.work);
250 set = nft_set_container_of(priv);
251
252 err = rhashtable_walk_init(&priv->ht, &hti);
253 if (err)
254 goto schedule;
255
256 err = rhashtable_walk_start(&hti);
257 if (err && err != -EAGAIN)
258 goto out;
259
260 while ((he = rhashtable_walk_next(&hti))) {
261 if (IS_ERR(he)) {
262 if (PTR_ERR(he) != -EAGAIN)
263 goto out;
264 continue;
265 }
266
267 if (!nft_set_elem_expired(&he->ext))
268 continue;
269 if (nft_set_elem_mark_busy(&he->ext))
270 continue;
271
272 gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC);
273 if (gcb == NULL)
274 goto out;
275 rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params);
276 atomic_dec(&set->nelems);
277 nft_set_gc_batch_add(gcb, he);
278 }
279out:
280 rhashtable_walk_stop(&hti);
281 rhashtable_walk_exit(&hti);
282
283 nft_set_gc_batch_complete(gcb);
284schedule:
285 queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
286 nft_set_gc_interval(set));
287}
288
191static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) 289static unsigned int nft_hash_privsize(const struct nlattr * const nla[])
192{ 290{
193 return sizeof(struct nft_hash); 291 return sizeof(struct nft_hash);
@@ -207,11 +305,20 @@ static int nft_hash_init(const struct nft_set *set,
207{ 305{
208 struct nft_hash *priv = nft_set_priv(set); 306 struct nft_hash *priv = nft_set_priv(set);
209 struct rhashtable_params params = nft_hash_params; 307 struct rhashtable_params params = nft_hash_params;
308 int err;
210 309
211 params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT; 310 params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT;
212 params.key_len = set->klen; 311 params.key_len = set->klen;
213 312
214 return rhashtable_init(&priv->ht, &params); 313 err = rhashtable_init(&priv->ht, &params);
314 if (err < 0)
315 return err;
316
317 INIT_DEFERRABLE_WORK(&priv->gc_work, nft_hash_gc);
318 if (set->flags & NFT_SET_TIMEOUT)
319 queue_delayed_work(system_power_efficient_wq, &priv->gc_work,
320 nft_set_gc_interval(set));
321 return 0;
215} 322}
216 323
217static void nft_hash_elem_destroy(void *ptr, void *arg) 324static void nft_hash_elem_destroy(void *ptr, void *arg)
@@ -223,6 +330,7 @@ static void nft_hash_destroy(const struct nft_set *set)
223{ 330{
224 struct nft_hash *priv = nft_set_priv(set); 331 struct nft_hash *priv = nft_set_priv(set);
225 332
333 cancel_delayed_work_sync(&priv->gc_work);
226 rhashtable_free_and_destroy(&priv->ht, nft_hash_elem_destroy, 334 rhashtable_free_and_destroy(&priv->ht, nft_hash_elem_destroy,
227 (void *)set); 335 (void *)set);
228} 336}
@@ -263,8 +371,9 @@ static struct nft_set_ops nft_hash_ops __read_mostly = {
263 .deactivate = nft_hash_deactivate, 371 .deactivate = nft_hash_deactivate,
264 .remove = nft_hash_remove, 372 .remove = nft_hash_remove,
265 .lookup = nft_hash_lookup, 373 .lookup = nft_hash_lookup,
374 .update = nft_hash_update,
266 .walk = nft_hash_walk, 375 .walk = nft_hash_walk,
267 .features = NFT_SET_MAP, 376 .features = NFT_SET_MAP | NFT_SET_TIMEOUT,
268 .owner = THIS_MODULE, 377 .owner = THIS_MODULE,
269}; 378};
270 379
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index a5f30b8760ea..d8cf86fb30fc 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -92,6 +92,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
92 } else if (set->flags & NFT_SET_MAP) 92 } else if (set->flags & NFT_SET_MAP)
93 return -EINVAL; 93 return -EINVAL;
94 94
95 priv->binding.flags = set->flags & NFT_SET_MAP;
96
95 err = nf_tables_bind_set(ctx, set, &priv->binding); 97 err = nf_tables_bind_set(ctx, set, &priv->binding);
96 if (err < 0) 98 if (err < 0)
97 return err; 99 return err;
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 5197874372ec..d79ce88be77f 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -166,9 +166,8 @@ void nft_meta_get_eval(const struct nft_expr *expr,
166 dest->data[0] = out->group; 166 dest->data[0] = out->group;
167 break; 167 break;
168 case NFT_META_CGROUP: 168 case NFT_META_CGROUP:
169 if (skb->sk == NULL) 169 if (skb->sk == NULL || !sk_fullsock(skb->sk))
170 break; 170 goto err;
171
172 dest->data[0] = skb->sk->sk_classid; 171 dest->data[0] = skb->sk->sk_classid;
173 break; 172 break;
174 default: 173 default:
diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c
index 7198d660b4de..a1d126f29463 100644
--- a/net/netfilter/xt_cgroup.c
+++ b/net/netfilter/xt_cgroup.c
@@ -39,7 +39,7 @@ cgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
39{ 39{
40 const struct xt_cgroup_info *info = par->matchinfo; 40 const struct xt_cgroup_info *info = par->matchinfo;
41 41
42 if (skb->sk == NULL) 42 if (skb->sk == NULL || !sk_fullsock(skb->sk))
43 return false; 43 return false;
44 44
45 return (info->id == skb->sk->sk_classid) ^ info->invert; 45 return (info->id == skb->sk->sk_classid) ^ info->invert;
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index 50a52043650f..1caaccbc306c 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -25,16 +25,15 @@ MODULE_ALIAS("ip6t_physdev");
25static bool 25static bool
26physdev_mt(const struct sk_buff *skb, struct xt_action_param *par) 26physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
27{ 27{
28 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
29 const struct xt_physdev_info *info = par->matchinfo; 28 const struct xt_physdev_info *info = par->matchinfo;
29 const struct net_device *physdev;
30 unsigned long ret; 30 unsigned long ret;
31 const char *indev, *outdev; 31 const char *indev, *outdev;
32 const struct nf_bridge_info *nf_bridge;
33 32
34 /* Not a bridged IP packet or no info available yet: 33 /* Not a bridged IP packet or no info available yet:
35 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if 34 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
36 * the destination device will be a bridge. */ 35 * the destination device will be a bridge. */
37 if (!(nf_bridge = skb->nf_bridge)) { 36 if (!skb->nf_bridge) {
38 /* Return MATCH if the invert flags of the used options are on */ 37 /* Return MATCH if the invert flags of the used options are on */
39 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && 38 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
40 !(info->invert & XT_PHYSDEV_OP_BRIDGED)) 39 !(info->invert & XT_PHYSDEV_OP_BRIDGED))
@@ -54,30 +53,41 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
54 return true; 53 return true;
55 } 54 }
56 55
56 physdev = nf_bridge_get_physoutdev(skb);
57 outdev = physdev ? physdev->name : NULL;
58
57 /* This only makes sense in the FORWARD and POSTROUTING chains */ 59 /* This only makes sense in the FORWARD and POSTROUTING chains */
58 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && 60 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
59 (!!nf_bridge->physoutdev ^ !(info->invert & XT_PHYSDEV_OP_BRIDGED))) 61 (!!outdev ^ !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
60 return false; 62 return false;
61 63
64 physdev = nf_bridge_get_physindev(skb);
65 indev = physdev ? physdev->name : NULL;
66
62 if ((info->bitmask & XT_PHYSDEV_OP_ISIN && 67 if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
63 (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || 68 (!indev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
64 (info->bitmask & XT_PHYSDEV_OP_ISOUT && 69 (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
65 (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) 70 (!outdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
66 return false; 71 return false;
67 72
68 if (!(info->bitmask & XT_PHYSDEV_OP_IN)) 73 if (!(info->bitmask & XT_PHYSDEV_OP_IN))
69 goto match_outdev; 74 goto match_outdev;
70 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
71 ret = ifname_compare_aligned(indev, info->physindev, info->in_mask);
72 75
73 if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN)) 76 if (indev) {
74 return false; 77 ret = ifname_compare_aligned(indev, info->physindev,
78 info->in_mask);
79
80 if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN))
81 return false;
82 }
75 83
76match_outdev: 84match_outdev:
77 if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) 85 if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
78 return true; 86 return true;
79 outdev = nf_bridge->physoutdev ? 87
80 nf_bridge->physoutdev->name : nulldevname; 88 if (!outdev)
89 return false;
90
81 ret = ifname_compare_aligned(outdev, info->physoutdev, info->out_mask); 91 ret = ifname_compare_aligned(outdev, info->physoutdev, info->out_mask);
82 92
83 return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT)); 93 return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT));
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 895534e87a47..e092cb046326 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -143,13 +143,10 @@ static bool xt_socket_sk_is_transparent(struct sock *sk)
143 } 143 }
144} 144}
145 145
146static bool 146static struct sock *xt_socket_lookup_slow_v4(const struct sk_buff *skb,
147socket_match(const struct sk_buff *skb, struct xt_action_param *par, 147 const struct net_device *indev)
148 const struct xt_socket_mtinfo1 *info)
149{ 148{
150 const struct iphdr *iph = ip_hdr(skb); 149 const struct iphdr *iph = ip_hdr(skb);
151 struct udphdr _hdr, *hp = NULL;
152 struct sock *sk = skb->sk;
153 __be32 uninitialized_var(daddr), uninitialized_var(saddr); 150 __be32 uninitialized_var(daddr), uninitialized_var(saddr);
154 __be16 uninitialized_var(dport), uninitialized_var(sport); 151 __be16 uninitialized_var(dport), uninitialized_var(sport);
155 u8 uninitialized_var(protocol); 152 u8 uninitialized_var(protocol);
@@ -159,10 +156,12 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
159#endif 156#endif
160 157
161 if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) { 158 if (iph->protocol == IPPROTO_UDP || iph->protocol == IPPROTO_TCP) {
159 struct udphdr _hdr, *hp;
160
162 hp = skb_header_pointer(skb, ip_hdrlen(skb), 161 hp = skb_header_pointer(skb, ip_hdrlen(skb),
163 sizeof(_hdr), &_hdr); 162 sizeof(_hdr), &_hdr);
164 if (hp == NULL) 163 if (hp == NULL)
165 return false; 164 return NULL;
166 165
167 protocol = iph->protocol; 166 protocol = iph->protocol;
168 saddr = iph->saddr; 167 saddr = iph->saddr;
@@ -172,16 +171,17 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
172 171
173 } else if (iph->protocol == IPPROTO_ICMP) { 172 } else if (iph->protocol == IPPROTO_ICMP) {
174 if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr, 173 if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr,
175 &sport, &dport)) 174 &sport, &dport))
176 return false; 175 return NULL;
177 } else { 176 } else {
178 return false; 177 return NULL;
179 } 178 }
180 179
181#ifdef XT_SOCKET_HAVE_CONNTRACK 180#ifdef XT_SOCKET_HAVE_CONNTRACK
182 /* Do the lookup with the original socket address in case this is a 181 /* Do the lookup with the original socket address in
183 * reply packet of an established SNAT-ted connection. */ 182 * case this is a reply packet of an established
184 183 * SNAT-ted connection.
184 */
185 ct = nf_ct_get(skb, &ctinfo); 185 ct = nf_ct_get(skb, &ctinfo);
186 if (ct && !nf_ct_is_untracked(ct) && 186 if (ct && !nf_ct_is_untracked(ct) &&
187 ((iph->protocol != IPPROTO_ICMP && 187 ((iph->protocol != IPPROTO_ICMP &&
@@ -197,10 +197,18 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
197 } 197 }
198#endif 198#endif
199 199
200 return xt_socket_get_sock_v4(dev_net(skb->dev), protocol, saddr, daddr,
201 sport, dport, indev);
202}
203
204static bool
205socket_match(const struct sk_buff *skb, struct xt_action_param *par,
206 const struct xt_socket_mtinfo1 *info)
207{
208 struct sock *sk = skb->sk;
209
200 if (!sk) 210 if (!sk)
201 sk = xt_socket_get_sock_v4(dev_net(skb->dev), protocol, 211 sk = xt_socket_lookup_slow_v4(skb, par->in);
202 saddr, daddr, sport, dport,
203 par->in);
204 if (sk) { 212 if (sk) {
205 bool wildcard; 213 bool wildcard;
206 bool transparent = true; 214 bool transparent = true;
@@ -225,12 +233,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
225 sk = NULL; 233 sk = NULL;
226 } 234 }
227 235
228 pr_debug("proto %hhu %pI4:%hu -> %pI4:%hu (orig %pI4:%hu) sock %p\n", 236 return sk != NULL;
229 protocol, &saddr, ntohs(sport),
230 &daddr, ntohs(dport),
231 &iph->daddr, hp ? ntohs(hp->dest) : 0, sk);
232
233 return (sk != NULL);
234} 237}
235 238
236static bool 239static bool
@@ -327,28 +330,26 @@ xt_socket_get_sock_v6(struct net *net, const u8 protocol,
327 return NULL; 330 return NULL;
328} 331}
329 332
330static bool 333static struct sock *xt_socket_lookup_slow_v6(const struct sk_buff *skb,
331socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par) 334 const struct net_device *indev)
332{ 335{
333 struct ipv6hdr ipv6_var, *iph = ipv6_hdr(skb);
334 struct udphdr _hdr, *hp = NULL;
335 struct sock *sk = skb->sk;
336 const struct in6_addr *daddr = NULL, *saddr = NULL;
337 __be16 uninitialized_var(dport), uninitialized_var(sport); 336 __be16 uninitialized_var(dport), uninitialized_var(sport);
338 int thoff = 0, uninitialized_var(tproto); 337 const struct in6_addr *daddr = NULL, *saddr = NULL;
339 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; 338 struct ipv6hdr *iph = ipv6_hdr(skb);
339 int thoff = 0, tproto;
340 340
341 tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL); 341 tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
342 if (tproto < 0) { 342 if (tproto < 0) {
343 pr_debug("unable to find transport header in IPv6 packet, dropping\n"); 343 pr_debug("unable to find transport header in IPv6 packet, dropping\n");
344 return NF_DROP; 344 return NULL;
345 } 345 }
346 346
347 if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) { 347 if (tproto == IPPROTO_UDP || tproto == IPPROTO_TCP) {
348 hp = skb_header_pointer(skb, thoff, 348 struct udphdr _hdr, *hp;
349 sizeof(_hdr), &_hdr); 349
350 hp = skb_header_pointer(skb, thoff, sizeof(_hdr), &_hdr);
350 if (hp == NULL) 351 if (hp == NULL)
351 return false; 352 return NULL;
352 353
353 saddr = &iph->saddr; 354 saddr = &iph->saddr;
354 sport = hp->source; 355 sport = hp->source;
@@ -356,17 +357,27 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
356 dport = hp->dest; 357 dport = hp->dest;
357 358
358 } else if (tproto == IPPROTO_ICMPV6) { 359 } else if (tproto == IPPROTO_ICMPV6) {
360 struct ipv6hdr ipv6_var;
361
359 if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr, 362 if (extract_icmp6_fields(skb, thoff, &tproto, &saddr, &daddr,
360 &sport, &dport, &ipv6_var)) 363 &sport, &dport, &ipv6_var))
361 return false; 364 return NULL;
362 } else { 365 } else {
363 return false; 366 return NULL;
364 } 367 }
365 368
369 return xt_socket_get_sock_v6(dev_net(skb->dev), tproto, saddr, daddr,
370 sport, dport, indev);
371}
372
373static bool
374socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
375{
376 const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
377 struct sock *sk = skb->sk;
378
366 if (!sk) 379 if (!sk)
367 sk = xt_socket_get_sock_v6(dev_net(skb->dev), tproto, 380 sk = xt_socket_lookup_slow_v6(skb, par->in);
368 saddr, daddr, sport, dport,
369 par->in);
370 if (sk) { 381 if (sk) {
371 bool wildcard; 382 bool wildcard;
372 bool transparent = true; 383 bool transparent = true;
@@ -391,13 +402,7 @@ socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
391 sk = NULL; 402 sk = NULL;
392 } 403 }
393 404
394 pr_debug("proto %hhd %pI6:%hu -> %pI6:%hu " 405 return sk != NULL;
395 "(orig %pI6:%hu) sock %p\n",
396 tproto, saddr, ntohs(sport),
397 daddr, ntohs(dport),
398 &iph->daddr, hp ? ntohs(hp->dest) : 0, sk);
399
400 return (sk != NULL);
401} 406}
402#endif 407#endif
403 408