.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * DDP: An implementation of the AppleTalk DDP protocol for |
---|
3 | 4 | * Ethernet 'ELAP'. |
---|
.. | .. |
---|
43 | 44 | * shared skb support 8) |
---|
44 | 45 | * Arnaldo C. de Melo : Move proc stuff to atalk_proc.c, |
---|
45 | 46 | * use seq_file |
---|
46 | | - * |
---|
47 | | - * This program is free software; you can redistribute it and/or |
---|
48 | | - * modify it under the terms of the GNU General Public License |
---|
49 | | - * as published by the Free Software Foundation; either version |
---|
50 | | - * 2 of the License, or (at your option) any later version. |
---|
51 | | - * |
---|
52 | 47 | */ |
---|
53 | 48 | |
---|
54 | 49 | #include <linux/capability.h> |
---|
.. | .. |
---|
62 | 57 | #include <net/sock.h> |
---|
63 | 58 | #include <net/tcp_states.h> |
---|
64 | 59 | #include <net/route.h> |
---|
| 60 | +#include <net/compat.h> |
---|
65 | 61 | #include <linux/atalk.h> |
---|
66 | 62 | #include <linux/highmem.h> |
---|
67 | 63 | |
---|
.. | .. |
---|
872 | 868 | return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0; |
---|
873 | 869 | } |
---|
874 | 870 | |
---|
| 871 | +static int atrtr_ioctl_addrt(struct rtentry *rt) |
---|
| 872 | +{ |
---|
| 873 | + struct net_device *dev = NULL; |
---|
| 874 | + |
---|
| 875 | + if (rt->rt_dev) { |
---|
| 876 | + char name[IFNAMSIZ]; |
---|
| 877 | + |
---|
| 878 | + if (copy_from_user(name, rt->rt_dev, IFNAMSIZ-1)) |
---|
| 879 | + return -EFAULT; |
---|
| 880 | + name[IFNAMSIZ-1] = '\0'; |
---|
| 881 | + |
---|
| 882 | + dev = __dev_get_by_name(&init_net, name); |
---|
| 883 | + if (!dev) |
---|
| 884 | + return -ENODEV; |
---|
| 885 | + } |
---|
| 886 | + return atrtr_create(rt, dev); |
---|
| 887 | +} |
---|
| 888 | + |
---|
875 | 889 | /* Routing ioctl() calls */ |
---|
876 | 890 | static int atrtr_ioctl(unsigned int cmd, void __user *arg) |
---|
877 | 891 | { |
---|
.. | .. |
---|
887 | 901 | return atrtr_delete(&((struct sockaddr_at *) |
---|
888 | 902 | &rt.rt_dst)->sat_addr); |
---|
889 | 903 | |
---|
890 | | - case SIOCADDRT: { |
---|
891 | | - struct net_device *dev = NULL; |
---|
892 | | - if (rt.rt_dev) { |
---|
893 | | - char name[IFNAMSIZ]; |
---|
894 | | - if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1)) |
---|
895 | | - return -EFAULT; |
---|
896 | | - name[IFNAMSIZ-1] = '\0'; |
---|
897 | | - dev = __dev_get_by_name(&init_net, name); |
---|
898 | | - if (!dev) |
---|
899 | | - return -ENODEV; |
---|
900 | | - } |
---|
901 | | - return atrtr_create(&rt, dev); |
---|
902 | | - } |
---|
| 904 | + case SIOCADDRT: |
---|
| 905 | + return atrtr_ioctl_addrt(&rt); |
---|
903 | 906 | } |
---|
904 | 907 | return -EINVAL; |
---|
905 | 908 | } |
---|
.. | .. |
---|
958 | 961 | if (copy > len) |
---|
959 | 962 | copy = len; |
---|
960 | 963 | vaddr = kmap_atomic(skb_frag_page(frag)); |
---|
961 | | - sum = atalk_sum_partial(vaddr + frag->page_offset + |
---|
962 | | - offset - start, copy, sum); |
---|
| 964 | + sum = atalk_sum_partial(vaddr + skb_frag_off(frag) + |
---|
| 965 | + offset - start, copy, sum); |
---|
963 | 966 | kunmap_atomic(vaddr); |
---|
964 | 967 | |
---|
965 | 968 | if (!(len -= copy)) |
---|
.. | .. |
---|
1820 | 1823 | rc = put_user(amount, (int __user *)argp); |
---|
1821 | 1824 | break; |
---|
1822 | 1825 | } |
---|
1823 | | - case SIOCGSTAMP: |
---|
1824 | | - rc = sock_get_timestamp(sk, argp); |
---|
1825 | | - break; |
---|
1826 | | - case SIOCGSTAMPNS: |
---|
1827 | | - rc = sock_get_timestampns(sk, argp); |
---|
1828 | | - break; |
---|
1829 | 1826 | /* Routing */ |
---|
1830 | 1827 | case SIOCADDRT: |
---|
1831 | 1828 | case SIOCDELRT: |
---|
.. | .. |
---|
1852 | 1849 | |
---|
1853 | 1850 | |
---|
1854 | 1851 | #ifdef CONFIG_COMPAT |
---|
| 1852 | +static int atalk_compat_routing_ioctl(struct sock *sk, unsigned int cmd, |
---|
| 1853 | + struct compat_rtentry __user *ur) |
---|
| 1854 | +{ |
---|
| 1855 | + compat_uptr_t rtdev; |
---|
| 1856 | + struct rtentry rt; |
---|
| 1857 | + |
---|
| 1858 | + if (copy_from_user(&rt.rt_dst, &ur->rt_dst, |
---|
| 1859 | + 3 * sizeof(struct sockaddr)) || |
---|
| 1860 | + get_user(rt.rt_flags, &ur->rt_flags) || |
---|
| 1861 | + get_user(rt.rt_metric, &ur->rt_metric) || |
---|
| 1862 | + get_user(rt.rt_mtu, &ur->rt_mtu) || |
---|
| 1863 | + get_user(rt.rt_window, &ur->rt_window) || |
---|
| 1864 | + get_user(rt.rt_irtt, &ur->rt_irtt) || |
---|
| 1865 | + get_user(rtdev, &ur->rt_dev)) |
---|
| 1866 | + return -EFAULT; |
---|
| 1867 | + |
---|
| 1868 | + switch (cmd) { |
---|
| 1869 | + case SIOCDELRT: |
---|
| 1870 | + if (rt.rt_dst.sa_family != AF_APPLETALK) |
---|
| 1871 | + return -EINVAL; |
---|
| 1872 | + return atrtr_delete(&((struct sockaddr_at *) |
---|
| 1873 | + &rt.rt_dst)->sat_addr); |
---|
| 1874 | + |
---|
| 1875 | + case SIOCADDRT: |
---|
| 1876 | + rt.rt_dev = compat_ptr(rtdev); |
---|
| 1877 | + return atrtr_ioctl_addrt(&rt); |
---|
| 1878 | + default: |
---|
| 1879 | + return -EINVAL; |
---|
| 1880 | + } |
---|
| 1881 | +} |
---|
1855 | 1882 | static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
---|
1856 | 1883 | { |
---|
| 1884 | + void __user *argp = compat_ptr(arg); |
---|
| 1885 | + struct sock *sk = sock->sk; |
---|
| 1886 | + |
---|
| 1887 | + switch (cmd) { |
---|
| 1888 | + case SIOCADDRT: |
---|
| 1889 | + case SIOCDELRT: |
---|
| 1890 | + return atalk_compat_routing_ioctl(sk, cmd, argp); |
---|
1857 | 1891 | /* |
---|
1858 | 1892 | * SIOCATALKDIFADDR is a SIOCPROTOPRIVATE ioctl number, so we |
---|
1859 | 1893 | * cannot handle it in common code. The data we access if ifreq |
---|
1860 | 1894 | * here is compatible, so we can simply call the native |
---|
1861 | 1895 | * handler. |
---|
1862 | 1896 | */ |
---|
1863 | | - if (cmd == SIOCATALKDIFADDR) |
---|
1864 | | - return atalk_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); |
---|
1865 | | - |
---|
1866 | | - return -ENOIOCTLCMD; |
---|
| 1897 | + case SIOCATALKDIFADDR: |
---|
| 1898 | + return atalk_ioctl(sock, cmd, (unsigned long)argp); |
---|
| 1899 | + default: |
---|
| 1900 | + return -ENOIOCTLCMD; |
---|
| 1901 | + } |
---|
1867 | 1902 | } |
---|
1868 | | -#endif |
---|
| 1903 | +#endif /* CONFIG_COMPAT */ |
---|
1869 | 1904 | |
---|
1870 | 1905 | |
---|
1871 | 1906 | static const struct net_proto_family atalk_family_ops = { |
---|
.. | .. |
---|
1885 | 1920 | .getname = atalk_getname, |
---|
1886 | 1921 | .poll = datagram_poll, |
---|
1887 | 1922 | .ioctl = atalk_ioctl, |
---|
| 1923 | + .gettstamp = sock_gettstamp, |
---|
1888 | 1924 | #ifdef CONFIG_COMPAT |
---|
1889 | 1925 | .compat_ioctl = atalk_compat_ioctl, |
---|
1890 | 1926 | #endif |
---|
1891 | 1927 | .listen = sock_no_listen, |
---|
1892 | 1928 | .shutdown = sock_no_shutdown, |
---|
1893 | | - .setsockopt = sock_no_setsockopt, |
---|
1894 | | - .getsockopt = sock_no_getsockopt, |
---|
1895 | 1929 | .sendmsg = atalk_sendmsg, |
---|
1896 | 1930 | .recvmsg = atalk_recvmsg, |
---|
1897 | 1931 | .mmap = sock_no_mmap, |
---|