aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Thery <benjamin.thery@bull.net>2008-12-10 19:07:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-10 19:07:08 -0500
commitbd91b8bf372911c1e4d66d6bb44fe409349a6791 (patch)
tree18a79fc3c86ad833523562d7b73a9a557207b51b
parent5eaa65b240c5eb7bf2235eb9dd177c83e6e3832c (diff)
netns: ip6mr: allocate mroute6_socket per-namespace.
Preliminary work to make IPv6 multicast forwarding netns-aware. Make IPv6 multicast forwarding mroute6_socket per-namespace, moves it into struct netns_ipv6. At the moment, mroute6_socket is only referenced in init_net. Signed-off-by: Benjamin Thery <benjamin.thery@bull.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/mroute6.h8
-rw-r--r--include/net/netns/ipv6.h3
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/ip6mr.c22
4 files changed, 21 insertions, 15 deletions
diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
index 6f4c180179e2..2cd9901ee5c7 100644
--- a/include/linux/mroute6.h
+++ b/include/linux/mroute6.h
@@ -117,6 +117,7 @@ struct sioc_mif_req6
117 117
118#include <linux/pim.h> 118#include <linux/pim.h>
119#include <linux/skbuff.h> /* for struct sk_buff_head */ 119#include <linux/skbuff.h> /* for struct sk_buff_head */
120#include <net/net_namespace.h>
120 121
121#ifdef CONFIG_IPV6_MROUTE 122#ifdef CONFIG_IPV6_MROUTE
122static inline int ip6_mroute_opt(int opt) 123static inline int ip6_mroute_opt(int opt)
@@ -232,10 +233,13 @@ struct rtmsg;
232extern int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait); 233extern int ip6mr_get_route(struct sk_buff *skb, struct rtmsg *rtm, int nowait);
233 234
234#ifdef CONFIG_IPV6_MROUTE 235#ifdef CONFIG_IPV6_MROUTE
235extern struct sock *mroute6_socket; 236static inline struct sock *mroute6_socket(struct net *net)
237{
238 return net->ipv6.mroute6_sk;
239}
236extern int ip6mr_sk_done(struct sock *sk); 240extern int ip6mr_sk_done(struct sock *sk);
237#else 241#else
238#define mroute6_socket NULL 242static inline struct sock *mroute6_socket(struct net *net) { return NULL; }
239static inline int ip6mr_sk_done(struct sock *sk) { return 0; } 243static inline int ip6mr_sk_done(struct sock *sk) { return 0; }
240#endif 244#endif
241#endif 245#endif
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 2932721180c0..8a0a67d073b3 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -55,5 +55,8 @@ struct netns_ipv6 {
55 struct sock *ndisc_sk; 55 struct sock *ndisc_sk;
56 struct sock *tcp_sk; 56 struct sock *tcp_sk;
57 struct sock *igmp_sk; 57 struct sock *igmp_sk;
58#ifdef CONFIG_IPV6_MROUTE
59 struct sock *mroute6_sk;
60#endif
58}; 61};
59#endif 62#endif
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7d92fd97cfb9..4b15938bef4d 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -137,7 +137,8 @@ static int ip6_output2(struct sk_buff *skb)
137 struct inet6_dev *idev = ip6_dst_idev(skb->dst); 137 struct inet6_dev *idev = ip6_dst_idev(skb->dst);
138 138
139 if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && 139 if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) &&
140 ((mroute6_socket && !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) || 140 ((mroute6_socket(dev_net(dev)) &&
141 !(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
141 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr, 142 ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
142 &ipv6_hdr(skb)->saddr))) { 143 &ipv6_hdr(skb)->saddr))) {
143 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC); 144 struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index d1008e6891e7..02163dbf84c3 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -49,9 +49,6 @@
49#include <net/addrconf.h> 49#include <net/addrconf.h>
50#include <linux/netfilter_ipv6.h> 50#include <linux/netfilter_ipv6.h>
51 51
52struct sock *mroute6_socket;
53
54
55/* Big lock, protecting vif table, mrt cache and mroute socket state. 52/* Big lock, protecting vif table, mrt cache and mroute socket state.
56 Note that the changes are semaphored via rtnl_lock. 53 Note that the changes are semaphored via rtnl_lock.
57 */ 54 */
@@ -820,7 +817,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
820 skb_pull(skb, sizeof(struct ipv6hdr)); 817 skb_pull(skb, sizeof(struct ipv6hdr));
821 } 818 }
822 819
823 if (mroute6_socket == NULL) { 820 if (init_net.ipv6.mroute6_sk == NULL) {
824 kfree_skb(skb); 821 kfree_skb(skb);
825 return -EINVAL; 822 return -EINVAL;
826 } 823 }
@@ -828,7 +825,8 @@ static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert)
828 /* 825 /*
829 * Deliver to user space multicast routing algorithms 826 * Deliver to user space multicast routing algorithms
830 */ 827 */
831 if ((ret = sock_queue_rcv_skb(mroute6_socket, skb)) < 0) { 828 ret = sock_queue_rcv_skb(init_net.ipv6.mroute6_sk, skb);
829 if (ret < 0) {
832 if (net_ratelimit()) 830 if (net_ratelimit())
833 printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n"); 831 printk(KERN_WARNING "mroute6: pending queue full, dropping entries.\n");
834 kfree_skb(skb); 832 kfree_skb(skb);
@@ -1145,8 +1143,8 @@ static int ip6mr_sk_init(struct sock *sk)
1145 1143
1146 rtnl_lock(); 1144 rtnl_lock();
1147 write_lock_bh(&mrt_lock); 1145 write_lock_bh(&mrt_lock);
1148 if (likely(mroute6_socket == NULL)) 1146 if (likely(init_net.ipv6.mroute6_sk == NULL))
1149 mroute6_socket = sk; 1147 init_net.ipv6.mroute6_sk = sk;
1150 else 1148 else
1151 err = -EADDRINUSE; 1149 err = -EADDRINUSE;
1152 write_unlock_bh(&mrt_lock); 1150 write_unlock_bh(&mrt_lock);
@@ -1161,9 +1159,9 @@ int ip6mr_sk_done(struct sock *sk)
1161 int err = 0; 1159 int err = 0;
1162 1160
1163 rtnl_lock(); 1161 rtnl_lock();
1164 if (sk == mroute6_socket) { 1162 if (sk == init_net.ipv6.mroute6_sk) {
1165 write_lock_bh(&mrt_lock); 1163 write_lock_bh(&mrt_lock);
1166 mroute6_socket = NULL; 1164 init_net.ipv6.mroute6_sk = NULL;
1167 write_unlock_bh(&mrt_lock); 1165 write_unlock_bh(&mrt_lock);
1168 1166
1169 mroute_clean_tables(sk); 1167 mroute_clean_tables(sk);
@@ -1189,7 +1187,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
1189 mifi_t mifi; 1187 mifi_t mifi;
1190 1188
1191 if (optname != MRT6_INIT) { 1189 if (optname != MRT6_INIT) {
1192 if (sk != mroute6_socket && !capable(CAP_NET_ADMIN)) 1190 if (sk != init_net.ipv6.mroute6_sk && !capable(CAP_NET_ADMIN))
1193 return -EACCES; 1191 return -EACCES;
1194 } 1192 }
1195 1193
@@ -1214,7 +1212,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
1214 if (vif.mif6c_mifi >= MAXMIFS) 1212 if (vif.mif6c_mifi >= MAXMIFS)
1215 return -ENFILE; 1213 return -ENFILE;
1216 rtnl_lock(); 1214 rtnl_lock();
1217 ret = mif6_add(&vif, sk == mroute6_socket); 1215 ret = mif6_add(&vif, sk == init_net.ipv6.mroute6_sk);
1218 rtnl_unlock(); 1216 rtnl_unlock();
1219 return ret; 1217 return ret;
1220 1218
@@ -1242,7 +1240,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int
1242 if (optname == MRT6_DEL_MFC) 1240 if (optname == MRT6_DEL_MFC)
1243 ret = ip6mr_mfc_delete(&mfc); 1241 ret = ip6mr_mfc_delete(&mfc);
1244 else 1242 else
1245 ret = ip6mr_mfc_add(&mfc, sk == mroute6_socket); 1243 ret = ip6mr_mfc_add(&mfc, sk == init_net.ipv6.mroute6_sk);
1246 rtnl_unlock(); 1244 rtnl_unlock();
1247 return ret; 1245 return ret;
1248 1246