diff options
author | David S. Miller <davem@davemloft.net> | 2015-03-09 15:58:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-09 15:58:21 -0400 |
commit | 5428aef81157768f1052b116e0cc8abf88ff3e36 (patch) | |
tree | a4fe8e39c5986b59ae50d3a6fefe46c309e2444e | |
parent | 26c459a8072f2bb0680081205376e1371c114b12 (diff) | |
parent | e5de75bf88858f5b3ab11e2504b86ec059f03102 (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. Basically, improvements for the packet rejection infrastructure,
deprecation of CLUSTERIP, cleanups for nf_tables and some untangling for
br_netfilter. More specifically they are:
1) Send packet to reset flow if checksum is valid, from Florian Westphal.
2) Fix nf_tables reject bridge from the input chain, also from Florian.
3) Deprecate the CLUSTERIP target, the cluster match supersedes it in
functionality and it's known to have problems.
4) A couple of cleanups for nf_tables rule tracing infrastructure, from
Patrick McHardy.
5) Another cleanup to place transaction declarations at the bottom of
nf_tables.h, also from Patrick.
6) Consolidate Kconfig dependencies wrt. NF_TABLES.
7) Limit table names to 32 bytes in nf_tables.
8) mac header copying in bridge netfilter is already required when
calling ip_fragment(), from Florian Westphal.
9) move nf_bridge_update_protocol() to br_netfilter.c, also from
Florian.
10) Small refactor in br_netfilter in the transmission path, again from
Florian.
11) Move br_nf_pre_routing_finish_bridge_slow() to br_netfilter.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter_bridge.h | 51 | ||||
-rw-r--r-- | include/net/netfilter/ipv4/nf_reject.h | 6 | ||||
-rw-r--r-- | include/net/netfilter/ipv6/nf_reject.h | 11 | ||||
-rw-r--r-- | include/net/netfilter/nf_tables.h | 176 | ||||
-rw-r--r-- | include/net/netns/x_tables.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/netfilter/nf_tables.h | 1 | ||||
-rw-r--r-- | net/bridge/br_device.c | 5 | ||||
-rw-r--r-- | net/bridge/br_forward.c | 4 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 78 | ||||
-rw-r--r-- | net/bridge/br_private.h | 5 | ||||
-rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 84 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 38 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 7 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 17 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_reject_ipv4.c | 23 | ||||
-rw-r--r-- | net/ipv4/netfilter/nft_reject_ipv4.c | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 18 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_reject_ipv6.c | 35 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 20 | ||||
-rw-r--r-- | net/netfilter/nf_tables_api.c | 7 | ||||
-rw-r--r-- | net/netfilter/nf_tables_core.c | 105 | ||||
-rw-r--r-- | net/netfilter/nft_reject_inet.c | 6 |
22 files changed, 412 insertions, 289 deletions
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index c755e4971fa3..bb39113ea596 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h | |||
@@ -36,44 +36,6 @@ static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb) | |||
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | static inline void nf_bridge_update_protocol(struct sk_buff *skb) | ||
40 | { | ||
41 | if (skb->nf_bridge->mask & BRNF_8021Q) | ||
42 | skb->protocol = htons(ETH_P_8021Q); | ||
43 | else if (skb->nf_bridge->mask & BRNF_PPPoE) | ||
44 | skb->protocol = htons(ETH_P_PPP_SES); | ||
45 | } | ||
46 | |||
47 | /* Fill in the header for fragmented IP packets handled by | ||
48 | * the IPv4 connection tracking code. | ||
49 | * | ||
50 | * Only used in br_forward.c | ||
51 | */ | ||
52 | static inline int nf_bridge_copy_header(struct sk_buff *skb) | ||
53 | { | ||
54 | int err; | ||
55 | unsigned int header_size; | ||
56 | |||
57 | nf_bridge_update_protocol(skb); | ||
58 | header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); | ||
59 | err = skb_cow_head(skb, header_size); | ||
60 | if (err) | ||
61 | return err; | ||
62 | |||
63 | skb_copy_to_linear_data_offset(skb, -header_size, | ||
64 | skb->nf_bridge->data, header_size); | ||
65 | __skb_push(skb, nf_bridge_encap_header_len(skb)); | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) | ||
70 | { | ||
71 | if (skb->nf_bridge && | ||
72 | skb->nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT)) | ||
73 | return nf_bridge_copy_header(skb); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) | 39 | static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) |
78 | { | 40 | { |
79 | if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE)) | 41 | if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE)) |
@@ -82,18 +44,6 @@ static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) | |||
82 | } | 44 | } |
83 | 45 | ||
84 | int br_handle_frame_finish(struct sk_buff *skb); | 46 | int br_handle_frame_finish(struct sk_buff *skb); |
85 | /* Only used in br_device.c */ | ||
86 | static inline int br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) | ||
87 | { | ||
88 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | ||
89 | |||
90 | skb_pull(skb, ETH_HLEN); | ||
91 | nf_bridge->mask ^= BRNF_BRIDGED_DNAT; | ||
92 | skb_copy_to_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), | ||
93 | skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); | ||
94 | skb->dev = nf_bridge->physindev; | ||
95 | return br_handle_frame_finish(skb); | ||
96 | } | ||
97 | 47 | ||
98 | /* This is called by the IP fragmenting code and it ensures there is | 48 | /* This is called by the IP fragmenting code and it ensures there is |
99 | * enough room for the encapsulating header (if there is one). */ | 49 | * enough room for the encapsulating header (if there is one). */ |
@@ -119,7 +69,6 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb) | |||
119 | } | 69 | } |
120 | 70 | ||
121 | #else | 71 | #else |
122 | #define nf_bridge_maybe_copy_header(skb) (0) | ||
123 | #define nf_bridge_pad(skb) (0) | 72 | #define nf_bridge_pad(skb) (0) |
124 | #define br_drop_fake_rtable(skb) do { } while (0) | 73 | #define br_drop_fake_rtable(skb) do { } while (0) |
125 | #endif /* CONFIG_BRIDGE_NETFILTER */ | 74 | #endif /* CONFIG_BRIDGE_NETFILTER */ |
diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h index 03e928a55229..864127573c32 100644 --- a/include/net/netfilter/ipv4/nf_reject.h +++ b/include/net/netfilter/ipv4/nf_reject.h | |||
@@ -5,11 +5,7 @@ | |||
5 | #include <net/ip.h> | 5 | #include <net/ip.h> |
6 | #include <net/icmp.h> | 6 | #include <net/icmp.h> |
7 | 7 | ||
8 | static inline void nf_send_unreach(struct sk_buff *skb_in, int code) | 8 | void nf_send_unreach(struct sk_buff *skb_in, int code, int hook); |
9 | { | ||
10 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | ||
11 | } | ||
12 | |||
13 | void nf_send_reset(struct sk_buff *oldskb, int hook); | 9 | void nf_send_reset(struct sk_buff *oldskb, int hook); |
14 | 10 | ||
15 | const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, | 11 | const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb, |
diff --git a/include/net/netfilter/ipv6/nf_reject.h b/include/net/netfilter/ipv6/nf_reject.h index 23216d48abf9..0ae445d3f217 100644 --- a/include/net/netfilter/ipv6/nf_reject.h +++ b/include/net/netfilter/ipv6/nf_reject.h | |||
@@ -3,15 +3,8 @@ | |||
3 | 3 | ||
4 | #include <linux/icmpv6.h> | 4 | #include <linux/icmpv6.h> |
5 | 5 | ||
6 | static inline void | 6 | void nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code, |
7 | nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code, | 7 | unsigned int hooknum); |
8 | unsigned int hooknum) | ||
9 | { | ||
10 | if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) | ||
11 | skb_in->dev = net->loopback_dev; | ||
12 | |||
13 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); | ||
14 | } | ||
15 | 8 | ||
16 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook); | 9 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook); |
17 | 10 | ||
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 9eaaa7884586..a143acafa5d9 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h | |||
@@ -393,74 +393,6 @@ struct nft_rule { | |||
393 | __attribute__((aligned(__alignof__(struct nft_expr)))); | 393 | __attribute__((aligned(__alignof__(struct nft_expr)))); |
394 | }; | 394 | }; |
395 | 395 | ||
396 | /** | ||
397 | * struct nft_trans - nf_tables object update in transaction | ||
398 | * | ||
399 | * @list: used internally | ||
400 | * @msg_type: message type | ||
401 | * @ctx: transaction context | ||
402 | * @data: internal information related to the transaction | ||
403 | */ | ||
404 | struct nft_trans { | ||
405 | struct list_head list; | ||
406 | int msg_type; | ||
407 | struct nft_ctx ctx; | ||
408 | char data[0]; | ||
409 | }; | ||
410 | |||
411 | struct nft_trans_rule { | ||
412 | struct nft_rule *rule; | ||
413 | }; | ||
414 | |||
415 | #define nft_trans_rule(trans) \ | ||
416 | (((struct nft_trans_rule *)trans->data)->rule) | ||
417 | |||
418 | struct nft_trans_set { | ||
419 | struct nft_set *set; | ||
420 | u32 set_id; | ||
421 | }; | ||
422 | |||
423 | #define nft_trans_set(trans) \ | ||
424 | (((struct nft_trans_set *)trans->data)->set) | ||
425 | #define nft_trans_set_id(trans) \ | ||
426 | (((struct nft_trans_set *)trans->data)->set_id) | ||
427 | |||
428 | struct nft_trans_chain { | ||
429 | bool update; | ||
430 | char name[NFT_CHAIN_MAXNAMELEN]; | ||
431 | struct nft_stats __percpu *stats; | ||
432 | u8 policy; | ||
433 | }; | ||
434 | |||
435 | #define nft_trans_chain_update(trans) \ | ||
436 | (((struct nft_trans_chain *)trans->data)->update) | ||
437 | #define nft_trans_chain_name(trans) \ | ||
438 | (((struct nft_trans_chain *)trans->data)->name) | ||
439 | #define nft_trans_chain_stats(trans) \ | ||
440 | (((struct nft_trans_chain *)trans->data)->stats) | ||
441 | #define nft_trans_chain_policy(trans) \ | ||
442 | (((struct nft_trans_chain *)trans->data)->policy) | ||
443 | |||
444 | struct nft_trans_table { | ||
445 | bool update; | ||
446 | bool enable; | ||
447 | }; | ||
448 | |||
449 | #define nft_trans_table_update(trans) \ | ||
450 | (((struct nft_trans_table *)trans->data)->update) | ||
451 | #define nft_trans_table_enable(trans) \ | ||
452 | (((struct nft_trans_table *)trans->data)->enable) | ||
453 | |||
454 | struct nft_trans_elem { | ||
455 | struct nft_set *set; | ||
456 | struct nft_set_elem elem; | ||
457 | }; | ||
458 | |||
459 | #define nft_trans_elem_set(trans) \ | ||
460 | (((struct nft_trans_elem *)trans->data)->set) | ||
461 | #define nft_trans_elem(trans) \ | ||
462 | (((struct nft_trans_elem *)trans->data)->elem) | ||
463 | |||
464 | static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule) | 396 | static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule) |
465 | { | 397 | { |
466 | return (struct nft_expr *)&rule->data[0]; | 398 | return (struct nft_expr *)&rule->data[0]; |
@@ -528,6 +460,25 @@ enum nft_chain_type { | |||
528 | NFT_CHAIN_T_MAX | 460 | NFT_CHAIN_T_MAX |
529 | }; | 461 | }; |
530 | 462 | ||
463 | /** | ||
464 | * struct nf_chain_type - nf_tables chain type info | ||
465 | * | ||
466 | * @name: name of the type | ||
467 | * @type: numeric identifier | ||
468 | * @family: address family | ||
469 | * @owner: module owner | ||
470 | * @hook_mask: mask of valid hooks | ||
471 | * @hooks: hookfn overrides | ||
472 | */ | ||
473 | struct nf_chain_type { | ||
474 | const char *name; | ||
475 | enum nft_chain_type type; | ||
476 | int family; | ||
477 | struct module *owner; | ||
478 | unsigned int hook_mask; | ||
479 | nf_hookfn *hooks[NF_MAX_HOOKS]; | ||
480 | }; | ||
481 | |||
531 | int nft_chain_validate_dependency(const struct nft_chain *chain, | 482 | int nft_chain_validate_dependency(const struct nft_chain *chain, |
532 | enum nft_chain_type type); | 483 | enum nft_chain_type type); |
533 | int nft_chain_validate_hooks(const struct nft_chain *chain, | 484 | int nft_chain_validate_hooks(const struct nft_chain *chain, |
@@ -584,7 +535,7 @@ struct nft_table { | |||
584 | u64 hgenerator; | 535 | u64 hgenerator; |
585 | u32 use; | 536 | u32 use; |
586 | u16 flags; | 537 | u16 flags; |
587 | char name[]; | 538 | char name[NFT_TABLE_MAXNAMELEN]; |
588 | }; | 539 | }; |
589 | 540 | ||
590 | /** | 541 | /** |
@@ -614,25 +565,6 @@ struct nft_af_info { | |||
614 | int nft_register_afinfo(struct net *, struct nft_af_info *); | 565 | int nft_register_afinfo(struct net *, struct nft_af_info *); |
615 | void nft_unregister_afinfo(struct nft_af_info *); | 566 | void nft_unregister_afinfo(struct nft_af_info *); |
616 | 567 | ||
617 | /** | ||
618 | * struct nf_chain_type - nf_tables chain type info | ||
619 | * | ||
620 | * @name: name of the type | ||
621 | * @type: numeric identifier | ||
622 | * @family: address family | ||
623 | * @owner: module owner | ||
624 | * @hook_mask: mask of valid hooks | ||
625 | * @hooks: hookfn overrides | ||
626 | */ | ||
627 | struct nf_chain_type { | ||
628 | const char *name; | ||
629 | enum nft_chain_type type; | ||
630 | int family; | ||
631 | struct module *owner; | ||
632 | unsigned int hook_mask; | ||
633 | nf_hookfn *hooks[NF_MAX_HOOKS]; | ||
634 | }; | ||
635 | |||
636 | int nft_register_chain_type(const struct nf_chain_type *); | 568 | int nft_register_chain_type(const struct nf_chain_type *); |
637 | void nft_unregister_chain_type(const struct nf_chain_type *); | 569 | void nft_unregister_chain_type(const struct nf_chain_type *); |
638 | 570 | ||
@@ -657,4 +589,72 @@ void nft_unregister_expr(struct nft_expr_type *); | |||
657 | #define MODULE_ALIAS_NFT_SET() \ | 589 | #define MODULE_ALIAS_NFT_SET() \ |
658 | MODULE_ALIAS("nft-set") | 590 | MODULE_ALIAS("nft-set") |
659 | 591 | ||
592 | /** | ||
593 | * struct nft_trans - nf_tables object update in transaction | ||
594 | * | ||
595 | * @list: used internally | ||
596 | * @msg_type: message type | ||
597 | * @ctx: transaction context | ||
598 | * @data: internal information related to the transaction | ||
599 | */ | ||
600 | struct nft_trans { | ||
601 | struct list_head list; | ||
602 | int msg_type; | ||
603 | struct nft_ctx ctx; | ||
604 | char data[0]; | ||
605 | }; | ||
606 | |||
607 | struct nft_trans_rule { | ||
608 | struct nft_rule *rule; | ||
609 | }; | ||
610 | |||
611 | #define nft_trans_rule(trans) \ | ||
612 | (((struct nft_trans_rule *)trans->data)->rule) | ||
613 | |||
614 | struct nft_trans_set { | ||
615 | struct nft_set *set; | ||
616 | u32 set_id; | ||
617 | }; | ||
618 | |||
619 | #define nft_trans_set(trans) \ | ||
620 | (((struct nft_trans_set *)trans->data)->set) | ||
621 | #define nft_trans_set_id(trans) \ | ||
622 | (((struct nft_trans_set *)trans->data)->set_id) | ||
623 | |||
624 | struct nft_trans_chain { | ||
625 | bool update; | ||
626 | char name[NFT_CHAIN_MAXNAMELEN]; | ||
627 | struct nft_stats __percpu *stats; | ||
628 | u8 policy; | ||
629 | }; | ||
630 | |||
631 | #define nft_trans_chain_update(trans) \ | ||
632 | (((struct nft_trans_chain *)trans->data)->update) | ||
633 | #define nft_trans_chain_name(trans) \ | ||
634 | (((struct nft_trans_chain *)trans->data)->name) | ||
635 | #define nft_trans_chain_stats(trans) \ | ||
636 | (((struct nft_trans_chain *)trans->data)->stats) | ||
637 | #define nft_trans_chain_policy(trans) \ | ||
638 | (((struct nft_trans_chain *)trans->data)->policy) | ||
639 | |||
640 | struct nft_trans_table { | ||
641 | bool update; | ||
642 | bool enable; | ||
643 | }; | ||
644 | |||
645 | #define nft_trans_table_update(trans) \ | ||
646 | (((struct nft_trans_table *)trans->data)->update) | ||
647 | #define nft_trans_table_enable(trans) \ | ||
648 | (((struct nft_trans_table *)trans->data)->enable) | ||
649 | |||
650 | struct nft_trans_elem { | ||
651 | struct nft_set *set; | ||
652 | struct nft_set_elem elem; | ||
653 | }; | ||
654 | |||
655 | #define nft_trans_elem_set(trans) \ | ||
656 | (((struct nft_trans_elem *)trans->data)->set) | ||
657 | #define nft_trans_elem(trans) \ | ||
658 | (((struct nft_trans_elem *)trans->data)->elem) | ||
659 | |||
660 | #endif /* _NET_NF_TABLES_H */ | 660 | #endif /* _NET_NF_TABLES_H */ |
diff --git a/include/net/netns/x_tables.h b/include/net/netns/x_tables.h index c24060ee411e..4d6597ad6067 100644 --- a/include/net/netns/x_tables.h +++ b/include/net/netns/x_tables.h | |||
@@ -9,6 +9,7 @@ struct ebt_table; | |||
9 | struct netns_xt { | 9 | struct netns_xt { |
10 | struct list_head tables[NFPROTO_NUMPROTO]; | 10 | struct list_head tables[NFPROTO_NUMPROTO]; |
11 | bool notrack_deprecated_warning; | 11 | bool notrack_deprecated_warning; |
12 | bool clusterip_deprecated_warning; | ||
12 | #if defined(CONFIG_BRIDGE_NF_EBTABLES) || \ | 13 | #if defined(CONFIG_BRIDGE_NF_EBTABLES) || \ |
13 | defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE) | 14 | defined(CONFIG_BRIDGE_NF_EBTABLES_MODULE) |
14 | struct ebt_table *broute_table; | 15 | struct ebt_table *broute_table; |
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 832bc46db78b..b9783931503b 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _LINUX_NF_TABLES_H | 1 | #ifndef _LINUX_NF_TABLES_H |
2 | #define _LINUX_NF_TABLES_H | 2 | #define _LINUX_NF_TABLES_H |
3 | 3 | ||
4 | #define NFT_TABLE_MAXNAMELEN 32 | ||
4 | #define NFT_CHAIN_MAXNAMELEN 32 | 5 | #define NFT_CHAIN_MAXNAMELEN 32 |
5 | #define NFT_USERDATA_MAXLEN 256 | 6 | #define NFT_USERDATA_MAXLEN 256 |
6 | 7 | ||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index ffd379db5938..294cbcc49263 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -36,13 +36,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
36 | u16 vid = 0; | 36 | u16 vid = 0; |
37 | 37 | ||
38 | rcu_read_lock(); | 38 | rcu_read_lock(); |
39 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | 39 | if (br_nf_prerouting_finish_bridge(skb)) { |
40 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | ||
41 | br_nf_pre_routing_finish_bridge_slow(skb); | ||
42 | rcu_read_unlock(); | 40 | rcu_read_unlock(); |
43 | return NETDEV_TX_OK; | 41 | return NETDEV_TX_OK; |
44 | } | 42 | } |
45 | #endif | ||
46 | 43 | ||
47 | u64_stats_update_begin(&brstats->syncp); | 44 | u64_stats_update_begin(&brstats->syncp); |
48 | brstats->tx_packets++; | 45 | brstats->tx_packets++; |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 1238fabff874..3304a5442331 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -37,9 +37,7 @@ static inline int should_deliver(const struct net_bridge_port *p, | |||
37 | 37 | ||
38 | int br_dev_queue_push_xmit(struct sk_buff *skb) | 38 | int br_dev_queue_push_xmit(struct sk_buff *skb) |
39 | { | 39 | { |
40 | /* ip_fragment doesn't copy the MAC header */ | 40 | if (!is_skb_forwardable(skb->dev, skb)) { |
41 | if (nf_bridge_maybe_copy_header(skb) || | ||
42 | !is_skb_forwardable(skb->dev, skb)) { | ||
43 | kfree_skb(skb); | 41 | kfree_skb(skb); |
44 | } else { | 42 | } else { |
45 | skb_push(skb, ETH_HLEN); | 43 | skb_push(skb, ETH_HLEN); |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 0ee453fad3de..a8361c7cdf81 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -239,6 +239,14 @@ drop: | |||
239 | return -1; | 239 | return -1; |
240 | } | 240 | } |
241 | 241 | ||
242 | static void nf_bridge_update_protocol(struct sk_buff *skb) | ||
243 | { | ||
244 | if (skb->nf_bridge->mask & BRNF_8021Q) | ||
245 | skb->protocol = htons(ETH_P_8021Q); | ||
246 | else if (skb->nf_bridge->mask & BRNF_PPPoE) | ||
247 | skb->protocol = htons(ETH_P_PPP_SES); | ||
248 | } | ||
249 | |||
242 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ | 250 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ |
243 | /* Undo the changes made for ip6tables PREROUTING and continue the | 251 | /* Undo the changes made for ip6tables PREROUTING and continue the |
244 | * bridge PRE_ROUTING hook. */ | 252 | * bridge PRE_ROUTING hook. */ |
@@ -764,23 +772,53 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops, | |||
764 | } | 772 | } |
765 | 773 | ||
766 | #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) | 774 | #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) |
775 | static bool nf_bridge_copy_header(struct sk_buff *skb) | ||
776 | { | ||
777 | int err; | ||
778 | unsigned int header_size; | ||
779 | |||
780 | nf_bridge_update_protocol(skb); | ||
781 | header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); | ||
782 | err = skb_cow_head(skb, header_size); | ||
783 | if (err) | ||
784 | return false; | ||
785 | |||
786 | skb_copy_to_linear_data_offset(skb, -header_size, | ||
787 | skb->nf_bridge->data, header_size); | ||
788 | __skb_push(skb, nf_bridge_encap_header_len(skb)); | ||
789 | return true; | ||
790 | } | ||
791 | |||
792 | static int br_nf_push_frag_xmit(struct sk_buff *skb) | ||
793 | { | ||
794 | if (!nf_bridge_copy_header(skb)) { | ||
795 | kfree_skb(skb); | ||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | return br_dev_queue_push_xmit(skb); | ||
800 | } | ||
801 | |||
767 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | 802 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) |
768 | { | 803 | { |
769 | int ret; | 804 | int ret; |
770 | int frag_max_size; | 805 | int frag_max_size; |
806 | unsigned int mtu_reserved; | ||
771 | 807 | ||
808 | if (skb_is_gso(skb) || skb->protocol != htons(ETH_P_IP)) | ||
809 | return br_dev_queue_push_xmit(skb); | ||
810 | |||
811 | mtu_reserved = nf_bridge_mtu_reduction(skb); | ||
772 | /* This is wrong! We should preserve the original fragment | 812 | /* This is wrong! We should preserve the original fragment |
773 | * boundaries by preserving frag_list rather than refragmenting. | 813 | * boundaries by preserving frag_list rather than refragmenting. |
774 | */ | 814 | */ |
775 | if (skb->protocol == htons(ETH_P_IP) && | 815 | if (skb->len + mtu_reserved > skb->dev->mtu) { |
776 | skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu && | ||
777 | !skb_is_gso(skb)) { | ||
778 | frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; | 816 | frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; |
779 | if (br_parse_ip_options(skb)) | 817 | if (br_parse_ip_options(skb)) |
780 | /* Drop invalid packet */ | 818 | /* Drop invalid packet */ |
781 | return NF_DROP; | 819 | return NF_DROP; |
782 | IPCB(skb)->frag_max_size = frag_max_size; | 820 | IPCB(skb)->frag_max_size = frag_max_size; |
783 | ret = ip_fragment(skb, br_dev_queue_push_xmit); | 821 | ret = ip_fragment(skb, br_nf_push_frag_xmit); |
784 | } else | 822 | } else |
785 | ret = br_dev_queue_push_xmit(skb); | 823 | ret = br_dev_queue_push_xmit(skb); |
786 | 824 | ||
@@ -854,6 +892,38 @@ static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops, | |||
854 | return NF_ACCEPT; | 892 | return NF_ACCEPT; |
855 | } | 893 | } |
856 | 894 | ||
895 | /* This is called when br_netfilter has called into iptables/netfilter, | ||
896 | * and DNAT has taken place on a bridge-forwarded packet. | ||
897 | * | ||
898 | * neigh->output has created a new MAC header, with local br0 MAC | ||
899 | * as saddr. | ||
900 | * | ||
901 | * This restores the original MAC saddr of the bridged packet | ||
902 | * before invoking bridge forward logic to transmit the packet. | ||
903 | */ | ||
904 | static void br_nf_pre_routing_finish_bridge_slow(struct sk_buff *skb) | ||
905 | { | ||
906 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | ||
907 | |||
908 | skb_pull(skb, ETH_HLEN); | ||
909 | nf_bridge->mask &= ~BRNF_BRIDGED_DNAT; | ||
910 | |||
911 | skb_copy_to_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), | ||
912 | skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); | ||
913 | skb->dev = nf_bridge->physindev; | ||
914 | br_handle_frame_finish(skb); | ||
915 | } | ||
916 | |||
917 | int br_nf_prerouting_finish_bridge(struct sk_buff *skb) | ||
918 | { | ||
919 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | ||
920 | br_nf_pre_routing_finish_bridge_slow(skb); | ||
921 | return 1; | ||
922 | } | ||
923 | return 0; | ||
924 | } | ||
925 | EXPORT_SYMBOL_GPL(br_nf_prerouting_finish_bridge); | ||
926 | |||
857 | void br_netfilter_enable(void) | 927 | void br_netfilter_enable(void) |
858 | { | 928 | { |
859 | } | 929 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c32e279c62f8..f0a0438dbd6d 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -765,10 +765,15 @@ static inline int br_vlan_enabled(struct net_bridge *br) | |||
765 | 765 | ||
766 | /* br_netfilter.c */ | 766 | /* br_netfilter.c */ |
767 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) | 767 | #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) |
768 | int br_nf_prerouting_finish_bridge(struct sk_buff *skb); | ||
768 | int br_nf_core_init(void); | 769 | int br_nf_core_init(void); |
769 | void br_nf_core_fini(void); | 770 | void br_nf_core_fini(void); |
770 | void br_netfilter_rtable_init(struct net_bridge *); | 771 | void br_netfilter_rtable_init(struct net_bridge *); |
771 | #else | 772 | #else |
773 | static inline int br_nf_prerouting_finish_bridge(struct sk_buff *skb) | ||
774 | { | ||
775 | return 0; | ||
776 | } | ||
772 | static inline int br_nf_core_init(void) { return 0; } | 777 | static inline int br_nf_core_init(void) { return 0; } |
773 | static inline void br_nf_core_fini(void) {} | 778 | static inline void br_nf_core_fini(void) {} |
774 | #define br_netfilter_rtable_init(x) | 779 | #define br_netfilter_rtable_init(x) |
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index 3244aead0926..5c6c96585acd 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <net/ip.h> | 21 | #include <net/ip.h> |
22 | #include <net/ip6_checksum.h> | 22 | #include <net/ip6_checksum.h> |
23 | #include <linux/netfilter_bridge.h> | 23 | #include <linux/netfilter_bridge.h> |
24 | #include <linux/netfilter_ipv6.h> | ||
24 | #include "../br_private.h" | 25 | #include "../br_private.h" |
25 | 26 | ||
26 | static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, | 27 | static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, |
@@ -36,7 +37,12 @@ static void nft_reject_br_push_etherhdr(struct sk_buff *oldskb, | |||
36 | skb_pull(nskb, ETH_HLEN); | 37 | skb_pull(nskb, ETH_HLEN); |
37 | } | 38 | } |
38 | 39 | ||
39 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | 40 | /* We cannot use oldskb->dev, it can be either bridge device (NF_BRIDGE INPUT) |
41 | * or the bridge port (NF_BRIDGE PREROUTING). | ||
42 | */ | ||
43 | static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, | ||
44 | const struct net_device *dev, | ||
45 | int hook) | ||
40 | { | 46 | { |
41 | struct sk_buff *nskb; | 47 | struct sk_buff *nskb; |
42 | struct iphdr *niph; | 48 | struct iphdr *niph; |
@@ -65,11 +71,12 @@ static void nft_reject_br_send_v4_tcp_reset(struct sk_buff *oldskb, int hook) | |||
65 | 71 | ||
66 | nft_reject_br_push_etherhdr(oldskb, nskb); | 72 | nft_reject_br_push_etherhdr(oldskb, nskb); |
67 | 73 | ||
68 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | 74 | br_deliver(br_port_get_rcu(dev), nskb); |
69 | } | 75 | } |
70 | 76 | ||
71 | static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | 77 | static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, |
72 | u8 code) | 78 | const struct net_device *dev, |
79 | int hook, u8 code) | ||
73 | { | 80 | { |
74 | struct sk_buff *nskb; | 81 | struct sk_buff *nskb; |
75 | struct iphdr *niph; | 82 | struct iphdr *niph; |
@@ -77,8 +84,9 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | |||
77 | unsigned int len; | 84 | unsigned int len; |
78 | void *payload; | 85 | void *payload; |
79 | __wsum csum; | 86 | __wsum csum; |
87 | u8 proto; | ||
80 | 88 | ||
81 | if (!nft_bridge_iphdr_validate(oldskb)) | 89 | if (oldskb->csum_bad || !nft_bridge_iphdr_validate(oldskb)) |
82 | return; | 90 | return; |
83 | 91 | ||
84 | /* IP header checks: fragment. */ | 92 | /* IP header checks: fragment. */ |
@@ -91,7 +99,17 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | |||
91 | if (!pskb_may_pull(oldskb, len)) | 99 | if (!pskb_may_pull(oldskb, len)) |
92 | return; | 100 | return; |
93 | 101 | ||
94 | if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), 0)) | 102 | if (pskb_trim_rcsum(oldskb, htons(ip_hdr(oldskb)->tot_len))) |
103 | return; | ||
104 | |||
105 | if (ip_hdr(oldskb)->protocol == IPPROTO_TCP || | ||
106 | ip_hdr(oldskb)->protocol == IPPROTO_UDP) | ||
107 | proto = ip_hdr(oldskb)->protocol; | ||
108 | else | ||
109 | proto = 0; | ||
110 | |||
111 | if (!skb_csum_unnecessary(oldskb) && | ||
112 | nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), proto)) | ||
95 | return; | 113 | return; |
96 | 114 | ||
97 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) + | 115 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmphdr) + |
@@ -120,11 +138,13 @@ static void nft_reject_br_send_v4_unreach(struct sk_buff *oldskb, int hook, | |||
120 | 138 | ||
121 | nft_reject_br_push_etherhdr(oldskb, nskb); | 139 | nft_reject_br_push_etherhdr(oldskb, nskb); |
122 | 140 | ||
123 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | 141 | br_deliver(br_port_get_rcu(dev), nskb); |
124 | } | 142 | } |
125 | 143 | ||
126 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, | 144 | static void nft_reject_br_send_v6_tcp_reset(struct net *net, |
127 | struct sk_buff *oldskb, int hook) | 145 | struct sk_buff *oldskb, |
146 | const struct net_device *dev, | ||
147 | int hook) | ||
128 | { | 148 | { |
129 | struct sk_buff *nskb; | 149 | struct sk_buff *nskb; |
130 | const struct tcphdr *oth; | 150 | const struct tcphdr *oth; |
@@ -152,12 +172,37 @@ static void nft_reject_br_send_v6_tcp_reset(struct net *net, | |||
152 | 172 | ||
153 | nft_reject_br_push_etherhdr(oldskb, nskb); | 173 | nft_reject_br_push_etherhdr(oldskb, nskb); |
154 | 174 | ||
155 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | 175 | br_deliver(br_port_get_rcu(dev), nskb); |
176 | } | ||
177 | |||
178 | static bool reject6_br_csum_ok(struct sk_buff *skb, int hook) | ||
179 | { | ||
180 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
181 | int thoff; | ||
182 | __be16 fo; | ||
183 | u8 proto = ip6h->nexthdr; | ||
184 | |||
185 | if (skb->csum_bad) | ||
186 | return false; | ||
187 | |||
188 | if (skb_csum_unnecessary(skb)) | ||
189 | return true; | ||
190 | |||
191 | if (ip6h->payload_len && | ||
192 | pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h))) | ||
193 | return false; | ||
194 | |||
195 | thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo); | ||
196 | if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0) | ||
197 | return false; | ||
198 | |||
199 | return nf_ip6_checksum(skb, hook, thoff, proto) == 0; | ||
156 | } | 200 | } |
157 | 201 | ||
158 | static void nft_reject_br_send_v6_unreach(struct net *net, | 202 | static void nft_reject_br_send_v6_unreach(struct net *net, |
159 | struct sk_buff *oldskb, int hook, | 203 | struct sk_buff *oldskb, |
160 | u8 code) | 204 | const struct net_device *dev, |
205 | int hook, u8 code) | ||
161 | { | 206 | { |
162 | struct sk_buff *nskb; | 207 | struct sk_buff *nskb; |
163 | struct ipv6hdr *nip6h; | 208 | struct ipv6hdr *nip6h; |
@@ -176,6 +221,9 @@ static void nft_reject_br_send_v6_unreach(struct net *net, | |||
176 | if (!pskb_may_pull(oldskb, len)) | 221 | if (!pskb_may_pull(oldskb, len)) |
177 | return; | 222 | return; |
178 | 223 | ||
224 | if (!reject6_br_csum_ok(oldskb, hook)) | ||
225 | return; | ||
226 | |||
179 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) + | 227 | nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) + |
180 | LL_MAX_HEADER + len, GFP_ATOMIC); | 228 | LL_MAX_HEADER + len, GFP_ATOMIC); |
181 | if (!nskb) | 229 | if (!nskb) |
@@ -205,7 +253,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net, | |||
205 | 253 | ||
206 | nft_reject_br_push_etherhdr(oldskb, nskb); | 254 | nft_reject_br_push_etherhdr(oldskb, nskb); |
207 | 255 | ||
208 | br_deliver(br_port_get_rcu(oldskb->dev), nskb); | 256 | br_deliver(br_port_get_rcu(dev), nskb); |
209 | } | 257 | } |
210 | 258 | ||
211 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | 259 | static void nft_reject_bridge_eval(const struct nft_expr *expr, |
@@ -224,16 +272,16 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
224 | case htons(ETH_P_IP): | 272 | case htons(ETH_P_IP): |
225 | switch (priv->type) { | 273 | switch (priv->type) { |
226 | case NFT_REJECT_ICMP_UNREACH: | 274 | case NFT_REJECT_ICMP_UNREACH: |
227 | nft_reject_br_send_v4_unreach(pkt->skb, | 275 | nft_reject_br_send_v4_unreach(pkt->skb, pkt->in, |
228 | pkt->ops->hooknum, | 276 | pkt->ops->hooknum, |
229 | priv->icmp_code); | 277 | priv->icmp_code); |
230 | break; | 278 | break; |
231 | case NFT_REJECT_TCP_RST: | 279 | case NFT_REJECT_TCP_RST: |
232 | nft_reject_br_send_v4_tcp_reset(pkt->skb, | 280 | nft_reject_br_send_v4_tcp_reset(pkt->skb, pkt->in, |
233 | pkt->ops->hooknum); | 281 | pkt->ops->hooknum); |
234 | break; | 282 | break; |
235 | case NFT_REJECT_ICMPX_UNREACH: | 283 | case NFT_REJECT_ICMPX_UNREACH: |
236 | nft_reject_br_send_v4_unreach(pkt->skb, | 284 | nft_reject_br_send_v4_unreach(pkt->skb, pkt->in, |
237 | pkt->ops->hooknum, | 285 | pkt->ops->hooknum, |
238 | nft_reject_icmp_code(priv->icmp_code)); | 286 | nft_reject_icmp_code(priv->icmp_code)); |
239 | break; | 287 | break; |
@@ -242,16 +290,16 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr, | |||
242 | case htons(ETH_P_IPV6): | 290 | case htons(ETH_P_IPV6): |
243 | switch (priv->type) { | 291 | switch (priv->type) { |
244 | case NFT_REJECT_ICMP_UNREACH: | 292 | case NFT_REJECT_ICMP_UNREACH: |
245 | nft_reject_br_send_v6_unreach(net, pkt->skb, | 293 | nft_reject_br_send_v6_unreach(net, pkt->skb, pkt->in, |
246 | pkt->ops->hooknum, | 294 | pkt->ops->hooknum, |
247 | priv->icmp_code); | 295 | priv->icmp_code); |
248 | break; | 296 | break; |
249 | case NFT_REJECT_TCP_RST: | 297 | case NFT_REJECT_TCP_RST: |
250 | nft_reject_br_send_v6_tcp_reset(net, pkt->skb, | 298 | nft_reject_br_send_v6_tcp_reset(net, pkt->skb, pkt->in, |
251 | pkt->ops->hooknum); | 299 | pkt->ops->hooknum); |
252 | break; | 300 | break; |
253 | case NFT_REJECT_ICMPX_UNREACH: | 301 | case NFT_REJECT_ICMPX_UNREACH: |
254 | nft_reject_br_send_v6_unreach(net, pkt->skb, | 302 | nft_reject_br_send_v6_unreach(net, pkt->skb, pkt->in, |
255 | pkt->ops->hooknum, | 303 | pkt->ops->hooknum, |
256 | nft_reject_icmpv6_code(priv->icmp_code)); | 304 | nft_reject_icmpv6_code(priv->icmp_code)); |
257 | break; | 305 | break; |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 59f883d9cadf..fb20f363151f 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -36,24 +36,16 @@ config NF_CONNTRACK_PROC_COMPAT | |||
36 | 36 | ||
37 | If unsure, say Y. | 37 | If unsure, say Y. |
38 | 38 | ||
39 | config NF_LOG_ARP | 39 | if NF_TABLES |
40 | tristate "ARP packet logging" | ||
41 | default m if NETFILTER_ADVANCED=n | ||
42 | select NF_LOG_COMMON | ||
43 | |||
44 | config NF_LOG_IPV4 | ||
45 | tristate "IPv4 packet logging" | ||
46 | default m if NETFILTER_ADVANCED=n | ||
47 | select NF_LOG_COMMON | ||
48 | 40 | ||
49 | config NF_TABLES_IPV4 | 41 | config NF_TABLES_IPV4 |
50 | depends on NF_TABLES | ||
51 | tristate "IPv4 nf_tables support" | 42 | tristate "IPv4 nf_tables support" |
52 | help | 43 | help |
53 | This option enables the IPv4 support for nf_tables. | 44 | This option enables the IPv4 support for nf_tables. |
54 | 45 | ||
46 | if NF_TABLES_IPV4 | ||
47 | |||
55 | config NFT_CHAIN_ROUTE_IPV4 | 48 | config NFT_CHAIN_ROUTE_IPV4 |
56 | depends on NF_TABLES_IPV4 | ||
57 | tristate "IPv4 nf_tables route chain support" | 49 | tristate "IPv4 nf_tables route chain support" |
58 | help | 50 | help |
59 | This option enables the "route" chain for IPv4 in nf_tables. This | 51 | This option enables the "route" chain for IPv4 in nf_tables. This |
@@ -61,22 +53,34 @@ config NFT_CHAIN_ROUTE_IPV4 | |||
61 | fields such as the source, destination, type of service and | 53 | fields such as the source, destination, type of service and |
62 | the packet mark. | 54 | the packet mark. |
63 | 55 | ||
64 | config NF_REJECT_IPV4 | ||
65 | tristate "IPv4 packet rejection" | ||
66 | default m if NETFILTER_ADVANCED=n | ||
67 | |||
68 | config NFT_REJECT_IPV4 | 56 | config NFT_REJECT_IPV4 |
69 | depends on NF_TABLES_IPV4 | ||
70 | select NF_REJECT_IPV4 | 57 | select NF_REJECT_IPV4 |
71 | default NFT_REJECT | 58 | default NFT_REJECT |
72 | tristate | 59 | tristate |
73 | 60 | ||
61 | endif # NF_TABLES_IPV4 | ||
62 | |||
74 | config NF_TABLES_ARP | 63 | config NF_TABLES_ARP |
75 | depends on NF_TABLES | ||
76 | tristate "ARP nf_tables support" | 64 | tristate "ARP nf_tables support" |
77 | help | 65 | help |
78 | This option enables the ARP support for nf_tables. | 66 | This option enables the ARP support for nf_tables. |
79 | 67 | ||
68 | endif # NF_TABLES | ||
69 | |||
70 | config NF_LOG_ARP | ||
71 | tristate "ARP packet logging" | ||
72 | default m if NETFILTER_ADVANCED=n | ||
73 | select NF_LOG_COMMON | ||
74 | |||
75 | config NF_LOG_IPV4 | ||
76 | tristate "IPv4 packet logging" | ||
77 | default m if NETFILTER_ADVANCED=n | ||
78 | select NF_LOG_COMMON | ||
79 | |||
80 | config NF_REJECT_IPV4 | ||
81 | tristate "IPv4 packet rejection" | ||
82 | default m if NETFILTER_ADVANCED=n | ||
83 | |||
80 | config NF_NAT_IPV4 | 84 | config NF_NAT_IPV4 |
81 | tristate "IPv4 NAT" | 85 | tristate "IPv4 NAT" |
82 | depends on NF_CONNTRACK_IPV4 | 86 | depends on NF_CONNTRACK_IPV4 |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index e90f83a3415b..f75e9df5e017 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -418,6 +418,13 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) | |||
418 | if (ret < 0) | 418 | if (ret < 0) |
419 | pr_info("cannot load conntrack support for proto=%u\n", | 419 | pr_info("cannot load conntrack support for proto=%u\n", |
420 | par->family); | 420 | par->family); |
421 | |||
422 | if (!par->net->xt.clusterip_deprecated_warning) { | ||
423 | pr_info("ipt_CLUSTERIP is deprecated and it will removed soon, " | ||
424 | "use xt_cluster instead\n"); | ||
425 | par->net->xt.clusterip_deprecated_warning = true; | ||
426 | } | ||
427 | |||
421 | return ret; | 428 | return ret; |
422 | } | 429 | } |
423 | 430 | ||
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 8f48f5517e33..87907d4bd259 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -34,31 +34,32 @@ static unsigned int | |||
34 | reject_tg(struct sk_buff *skb, const struct xt_action_param *par) | 34 | reject_tg(struct sk_buff *skb, const struct xt_action_param *par) |
35 | { | 35 | { |
36 | const struct ipt_reject_info *reject = par->targinfo; | 36 | const struct ipt_reject_info *reject = par->targinfo; |
37 | int hook = par->hooknum; | ||
37 | 38 | ||
38 | switch (reject->with) { | 39 | switch (reject->with) { |
39 | case IPT_ICMP_NET_UNREACHABLE: | 40 | case IPT_ICMP_NET_UNREACHABLE: |
40 | nf_send_unreach(skb, ICMP_NET_UNREACH); | 41 | nf_send_unreach(skb, ICMP_NET_UNREACH, hook); |
41 | break; | 42 | break; |
42 | case IPT_ICMP_HOST_UNREACHABLE: | 43 | case IPT_ICMP_HOST_UNREACHABLE: |
43 | nf_send_unreach(skb, ICMP_HOST_UNREACH); | 44 | nf_send_unreach(skb, ICMP_HOST_UNREACH, hook); |
44 | break; | 45 | break; |
45 | case IPT_ICMP_PROT_UNREACHABLE: | 46 | case IPT_ICMP_PROT_UNREACHABLE: |
46 | nf_send_unreach(skb, ICMP_PROT_UNREACH); | 47 | nf_send_unreach(skb, ICMP_PROT_UNREACH, hook); |
47 | break; | 48 | break; |
48 | case IPT_ICMP_PORT_UNREACHABLE: | 49 | case IPT_ICMP_PORT_UNREACHABLE: |
49 | nf_send_unreach(skb, ICMP_PORT_UNREACH); | 50 | nf_send_unreach(skb, ICMP_PORT_UNREACH, hook); |
50 | break; | 51 | break; |
51 | case IPT_ICMP_NET_PROHIBITED: | 52 | case IPT_ICMP_NET_PROHIBITED: |
52 | nf_send_unreach(skb, ICMP_NET_ANO); | 53 | nf_send_unreach(skb, ICMP_NET_ANO, hook); |
53 | break; | 54 | break; |
54 | case IPT_ICMP_HOST_PROHIBITED: | 55 | case IPT_ICMP_HOST_PROHIBITED: |
55 | nf_send_unreach(skb, ICMP_HOST_ANO); | 56 | nf_send_unreach(skb, ICMP_HOST_ANO, hook); |
56 | break; | 57 | break; |
57 | case IPT_ICMP_ADMIN_PROHIBITED: | 58 | case IPT_ICMP_ADMIN_PROHIBITED: |
58 | nf_send_unreach(skb, ICMP_PKT_FILTERED); | 59 | nf_send_unreach(skb, ICMP_PKT_FILTERED, hook); |
59 | break; | 60 | break; |
60 | case IPT_TCP_RESET: | 61 | case IPT_TCP_RESET: |
61 | nf_send_reset(skb, par->hooknum); | 62 | nf_send_reset(skb, hook); |
62 | case IPT_ICMP_ECHOREPLY: | 63 | case IPT_ICMP_ECHOREPLY: |
63 | /* Doesn't happen. */ | 64 | /* Doesn't happen. */ |
64 | break; | 65 | break; |
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index 536da7bc598a..b7405eb7f1ef 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c | |||
@@ -164,4 +164,27 @@ void nf_send_reset(struct sk_buff *oldskb, int hook) | |||
164 | } | 164 | } |
165 | EXPORT_SYMBOL_GPL(nf_send_reset); | 165 | EXPORT_SYMBOL_GPL(nf_send_reset); |
166 | 166 | ||
167 | void nf_send_unreach(struct sk_buff *skb_in, int code, int hook) | ||
168 | { | ||
169 | struct iphdr *iph = ip_hdr(skb_in); | ||
170 | u8 proto; | ||
171 | |||
172 | if (skb_in->csum_bad || iph->frag_off & htons(IP_OFFSET)) | ||
173 | return; | ||
174 | |||
175 | if (skb_csum_unnecessary(skb_in)) { | ||
176 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) | ||
181 | proto = iph->protocol; | ||
182 | else | ||
183 | proto = 0; | ||
184 | |||
185 | if (nf_ip_checksum(skb_in, hook, ip_hdrlen(skb_in), proto) == 0) | ||
186 | icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); | ||
187 | } | ||
188 | EXPORT_SYMBOL_GPL(nf_send_unreach); | ||
189 | |||
167 | MODULE_LICENSE("GPL"); | 190 | MODULE_LICENSE("GPL"); |
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c index d729542bd1b7..16a5d4d73d75 100644 --- a/net/ipv4/netfilter/nft_reject_ipv4.c +++ b/net/ipv4/netfilter/nft_reject_ipv4.c | |||
@@ -27,7 +27,8 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr, | |||
27 | 27 | ||
28 | switch (priv->type) { | 28 | switch (priv->type) { |
29 | case NFT_REJECT_ICMP_UNREACH: | 29 | case NFT_REJECT_ICMP_UNREACH: |
30 | nf_send_unreach(pkt->skb, priv->icmp_code); | 30 | nf_send_unreach(pkt->skb, priv->icmp_code, |
31 | pkt->ops->hooknum); | ||
31 | break; | 32 | break; |
32 | case NFT_REJECT_TCP_RST: | 33 | case NFT_REJECT_TCP_RST: |
33 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | 34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index a069822936e6..ca6998345b42 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -25,14 +25,16 @@ config NF_CONNTRACK_IPV6 | |||
25 | 25 | ||
26 | To compile it as a module, choose M here. If unsure, say N. | 26 | To compile it as a module, choose M here. If unsure, say N. |
27 | 27 | ||
28 | if NF_TABLES | ||
29 | |||
28 | config NF_TABLES_IPV6 | 30 | config NF_TABLES_IPV6 |
29 | depends on NF_TABLES | ||
30 | tristate "IPv6 nf_tables support" | 31 | tristate "IPv6 nf_tables support" |
31 | help | 32 | help |
32 | This option enables the IPv6 support for nf_tables. | 33 | This option enables the IPv6 support for nf_tables. |
33 | 34 | ||
35 | if NF_TABLES_IPV6 | ||
36 | |||
34 | config NFT_CHAIN_ROUTE_IPV6 | 37 | config NFT_CHAIN_ROUTE_IPV6 |
35 | depends on NF_TABLES_IPV6 | ||
36 | tristate "IPv6 nf_tables route chain support" | 38 | tristate "IPv6 nf_tables route chain support" |
37 | help | 39 | help |
38 | This option enables the "route" chain for IPv6 in nf_tables. This | 40 | This option enables the "route" chain for IPv6 in nf_tables. This |
@@ -40,16 +42,18 @@ config NFT_CHAIN_ROUTE_IPV6 | |||
40 | fields such as the source, destination, flowlabel, hop-limit and | 42 | fields such as the source, destination, flowlabel, hop-limit and |
41 | the packet mark. | 43 | the packet mark. |
42 | 44 | ||
43 | config NF_REJECT_IPV6 | ||
44 | tristate "IPv6 packet rejection" | ||
45 | default m if NETFILTER_ADVANCED=n | ||
46 | |||
47 | config NFT_REJECT_IPV6 | 45 | config NFT_REJECT_IPV6 |
48 | depends on NF_TABLES_IPV6 | ||
49 | select NF_REJECT_IPV6 | 46 | select NF_REJECT_IPV6 |
50 | default NFT_REJECT | 47 | default NFT_REJECT |
51 | tristate | 48 | tristate |
52 | 49 | ||
50 | endif # NF_TABLES_IPV6 | ||
51 | endif # NF_TABLES | ||
52 | |||
53 | config NF_REJECT_IPV6 | ||
54 | tristate "IPv6 packet rejection" | ||
55 | default m if NETFILTER_ADVANCED=n | ||
56 | |||
53 | config NF_LOG_IPV6 | 57 | config NF_LOG_IPV6 |
54 | tristate "IPv6 packet logging" | 58 | tristate "IPv6 packet logging" |
55 | default m if NETFILTER_ADVANCED=n | 59 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index d05b36440e8b..68e0bb4db1bf 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c | |||
@@ -208,4 +208,39 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | |||
208 | } | 208 | } |
209 | EXPORT_SYMBOL_GPL(nf_send_reset6); | 209 | EXPORT_SYMBOL_GPL(nf_send_reset6); |
210 | 210 | ||
211 | static bool reject6_csum_ok(struct sk_buff *skb, int hook) | ||
212 | { | ||
213 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
214 | int thoff; | ||
215 | __be16 fo; | ||
216 | u8 proto; | ||
217 | |||
218 | if (skb->csum_bad) | ||
219 | return false; | ||
220 | |||
221 | if (skb_csum_unnecessary(skb)) | ||
222 | return true; | ||
223 | |||
224 | proto = ip6h->nexthdr; | ||
225 | thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo); | ||
226 | |||
227 | if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0) | ||
228 | return false; | ||
229 | |||
230 | return nf_ip6_checksum(skb, hook, thoff, proto) == 0; | ||
231 | } | ||
232 | |||
233 | void nf_send_unreach6(struct net *net, struct sk_buff *skb_in, | ||
234 | unsigned char code, unsigned int hooknum) | ||
235 | { | ||
236 | if (!reject6_csum_ok(skb_in, hooknum)) | ||
237 | return; | ||
238 | |||
239 | if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) | ||
240 | skb_in->dev = net->loopback_dev; | ||
241 | |||
242 | icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); | ||
243 | } | ||
244 | EXPORT_SYMBOL_GPL(nf_send_unreach6); | ||
245 | |||
211 | MODULE_LICENSE("GPL"); | 246 | MODULE_LICENSE("GPL"); |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c68c3b441381..971cd7526f4b 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -438,8 +438,10 @@ config NF_TABLES | |||
438 | 438 | ||
439 | To compile it as a module, choose M here. | 439 | To compile it as a module, choose M here. |
440 | 440 | ||
441 | if NF_TABLES | ||
442 | |||
441 | config NF_TABLES_INET | 443 | config NF_TABLES_INET |
442 | depends on NF_TABLES && IPV6 | 444 | depends on IPV6 |
443 | select NF_TABLES_IPV4 | 445 | select NF_TABLES_IPV4 |
444 | select NF_TABLES_IPV6 | 446 | select NF_TABLES_IPV6 |
445 | tristate "Netfilter nf_tables mixed IPv4/IPv6 tables support" | 447 | tristate "Netfilter nf_tables mixed IPv4/IPv6 tables support" |
@@ -447,21 +449,18 @@ config NF_TABLES_INET | |||
447 | This option enables support for a mixed IPv4/IPv6 "inet" table. | 449 | This option enables support for a mixed IPv4/IPv6 "inet" table. |
448 | 450 | ||
449 | config NFT_EXTHDR | 451 | config NFT_EXTHDR |
450 | depends on NF_TABLES | ||
451 | tristate "Netfilter nf_tables IPv6 exthdr module" | 452 | tristate "Netfilter nf_tables IPv6 exthdr module" |
452 | help | 453 | help |
453 | This option adds the "exthdr" expression that you can use to match | 454 | This option adds the "exthdr" expression that you can use to match |
454 | IPv6 extension headers. | 455 | IPv6 extension headers. |
455 | 456 | ||
456 | config NFT_META | 457 | config NFT_META |
457 | depends on NF_TABLES | ||
458 | tristate "Netfilter nf_tables meta module" | 458 | tristate "Netfilter nf_tables meta module" |
459 | help | 459 | help |
460 | This option adds the "meta" expression that you can use to match and | 460 | This option adds the "meta" expression that you can use to match and |
461 | to set packet metainformation such as the packet mark. | 461 | to set packet metainformation such as the packet mark. |
462 | 462 | ||
463 | config NFT_CT | 463 | config NFT_CT |
464 | depends on NF_TABLES | ||
465 | depends on NF_CONNTRACK | 464 | depends on NF_CONNTRACK |
466 | tristate "Netfilter nf_tables conntrack module" | 465 | tristate "Netfilter nf_tables conntrack module" |
467 | help | 466 | help |
@@ -469,42 +468,36 @@ config NFT_CT | |||
469 | connection tracking information such as the flow state. | 468 | connection tracking information such as the flow state. |
470 | 469 | ||
471 | config NFT_RBTREE | 470 | config NFT_RBTREE |
472 | depends on NF_TABLES | ||
473 | tristate "Netfilter nf_tables rbtree set module" | 471 | tristate "Netfilter nf_tables rbtree set module" |
474 | help | 472 | help |
475 | This option adds the "rbtree" set type (Red Black tree) that is used | 473 | This option adds the "rbtree" set type (Red Black tree) that is used |
476 | to build interval-based sets. | 474 | to build interval-based sets. |
477 | 475 | ||
478 | config NFT_HASH | 476 | config NFT_HASH |
479 | depends on NF_TABLES | ||
480 | tristate "Netfilter nf_tables hash set module" | 477 | tristate "Netfilter nf_tables hash set module" |
481 | help | 478 | help |
482 | This option adds the "hash" set type that is used to build one-way | 479 | This option adds the "hash" set type that is used to build one-way |
483 | mappings between matchings and actions. | 480 | mappings between matchings and actions. |
484 | 481 | ||
485 | config NFT_COUNTER | 482 | config NFT_COUNTER |
486 | depends on NF_TABLES | ||
487 | tristate "Netfilter nf_tables counter module" | 483 | tristate "Netfilter nf_tables counter module" |
488 | help | 484 | help |
489 | This option adds the "counter" expression that you can use to | 485 | This option adds the "counter" expression that you can use to |
490 | include packet and byte counters in a rule. | 486 | include packet and byte counters in a rule. |
491 | 487 | ||
492 | config NFT_LOG | 488 | config NFT_LOG |
493 | depends on NF_TABLES | ||
494 | tristate "Netfilter nf_tables log module" | 489 | tristate "Netfilter nf_tables log module" |
495 | help | 490 | help |
496 | This option adds the "log" expression that you can use to log | 491 | This option adds the "log" expression that you can use to log |
497 | packets matching some criteria. | 492 | packets matching some criteria. |
498 | 493 | ||
499 | config NFT_LIMIT | 494 | config NFT_LIMIT |
500 | depends on NF_TABLES | ||
501 | tristate "Netfilter nf_tables limit module" | 495 | tristate "Netfilter nf_tables limit module" |
502 | help | 496 | help |
503 | This option adds the "limit" expression that you can use to | 497 | This option adds the "limit" expression that you can use to |
504 | ratelimit rule matchings. | 498 | ratelimit rule matchings. |
505 | 499 | ||
506 | config NFT_MASQ | 500 | config NFT_MASQ |
507 | depends on NF_TABLES | ||
508 | depends on NF_CONNTRACK | 501 | depends on NF_CONNTRACK |
509 | depends on NF_NAT | 502 | depends on NF_NAT |
510 | tristate "Netfilter nf_tables masquerade support" | 503 | tristate "Netfilter nf_tables masquerade support" |
@@ -513,7 +506,6 @@ config NFT_MASQ | |||
513 | to perform NAT in the masquerade flavour. | 506 | to perform NAT in the masquerade flavour. |
514 | 507 | ||
515 | config NFT_REDIR | 508 | config NFT_REDIR |
516 | depends on NF_TABLES | ||
517 | depends on NF_CONNTRACK | 509 | depends on NF_CONNTRACK |
518 | depends on NF_NAT | 510 | depends on NF_NAT |
519 | tristate "Netfilter nf_tables redirect support" | 511 | tristate "Netfilter nf_tables redirect support" |
@@ -522,7 +514,6 @@ config NFT_REDIR | |||
522 | to perform NAT in the redirect flavour. | 514 | to perform NAT in the redirect flavour. |
523 | 515 | ||
524 | config NFT_NAT | 516 | config NFT_NAT |
525 | depends on NF_TABLES | ||
526 | depends on NF_CONNTRACK | 517 | depends on NF_CONNTRACK |
527 | select NF_NAT | 518 | select NF_NAT |
528 | tristate "Netfilter nf_tables nat module" | 519 | tristate "Netfilter nf_tables nat module" |
@@ -531,7 +522,6 @@ config NFT_NAT | |||
531 | typical Network Address Translation (NAT) packet transformations. | 522 | typical Network Address Translation (NAT) packet transformations. |
532 | 523 | ||
533 | config NFT_QUEUE | 524 | config NFT_QUEUE |
534 | depends on NF_TABLES | ||
535 | depends on NETFILTER_XTABLES | 525 | depends on NETFILTER_XTABLES |
536 | depends on NETFILTER_NETLINK_QUEUE | 526 | depends on NETFILTER_NETLINK_QUEUE |
537 | tristate "Netfilter nf_tables queue module" | 527 | tristate "Netfilter nf_tables queue module" |
@@ -540,7 +530,6 @@ config NFT_QUEUE | |||
540 | infrastructure (also known as NFQUEUE) from nftables. | 530 | infrastructure (also known as NFQUEUE) from nftables. |
541 | 531 | ||
542 | config NFT_REJECT | 532 | config NFT_REJECT |
543 | depends on NF_TABLES | ||
544 | default m if NETFILTER_ADVANCED=n | 533 | default m if NETFILTER_ADVANCED=n |
545 | tristate "Netfilter nf_tables reject support" | 534 | tristate "Netfilter nf_tables reject support" |
546 | help | 535 | help |
@@ -554,7 +543,6 @@ config NFT_REJECT_INET | |||
554 | tristate | 543 | tristate |
555 | 544 | ||
556 | config NFT_COMPAT | 545 | config NFT_COMPAT |
557 | depends on NF_TABLES | ||
558 | depends on NETFILTER_XTABLES | 546 | depends on NETFILTER_XTABLES |
559 | tristate "Netfilter x_tables over nf_tables module" | 547 | tristate "Netfilter x_tables over nf_tables module" |
560 | help | 548 | help |
@@ -562,6 +550,8 @@ config NFT_COMPAT | |||
562 | x_tables match/target extensions over the nf_tables | 550 | x_tables match/target extensions over the nf_tables |
563 | framework. | 551 | framework. |
564 | 552 | ||
553 | endif # NF_TABLES | ||
554 | |||
565 | config NETFILTER_XTABLES | 555 | config NETFILTER_XTABLES |
566 | tristate "Netfilter Xtables support (required for ip_tables)" | 556 | tristate "Netfilter Xtables support (required for ip_tables)" |
567 | default m if NETFILTER_ADVANCED=n | 557 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 199fd0f27b0e..284b20ce566b 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -401,7 +401,8 @@ nf_tables_chain_type_lookup(const struct nft_af_info *afi, | |||
401 | } | 401 | } |
402 | 402 | ||
403 | static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { | 403 | static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { |
404 | [NFTA_TABLE_NAME] = { .type = NLA_STRING }, | 404 | [NFTA_TABLE_NAME] = { .type = NLA_STRING, |
405 | .len = NFT_TABLE_MAXNAMELEN - 1 }, | ||
405 | [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, | 406 | [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, |
406 | }; | 407 | }; |
407 | 408 | ||
@@ -686,13 +687,13 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, | |||
686 | if (!try_module_get(afi->owner)) | 687 | if (!try_module_get(afi->owner)) |
687 | return -EAFNOSUPPORT; | 688 | return -EAFNOSUPPORT; |
688 | 689 | ||
689 | table = kzalloc(sizeof(*table) + nla_len(name), GFP_KERNEL); | 690 | table = kzalloc(sizeof(*table), GFP_KERNEL); |
690 | if (table == NULL) { | 691 | if (table == NULL) { |
691 | module_put(afi->owner); | 692 | module_put(afi->owner); |
692 | return -ENOMEM; | 693 | return -ENOMEM; |
693 | } | 694 | } |
694 | 695 | ||
695 | nla_strlcpy(table->name, name, nla_len(name)); | 696 | nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN); |
696 | INIT_LIST_HEAD(&table->chains); | 697 | INIT_LIST_HEAD(&table->chains); |
697 | INIT_LIST_HEAD(&table->sets); | 698 | INIT_LIST_HEAD(&table->sets); |
698 | table->flags = flags; | 699 | table->flags = flags; |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 3b90eb2b2c55..77165bf023f3 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -21,6 +21,48 @@ | |||
21 | #include <net/netfilter/nf_tables.h> | 21 | #include <net/netfilter/nf_tables.h> |
22 | #include <net/netfilter/nf_log.h> | 22 | #include <net/netfilter/nf_log.h> |
23 | 23 | ||
24 | enum nft_trace { | ||
25 | NFT_TRACE_RULE, | ||
26 | NFT_TRACE_RETURN, | ||
27 | NFT_TRACE_POLICY, | ||
28 | }; | ||
29 | |||
30 | static const char *const comments[] = { | ||
31 | [NFT_TRACE_RULE] = "rule", | ||
32 | [NFT_TRACE_RETURN] = "return", | ||
33 | [NFT_TRACE_POLICY] = "policy", | ||
34 | }; | ||
35 | |||
36 | static struct nf_loginfo trace_loginfo = { | ||
37 | .type = NF_LOG_TYPE_LOG, | ||
38 | .u = { | ||
39 | .log = { | ||
40 | .level = 4, | ||
41 | .logflags = NF_LOG_MASK, | ||
42 | }, | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | static void __nft_trace_packet(const struct nft_pktinfo *pkt, | ||
47 | const struct nft_chain *chain, | ||
48 | int rulenum, enum nft_trace type) | ||
49 | { | ||
50 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | ||
51 | |||
52 | nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, | ||
53 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", | ||
54 | chain->table->name, chain->name, comments[type], | ||
55 | rulenum); | ||
56 | } | ||
57 | |||
58 | static inline void nft_trace_packet(const struct nft_pktinfo *pkt, | ||
59 | const struct nft_chain *chain, | ||
60 | int rulenum, enum nft_trace type) | ||
61 | { | ||
62 | if (unlikely(pkt->skb->nf_trace)) | ||
63 | __nft_trace_packet(pkt, chain, rulenum, type); | ||
64 | } | ||
65 | |||
24 | static void nft_cmp_fast_eval(const struct nft_expr *expr, | 66 | static void nft_cmp_fast_eval(const struct nft_expr *expr, |
25 | struct nft_data data[NFT_REG_MAX + 1]) | 67 | struct nft_data data[NFT_REG_MAX + 1]) |
26 | { | 68 | { |
@@ -66,40 +108,6 @@ struct nft_jumpstack { | |||
66 | int rulenum; | 108 | int rulenum; |
67 | }; | 109 | }; |
68 | 110 | ||
69 | enum nft_trace { | ||
70 | NFT_TRACE_RULE, | ||
71 | NFT_TRACE_RETURN, | ||
72 | NFT_TRACE_POLICY, | ||
73 | }; | ||
74 | |||
75 | static const char *const comments[] = { | ||
76 | [NFT_TRACE_RULE] = "rule", | ||
77 | [NFT_TRACE_RETURN] = "return", | ||
78 | [NFT_TRACE_POLICY] = "policy", | ||
79 | }; | ||
80 | |||
81 | static struct nf_loginfo trace_loginfo = { | ||
82 | .type = NF_LOG_TYPE_LOG, | ||
83 | .u = { | ||
84 | .log = { | ||
85 | .level = 4, | ||
86 | .logflags = NF_LOG_MASK, | ||
87 | }, | ||
88 | }, | ||
89 | }; | ||
90 | |||
91 | static void nft_trace_packet(const struct nft_pktinfo *pkt, | ||
92 | const struct nft_chain *chain, | ||
93 | int rulenum, enum nft_trace type) | ||
94 | { | ||
95 | struct net *net = dev_net(pkt->in ? pkt->in : pkt->out); | ||
96 | |||
97 | nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in, | ||
98 | pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ", | ||
99 | chain->table->name, chain->name, comments[type], | ||
100 | rulenum); | ||
101 | } | ||
102 | |||
103 | unsigned int | 111 | unsigned int |
104 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | 112 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) |
105 | { | 113 | { |
@@ -146,8 +154,7 @@ next_rule: | |||
146 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 154 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; |
147 | continue; | 155 | continue; |
148 | case NFT_CONTINUE: | 156 | case NFT_CONTINUE: |
149 | if (unlikely(pkt->skb->nf_trace)) | 157 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); |
150 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | ||
151 | continue; | 158 | continue; |
152 | } | 159 | } |
153 | break; | 160 | break; |
@@ -157,37 +164,28 @@ next_rule: | |||
157 | case NF_ACCEPT: | 164 | case NF_ACCEPT: |
158 | case NF_DROP: | 165 | case NF_DROP: |
159 | case NF_QUEUE: | 166 | case NF_QUEUE: |
160 | if (unlikely(pkt->skb->nf_trace)) | 167 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); |
161 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | ||
162 | |||
163 | return data[NFT_REG_VERDICT].verdict; | 168 | return data[NFT_REG_VERDICT].verdict; |
164 | } | 169 | } |
165 | 170 | ||
166 | switch (data[NFT_REG_VERDICT].verdict) { | 171 | switch (data[NFT_REG_VERDICT].verdict) { |
167 | case NFT_JUMP: | 172 | case NFT_JUMP: |
168 | if (unlikely(pkt->skb->nf_trace)) | ||
169 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | ||
170 | |||
171 | BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); | 173 | BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE); |
172 | jumpstack[stackptr].chain = chain; | 174 | jumpstack[stackptr].chain = chain; |
173 | jumpstack[stackptr].rule = rule; | 175 | jumpstack[stackptr].rule = rule; |
174 | jumpstack[stackptr].rulenum = rulenum; | 176 | jumpstack[stackptr].rulenum = rulenum; |
175 | stackptr++; | 177 | stackptr++; |
176 | chain = data[NFT_REG_VERDICT].chain; | 178 | /* fall through */ |
177 | goto do_chain; | ||
178 | case NFT_GOTO: | 179 | case NFT_GOTO: |
179 | if (unlikely(pkt->skb->nf_trace)) | 180 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); |
180 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | ||
181 | 181 | ||
182 | chain = data[NFT_REG_VERDICT].chain; | 182 | chain = data[NFT_REG_VERDICT].chain; |
183 | goto do_chain; | 183 | goto do_chain; |
184 | case NFT_RETURN: | ||
185 | if (unlikely(pkt->skb->nf_trace)) | ||
186 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); | ||
187 | break; | ||
188 | case NFT_CONTINUE: | 184 | case NFT_CONTINUE: |
189 | if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN))) | 185 | rulenum++; |
190 | nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN); | 186 | /* fall through */ |
187 | case NFT_RETURN: | ||
188 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); | ||
191 | break; | 189 | break; |
192 | default: | 190 | default: |
193 | WARN_ON(1); | 191 | WARN_ON(1); |
@@ -201,8 +199,7 @@ next_rule: | |||
201 | goto next_rule; | 199 | goto next_rule; |
202 | } | 200 | } |
203 | 201 | ||
204 | if (unlikely(pkt->skb->nf_trace)) | 202 | nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY); |
205 | nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY); | ||
206 | 203 | ||
207 | rcu_read_lock_bh(); | 204 | rcu_read_lock_bh(); |
208 | stats = this_cpu_ptr(rcu_dereference(nft_base_chain(basechain)->stats)); | 205 | stats = this_cpu_ptr(rcu_dereference(nft_base_chain(basechain)->stats)); |
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c index 7b5f9d58680a..92877114aff4 100644 --- a/net/netfilter/nft_reject_inet.c +++ b/net/netfilter/nft_reject_inet.c | |||
@@ -28,14 +28,16 @@ static void nft_reject_inet_eval(const struct nft_expr *expr, | |||
28 | case NFPROTO_IPV4: | 28 | case NFPROTO_IPV4: |
29 | switch (priv->type) { | 29 | switch (priv->type) { |
30 | case NFT_REJECT_ICMP_UNREACH: | 30 | case NFT_REJECT_ICMP_UNREACH: |
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | 31 | nf_send_unreach(pkt->skb, priv->icmp_code, |
32 | pkt->ops->hooknum); | ||
32 | break; | 33 | break; |
33 | case NFT_REJECT_TCP_RST: | 34 | case NFT_REJECT_TCP_RST: |
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | 35 | nf_send_reset(pkt->skb, pkt->ops->hooknum); |
35 | break; | 36 | break; |
36 | case NFT_REJECT_ICMPX_UNREACH: | 37 | case NFT_REJECT_ICMPX_UNREACH: |
37 | nf_send_unreach(pkt->skb, | 38 | nf_send_unreach(pkt->skb, |
38 | nft_reject_icmp_code(priv->icmp_code)); | 39 | nft_reject_icmp_code(priv->icmp_code), |
40 | pkt->ops->hooknum); | ||
39 | break; | 41 | break; |
40 | } | 42 | } |
41 | break; | 43 | break; |