Commit e2d57766e6744f2956975dd2086d82957187b0f6

Authored by David S. Miller
1 parent ca6b8bb097

net: Provide compat support for SIOCGETMIFCNT_IN6 and SIOCGETSGCNT_IN6.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 3 changed files with 95 additions and 0 deletions Side-by-side Diff

include/linux/mroute6.h
... ... @@ -136,6 +136,7 @@
136 136 extern int ip6_mroute_getsockopt(struct sock *, int, char __user *, int __user *);
137 137 extern int ip6_mr_input(struct sk_buff *skb);
138 138 extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
  139 +extern int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
139 140 extern int ip6_mr_init(void);
140 141 extern void ip6_mr_cleanup(void);
141 142 #else
... ... @@ -34,6 +34,7 @@
34 34 #include <linux/seq_file.h>
35 35 #include <linux/init.h>
36 36 #include <linux/slab.h>
  37 +#include <linux/compat.h>
37 38 #include <net/protocol.h>
38 39 #include <linux/skbuff.h>
39 40 #include <net/sock.h>
... ... @@ -1804,6 +1805,80 @@
1804 1805 }
1805 1806 }
1806 1807  
  1808 +#ifdef CONFIG_COMPAT
  1809 +struct 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 +
  1817 +struct 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 +
  1825 +int 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  
1808 1883 static inline int ip6mr_forward2_finish(struct sk_buff *skb)
1809 1884 {
... ... @@ -31,6 +31,7 @@
31 31 #include <linux/netfilter.h>
32 32 #include <linux/netfilter_ipv6.h>
33 33 #include <linux/skbuff.h>
  34 +#include <linux/compat.h>
34 35 #include <asm/uaccess.h>
35 36 #include <asm/ioctls.h>
36 37  
... ... @@ -1157,6 +1158,23 @@
1157 1158 }
1158 1159 }
1159 1160  
  1161 +#ifdef CONFIG_COMPAT
  1162 +static 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 +
1160 1178 static void rawv6_close(struct sock *sk, long timeout)
1161 1179 {
1162 1180 if (inet_sk(sk)->inet_num == IPPROTO_RAW)
... ... @@ -1215,6 +1233,7 @@
1215 1233 #ifdef CONFIG_COMPAT
1216 1234 .compat_setsockopt = compat_rawv6_setsockopt,
1217 1235 .compat_getsockopt = compat_rawv6_getsockopt,
  1236 + .compat_ioctl = compat_rawv6_ioctl,
1218 1237 #endif
1219 1238 };
1220 1239