diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 471 |
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; | ||
1452 | out_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; | ||
1451 | out_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; | ||
1487 | out_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; | ||
1486 | out_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; |
1555 | out_cud_release: | 1552 | out_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; |