Commit e2d57766e6744f2956975dd2086d82957187b0f6
1 parent
ca6b8bb097
Exists in
master
and in
4 other branches
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 |
net/ipv6/ip6mr.c
... | ... | @@ -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 | { |
net/ipv6/raw.c
... | ... | @@ -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 |