|
@@ -54,7 +54,10 @@
|
|
|
#include <linux/termios.h> /* For TIOCINQ/OUTQ */
|
|
|
#include <linux/notifier.h>
|
|
|
#include <linux/init.h>
|
|
|
+#include <linux/compat.h>
|
|
|
+
|
|
|
#include <net/x25.h>
|
|
|
+#include <net/compat.h>
|
|
|
|
|
|
int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
|
|
|
int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
|
|
@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops;
|
|
|
|
|
|
static struct x25_address null_x25_address = {" "};
|
|
|
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+struct compat_x25_subscrip_struct {
|
|
|
+ char device[200-sizeof(compat_ulong_t)];
|
|
|
+ compat_ulong_t global_facil_mask;
|
|
|
+ compat_uint_t extended;
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr,
|
|
|
struct x25_address *calling_addr)
|
|
|
{
|
|
@@ -1387,6 +1398,116 @@ static struct net_proto_family x25_family_ops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
};
|
|
|
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+static int compat_x25_subscr_ioctl(unsigned int cmd,
|
|
|
+ struct compat_x25_subscrip_struct __user *x25_subscr32)
|
|
|
+{
|
|
|
+ struct compat_x25_subscrip_struct x25_subscr;
|
|
|
+ struct x25_neigh *nb;
|
|
|
+ struct net_device *dev;
|
|
|
+ int rc = -EINVAL;
|
|
|
+
|
|
|
+ rc = -EFAULT;
|
|
|
+ if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ rc = -EINVAL;
|
|
|
+ dev = x25_dev_get(x25_subscr.device);
|
|
|
+ if (dev == NULL)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ nb = x25_get_neigh(dev);
|
|
|
+ if (nb == NULL)
|
|
|
+ goto out_dev_put;
|
|
|
+
|
|
|
+ dev_put(dev);
|
|
|
+
|
|
|
+ if (cmd == SIOCX25GSUBSCRIP) {
|
|
|
+ x25_subscr.extended = nb->extended;
|
|
|
+ x25_subscr.global_facil_mask = nb->global_facil_mask;
|
|
|
+ rc = copy_to_user(x25_subscr32, &x25_subscr,
|
|
|
+ sizeof(*x25_subscr32)) ? -EFAULT : 0;
|
|
|
+ } else {
|
|
|
+ rc = -EINVAL;
|
|
|
+ if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
|
|
|
+ rc = 0;
|
|
|
+ nb->extended = x25_subscr.extended;
|
|
|
+ nb->global_facil_mask = x25_subscr.global_facil_mask;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ x25_neigh_put(nb);
|
|
|
+out:
|
|
|
+ return rc;
|
|
|
+out_dev_put:
|
|
|
+ dev_put(dev);
|
|
|
+ goto out;
|
|
|
+}
|
|
|
+
|
|
|
+static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
|
|
|
+ unsigned long arg)
|
|
|
+{
|
|
|
+ void __user *argp = compat_ptr(arg);
|
|
|
+ struct sock *sk = sock->sk;
|
|
|
+
|
|
|
+ int rc = -ENOIOCTLCMD;
|
|
|
+
|
|
|
+ switch(cmd) {
|
|
|
+ case TIOCOUTQ:
|
|
|
+ case TIOCINQ:
|
|
|
+ rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
|
|
+ break;
|
|
|
+ case SIOCGSTAMP:
|
|
|
+ rc = -EINVAL;
|
|
|
+ if (sk)
|
|
|
+ rc = compat_sock_get_timestamp(sk,
|
|
|
+ (struct timeval __user*)argp);
|
|
|
+ break;
|
|
|
+ case SIOCGIFADDR:
|
|
|
+ case SIOCSIFADDR:
|
|
|
+ case SIOCGIFDSTADDR:
|
|
|
+ case SIOCSIFDSTADDR:
|
|
|
+ case SIOCGIFBRDADDR:
|
|
|
+ case SIOCSIFBRDADDR:
|
|
|
+ case SIOCGIFNETMASK:
|
|
|
+ case SIOCSIFNETMASK:
|
|
|
+ case SIOCGIFMETRIC:
|
|
|
+ case SIOCSIFMETRIC:
|
|
|
+ rc = -EINVAL;
|
|
|
+ break;
|
|
|
+ case SIOCADDRT:
|
|
|
+ case SIOCDELRT:
|
|
|
+ rc = -EPERM;
|
|
|
+ if (!capable(CAP_NET_ADMIN))
|
|
|
+ break;
|
|
|
+ rc = x25_route_ioctl(cmd, argp);
|
|
|
+ break;
|
|
|
+ case SIOCX25GSUBSCRIP:
|
|
|
+ rc = compat_x25_subscr_ioctl(cmd, argp);
|
|
|
+ break;
|
|
|
+ case SIOCX25SSUBSCRIP:
|
|
|
+ rc = -EPERM;
|
|
|
+ if (!capable(CAP_NET_ADMIN))
|
|
|
+ break;
|
|
|
+ rc = compat_x25_subscr_ioctl(cmd, argp);
|
|
|
+ break;
|
|
|
+ case SIOCX25GFACILITIES:
|
|
|
+ case SIOCX25SFACILITIES:
|
|
|
+ case SIOCX25GCALLUSERDATA:
|
|
|
+ case SIOCX25SCALLUSERDATA:
|
|
|
+ case SIOCX25GCAUSEDIAG:
|
|
|
+ case SIOCX25SCUDMATCHLEN:
|
|
|
+ case SIOCX25CALLACCPTAPPRV:
|
|
|
+ case SIOCX25SENDCALLACCPT:
|
|
|
+ rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ rc = -ENOIOCTLCMD;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
|
|
|
.family = AF_X25,
|
|
|
.owner = THIS_MODULE,
|
|
@@ -1398,6 +1519,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
|
|
|
.getname = x25_getname,
|
|
|
.poll = datagram_poll,
|
|
|
.ioctl = x25_ioctl,
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
+ .compat_ioctl = compat_x25_ioctl,
|
|
|
+#endif
|
|
|
.listen = x25_listen,
|
|
|
.shutdown = sock_no_shutdown,
|
|
|
.setsockopt = x25_setsockopt,
|