diff options
-rw-r--r-- | net/x25/af_x25.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 72b6ff3299ba..a41cc0201760 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -54,7 +54,10 @@ | |||
54 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 54 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
55 | #include <linux/notifier.h> | 55 | #include <linux/notifier.h> |
56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
57 | #include <linux/compat.h> | ||
58 | |||
57 | #include <net/x25.h> | 59 | #include <net/x25.h> |
60 | #include <net/compat.h> | ||
58 | 61 | ||
59 | int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; | 62 | int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; |
60 | int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; | 63 | int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; |
@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops; | |||
69 | 72 | ||
70 | static struct x25_address null_x25_address = {" "}; | 73 | static struct x25_address null_x25_address = {" "}; |
71 | 74 | ||
75 | #ifdef CONFIG_COMPAT | ||
76 | struct compat_x25_subscrip_struct { | ||
77 | char device[200-sizeof(compat_ulong_t)]; | ||
78 | compat_ulong_t global_facil_mask; | ||
79 | compat_uint_t extended; | ||
80 | }; | ||
81 | #endif | ||
82 | |||
72 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 83 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
73 | struct x25_address *calling_addr) | 84 | struct x25_address *calling_addr) |
74 | { | 85 | { |
@@ -1387,6 +1398,116 @@ static struct net_proto_family x25_family_ops = { | |||
1387 | .owner = THIS_MODULE, | 1398 | .owner = THIS_MODULE, |
1388 | }; | 1399 | }; |
1389 | 1400 | ||
1401 | #ifdef CONFIG_COMPAT | ||
1402 | static int compat_x25_subscr_ioctl(unsigned int cmd, | ||
1403 | struct compat_x25_subscrip_struct __user *x25_subscr32) | ||
1404 | { | ||
1405 | struct compat_x25_subscrip_struct x25_subscr; | ||
1406 | struct x25_neigh *nb; | ||
1407 | struct net_device *dev; | ||
1408 | int rc = -EINVAL; | ||
1409 | |||
1410 | rc = -EFAULT; | ||
1411 | if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32))) | ||
1412 | goto out; | ||
1413 | |||
1414 | rc = -EINVAL; | ||
1415 | dev = x25_dev_get(x25_subscr.device); | ||
1416 | if (dev == NULL) | ||
1417 | goto out; | ||
1418 | |||
1419 | nb = x25_get_neigh(dev); | ||
1420 | if (nb == NULL) | ||
1421 | goto out_dev_put; | ||
1422 | |||
1423 | dev_put(dev); | ||
1424 | |||
1425 | if (cmd == SIOCX25GSUBSCRIP) { | ||
1426 | x25_subscr.extended = nb->extended; | ||
1427 | x25_subscr.global_facil_mask = nb->global_facil_mask; | ||
1428 | rc = copy_to_user(x25_subscr32, &x25_subscr, | ||
1429 | sizeof(*x25_subscr32)) ? -EFAULT : 0; | ||
1430 | } else { | ||
1431 | rc = -EINVAL; | ||
1432 | if (x25_subscr.extended == 0 || x25_subscr.extended == 1) { | ||
1433 | rc = 0; | ||
1434 | nb->extended = x25_subscr.extended; | ||
1435 | nb->global_facil_mask = x25_subscr.global_facil_mask; | ||
1436 | } | ||
1437 | } | ||
1438 | x25_neigh_put(nb); | ||
1439 | out: | ||
1440 | return rc; | ||
1441 | out_dev_put: | ||
1442 | dev_put(dev); | ||
1443 | goto out; | ||
1444 | } | ||
1445 | |||
1446 | static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | ||
1447 | unsigned long arg) | ||
1448 | { | ||
1449 | void __user *argp = compat_ptr(arg); | ||
1450 | struct sock *sk = sock->sk; | ||
1451 | |||
1452 | int rc = -ENOIOCTLCMD; | ||
1453 | |||
1454 | switch(cmd) { | ||
1455 | case TIOCOUTQ: | ||
1456 | case TIOCINQ: | ||
1457 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||
1458 | break; | ||
1459 | case SIOCGSTAMP: | ||
1460 | rc = -EINVAL; | ||
1461 | if (sk) | ||
1462 | rc = compat_sock_get_timestamp(sk, | ||
1463 | (struct timeval __user*)argp); | ||
1464 | break; | ||
1465 | case SIOCGIFADDR: | ||
1466 | case SIOCSIFADDR: | ||
1467 | case SIOCGIFDSTADDR: | ||
1468 | case SIOCSIFDSTADDR: | ||
1469 | case SIOCGIFBRDADDR: | ||
1470 | case SIOCSIFBRDADDR: | ||
1471 | case SIOCGIFNETMASK: | ||
1472 | case SIOCSIFNETMASK: | ||
1473 | case SIOCGIFMETRIC: | ||
1474 | case SIOCSIFMETRIC: | ||
1475 | rc = -EINVAL; | ||
1476 | break; | ||
1477 | case SIOCADDRT: | ||
1478 | case SIOCDELRT: | ||
1479 | rc = -EPERM; | ||
1480 | if (!capable(CAP_NET_ADMIN)) | ||
1481 | break; | ||
1482 | rc = x25_route_ioctl(cmd, argp); | ||
1483 | break; | ||
1484 | case SIOCX25GSUBSCRIP: | ||
1485 | rc = compat_x25_subscr_ioctl(cmd, argp); | ||
1486 | break; | ||
1487 | case SIOCX25SSUBSCRIP: | ||
1488 | rc = -EPERM; | ||
1489 | if (!capable(CAP_NET_ADMIN)) | ||
1490 | break; | ||
1491 | rc = compat_x25_subscr_ioctl(cmd, argp); | ||
1492 | break; | ||
1493 | case SIOCX25GFACILITIES: | ||
1494 | case SIOCX25SFACILITIES: | ||
1495 | case SIOCX25GCALLUSERDATA: | ||
1496 | case SIOCX25SCALLUSERDATA: | ||
1497 | case SIOCX25GCAUSEDIAG: | ||
1498 | case SIOCX25SCUDMATCHLEN: | ||
1499 | case SIOCX25CALLACCPTAPPRV: | ||
1500 | case SIOCX25SENDCALLACCPT: | ||
1501 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||
1502 | break; | ||
1503 | default: | ||
1504 | rc = -ENOIOCTLCMD; | ||
1505 | break; | ||
1506 | } | ||
1507 | return rc; | ||
1508 | } | ||
1509 | #endif | ||
1510 | |||
1390 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | 1511 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { |
1391 | .family = AF_X25, | 1512 | .family = AF_X25, |
1392 | .owner = THIS_MODULE, | 1513 | .owner = THIS_MODULE, |
@@ -1398,6 +1519,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1398 | .getname = x25_getname, | 1519 | .getname = x25_getname, |
1399 | .poll = datagram_poll, | 1520 | .poll = datagram_poll, |
1400 | .ioctl = x25_ioctl, | 1521 | .ioctl = x25_ioctl, |
1522 | #ifdef CONFIG_COMPAT | ||
1523 | .compat_ioctl = compat_x25_ioctl, | ||
1524 | #endif | ||
1401 | .listen = x25_listen, | 1525 | .listen = x25_listen, |
1402 | .shutdown = sock_no_shutdown, | 1526 | .shutdown = sock_no_shutdown, |
1403 | .setsockopt = x25_setsockopt, | 1527 | .setsockopt = x25_setsockopt, |