.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * X.25 Packet Layer release 002 |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * screw up. It might even work. |
---|
7 | 8 | * |
---|
8 | 9 | * This code REQUIRES 2.1.15 or higher |
---|
9 | | - * |
---|
10 | | - * This module: |
---|
11 | | - * This module is free software; you can redistribute it and/or |
---|
12 | | - * modify it under the terms of the GNU General Public License |
---|
13 | | - * as published by the Free Software Foundation; either version |
---|
14 | | - * 2 of the License, or (at your option) any later version. |
---|
15 | 10 | * |
---|
16 | 11 | * History |
---|
17 | 12 | * X.25 001 Jonathan Naylor Started coding. |
---|
.. | .. |
---|
436 | 431 | */ |
---|
437 | 432 | |
---|
438 | 433 | static int x25_setsockopt(struct socket *sock, int level, int optname, |
---|
439 | | - char __user *optval, unsigned int optlen) |
---|
| 434 | + sockptr_t optval, unsigned int optlen) |
---|
440 | 435 | { |
---|
441 | 436 | int opt; |
---|
442 | 437 | struct sock *sk = sock->sk; |
---|
.. | .. |
---|
450 | 445 | goto out; |
---|
451 | 446 | |
---|
452 | 447 | rc = -EFAULT; |
---|
453 | | - if (get_user(opt, (int __user *)optval)) |
---|
| 448 | + if (copy_from_sockptr(&opt, optval, sizeof(int))) |
---|
454 | 449 | goto out; |
---|
455 | 450 | |
---|
456 | 451 | if (opt) |
---|
.. | .. |
---|
497 | 492 | int rc = -EOPNOTSUPP; |
---|
498 | 493 | |
---|
499 | 494 | lock_sock(sk); |
---|
| 495 | + if (sock->state != SS_UNCONNECTED) { |
---|
| 496 | + rc = -EINVAL; |
---|
| 497 | + release_sock(sk); |
---|
| 498 | + return rc; |
---|
| 499 | + } |
---|
| 500 | + |
---|
500 | 501 | if (sk->sk_state != TCP_LISTEN) { |
---|
501 | 502 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); |
---|
502 | 503 | sk->sk_max_ack_backlog = backlog; |
---|
.. | .. |
---|
664 | 665 | sock_set_flag(sk, SOCK_DEAD); |
---|
665 | 666 | sock_set_flag(sk, SOCK_DESTROY); |
---|
666 | 667 | break; |
---|
| 668 | + |
---|
| 669 | + case X25_STATE_5: |
---|
| 670 | + x25_write_internal(sk, X25_CLEAR_REQUEST); |
---|
| 671 | + x25_disconnect(sk, 0, 0, 0); |
---|
| 672 | + __x25_destroy_socket(sk); |
---|
| 673 | + goto out; |
---|
667 | 674 | } |
---|
668 | 675 | |
---|
669 | 676 | sock_orphan(sk); |
---|
.. | .. |
---|
902 | 909 | /* Now attach up the new socket */ |
---|
903 | 910 | skb->sk = NULL; |
---|
904 | 911 | kfree_skb(skb); |
---|
905 | | - sk->sk_ack_backlog--; |
---|
| 912 | + sk_acceptq_removed(sk); |
---|
906 | 913 | newsock->state = SS_CONNECTED; |
---|
907 | 914 | rc = 0; |
---|
908 | 915 | out2: |
---|
.. | .. |
---|
1066 | 1073 | if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) { |
---|
1067 | 1074 | x25_write_internal(make, X25_CALL_ACCEPTED); |
---|
1068 | 1075 | makex25->state = X25_STATE_3; |
---|
| 1076 | + } else { |
---|
| 1077 | + makex25->state = X25_STATE_5; |
---|
1069 | 1078 | } |
---|
1070 | 1079 | |
---|
1071 | 1080 | /* |
---|
.. | .. |
---|
1074 | 1083 | skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len); |
---|
1075 | 1084 | makex25->calluserdata.cudlength = skb->len; |
---|
1076 | 1085 | |
---|
1077 | | - sk->sk_ack_backlog++; |
---|
| 1086 | + sk_acceptq_added(sk); |
---|
1078 | 1087 | |
---|
1079 | 1088 | x25_insert_socket(make); |
---|
1080 | 1089 | |
---|
.. | .. |
---|
1405 | 1414 | break; |
---|
1406 | 1415 | } |
---|
1407 | 1416 | |
---|
1408 | | - case SIOCGSTAMP: |
---|
1409 | | - rc = -EINVAL; |
---|
1410 | | - if (sk) |
---|
1411 | | - rc = sock_get_timestamp(sk, |
---|
1412 | | - (struct timeval __user *)argp); |
---|
1413 | | - break; |
---|
1414 | | - case SIOCGSTAMPNS: |
---|
1415 | | - rc = -EINVAL; |
---|
1416 | | - if (sk) |
---|
1417 | | - rc = sock_get_timestampns(sk, |
---|
1418 | | - (struct timespec __user *)argp); |
---|
1419 | | - break; |
---|
1420 | 1417 | case SIOCGIFADDR: |
---|
1421 | 1418 | case SIOCSIFADDR: |
---|
1422 | 1419 | case SIOCGIFDSTADDR: |
---|
.. | .. |
---|
1688 | 1685 | unsigned long arg) |
---|
1689 | 1686 | { |
---|
1690 | 1687 | void __user *argp = compat_ptr(arg); |
---|
1691 | | - struct sock *sk = sock->sk; |
---|
1692 | | - |
---|
1693 | 1688 | int rc = -ENOIOCTLCMD; |
---|
1694 | 1689 | |
---|
1695 | 1690 | switch(cmd) { |
---|
1696 | 1691 | case TIOCOUTQ: |
---|
1697 | 1692 | case TIOCINQ: |
---|
1698 | 1693 | rc = x25_ioctl(sock, cmd, (unsigned long)argp); |
---|
1699 | | - break; |
---|
1700 | | - case SIOCGSTAMP: |
---|
1701 | | - rc = -EINVAL; |
---|
1702 | | - if (sk) |
---|
1703 | | - rc = compat_sock_get_timestamp(sk, |
---|
1704 | | - (struct timeval __user*)argp); |
---|
1705 | | - break; |
---|
1706 | | - case SIOCGSTAMPNS: |
---|
1707 | | - rc = -EINVAL; |
---|
1708 | | - if (sk) |
---|
1709 | | - rc = compat_sock_get_timestampns(sk, |
---|
1710 | | - (struct timespec __user*)argp); |
---|
1711 | 1694 | break; |
---|
1712 | 1695 | case SIOCGIFADDR: |
---|
1713 | 1696 | case SIOCSIFADDR: |
---|
.. | .. |
---|
1772 | 1755 | #ifdef CONFIG_COMPAT |
---|
1773 | 1756 | .compat_ioctl = compat_x25_ioctl, |
---|
1774 | 1757 | #endif |
---|
| 1758 | + .gettstamp = sock_gettstamp, |
---|
1775 | 1759 | .listen = x25_listen, |
---|
1776 | 1760 | .shutdown = sock_no_shutdown, |
---|
1777 | 1761 | .setsockopt = x25_setsockopt, |
---|
.. | .. |
---|
1797 | 1781 | |
---|
1798 | 1782 | write_lock_bh(&x25_list_lock); |
---|
1799 | 1783 | |
---|
1800 | | - sk_for_each(s, &x25_list) |
---|
1801 | | - if (x25_sk(s)->neighbour == nb) |
---|
| 1784 | + sk_for_each(s, &x25_list) { |
---|
| 1785 | + if (x25_sk(s)->neighbour == nb) { |
---|
| 1786 | + write_unlock_bh(&x25_list_lock); |
---|
| 1787 | + lock_sock(s); |
---|
1802 | 1788 | x25_disconnect(s, ENETUNREACH, 0, 0); |
---|
1803 | | - |
---|
| 1789 | + release_sock(s); |
---|
| 1790 | + write_lock_bh(&x25_list_lock); |
---|
| 1791 | + } |
---|
| 1792 | + } |
---|
1804 | 1793 | write_unlock_bh(&x25_list_lock); |
---|
1805 | 1794 | |
---|
1806 | 1795 | /* Remove any related forwards */ |
---|