aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-02-05 17:33:28 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-05 17:33:28 -0500
commit6e03f896b52cd2ca88942170c5c9c407ec0ede69 (patch)
tree48ca9a6efa5f99819667538838bab3679416f92c /net/netfilter
parentdb79a621835ee91d3e10177abd97f48e0a4dcf9b (diff)
parent9d82f5eb3376cbae96ad36a063a9390de1694546 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/vxlan.c drivers/vhost/net.c include/linux/if_vlan.h net/core/dev.c The net/core/dev.c conflict was the overlap of one commit marking an existing function static whilst another was adding a new function. In the include/linux/if_vlan.h case, the type used for a local variable was changed in 'net', whereas the function got rewritten to fix a stacked vlan bug in 'net-next'. In drivers/vhost/net.c, Al Viro's iov_iter conversions in 'net-next' overlapped with an endainness fix for VHOST 1.0 in 'net'. In drivers/net/vxlan.c, vxlan_find_vni() added a 'flags' parameter in 'net-next' whereas in 'net' there was a bug fix to pass in the correct network namespace pointer in calls to this function. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c33
-rw-r--r--net/netfilter/nf_tables_api.c28
-rw-r--r--net/netfilter/nft_masq.c26
-rw-r--r--net/netfilter/nft_nat.c40
-rw-r--r--net/netfilter/nft_redir.c25
5 files changed, 112 insertions, 40 deletions
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 990decba1fe4..b87ca32efa0b 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -659,16 +659,24 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
659 return err; 659 return err;
660} 660}
661 661
662static int ip_vs_route_me_harder(int af, struct sk_buff *skb) 662static int ip_vs_route_me_harder(int af, struct sk_buff *skb,
663 unsigned int hooknum)
663{ 664{
665 if (!sysctl_snat_reroute(skb))
666 return 0;
667 /* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */
668 if (NF_INET_LOCAL_IN == hooknum)
669 return 0;
664#ifdef CONFIG_IP_VS_IPV6 670#ifdef CONFIG_IP_VS_IPV6
665 if (af == AF_INET6) { 671 if (af == AF_INET6) {
666 if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0) 672 struct dst_entry *dst = skb_dst(skb);
673
674 if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) &&
675 ip6_route_me_harder(skb) != 0)
667 return 1; 676 return 1;
668 } else 677 } else
669#endif 678#endif
670 if ((sysctl_snat_reroute(skb) || 679 if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
671 skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
672 ip_route_me_harder(skb, RTN_LOCAL) != 0) 680 ip_route_me_harder(skb, RTN_LOCAL) != 0)
673 return 1; 681 return 1;
674 682
@@ -791,7 +799,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
791 union nf_inet_addr *snet, 799 union nf_inet_addr *snet,
792 __u8 protocol, struct ip_vs_conn *cp, 800 __u8 protocol, struct ip_vs_conn *cp,
793 struct ip_vs_protocol *pp, 801 struct ip_vs_protocol *pp,
794 unsigned int offset, unsigned int ihl) 802 unsigned int offset, unsigned int ihl,
803 unsigned int hooknum)
795{ 804{
796 unsigned int verdict = NF_DROP; 805 unsigned int verdict = NF_DROP;
797 806
@@ -821,7 +830,7 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
821#endif 830#endif
822 ip_vs_nat_icmp(skb, pp, cp, 1); 831 ip_vs_nat_icmp(skb, pp, cp, 1);
823 832
824 if (ip_vs_route_me_harder(af, skb)) 833 if (ip_vs_route_me_harder(af, skb, hooknum))
825 goto out; 834 goto out;
826 835
827 /* do the statistics and put it back */ 836 /* do the statistics and put it back */
@@ -916,7 +925,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
916 925
917 snet.ip = iph->saddr; 926 snet.ip = iph->saddr;
918 return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp, 927 return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
919 pp, ciph.len, ihl); 928 pp, ciph.len, ihl, hooknum);
920} 929}
921 930
922#ifdef CONFIG_IP_VS_IPV6 931#ifdef CONFIG_IP_VS_IPV6
@@ -981,7 +990,8 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
981 snet.in6 = ciph.saddr.in6; 990 snet.in6 = ciph.saddr.in6;
982 writable = ciph.len; 991 writable = ciph.len;
983 return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp, 992 return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
984 pp, writable, sizeof(struct ipv6hdr)); 993 pp, writable, sizeof(struct ipv6hdr),
994 hooknum);
985} 995}
986#endif 996#endif
987 997
@@ -1040,7 +1050,8 @@ static inline bool is_new_conn(const struct sk_buff *skb,
1040 */ 1050 */
1041static unsigned int 1051static unsigned int
1042handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, 1052handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
1043 struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) 1053 struct ip_vs_conn *cp, struct ip_vs_iphdr *iph,
1054 unsigned int hooknum)
1044{ 1055{
1045 struct ip_vs_protocol *pp = pd->pp; 1056 struct ip_vs_protocol *pp = pd->pp;
1046 1057
@@ -1078,7 +1089,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
1078 * if it came from this machine itself. So re-compute 1089 * if it came from this machine itself. So re-compute
1079 * the routing information. 1090 * the routing information.
1080 */ 1091 */
1081 if (ip_vs_route_me_harder(af, skb)) 1092 if (ip_vs_route_me_harder(af, skb, hooknum))
1082 goto drop; 1093 goto drop;
1083 1094
1084 IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT"); 1095 IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
@@ -1181,7 +1192,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
1181 cp = pp->conn_out_get(af, skb, &iph, 0); 1192 cp = pp->conn_out_get(af, skb, &iph, 0);
1182 1193
1183 if (likely(cp)) 1194 if (likely(cp))
1184 return handle_response(af, skb, pd, cp, &iph); 1195 return handle_response(af, skb, pd, cp, &iph, hooknum);
1185 if (sysctl_nat_icmp_send(net) && 1196 if (sysctl_nat_icmp_send(net) &&
1186 (pp->protocol == IPPROTO_TCP || 1197 (pp->protocol == IPPROTO_TCP ||
1187 pp->protocol == IPPROTO_UDP || 1198 pp->protocol == IPPROTO_UDP ||
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 70f697827b9b..199fd0f27b0e 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1136,9 +1136,11 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)
1136 /* Restore old counters on this cpu, no problem. Per-cpu statistics 1136 /* Restore old counters on this cpu, no problem. Per-cpu statistics
1137 * are not exposed to userspace. 1137 * are not exposed to userspace.
1138 */ 1138 */
1139 preempt_disable();
1139 stats = this_cpu_ptr(newstats); 1140 stats = this_cpu_ptr(newstats);
1140 stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])); 1141 stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
1141 stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); 1142 stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
1143 preempt_enable();
1142 1144
1143 return newstats; 1145 return newstats;
1144} 1146}
@@ -1264,8 +1266,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
1264 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); 1266 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1265 trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN, 1267 trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN,
1266 sizeof(struct nft_trans_chain)); 1268 sizeof(struct nft_trans_chain));
1267 if (trans == NULL) 1269 if (trans == NULL) {
1270 free_percpu(stats);
1268 return -ENOMEM; 1271 return -ENOMEM;
1272 }
1269 1273
1270 nft_trans_chain_stats(trans) = stats; 1274 nft_trans_chain_stats(trans) = stats;
1271 nft_trans_chain_update(trans) = true; 1275 nft_trans_chain_update(trans) = true;
@@ -1321,8 +1325,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
1321 hookfn = type->hooks[hooknum]; 1325 hookfn = type->hooks[hooknum];
1322 1326
1323 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); 1327 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
1324 if (basechain == NULL) 1328 if (basechain == NULL) {
1329 module_put(type->owner);
1325 return -ENOMEM; 1330 return -ENOMEM;
1331 }
1326 1332
1327 if (nla[NFTA_CHAIN_COUNTERS]) { 1333 if (nla[NFTA_CHAIN_COUNTERS]) {
1328 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]); 1334 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
@@ -3759,6 +3765,24 @@ int nft_chain_validate_dependency(const struct nft_chain *chain,
3759} 3765}
3760EXPORT_SYMBOL_GPL(nft_chain_validate_dependency); 3766EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
3761 3767
3768int nft_chain_validate_hooks(const struct nft_chain *chain,
3769 unsigned int hook_flags)
3770{
3771 struct nft_base_chain *basechain;
3772
3773 if (chain->flags & NFT_BASE_CHAIN) {
3774 basechain = nft_base_chain(chain);
3775
3776 if ((1 << basechain->ops[0].hooknum) & hook_flags)
3777 return 0;
3778
3779 return -EOPNOTSUPP;
3780 }
3781
3782 return 0;
3783}
3784EXPORT_SYMBOL_GPL(nft_chain_validate_hooks);
3785
3762/* 3786/*
3763 * Loop detection - walk through the ruleset beginning at the destination chain 3787 * Loop detection - walk through the ruleset beginning at the destination chain
3764 * of a new jump until either the source chain is reached (loop) or all 3788 * of a new jump until either the source chain is reached (loop) or all
diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
index d1ffd5eb3a9b..9aea747b43ea 100644
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -21,6 +21,21 @@ const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX + 1] = {
21}; 21};
22EXPORT_SYMBOL_GPL(nft_masq_policy); 22EXPORT_SYMBOL_GPL(nft_masq_policy);
23 23
24int nft_masq_validate(const struct nft_ctx *ctx,
25 const struct nft_expr *expr,
26 const struct nft_data **data)
27{
28 int err;
29
30 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
31 if (err < 0)
32 return err;
33
34 return nft_chain_validate_hooks(ctx->chain,
35 (1 << NF_INET_POST_ROUTING));
36}
37EXPORT_SYMBOL_GPL(nft_masq_validate);
38
24int nft_masq_init(const struct nft_ctx *ctx, 39int nft_masq_init(const struct nft_ctx *ctx,
25 const struct nft_expr *expr, 40 const struct nft_expr *expr,
26 const struct nlattr * const tb[]) 41 const struct nlattr * const tb[])
@@ -28,8 +43,8 @@ int nft_masq_init(const struct nft_ctx *ctx,
28 struct nft_masq *priv = nft_expr_priv(expr); 43 struct nft_masq *priv = nft_expr_priv(expr);
29 int err; 44 int err;
30 45
31 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); 46 err = nft_masq_validate(ctx, expr, NULL);
32 if (err < 0) 47 if (err)
33 return err; 48 return err;
34 49
35 if (tb[NFTA_MASQ_FLAGS] == NULL) 50 if (tb[NFTA_MASQ_FLAGS] == NULL)
@@ -60,12 +75,5 @@ nla_put_failure:
60} 75}
61EXPORT_SYMBOL_GPL(nft_masq_dump); 76EXPORT_SYMBOL_GPL(nft_masq_dump);
62 77
63int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
64 const struct nft_data **data)
65{
66 return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
67}
68EXPORT_SYMBOL_GPL(nft_masq_validate);
69
70MODULE_LICENSE("GPL"); 78MODULE_LICENSE("GPL");
71MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 79MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
index aff54fb1c8a0..a0837c6c9283 100644
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -88,17 +88,40 @@ static const struct nla_policy nft_nat_policy[NFTA_NAT_MAX + 1] = {
88 [NFTA_NAT_FLAGS] = { .type = NLA_U32 }, 88 [NFTA_NAT_FLAGS] = { .type = NLA_U32 },
89}; 89};
90 90
91static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, 91static int nft_nat_validate(const struct nft_ctx *ctx,
92 const struct nlattr * const tb[]) 92 const struct nft_expr *expr,
93 const struct nft_data **data)
93{ 94{
94 struct nft_nat *priv = nft_expr_priv(expr); 95 struct nft_nat *priv = nft_expr_priv(expr);
95 u32 family;
96 int err; 96 int err;
97 97
98 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); 98 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
99 if (err < 0) 99 if (err < 0)
100 return err; 100 return err;
101 101
102 switch (priv->type) {
103 case NFT_NAT_SNAT:
104 err = nft_chain_validate_hooks(ctx->chain,
105 (1 << NF_INET_POST_ROUTING) |
106 (1 << NF_INET_LOCAL_IN));
107 break;
108 case NFT_NAT_DNAT:
109 err = nft_chain_validate_hooks(ctx->chain,
110 (1 << NF_INET_PRE_ROUTING) |
111 (1 << NF_INET_LOCAL_OUT));
112 break;
113 }
114
115 return err;
116}
117
118static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
119 const struct nlattr * const tb[])
120{
121 struct nft_nat *priv = nft_expr_priv(expr);
122 u32 family;
123 int err;
124
102 if (tb[NFTA_NAT_TYPE] == NULL || 125 if (tb[NFTA_NAT_TYPE] == NULL ||
103 (tb[NFTA_NAT_REG_ADDR_MIN] == NULL && 126 (tb[NFTA_NAT_REG_ADDR_MIN] == NULL &&
104 tb[NFTA_NAT_REG_PROTO_MIN] == NULL)) 127 tb[NFTA_NAT_REG_PROTO_MIN] == NULL))
@@ -115,6 +138,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
115 return -EINVAL; 138 return -EINVAL;
116 } 139 }
117 140
141 err = nft_nat_validate(ctx, expr, NULL);
142 if (err < 0)
143 return err;
144
118 if (tb[NFTA_NAT_FAMILY] == NULL) 145 if (tb[NFTA_NAT_FAMILY] == NULL)
119 return -EINVAL; 146 return -EINVAL;
120 147
@@ -219,13 +246,6 @@ nla_put_failure:
219 return -1; 246 return -1;
220} 247}
221 248
222static int nft_nat_validate(const struct nft_ctx *ctx,
223 const struct nft_expr *expr,
224 const struct nft_data **data)
225{
226 return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
227}
228
229static struct nft_expr_type nft_nat_type; 249static struct nft_expr_type nft_nat_type;
230static const struct nft_expr_ops nft_nat_ops = { 250static const struct nft_expr_ops nft_nat_ops = {
231 .type = &nft_nat_type, 251 .type = &nft_nat_type,
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
index 9e8093f28311..d7e9e93a4e90 100644
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -23,6 +23,22 @@ const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = {
23}; 23};
24EXPORT_SYMBOL_GPL(nft_redir_policy); 24EXPORT_SYMBOL_GPL(nft_redir_policy);
25 25
26int nft_redir_validate(const struct nft_ctx *ctx,
27 const struct nft_expr *expr,
28 const struct nft_data **data)
29{
30 int err;
31
32 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
33 if (err < 0)
34 return err;
35
36 return nft_chain_validate_hooks(ctx->chain,
37 (1 << NF_INET_PRE_ROUTING) |
38 (1 << NF_INET_LOCAL_OUT));
39}
40EXPORT_SYMBOL_GPL(nft_redir_validate);
41
26int nft_redir_init(const struct nft_ctx *ctx, 42int nft_redir_init(const struct nft_ctx *ctx,
27 const struct nft_expr *expr, 43 const struct nft_expr *expr,
28 const struct nlattr * const tb[]) 44 const struct nlattr * const tb[])
@@ -30,7 +46,7 @@ int nft_redir_init(const struct nft_ctx *ctx,
30 struct nft_redir *priv = nft_expr_priv(expr); 46 struct nft_redir *priv = nft_expr_priv(expr);
31 int err; 47 int err;
32 48
33 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); 49 err = nft_redir_validate(ctx, expr, NULL);
34 if (err < 0) 50 if (err < 0)
35 return err; 51 return err;
36 52
@@ -88,12 +104,5 @@ nla_put_failure:
88} 104}
89EXPORT_SYMBOL_GPL(nft_redir_dump); 105EXPORT_SYMBOL_GPL(nft_redir_dump);
90 106
91int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
92 const struct nft_data **data)
93{
94 return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
95}
96EXPORT_SYMBOL_GPL(nft_redir_validate);
97
98MODULE_LICENSE("GPL"); 107MODULE_LICENSE("GPL");
99MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 108MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");