aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-05-30 19:38:38 -0400
committerDavid S. Miller <davem@davemloft.net>2013-05-30 19:38:38 -0400
commit73ce00d4d6369c1a91c95f9b41e6ce498fbbd56f (patch)
tree71b6049295835ece130e65d6ce050f4119714e45 /net
parent8e6d91ae0917bf934ed86411148f79d904728d51 (diff)
parenta70b9641e6a90d6821e4354a2c2fede74015db29 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== The following patchset contains Netfilter/IPVS fixes for 3.10-rc3, they are: * fix xt_addrtype with IPv6, from Florian Westphal. This required a new hook for IPv6 functions in the netfilter core to avoid hard dependencies with the ipv6 subsystem when this match is only used for IPv4. * fix connection reuse case in IPVS. Currently, if an reused connection are directed to the same server. If that server is down, those connection would fail. Therefore, clear the connection and choose a new server among the available ones. * fix possible non-nul terminated string sent to user-space if ipt_ULOG is used as the default netfilter logging stub, from Chen Gang. * fix mark logging of IPv6 packets in xt_LOG, from Michal Kubecek. This bug has been there since 2.6.26. * Fix breakage ip_vs_sh due to incorrect structure layout for RCU, from Jan Beulich. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c6
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/netfilter.c7
-rw-r--r--net/netfilter/core.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c35
-rw-r--r--net/netfilter/ipvs/ip_vs_sh.c2
-rw-r--r--net/netfilter/xt_LOG.c2
-rw-r--r--net/netfilter/xt_addrtype.c27
8 files changed, 67 insertions, 16 deletions
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index cf08218ddbcf..ff4b781b1056 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -231,8 +231,10 @@ static void ipt_ulog_packet(struct net *net,
231 put_unaligned(tv.tv_usec, &pm->timestamp_usec); 231 put_unaligned(tv.tv_usec, &pm->timestamp_usec);
232 put_unaligned(skb->mark, &pm->mark); 232 put_unaligned(skb->mark, &pm->mark);
233 pm->hook = hooknum; 233 pm->hook = hooknum;
234 if (prefix != NULL) 234 if (prefix != NULL) {
235 strncpy(pm->prefix, prefix, sizeof(pm->prefix)); 235 strncpy(pm->prefix, prefix, sizeof(pm->prefix) - 1);
236 pm->prefix[sizeof(pm->prefix) - 1] = '\0';
237 }
236 else if (loginfo->prefix[0] != '\0') 238 else if (loginfo->prefix[0] != '\0')
237 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); 239 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
238 else 240 else
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d1ab6ab29a55..d1b2d8034b54 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1487,7 +1487,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev)
1487} 1487}
1488 1488
1489int ipv6_chk_addr(struct net *net, const struct in6_addr *addr, 1489int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
1490 struct net_device *dev, int strict) 1490 const struct net_device *dev, int strict)
1491{ 1491{
1492 struct inet6_ifaddr *ifp; 1492 struct inet6_ifaddr *ifp;
1493 unsigned int hash = inet6_addr_hash(addr); 1493 unsigned int hash = inet6_addr_hash(addr);
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 72836f40b730..95f3f1da0d7f 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -10,6 +10,7 @@
10#include <linux/netfilter.h> 10#include <linux/netfilter.h>
11#include <linux/netfilter_ipv6.h> 11#include <linux/netfilter_ipv6.h>
12#include <linux/export.h> 12#include <linux/export.h>
13#include <net/addrconf.h>
13#include <net/dst.h> 14#include <net/dst.h>
14#include <net/ipv6.h> 15#include <net/ipv6.h>
15#include <net/ip6_route.h> 16#include <net/ip6_route.h>
@@ -186,6 +187,10 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
186 return csum; 187 return csum;
187}; 188};
188 189
190static const struct nf_ipv6_ops ipv6ops = {
191 .chk_addr = ipv6_chk_addr,
192};
193
189static const struct nf_afinfo nf_ip6_afinfo = { 194static const struct nf_afinfo nf_ip6_afinfo = {
190 .family = AF_INET6, 195 .family = AF_INET6,
191 .checksum = nf_ip6_checksum, 196 .checksum = nf_ip6_checksum,
@@ -198,6 +203,7 @@ static const struct nf_afinfo nf_ip6_afinfo = {
198 203
199int __init ipv6_netfilter_init(void) 204int __init ipv6_netfilter_init(void)
200{ 205{
206 RCU_INIT_POINTER(nf_ipv6_ops, &ipv6ops);
201 return nf_register_afinfo(&nf_ip6_afinfo); 207 return nf_register_afinfo(&nf_ip6_afinfo);
202} 208}
203 209
@@ -206,5 +212,6 @@ int __init ipv6_netfilter_init(void)
206 */ 212 */
207void ipv6_netfilter_fini(void) 213void ipv6_netfilter_fini(void)
208{ 214{
215 RCU_INIT_POINTER(nf_ipv6_ops, NULL);
209 nf_unregister_afinfo(&nf_ip6_afinfo); 216 nf_unregister_afinfo(&nf_ip6_afinfo);
210} 217}
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 07c865a31a3d..857ca9f35177 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -30,6 +30,8 @@ static DEFINE_MUTEX(afinfo_mutex);
30 30
31const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; 31const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly;
32EXPORT_SYMBOL(nf_afinfo); 32EXPORT_SYMBOL(nf_afinfo);
33const struct nf_ipv6_ops __rcu *nf_ipv6_ops __read_mostly;
34EXPORT_SYMBOL_GPL(nf_ipv6_ops);
33 35
34int nf_register_afinfo(const struct nf_afinfo *afinfo) 36int nf_register_afinfo(const struct nf_afinfo *afinfo)
35{ 37{
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 085b5880ab0d..05565d2b3a61 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1001,6 +1001,32 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
1001 return th->rst; 1001 return th->rst;
1002} 1002}
1003 1003
1004static inline bool is_new_conn(const struct sk_buff *skb,
1005 struct ip_vs_iphdr *iph)
1006{
1007 switch (iph->protocol) {
1008 case IPPROTO_TCP: {
1009 struct tcphdr _tcph, *th;
1010
1011 th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
1012 if (th == NULL)
1013 return false;
1014 return th->syn;
1015 }
1016 case IPPROTO_SCTP: {
1017 sctp_chunkhdr_t *sch, schunk;
1018
1019 sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t),
1020 sizeof(schunk), &schunk);
1021 if (sch == NULL)
1022 return false;
1023 return sch->type == SCTP_CID_INIT;
1024 }
1025 default:
1026 return false;
1027 }
1028}
1029
1004/* Handle response packets: rewrite addresses and send away... 1030/* Handle response packets: rewrite addresses and send away...
1005 */ 1031 */
1006static unsigned int 1032static unsigned int
@@ -1612,6 +1638,15 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
1612 * Check if the packet belongs to an existing connection entry 1638 * Check if the packet belongs to an existing connection entry
1613 */ 1639 */
1614 cp = pp->conn_in_get(af, skb, &iph, 0); 1640 cp = pp->conn_in_get(af, skb, &iph, 0);
1641
1642 if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp && cp->dest &&
1643 unlikely(!atomic_read(&cp->dest->weight)) && !iph.fragoffs &&
1644 is_new_conn(skb, &iph)) {
1645 ip_vs_conn_expire_now(cp);
1646 __ip_vs_conn_put(cp);
1647 cp = NULL;
1648 }
1649
1615 if (unlikely(!cp) && !iph.fragoffs) { 1650 if (unlikely(!cp) && !iph.fragoffs) {
1616 /* No (second) fragments need to enter here, as nf_defrag_ipv6 1651 /* No (second) fragments need to enter here, as nf_defrag_ipv6
1617 * replayed fragment zero will already have created the cp 1652 * replayed fragment zero will already have created the cp
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 0df269d7c99f..a65edfe4b16c 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -67,8 +67,8 @@ struct ip_vs_sh_bucket {
67#define IP_VS_SH_TAB_MASK (IP_VS_SH_TAB_SIZE - 1) 67#define IP_VS_SH_TAB_MASK (IP_VS_SH_TAB_SIZE - 1)
68 68
69struct ip_vs_sh_state { 69struct ip_vs_sh_state {
70 struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE];
71 struct rcu_head rcu_head; 70 struct rcu_head rcu_head;
71 struct ip_vs_sh_bucket buckets[IP_VS_SH_TAB_SIZE];
72}; 72};
73 73
74/* 74/*
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index 491c7d821a0b..5ab24843370a 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -737,7 +737,7 @@ static void dump_ipv6_packet(struct sbuff *m,
737 dump_sk_uid_gid(m, skb->sk); 737 dump_sk_uid_gid(m, skb->sk);
738 738
739 /* Max length: 16 "MARK=0xFFFFFFFF " */ 739 /* Max length: 16 "MARK=0xFFFFFFFF " */
740 if (!recurse && skb->mark) 740 if (recurse && skb->mark)
741 sb_add(m, "MARK=0x%x ", skb->mark); 741 sb_add(m, "MARK=0x%x ", skb->mark);
742} 742}
743 743
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c
index 49c5ff7f6dd6..68ff29f60867 100644
--- a/net/netfilter/xt_addrtype.c
+++ b/net/netfilter/xt_addrtype.c
@@ -22,6 +22,7 @@
22#include <net/ip6_fib.h> 22#include <net/ip6_fib.h>
23#endif 23#endif
24 24
25#include <linux/netfilter_ipv6.h>
25#include <linux/netfilter/xt_addrtype.h> 26#include <linux/netfilter/xt_addrtype.h>
26#include <linux/netfilter/x_tables.h> 27#include <linux/netfilter/x_tables.h>
27 28
@@ -33,12 +34,12 @@ MODULE_ALIAS("ip6t_addrtype");
33 34
34#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 35#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
35static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, 36static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
36 const struct in6_addr *addr) 37 const struct in6_addr *addr, u16 mask)
37{ 38{
38 const struct nf_afinfo *afinfo; 39 const struct nf_afinfo *afinfo;
39 struct flowi6 flow; 40 struct flowi6 flow;
40 struct rt6_info *rt; 41 struct rt6_info *rt;
41 u32 ret; 42 u32 ret = 0;
42 int route_err; 43 int route_err;
43 44
44 memset(&flow, 0, sizeof(flow)); 45 memset(&flow, 0, sizeof(flow));
@@ -49,12 +50,19 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
49 rcu_read_lock(); 50 rcu_read_lock();
50 51
51 afinfo = nf_get_afinfo(NFPROTO_IPV6); 52 afinfo = nf_get_afinfo(NFPROTO_IPV6);
52 if (afinfo != NULL) 53 if (afinfo != NULL) {
54 const struct nf_ipv6_ops *v6ops;
55
56 if (dev && (mask & XT_ADDRTYPE_LOCAL)) {
57 v6ops = nf_get_ipv6_ops();
58 if (v6ops && v6ops->chk_addr(net, addr, dev, true))
59 ret = XT_ADDRTYPE_LOCAL;
60 }
53 route_err = afinfo->route(net, (struct dst_entry **)&rt, 61 route_err = afinfo->route(net, (struct dst_entry **)&rt,
54 flowi6_to_flowi(&flow), !!dev); 62 flowi6_to_flowi(&flow), false);
55 else 63 } else {
56 route_err = 1; 64 route_err = 1;
57 65 }
58 rcu_read_unlock(); 66 rcu_read_unlock();
59 67
60 if (route_err) 68 if (route_err)
@@ -62,15 +70,12 @@ static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
62 70
63 if (rt->rt6i_flags & RTF_REJECT) 71 if (rt->rt6i_flags & RTF_REJECT)
64 ret = XT_ADDRTYPE_UNREACHABLE; 72 ret = XT_ADDRTYPE_UNREACHABLE;
65 else
66 ret = 0;
67 73
68 if (rt->rt6i_flags & RTF_LOCAL) 74 if (dev == NULL && rt->rt6i_flags & RTF_LOCAL)
69 ret |= XT_ADDRTYPE_LOCAL; 75 ret |= XT_ADDRTYPE_LOCAL;
70 if (rt->rt6i_flags & RTF_ANYCAST) 76 if (rt->rt6i_flags & RTF_ANYCAST)
71 ret |= XT_ADDRTYPE_ANYCAST; 77 ret |= XT_ADDRTYPE_ANYCAST;
72 78
73
74 dst_release(&rt->dst); 79 dst_release(&rt->dst);
75 return ret; 80 return ret;
76} 81}
@@ -90,7 +95,7 @@ static bool match_type6(struct net *net, const struct net_device *dev,
90 95
91 if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | 96 if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST |
92 XT_ADDRTYPE_UNREACHABLE) & mask) 97 XT_ADDRTYPE_UNREACHABLE) & mask)
93 return !!(mask & match_lookup_rt6(net, dev, addr)); 98 return !!(mask & match_lookup_rt6(net, dev, addr, mask));
94 return true; 99 return true;
95} 100}
96 101