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.c471
1 files changed, 234 insertions, 237 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 4680b1e4c79c..d30615419b4d 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -237,21 +237,21 @@ static int x25_device_event(struct notifier_block *this, unsigned long event,
237#endif 237#endif
238 ) { 238 ) {
239 switch (event) { 239 switch (event) {
240 case NETDEV_UP: 240 case NETDEV_UP:
241 x25_link_device_up(dev); 241 x25_link_device_up(dev);
242 break; 242 break;
243 case NETDEV_GOING_DOWN: 243 case NETDEV_GOING_DOWN:
244 nb = x25_get_neigh(dev); 244 nb = x25_get_neigh(dev);
245 if (nb) { 245 if (nb) {
246 x25_terminate_link(nb); 246 x25_terminate_link(nb);
247 x25_neigh_put(nb); 247 x25_neigh_put(nb);
248 } 248 }
249 break; 249 break;
250 case NETDEV_DOWN: 250 case NETDEV_DOWN:
251 x25_kill_by_device(dev); 251 x25_kill_by_device(dev);
252 x25_route_device_down(dev); 252 x25_route_device_down(dev);
253 x25_link_device_down(dev); 253 x25_link_device_down(dev);
254 break; 254 break;
255 } 255 }
256 } 256 }
257 257
@@ -1336,256 +1336,253 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1336 int rc; 1336 int rc;
1337 1337
1338 switch (cmd) { 1338 switch (cmd) {
1339 case TIOCOUTQ: { 1339 case TIOCOUTQ: {
1340 int amount; 1340 int amount;
1341 1341
1342 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); 1342 amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
1343 if (amount < 0) 1343 if (amount < 0)
1344 amount = 0; 1344 amount = 0;
1345 rc = put_user(amount, (unsigned int __user *)argp); 1345 rc = put_user(amount, (unsigned int __user *)argp);
1346 break; 1346 break;
1347 } 1347 }
1348 1348
1349 case TIOCINQ: { 1349 case TIOCINQ: {
1350 struct sk_buff *skb; 1350 struct sk_buff *skb;
1351 int amount = 0; 1351 int amount = 0;
1352 /* 1352 /*
1353 * These two are safe on a single CPU system as 1353 * These two are safe on a single CPU system as
1354 * only user tasks fiddle here 1354 * only user tasks fiddle here
1355 */ 1355 */
1356 lock_sock(sk); 1356 lock_sock(sk);
1357 if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) 1357 if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
1358 amount = skb->len; 1358 amount = skb->len;
1359 release_sock(sk); 1359 release_sock(sk);
1360 rc = put_user(amount, (unsigned int __user *)argp); 1360 rc = put_user(amount, (unsigned int __user *)argp);
1361 break; 1361 break;
1362 } 1362 }
1363 1363
1364 case SIOCGSTAMP: 1364 case SIOCGSTAMP:
1365 rc = -EINVAL; 1365 rc = -EINVAL;
1366 if (sk) 1366 if (sk)
1367 rc = sock_get_timestamp(sk, 1367 rc = sock_get_timestamp(sk,
1368 (struct timeval __user *)argp); 1368 (struct timeval __user *)argp);
1369 break;
1370 case SIOCGSTAMPNS:
1371 rc = -EINVAL;
1372 if (sk)
1373 rc = sock_get_timestampns(sk,
1374 (struct timespec __user *)argp);
1375 break;
1376 case SIOCGIFADDR:
1377 case SIOCSIFADDR:
1378 case SIOCGIFDSTADDR:
1379 case SIOCSIFDSTADDR:
1380 case SIOCGIFBRDADDR:
1381 case SIOCSIFBRDADDR:
1382 case SIOCGIFNETMASK:
1383 case SIOCSIFNETMASK:
1384 case SIOCGIFMETRIC:
1385 case SIOCSIFMETRIC:
1386 rc = -EINVAL;
1387 break;
1388 case SIOCADDRT:
1389 case SIOCDELRT:
1390 rc = -EPERM;
1391 if (!capable(CAP_NET_ADMIN))
1369 break; 1392 break;
1370 case SIOCGSTAMPNS: 1393 rc = x25_route_ioctl(cmd, argp);
1371 rc = -EINVAL; 1394 break;
1372 if (sk) 1395 case SIOCX25GSUBSCRIP:
1373 rc = sock_get_timestampns(sk, 1396 rc = x25_subscr_ioctl(cmd, argp);
1374 (struct timespec __user *)argp); 1397 break;
1375 break; 1398 case SIOCX25SSUBSCRIP:
1376 case SIOCGIFADDR: 1399 rc = -EPERM;
1377 case SIOCSIFADDR: 1400 if (!capable(CAP_NET_ADMIN))
1378 case SIOCGIFDSTADDR:
1379 case SIOCSIFDSTADDR:
1380 case SIOCGIFBRDADDR:
1381 case SIOCSIFBRDADDR:
1382 case SIOCGIFNETMASK:
1383 case SIOCSIFNETMASK:
1384 case SIOCGIFMETRIC:
1385 case SIOCSIFMETRIC:
1386 rc = -EINVAL;
1387 break;
1388 case SIOCADDRT:
1389 case SIOCDELRT:
1390 rc = -EPERM;
1391 if (!capable(CAP_NET_ADMIN))
1392 break;
1393 rc = x25_route_ioctl(cmd, argp);
1394 break;
1395 case SIOCX25GSUBSCRIP:
1396 rc = x25_subscr_ioctl(cmd, argp);
1397 break;
1398 case SIOCX25SSUBSCRIP:
1399 rc = -EPERM;
1400 if (!capable(CAP_NET_ADMIN))
1401 break;
1402 rc = x25_subscr_ioctl(cmd, argp);
1403 break;
1404 case SIOCX25GFACILITIES: {
1405 lock_sock(sk);
1406 rc = copy_to_user(argp, &x25->facilities,
1407 sizeof(x25->facilities))
1408 ? -EFAULT : 0;
1409 release_sock(sk);
1410 break; 1401 break;
1411 } 1402 rc = x25_subscr_ioctl(cmd, argp);
1403 break;
1404 case SIOCX25GFACILITIES: {
1405 lock_sock(sk);
1406 rc = copy_to_user(argp, &x25->facilities,
1407 sizeof(x25->facilities))
1408 ? -EFAULT : 0;
1409 release_sock(sk);
1410 break;
1411 }
1412 1412
1413 case SIOCX25SFACILITIES: { 1413 case SIOCX25SFACILITIES: {
1414 struct x25_facilities facilities; 1414 struct x25_facilities facilities;
1415 rc = -EFAULT; 1415 rc = -EFAULT;
1416 if (copy_from_user(&facilities, argp, 1416 if (copy_from_user(&facilities, argp, sizeof(facilities)))
1417 sizeof(facilities))) 1417 break;
1418 break; 1418 rc = -EINVAL;
1419 rc = -EINVAL; 1419 lock_sock(sk);
1420 lock_sock(sk); 1420 if (sk->sk_state != TCP_LISTEN &&
1421 if (sk->sk_state != TCP_LISTEN && 1421 sk->sk_state != TCP_CLOSE)
1422 sk->sk_state != TCP_CLOSE) 1422 goto out_fac_release;
1423 goto out_fac_release; 1423 if (facilities.pacsize_in < X25_PS16 ||
1424 if (facilities.pacsize_in < X25_PS16 || 1424 facilities.pacsize_in > X25_PS4096)
1425 facilities.pacsize_in > X25_PS4096) 1425 goto out_fac_release;
1426 goto out_fac_release; 1426 if (facilities.pacsize_out < X25_PS16 ||
1427 if (facilities.pacsize_out < X25_PS16 || 1427 facilities.pacsize_out > X25_PS4096)
1428 facilities.pacsize_out > X25_PS4096) 1428 goto out_fac_release;
1429 goto out_fac_release; 1429 if (facilities.winsize_in < 1 ||
1430 if (facilities.winsize_in < 1 || 1430 facilities.winsize_in > 127)
1431 facilities.winsize_in > 127) 1431 goto out_fac_release;
1432 if (facilities.throughput) {
1433 int out = facilities.throughput & 0xf0;
1434 int in = facilities.throughput & 0x0f;
1435 if (!out)
1436 facilities.throughput |=
1437 X25_DEFAULT_THROUGHPUT << 4;
1438 else if (out < 0x30 || out > 0xD0)
1432 goto out_fac_release; 1439 goto out_fac_release;
1433 if (facilities.throughput) { 1440 if (!in)
1434 int out = facilities.throughput & 0xf0; 1441 facilities.throughput |=
1435 int in = facilities.throughput & 0x0f; 1442 X25_DEFAULT_THROUGHPUT;
1436 if (!out) 1443 else if (in < 0x03 || in > 0x0D)
1437 facilities.throughput |=
1438 X25_DEFAULT_THROUGHPUT << 4;
1439 else if (out < 0x30 || out > 0xD0)
1440 goto out_fac_release;
1441 if (!in)
1442 facilities.throughput |=
1443 X25_DEFAULT_THROUGHPUT;
1444 else if (in < 0x03 || in > 0x0D)
1445 goto out_fac_release;
1446 }
1447 if (facilities.reverse &&
1448 (facilities.reverse & 0x81) != 0x81)
1449 goto out_fac_release; 1444 goto out_fac_release;
1450 x25->facilities = facilities;
1451 rc = 0;
1452out_fac_release:
1453 release_sock(sk);
1454 break;
1455 }
1456
1457 case SIOCX25GDTEFACILITIES: {
1458 lock_sock(sk);
1459 rc = copy_to_user(argp, &x25->dte_facilities,
1460 sizeof(x25->dte_facilities));
1461 release_sock(sk);
1462 if (rc)
1463 rc = -EFAULT;
1464 break;
1465 } 1445 }
1446 if (facilities.reverse &&
1447 (facilities.reverse & 0x81) != 0x81)
1448 goto out_fac_release;
1449 x25->facilities = facilities;
1450 rc = 0;
1451out_fac_release:
1452 release_sock(sk);
1453 break;
1454 }
1466 1455
1467 case SIOCX25SDTEFACILITIES: { 1456 case SIOCX25GDTEFACILITIES: {
1468 struct x25_dte_facilities dtefacs; 1457 lock_sock(sk);
1458 rc = copy_to_user(argp, &x25->dte_facilities,
1459 sizeof(x25->dte_facilities));
1460 release_sock(sk);
1461 if (rc)
1469 rc = -EFAULT; 1462 rc = -EFAULT;
1470 if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) 1463 break;
1471 break; 1464 }
1472 rc = -EINVAL;
1473 lock_sock(sk);
1474 if (sk->sk_state != TCP_LISTEN &&
1475 sk->sk_state != TCP_CLOSE)
1476 goto out_dtefac_release;
1477 if (dtefacs.calling_len > X25_MAX_AE_LEN)
1478 goto out_dtefac_release;
1479 if (dtefacs.calling_ae == NULL)
1480 goto out_dtefac_release;
1481 if (dtefacs.called_len > X25_MAX_AE_LEN)
1482 goto out_dtefac_release;
1483 if (dtefacs.called_ae == NULL)
1484 goto out_dtefac_release;
1485 x25->dte_facilities = dtefacs;
1486 rc = 0;
1487out_dtefac_release:
1488 release_sock(sk);
1489 break;
1490 }
1491 1465
1492 case SIOCX25GCALLUSERDATA: { 1466 case SIOCX25SDTEFACILITIES: {
1493 lock_sock(sk); 1467 struct x25_dte_facilities dtefacs;
1494 rc = copy_to_user(argp, &x25->calluserdata, 1468 rc = -EFAULT;
1495 sizeof(x25->calluserdata)) 1469 if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
1496 ? -EFAULT : 0;
1497 release_sock(sk);
1498 break; 1470 break;
1499 } 1471 rc = -EINVAL;
1472 lock_sock(sk);
1473 if (sk->sk_state != TCP_LISTEN &&
1474 sk->sk_state != TCP_CLOSE)
1475 goto out_dtefac_release;
1476 if (dtefacs.calling_len > X25_MAX_AE_LEN)
1477 goto out_dtefac_release;
1478 if (dtefacs.calling_ae == NULL)
1479 goto out_dtefac_release;
1480 if (dtefacs.called_len > X25_MAX_AE_LEN)
1481 goto out_dtefac_release;
1482 if (dtefacs.called_ae == NULL)
1483 goto out_dtefac_release;
1484 x25->dte_facilities = dtefacs;
1485 rc = 0;
1486out_dtefac_release:
1487 release_sock(sk);
1488 break;
1489 }
1500 1490
1501 case SIOCX25SCALLUSERDATA: { 1491 case SIOCX25GCALLUSERDATA: {
1502 struct x25_calluserdata calluserdata; 1492 lock_sock(sk);
1493 rc = copy_to_user(argp, &x25->calluserdata,
1494 sizeof(x25->calluserdata))
1495 ? -EFAULT : 0;
1496 release_sock(sk);
1497 break;
1498 }
1503 1499
1504 rc = -EFAULT; 1500 case SIOCX25SCALLUSERDATA: {
1505 if (copy_from_user(&calluserdata, argp, 1501 struct x25_calluserdata calluserdata;
1506 sizeof(calluserdata)))
1507 break;
1508 rc = -EINVAL;
1509 if (calluserdata.cudlength > X25_MAX_CUD_LEN)
1510 break;
1511 lock_sock(sk);
1512 x25->calluserdata = calluserdata;
1513 release_sock(sk);
1514 rc = 0;
1515 break;
1516 }
1517 1502
1518 case SIOCX25GCAUSEDIAG: { 1503 rc = -EFAULT;
1519 lock_sock(sk); 1504 if (copy_from_user(&calluserdata, argp, sizeof(calluserdata)))
1520 rc = copy_to_user(argp, &x25->causediag,
1521 sizeof(x25->causediag))
1522 ? -EFAULT : 0;
1523 release_sock(sk);
1524 break; 1505 break;
1525 } 1506 rc = -EINVAL;
1507 if (calluserdata.cudlength > X25_MAX_CUD_LEN)
1508 break;
1509 lock_sock(sk);
1510 x25->calluserdata = calluserdata;
1511 release_sock(sk);
1512 rc = 0;
1513 break;
1514 }
1526 1515
1527 case SIOCX25SCAUSEDIAG: { 1516 case SIOCX25GCAUSEDIAG: {
1528 struct x25_causediag causediag; 1517 lock_sock(sk);
1529 rc = -EFAULT; 1518 rc = copy_to_user(argp, &x25->causediag, sizeof(x25->causediag))
1530 if (copy_from_user(&causediag, argp, sizeof(causediag))) 1519 ? -EFAULT : 0;
1531 break; 1520 release_sock(sk);
1532 lock_sock(sk); 1521 break;
1533 x25->causediag = causediag; 1522 }
1534 release_sock(sk); 1523
1535 rc = 0; 1524 case SIOCX25SCAUSEDIAG: {
1525 struct x25_causediag causediag;
1526 rc = -EFAULT;
1527 if (copy_from_user(&causediag, argp, sizeof(causediag)))
1536 break; 1528 break;
1529 lock_sock(sk);
1530 x25->causediag = causediag;
1531 release_sock(sk);
1532 rc = 0;
1533 break;
1537 1534
1538 } 1535 }
1539 1536
1540 case SIOCX25SCUDMATCHLEN: { 1537 case SIOCX25SCUDMATCHLEN: {
1541 struct x25_subaddr sub_addr; 1538 struct x25_subaddr sub_addr;
1542 rc = -EINVAL; 1539 rc = -EINVAL;
1543 lock_sock(sk); 1540 lock_sock(sk);
1544 if(sk->sk_state != TCP_CLOSE) 1541 if(sk->sk_state != TCP_CLOSE)
1545 goto out_cud_release; 1542 goto out_cud_release;
1546 rc = -EFAULT; 1543 rc = -EFAULT;
1547 if (copy_from_user(&sub_addr, argp, 1544 if (copy_from_user(&sub_addr, argp,
1548 sizeof(sub_addr))) 1545 sizeof(sub_addr)))
1549 goto out_cud_release; 1546 goto out_cud_release;
1550 rc = -EINVAL; 1547 rc = -EINVAL;
1551 if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN) 1548 if (sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
1552 goto out_cud_release; 1549 goto out_cud_release;
1553 x25->cudmatchlength = sub_addr.cudmatchlength; 1550 x25->cudmatchlength = sub_addr.cudmatchlength;
1554 rc = 0; 1551 rc = 0;
1555out_cud_release: 1552out_cud_release:
1556 release_sock(sk); 1553 release_sock(sk);
1557 break; 1554 break;
1558 } 1555 }
1559 1556
1560 case SIOCX25CALLACCPTAPPRV: { 1557 case SIOCX25CALLACCPTAPPRV: {
1561 rc = -EINVAL; 1558 rc = -EINVAL;
1562 lock_sock(sk); 1559 lock_sock(sk);
1563 if (sk->sk_state != TCP_CLOSE) 1560 if (sk->sk_state != TCP_CLOSE)
1564 break;
1565 clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
1566 release_sock(sk);
1567 rc = 0;
1568 break; 1561 break;
1569 } 1562 clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
1563 release_sock(sk);
1564 rc = 0;
1565 break;
1566 }
1570 1567
1571 case SIOCX25SENDCALLACCPT: { 1568 case SIOCX25SENDCALLACCPT: {
1572 rc = -EINVAL; 1569 rc = -EINVAL;
1573 lock_sock(sk); 1570 lock_sock(sk);
1574 if (sk->sk_state != TCP_ESTABLISHED) 1571 if (sk->sk_state != TCP_ESTABLISHED)
1575 break;
1576 /* must call accptapprv above */
1577 if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
1578 break;
1579 x25_write_internal(sk, X25_CALL_ACCEPTED);
1580 x25->state = X25_STATE_3;
1581 release_sock(sk);
1582 rc = 0;
1583 break; 1572 break;
1584 } 1573 /* must call accptapprv above */
1585 1574 if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
1586 default:
1587 rc = -ENOIOCTLCMD;
1588 break; 1575 break;
1576 x25_write_internal(sk, X25_CALL_ACCEPTED);
1577 x25->state = X25_STATE_3;
1578 release_sock(sk);
1579 rc = 0;
1580 break;
1581 }
1582
1583 default:
1584 rc = -ENOIOCTLCMD;
1585 break;
1589 } 1586 }
1590 1587
1591 return rc; 1588 return rc;