aboutsummaryrefslogtreecommitdiffstats
path: root/net/x25/af_x25.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r--net/x25/af_x25.c173
1 files changed, 171 insertions, 2 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 72b6ff3299ba..282ce4e40d7b 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
59int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20; 62int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
60int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; 63int sysctl_x25_call_request_timeout = X25_DEFAULT_T21;
@@ -69,6 +72,14 @@ static const struct proto_ops x25_proto_ops;
69 72
70static struct x25_address null_x25_address = {" "}; 73static struct x25_address null_x25_address = {" "};
71 74
75#ifdef CONFIG_COMPAT
76struct 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
72int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, 83int 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{
@@ -514,6 +525,13 @@ static int x25_create(struct socket *sock, int protocol)
514 x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; 525 x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
515 x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; 526 x25->facilities.throughput = X25_DEFAULT_THROUGHPUT;
516 x25->facilities.reverse = X25_DEFAULT_REVERSE; 527 x25->facilities.reverse = X25_DEFAULT_REVERSE;
528 x25->dte_facilities.calling_len = 0;
529 x25->dte_facilities.called_len = 0;
530 memset(x25->dte_facilities.called_ae, '\0',
531 sizeof(x25->dte_facilities.called_ae));
532 memset(x25->dte_facilities.calling_ae, '\0',
533 sizeof(x25->dte_facilities.calling_ae));
534
517 rc = 0; 535 rc = 0;
518out: 536out:
519 return rc; 537 return rc;
@@ -550,6 +568,7 @@ static struct sock *x25_make_new(struct sock *osk)
550 x25->t2 = ox25->t2; 568 x25->t2 = ox25->t2;
551 x25->facilities = ox25->facilities; 569 x25->facilities = ox25->facilities;
552 x25->qbitincl = ox25->qbitincl; 570 x25->qbitincl = ox25->qbitincl;
571 x25->dte_facilities = ox25->dte_facilities;
553 x25->cudmatchlength = ox25->cudmatchlength; 572 x25->cudmatchlength = ox25->cudmatchlength;
554 x25->accptapprv = ox25->accptapprv; 573 x25->accptapprv = ox25->accptapprv;
555 574
@@ -733,7 +752,7 @@ out:
733 return rc; 752 return rc;
734} 753}
735 754
736static int x25_wait_for_data(struct sock *sk, int timeout) 755static int x25_wait_for_data(struct sock *sk, long timeout)
737{ 756{
738 DECLARE_WAITQUEUE(wait, current); 757 DECLARE_WAITQUEUE(wait, current);
739 int rc = 0; 758 int rc = 0;
@@ -829,6 +848,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
829 struct x25_sock *makex25; 848 struct x25_sock *makex25;
830 struct x25_address source_addr, dest_addr; 849 struct x25_address source_addr, dest_addr;
831 struct x25_facilities facilities; 850 struct x25_facilities facilities;
851 struct x25_dte_facilities dte_facilities;
832 int len, rc; 852 int len, rc;
833 853
834 /* 854 /*
@@ -865,7 +885,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
865 /* 885 /*
866 * Try to reach a compromise on the requested facilities. 886 * Try to reach a compromise on the requested facilities.
867 */ 887 */
868 if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) 888 len = x25_negotiate_facilities(skb, sk, &facilities, &dte_facilities);
889 if (len == -1)
869 goto out_sock_put; 890 goto out_sock_put;
870 891
871 /* 892 /*
@@ -896,9 +917,12 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
896 makex25->source_addr = source_addr; 917 makex25->source_addr = source_addr;
897 makex25->neighbour = nb; 918 makex25->neighbour = nb;
898 makex25->facilities = facilities; 919 makex25->facilities = facilities;
920 makex25->dte_facilities= dte_facilities;
899 makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; 921 makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
900 /* ensure no reverse facil on accept */ 922 /* ensure no reverse facil on accept */
901 makex25->vc_facil_mask &= ~X25_MASK_REVERSE; 923 makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
924 /* ensure no calling address extension on accept */
925 makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;
902 makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; 926 makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
903 927
904 /* Normally all calls are accepted immediatly */ 928 /* Normally all calls are accepted immediatly */
@@ -1305,6 +1329,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1305 break; 1329 break;
1306 } 1330 }
1307 1331
1332 case SIOCX25GDTEFACILITIES: {
1333 rc = copy_to_user(argp, &x25->dte_facilities,
1334 sizeof(x25->dte_facilities));
1335 if (rc)
1336 rc = -EFAULT;
1337 break;
1338 }
1339
1340 case SIOCX25SDTEFACILITIES: {
1341 struct x25_dte_facilities dtefacs;
1342 rc = -EFAULT;
1343 if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
1344 break;
1345 rc = -EINVAL;
1346 if (sk->sk_state != TCP_LISTEN &&
1347 sk->sk_state != TCP_CLOSE)
1348 break;
1349 if (dtefacs.calling_len > X25_MAX_AE_LEN)
1350 break;
1351 if (dtefacs.calling_ae == NULL)
1352 break;
1353 if (dtefacs.called_len > X25_MAX_AE_LEN)
1354 break;
1355 if (dtefacs.called_ae == NULL)
1356 break;
1357 x25->dte_facilities = dtefacs;
1358 rc = 0;
1359 break;
1360 }
1361
1308 case SIOCX25GCALLUSERDATA: { 1362 case SIOCX25GCALLUSERDATA: {
1309 struct x25_calluserdata cud = x25->calluserdata; 1363 struct x25_calluserdata cud = x25->calluserdata;
1310 rc = copy_to_user(argp, &cud, 1364 rc = copy_to_user(argp, &cud,
@@ -1387,6 +1441,118 @@ static struct net_proto_family x25_family_ops = {
1387 .owner = THIS_MODULE, 1441 .owner = THIS_MODULE,
1388}; 1442};
1389 1443
1444#ifdef CONFIG_COMPAT
1445static int compat_x25_subscr_ioctl(unsigned int cmd,
1446 struct compat_x25_subscrip_struct __user *x25_subscr32)
1447{
1448 struct compat_x25_subscrip_struct x25_subscr;
1449 struct x25_neigh *nb;
1450 struct net_device *dev;
1451 int rc = -EINVAL;
1452
1453 rc = -EFAULT;
1454 if (copy_from_user(&x25_subscr, x25_subscr32, sizeof(*x25_subscr32)))
1455 goto out;
1456
1457 rc = -EINVAL;
1458 dev = x25_dev_get(x25_subscr.device);
1459 if (dev == NULL)
1460 goto out;
1461
1462 nb = x25_get_neigh(dev);
1463 if (nb == NULL)
1464 goto out_dev_put;
1465
1466 dev_put(dev);
1467
1468 if (cmd == SIOCX25GSUBSCRIP) {
1469 x25_subscr.extended = nb->extended;
1470 x25_subscr.global_facil_mask = nb->global_facil_mask;
1471 rc = copy_to_user(x25_subscr32, &x25_subscr,
1472 sizeof(*x25_subscr32)) ? -EFAULT : 0;
1473 } else {
1474 rc = -EINVAL;
1475 if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
1476 rc = 0;
1477 nb->extended = x25_subscr.extended;
1478 nb->global_facil_mask = x25_subscr.global_facil_mask;
1479 }
1480 }
1481 x25_neigh_put(nb);
1482out:
1483 return rc;
1484out_dev_put:
1485 dev_put(dev);
1486 goto out;
1487}
1488
1489static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
1490 unsigned long arg)
1491{
1492 void __user *argp = compat_ptr(arg);
1493 struct sock *sk = sock->sk;
1494
1495 int rc = -ENOIOCTLCMD;
1496
1497 switch(cmd) {
1498 case TIOCOUTQ:
1499 case TIOCINQ:
1500 rc = x25_ioctl(sock, cmd, (unsigned long)argp);
1501 break;
1502 case SIOCGSTAMP:
1503 rc = -EINVAL;
1504 if (sk)
1505 rc = compat_sock_get_timestamp(sk,
1506 (struct timeval __user*)argp);
1507 break;
1508 case SIOCGIFADDR:
1509 case SIOCSIFADDR:
1510 case SIOCGIFDSTADDR:
1511 case SIOCSIFDSTADDR:
1512 case SIOCGIFBRDADDR:
1513 case SIOCSIFBRDADDR:
1514 case SIOCGIFNETMASK:
1515 case SIOCSIFNETMASK:
1516 case SIOCGIFMETRIC:
1517 case SIOCSIFMETRIC:
1518 rc = -EINVAL;
1519 break;
1520 case SIOCADDRT:
1521 case SIOCDELRT:
1522 rc = -EPERM;
1523 if (!capable(CAP_NET_ADMIN))
1524 break;
1525 rc = x25_route_ioctl(cmd, argp);
1526 break;
1527 case SIOCX25GSUBSCRIP:
1528 rc = compat_x25_subscr_ioctl(cmd, argp);
1529 break;
1530 case SIOCX25SSUBSCRIP:
1531 rc = -EPERM;
1532 if (!capable(CAP_NET_ADMIN))
1533 break;
1534 rc = compat_x25_subscr_ioctl(cmd, argp);
1535 break;
1536 case SIOCX25GFACILITIES:
1537 case SIOCX25SFACILITIES:
1538 case SIOCX25GDTEFACILITIES:
1539 case SIOCX25SDTEFACILITIES:
1540 case SIOCX25GCALLUSERDATA:
1541 case SIOCX25SCALLUSERDATA:
1542 case SIOCX25GCAUSEDIAG:
1543 case SIOCX25SCUDMATCHLEN:
1544 case SIOCX25CALLACCPTAPPRV:
1545 case SIOCX25SENDCALLACCPT:
1546 rc = x25_ioctl(sock, cmd, (unsigned long)argp);
1547 break;
1548 default:
1549 rc = -ENOIOCTLCMD;
1550 break;
1551 }
1552 return rc;
1553}
1554#endif
1555
1390static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { 1556static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
1391 .family = AF_X25, 1557 .family = AF_X25,
1392 .owner = THIS_MODULE, 1558 .owner = THIS_MODULE,
@@ -1398,6 +1564,9 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
1398 .getname = x25_getname, 1564 .getname = x25_getname,
1399 .poll = datagram_poll, 1565 .poll = datagram_poll,
1400 .ioctl = x25_ioctl, 1566 .ioctl = x25_ioctl,
1567#ifdef CONFIG_COMPAT
1568 .compat_ioctl = compat_x25_ioctl,
1569#endif
1401 .listen = x25_listen, 1570 .listen = x25_listen,
1402 .shutdown = sock_no_shutdown, 1571 .shutdown = sock_no_shutdown,
1403 .setsockopt = x25_setsockopt, 1572 .setsockopt = x25_setsockopt,