aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6mr.c75
-rw-r--r--net/ipv6/raw.c19
-rw-r--r--net/ipv6/route.c11
-rw-r--r--net/ipv6/sysctl_net_ipv6.c9
4 files changed, 109 insertions, 5 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 9fab274019c0..0e1d53bcf1e0 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -34,6 +34,7 @@
34#include <linux/seq_file.h> 34#include <linux/seq_file.h>
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/slab.h> 36#include <linux/slab.h>
37#include <linux/compat.h>
37#include <net/protocol.h> 38#include <net/protocol.h>
38#include <linux/skbuff.h> 39#include <linux/skbuff.h>
39#include <net/sock.h> 40#include <net/sock.h>
@@ -1804,6 +1805,80 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
1804 } 1805 }
1805} 1806}
1806 1807
1808#ifdef CONFIG_COMPAT
1809struct compat_sioc_sg_req6 {
1810 struct sockaddr_in6 src;
1811 struct sockaddr_in6 grp;
1812 compat_ulong_t pktcnt;
1813 compat_ulong_t bytecnt;
1814 compat_ulong_t wrong_if;
1815};
1816
1817struct compat_sioc_mif_req6 {
1818 mifi_t mifi;
1819 compat_ulong_t icount;
1820 compat_ulong_t ocount;
1821 compat_ulong_t ibytes;
1822 compat_ulong_t obytes;
1823};
1824
1825int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
1826{
1827 struct compat_sioc_sg_req6 sr;
1828 struct compat_sioc_mif_req6 vr;
1829 struct mif_device *vif;
1830 struct mfc6_cache *c;
1831 struct net *net = sock_net(sk);
1832 struct mr6_table *mrt;
1833
1834 mrt = ip6mr_get_table(net, raw6_sk(sk)->ip6mr_table ? : RT6_TABLE_DFLT);
1835 if (mrt == NULL)
1836 return -ENOENT;
1837
1838 switch (cmd) {
1839 case SIOCGETMIFCNT_IN6:
1840 if (copy_from_user(&vr, arg, sizeof(vr)))
1841 return -EFAULT;
1842 if (vr.mifi >= mrt->maxvif)
1843 return -EINVAL;
1844 read_lock(&mrt_lock);
1845 vif = &mrt->vif6_table[vr.mifi];
1846 if (MIF_EXISTS(mrt, vr.mifi)) {
1847 vr.icount = vif->pkt_in;
1848 vr.ocount = vif->pkt_out;
1849 vr.ibytes = vif->bytes_in;
1850 vr.obytes = vif->bytes_out;
1851 read_unlock(&mrt_lock);
1852
1853 if (copy_to_user(arg, &vr, sizeof(vr)))
1854 return -EFAULT;
1855 return 0;
1856 }
1857 read_unlock(&mrt_lock);
1858 return -EADDRNOTAVAIL;
1859 case SIOCGETSGCNT_IN6:
1860 if (copy_from_user(&sr, arg, sizeof(sr)))
1861 return -EFAULT;
1862
1863 read_lock(&mrt_lock);
1864 c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
1865 if (c) {
1866 sr.pktcnt = c->mfc_un.res.pkt;
1867 sr.bytecnt = c->mfc_un.res.bytes;
1868 sr.wrong_if = c->mfc_un.res.wrong_if;
1869 read_unlock(&mrt_lock);
1870
1871 if (copy_to_user(arg, &sr, sizeof(sr)))
1872 return -EFAULT;
1873 return 0;
1874 }
1875 read_unlock(&mrt_lock);
1876 return -EADDRNOTAVAIL;
1877 default:
1878 return -ENOIOCTLCMD;
1879 }
1880}
1881#endif
1807 1882
1808static inline int ip6mr_forward2_finish(struct sk_buff *skb) 1883static inline int ip6mr_forward2_finish(struct sk_buff *skb)
1809{ 1884{
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 86c39526ba5e..c5b0915d106b 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -31,6 +31,7 @@
31#include <linux/netfilter.h> 31#include <linux/netfilter.h>
32#include <linux/netfilter_ipv6.h> 32#include <linux/netfilter_ipv6.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <linux/compat.h>
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
35#include <asm/ioctls.h> 36#include <asm/ioctls.h>
36 37
@@ -1157,6 +1158,23 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
1157 } 1158 }
1158} 1159}
1159 1160
1161#ifdef CONFIG_COMPAT
1162static int compat_rawv6_ioctl(struct sock *sk, unsigned int cmd, unsigned long arg)
1163{
1164 switch (cmd) {
1165 case SIOCOUTQ:
1166 case SIOCINQ:
1167 return -ENOIOCTLCMD;
1168 default:
1169#ifdef CONFIG_IPV6_MROUTE
1170 return ip6mr_compat_ioctl(sk, cmd, compat_ptr(arg));
1171#else
1172 return -ENOIOCTLCMD;
1173#endif
1174 }
1175}
1176#endif
1177
1160static void rawv6_close(struct sock *sk, long timeout) 1178static void rawv6_close(struct sock *sk, long timeout)
1161{ 1179{
1162 if (inet_sk(sk)->inet_num == IPPROTO_RAW) 1180 if (inet_sk(sk)->inet_num == IPPROTO_RAW)
@@ -1215,6 +1233,7 @@ struct proto rawv6_prot = {
1215#ifdef CONFIG_COMPAT 1233#ifdef CONFIG_COMPAT
1216 .compat_setsockopt = compat_rawv6_setsockopt, 1234 .compat_setsockopt = compat_rawv6_setsockopt,
1217 .compat_getsockopt = compat_rawv6_getsockopt, 1235 .compat_getsockopt = compat_rawv6_getsockopt,
1236 .compat_ioctl = compat_rawv6_ioctl,
1218#endif 1237#endif
1219}; 1238};
1220 1239
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1534508f6c68..a998db6e7895 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -113,6 +113,11 @@ static struct dst_ops ip6_dst_ops_template = {
113 .local_out = __ip6_local_out, 113 .local_out = __ip6_local_out,
114}; 114};
115 115
116static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
117{
118 return 0;
119}
120
116static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) 121static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
117{ 122{
118} 123}
@@ -122,6 +127,8 @@ static struct dst_ops ip6_dst_blackhole_ops = {
122 .protocol = cpu_to_be16(ETH_P_IPV6), 127 .protocol = cpu_to_be16(ETH_P_IPV6),
123 .destroy = ip6_dst_destroy, 128 .destroy = ip6_dst_destroy,
124 .check = ip6_dst_check, 129 .check = ip6_dst_check,
130 .default_mtu = ip6_blackhole_default_mtu,
131 .default_advmss = ip6_default_advmss,
125 .update_pmtu = ip6_rt_blackhole_update_pmtu, 132 .update_pmtu = ip6_rt_blackhole_update_pmtu,
126}; 133};
127 134
@@ -194,7 +201,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
194 in6_dev_put(idev); 201 in6_dev_put(idev);
195 } 202 }
196 if (peer) { 203 if (peer) {
197 BUG_ON(!(rt->rt6i_flags & RTF_CACHE));
198 rt->rt6i_peer = NULL; 204 rt->rt6i_peer = NULL;
199 inet_putpeer(peer); 205 inet_putpeer(peer);
200 } 206 }
@@ -204,9 +210,6 @@ void rt6_bind_peer(struct rt6_info *rt, int create)
204{ 210{
205 struct inet_peer *peer; 211 struct inet_peer *peer;
206 212
207 if (WARN_ON(!(rt->rt6i_flags & RTF_CACHE)))
208 return;
209
210 peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create); 213 peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create);
211 if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL) 214 if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL)
212 inet_putpeer(peer); 215 inet_putpeer(peer);
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index fa1d8f4e0051..7cb65ef79f9c 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -15,6 +15,8 @@
15#include <net/addrconf.h> 15#include <net/addrconf.h>
16#include <net/inet_frag.h> 16#include <net/inet_frag.h>
17 17
18static struct ctl_table empty[1];
19
18static ctl_table ipv6_table_template[] = { 20static ctl_table ipv6_table_template[] = {
19 { 21 {
20 .procname = "route", 22 .procname = "route",
@@ -35,6 +37,12 @@ static ctl_table ipv6_table_template[] = {
35 .mode = 0644, 37 .mode = 0644,
36 .proc_handler = proc_dointvec 38 .proc_handler = proc_dointvec
37 }, 39 },
40 {
41 .procname = "neigh",
42 .maxlen = 0,
43 .mode = 0555,
44 .child = empty,
45 },
38 { } 46 { }
39}; 47};
40 48
@@ -152,7 +160,6 @@ static struct ctl_table_header *ip6_base;
152 160
153int ipv6_static_sysctl_register(void) 161int ipv6_static_sysctl_register(void)
154{ 162{
155 static struct ctl_table empty[1];
156 ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); 163 ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
157 if (ip6_base == NULL) 164 if (ip6_base == NULL)
158 return -ENOMEM; 165 return -ENOMEM;