.. | .. |
---|
161 | 161 | break; |
---|
162 | 162 | } |
---|
163 | 163 | |
---|
164 | | - if (chan->psm && bdaddr_type_is_le(chan->src_type)) |
---|
| 164 | + /* Use L2CAP_MODE_LE_FLOWCTL (CoC) in case of LE address and |
---|
| 165 | + * L2CAP_MODE_EXT_FLOWCTL (ECRED) has not been set. |
---|
| 166 | + */ |
---|
| 167 | + if (chan->psm && bdaddr_type_is_le(chan->src_type) && |
---|
| 168 | + chan->mode != L2CAP_MODE_EXT_FLOWCTL) |
---|
165 | 169 | chan->mode = L2CAP_MODE_LE_FLOWCTL; |
---|
166 | 170 | |
---|
167 | 171 | chan->state = BT_BOUND; |
---|
.. | .. |
---|
170 | 174 | done: |
---|
171 | 175 | release_sock(sk); |
---|
172 | 176 | return err; |
---|
| 177 | +} |
---|
| 178 | + |
---|
| 179 | +static void l2cap_sock_init_pid(struct sock *sk) |
---|
| 180 | +{ |
---|
| 181 | + struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
---|
| 182 | + |
---|
| 183 | + /* Only L2CAP_MODE_EXT_FLOWCTL ever need to access the PID in order to |
---|
| 184 | + * group the channels being requested. |
---|
| 185 | + */ |
---|
| 186 | + if (chan->mode != L2CAP_MODE_EXT_FLOWCTL) |
---|
| 187 | + return; |
---|
| 188 | + |
---|
| 189 | + spin_lock(&sk->sk_peer_lock); |
---|
| 190 | + sk->sk_peer_pid = get_pid(task_tgid(current)); |
---|
| 191 | + spin_unlock(&sk->sk_peer_lock); |
---|
173 | 192 | } |
---|
174 | 193 | |
---|
175 | 194 | static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, |
---|
.. | .. |
---|
240 | 259 | return -EINVAL; |
---|
241 | 260 | } |
---|
242 | 261 | |
---|
243 | | - if (chan->psm && bdaddr_type_is_le(chan->src_type)) |
---|
| 262 | + /* Use L2CAP_MODE_LE_FLOWCTL (CoC) in case of LE address and |
---|
| 263 | + * L2CAP_MODE_EXT_FLOWCTL (ECRED) has not been set. |
---|
| 264 | + */ |
---|
| 265 | + if (chan->psm && bdaddr_type_is_le(chan->src_type) && |
---|
| 266 | + chan->mode != L2CAP_MODE_EXT_FLOWCTL) |
---|
244 | 267 | chan->mode = L2CAP_MODE_LE_FLOWCTL; |
---|
| 268 | + |
---|
| 269 | + l2cap_sock_init_pid(sk); |
---|
245 | 270 | |
---|
246 | 271 | err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), |
---|
247 | 272 | &la.l2_bdaddr, la.l2_bdaddr_type); |
---|
.. | .. |
---|
282 | 307 | case L2CAP_MODE_BASIC: |
---|
283 | 308 | case L2CAP_MODE_LE_FLOWCTL: |
---|
284 | 309 | break; |
---|
| 310 | + case L2CAP_MODE_EXT_FLOWCTL: |
---|
| 311 | + if (!enable_ecred) { |
---|
| 312 | + err = -EOPNOTSUPP; |
---|
| 313 | + goto done; |
---|
| 314 | + } |
---|
| 315 | + break; |
---|
285 | 316 | case L2CAP_MODE_ERTM: |
---|
286 | 317 | case L2CAP_MODE_STREAMING: |
---|
287 | 318 | if (!disable_ertm) |
---|
288 | 319 | break; |
---|
289 | | - /* fall through */ |
---|
| 320 | + fallthrough; |
---|
290 | 321 | default: |
---|
291 | 322 | err = -EOPNOTSUPP; |
---|
292 | 323 | goto done; |
---|
293 | 324 | } |
---|
| 325 | + |
---|
| 326 | + l2cap_sock_init_pid(sk); |
---|
294 | 327 | |
---|
295 | 328 | sk->sk_max_ack_backlog = backlog; |
---|
296 | 329 | sk->sk_ack_backlog = 0; |
---|
.. | .. |
---|
397 | 430 | return sizeof(struct sockaddr_l2); |
---|
398 | 431 | } |
---|
399 | 432 | |
---|
| 433 | +static int l2cap_get_mode(struct l2cap_chan *chan) |
---|
| 434 | +{ |
---|
| 435 | + switch (chan->mode) { |
---|
| 436 | + case L2CAP_MODE_BASIC: |
---|
| 437 | + return BT_MODE_BASIC; |
---|
| 438 | + case L2CAP_MODE_ERTM: |
---|
| 439 | + return BT_MODE_ERTM; |
---|
| 440 | + case L2CAP_MODE_STREAMING: |
---|
| 441 | + return BT_MODE_STREAMING; |
---|
| 442 | + case L2CAP_MODE_LE_FLOWCTL: |
---|
| 443 | + return BT_MODE_LE_FLOWCTL; |
---|
| 444 | + case L2CAP_MODE_EXT_FLOWCTL: |
---|
| 445 | + return BT_MODE_EXT_FLOWCTL; |
---|
| 446 | + } |
---|
| 447 | + |
---|
| 448 | + return -EINVAL; |
---|
| 449 | +} |
---|
| 450 | + |
---|
400 | 451 | static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, |
---|
401 | 452 | char __user *optval, int __user *optlen) |
---|
402 | 453 | { |
---|
.. | .. |
---|
426 | 477 | break; |
---|
427 | 478 | } |
---|
428 | 479 | |
---|
| 480 | + /* Only BR/EDR modes are supported here */ |
---|
| 481 | + switch (chan->mode) { |
---|
| 482 | + case L2CAP_MODE_BASIC: |
---|
| 483 | + case L2CAP_MODE_ERTM: |
---|
| 484 | + case L2CAP_MODE_STREAMING: |
---|
| 485 | + break; |
---|
| 486 | + default: |
---|
| 487 | + err = -EINVAL; |
---|
| 488 | + break; |
---|
| 489 | + } |
---|
| 490 | + |
---|
| 491 | + if (err < 0) |
---|
| 492 | + break; |
---|
| 493 | + |
---|
429 | 494 | memset(&opts, 0, sizeof(opts)); |
---|
430 | 495 | opts.imtu = chan->imtu; |
---|
431 | 496 | opts.omtu = chan->omtu; |
---|
.. | .. |
---|
434 | 499 | opts.fcs = chan->fcs; |
---|
435 | 500 | opts.max_tx = chan->max_tx; |
---|
436 | 501 | opts.txwin_size = chan->tx_win; |
---|
| 502 | + |
---|
| 503 | + BT_DBG("mode 0x%2.2x", chan->mode); |
---|
437 | 504 | |
---|
438 | 505 | len = min_t(unsigned int, len, sizeof(opts)); |
---|
439 | 506 | if (copy_to_user(optval, (char *) &opts, len)) |
---|
.. | .. |
---|
507 | 574 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
---|
508 | 575 | struct bt_security sec; |
---|
509 | 576 | struct bt_power pwr; |
---|
510 | | - int len, err = 0; |
---|
| 577 | + u32 phys; |
---|
| 578 | + int len, mode, err = 0; |
---|
511 | 579 | |
---|
512 | 580 | BT_DBG("sk %p", sk); |
---|
513 | 581 | |
---|
.. | .. |
---|
611 | 679 | err = -EFAULT; |
---|
612 | 680 | break; |
---|
613 | 681 | |
---|
| 682 | + case BT_PHY: |
---|
| 683 | + if (sk->sk_state != BT_CONNECTED) { |
---|
| 684 | + err = -ENOTCONN; |
---|
| 685 | + break; |
---|
| 686 | + } |
---|
| 687 | + |
---|
| 688 | + phys = hci_conn_get_phy(chan->conn->hcon); |
---|
| 689 | + |
---|
| 690 | + if (put_user(phys, (u32 __user *) optval)) |
---|
| 691 | + err = -EFAULT; |
---|
| 692 | + break; |
---|
| 693 | + |
---|
| 694 | + case BT_MODE: |
---|
| 695 | + if (!enable_ecred) { |
---|
| 696 | + err = -ENOPROTOOPT; |
---|
| 697 | + break; |
---|
| 698 | + } |
---|
| 699 | + |
---|
| 700 | + if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
---|
| 701 | + err = -EINVAL; |
---|
| 702 | + break; |
---|
| 703 | + } |
---|
| 704 | + |
---|
| 705 | + mode = l2cap_get_mode(chan); |
---|
| 706 | + if (mode < 0) { |
---|
| 707 | + err = mode; |
---|
| 708 | + break; |
---|
| 709 | + } |
---|
| 710 | + |
---|
| 711 | + if (put_user(mode, (u8 __user *) optval)) |
---|
| 712 | + err = -EFAULT; |
---|
| 713 | + break; |
---|
| 714 | + |
---|
614 | 715 | default: |
---|
615 | 716 | err = -ENOPROTOOPT; |
---|
616 | 717 | break; |
---|
.. | .. |
---|
637 | 738 | } |
---|
638 | 739 | |
---|
639 | 740 | static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, |
---|
640 | | - char __user *optval, unsigned int optlen) |
---|
| 741 | + sockptr_t optval, unsigned int optlen) |
---|
641 | 742 | { |
---|
642 | 743 | struct sock *sk = sock->sk; |
---|
643 | 744 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
---|
.. | .. |
---|
670 | 771 | opts.txwin_size = chan->tx_win; |
---|
671 | 772 | |
---|
672 | 773 | len = min_t(unsigned int, sizeof(opts), optlen); |
---|
673 | | - if (copy_from_user((char *) &opts, optval, len)) { |
---|
| 774 | + if (copy_from_sockptr(&opts, optval, len)) { |
---|
674 | 775 | err = -EFAULT; |
---|
675 | 776 | break; |
---|
676 | 777 | } |
---|
.. | .. |
---|
685 | 786 | break; |
---|
686 | 787 | } |
---|
687 | 788 | |
---|
688 | | - chan->mode = opts.mode; |
---|
689 | | - switch (chan->mode) { |
---|
690 | | - case L2CAP_MODE_LE_FLOWCTL: |
---|
691 | | - break; |
---|
| 789 | + /* Only BR/EDR modes are supported here */ |
---|
| 790 | + switch (opts.mode) { |
---|
692 | 791 | case L2CAP_MODE_BASIC: |
---|
693 | 792 | clear_bit(CONF_STATE2_DEVICE, &chan->conf_state); |
---|
694 | 793 | break; |
---|
.. | .. |
---|
696 | 795 | case L2CAP_MODE_STREAMING: |
---|
697 | 796 | if (!disable_ertm) |
---|
698 | 797 | break; |
---|
699 | | - /* fall through */ |
---|
| 798 | + fallthrough; |
---|
700 | 799 | default: |
---|
701 | 800 | err = -EINVAL; |
---|
702 | 801 | break; |
---|
703 | 802 | } |
---|
| 803 | + |
---|
| 804 | + if (err < 0) |
---|
| 805 | + break; |
---|
| 806 | + |
---|
| 807 | + chan->mode = opts.mode; |
---|
| 808 | + |
---|
| 809 | + BT_DBG("mode 0x%2.2x", chan->mode); |
---|
704 | 810 | |
---|
705 | 811 | chan->imtu = opts.imtu; |
---|
706 | 812 | chan->omtu = opts.omtu; |
---|
.. | .. |
---|
711 | 817 | break; |
---|
712 | 818 | |
---|
713 | 819 | case L2CAP_LM: |
---|
714 | | - if (get_user(opt, (u32 __user *) optval)) { |
---|
| 820 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
---|
715 | 821 | err = -EFAULT; |
---|
716 | 822 | break; |
---|
717 | 823 | } |
---|
.. | .. |
---|
748 | 854 | return err; |
---|
749 | 855 | } |
---|
750 | 856 | |
---|
| 857 | +static int l2cap_set_mode(struct l2cap_chan *chan, u8 mode) |
---|
| 858 | +{ |
---|
| 859 | + switch (mode) { |
---|
| 860 | + case BT_MODE_BASIC: |
---|
| 861 | + if (bdaddr_type_is_le(chan->src_type)) |
---|
| 862 | + return -EINVAL; |
---|
| 863 | + mode = L2CAP_MODE_BASIC; |
---|
| 864 | + clear_bit(CONF_STATE2_DEVICE, &chan->conf_state); |
---|
| 865 | + break; |
---|
| 866 | + case BT_MODE_ERTM: |
---|
| 867 | + if (!disable_ertm || bdaddr_type_is_le(chan->src_type)) |
---|
| 868 | + return -EINVAL; |
---|
| 869 | + mode = L2CAP_MODE_ERTM; |
---|
| 870 | + break; |
---|
| 871 | + case BT_MODE_STREAMING: |
---|
| 872 | + if (!disable_ertm || bdaddr_type_is_le(chan->src_type)) |
---|
| 873 | + return -EINVAL; |
---|
| 874 | + mode = L2CAP_MODE_STREAMING; |
---|
| 875 | + break; |
---|
| 876 | + case BT_MODE_LE_FLOWCTL: |
---|
| 877 | + if (!bdaddr_type_is_le(chan->src_type)) |
---|
| 878 | + return -EINVAL; |
---|
| 879 | + mode = L2CAP_MODE_LE_FLOWCTL; |
---|
| 880 | + break; |
---|
| 881 | + case BT_MODE_EXT_FLOWCTL: |
---|
| 882 | + /* TODO: Add support for ECRED PDUs to BR/EDR */ |
---|
| 883 | + if (!bdaddr_type_is_le(chan->src_type)) |
---|
| 884 | + return -EINVAL; |
---|
| 885 | + mode = L2CAP_MODE_EXT_FLOWCTL; |
---|
| 886 | + break; |
---|
| 887 | + default: |
---|
| 888 | + return -EINVAL; |
---|
| 889 | + } |
---|
| 890 | + |
---|
| 891 | + chan->mode = mode; |
---|
| 892 | + |
---|
| 893 | + return 0; |
---|
| 894 | +} |
---|
| 895 | + |
---|
751 | 896 | static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, |
---|
752 | | - char __user *optval, unsigned int optlen) |
---|
| 897 | + sockptr_t optval, unsigned int optlen) |
---|
753 | 898 | { |
---|
754 | 899 | struct sock *sk = sock->sk; |
---|
755 | 900 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
---|
.. | .. |
---|
758 | 903 | struct l2cap_conn *conn; |
---|
759 | 904 | int len, err = 0; |
---|
760 | 905 | u32 opt; |
---|
| 906 | + u16 mtu; |
---|
| 907 | + u8 mode; |
---|
761 | 908 | |
---|
762 | 909 | BT_DBG("sk %p", sk); |
---|
763 | 910 | |
---|
.. | .. |
---|
781 | 928 | sec.level = BT_SECURITY_LOW; |
---|
782 | 929 | |
---|
783 | 930 | len = min_t(unsigned int, sizeof(sec), optlen); |
---|
784 | | - if (copy_from_user((char *) &sec, optval, len)) { |
---|
| 931 | + if (copy_from_sockptr(&sec, optval, len)) { |
---|
785 | 932 | err = -EFAULT; |
---|
786 | 933 | break; |
---|
787 | 934 | } |
---|
.. | .. |
---|
799 | 946 | |
---|
800 | 947 | conn = chan->conn; |
---|
801 | 948 | |
---|
802 | | - /*change security for LE channels */ |
---|
| 949 | + /* change security for LE channels */ |
---|
803 | 950 | if (chan->scid == L2CAP_CID_ATT) { |
---|
804 | | - if (smp_conn_security(conn->hcon, sec.level)) |
---|
| 951 | + if (smp_conn_security(conn->hcon, sec.level)) { |
---|
| 952 | + err = -EINVAL; |
---|
805 | 953 | break; |
---|
| 954 | + } |
---|
| 955 | + |
---|
806 | 956 | set_bit(FLAG_PENDING_SECURITY, &chan->flags); |
---|
807 | 957 | sk->sk_state = BT_CONFIG; |
---|
808 | 958 | chan->state = BT_CONFIG; |
---|
.. | .. |
---|
826 | 976 | break; |
---|
827 | 977 | } |
---|
828 | 978 | |
---|
829 | | - if (get_user(opt, (u32 __user *) optval)) { |
---|
| 979 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
---|
830 | 980 | err = -EFAULT; |
---|
831 | 981 | break; |
---|
832 | 982 | } |
---|
.. | .. |
---|
841 | 991 | break; |
---|
842 | 992 | |
---|
843 | 993 | case BT_FLUSHABLE: |
---|
844 | | - if (get_user(opt, (u32 __user *) optval)) { |
---|
| 994 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
---|
845 | 995 | err = -EFAULT; |
---|
846 | 996 | break; |
---|
847 | 997 | } |
---|
.. | .. |
---|
877 | 1027 | pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; |
---|
878 | 1028 | |
---|
879 | 1029 | len = min_t(unsigned int, sizeof(pwr), optlen); |
---|
880 | | - if (copy_from_user((char *) &pwr, optval, len)) { |
---|
| 1030 | + if (copy_from_sockptr(&pwr, optval, len)) { |
---|
881 | 1031 | err = -EFAULT; |
---|
882 | 1032 | break; |
---|
883 | 1033 | } |
---|
.. | .. |
---|
889 | 1039 | break; |
---|
890 | 1040 | |
---|
891 | 1041 | case BT_CHANNEL_POLICY: |
---|
892 | | - if (get_user(opt, (u32 __user *) optval)) { |
---|
| 1042 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
---|
893 | 1043 | err = -EFAULT; |
---|
894 | 1044 | break; |
---|
895 | 1045 | } |
---|
.. | .. |
---|
931 | 1081 | break; |
---|
932 | 1082 | } |
---|
933 | 1083 | |
---|
934 | | - if (sk->sk_state == BT_CONNECTED) { |
---|
| 1084 | + if (chan->mode == L2CAP_MODE_LE_FLOWCTL && |
---|
| 1085 | + sk->sk_state == BT_CONNECTED) { |
---|
935 | 1086 | err = -EISCONN; |
---|
936 | 1087 | break; |
---|
937 | 1088 | } |
---|
938 | 1089 | |
---|
939 | | - if (get_user(opt, (u16 __user *) optval)) { |
---|
| 1090 | + if (copy_from_sockptr(&mtu, optval, sizeof(u16))) { |
---|
940 | 1091 | err = -EFAULT; |
---|
941 | 1092 | break; |
---|
942 | 1093 | } |
---|
943 | 1094 | |
---|
944 | | - chan->imtu = opt; |
---|
| 1095 | + if (chan->mode == L2CAP_MODE_EXT_FLOWCTL && |
---|
| 1096 | + sk->sk_state == BT_CONNECTED) |
---|
| 1097 | + err = l2cap_chan_reconfigure(chan, mtu); |
---|
| 1098 | + else |
---|
| 1099 | + chan->imtu = mtu; |
---|
| 1100 | + |
---|
| 1101 | + break; |
---|
| 1102 | + |
---|
| 1103 | + case BT_MODE: |
---|
| 1104 | + if (!enable_ecred) { |
---|
| 1105 | + err = -ENOPROTOOPT; |
---|
| 1106 | + break; |
---|
| 1107 | + } |
---|
| 1108 | + |
---|
| 1109 | + BT_DBG("sk->sk_state %u", sk->sk_state); |
---|
| 1110 | + |
---|
| 1111 | + if (sk->sk_state != BT_BOUND) { |
---|
| 1112 | + err = -EINVAL; |
---|
| 1113 | + break; |
---|
| 1114 | + } |
---|
| 1115 | + |
---|
| 1116 | + if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
---|
| 1117 | + err = -EINVAL; |
---|
| 1118 | + break; |
---|
| 1119 | + } |
---|
| 1120 | + |
---|
| 1121 | + if (copy_from_sockptr(&mode, optval, sizeof(u8))) { |
---|
| 1122 | + err = -EFAULT; |
---|
| 1123 | + break; |
---|
| 1124 | + } |
---|
| 1125 | + |
---|
| 1126 | + BT_DBG("mode %u", mode); |
---|
| 1127 | + |
---|
| 1128 | + err = l2cap_set_mode(chan, mode); |
---|
| 1129 | + if (err) |
---|
| 1130 | + break; |
---|
| 1131 | + |
---|
| 1132 | + BT_DBG("mode 0x%2.2x", chan->mode); |
---|
| 1133 | + |
---|
945 | 1134 | break; |
---|
946 | 1135 | |
---|
947 | 1136 | default: |
---|
.. | .. |
---|
996 | 1185 | |
---|
997 | 1186 | if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP, |
---|
998 | 1187 | &bt_sk(sk)->flags)) { |
---|
999 | | - if (bdaddr_type_is_le(pi->chan->src_type)) { |
---|
| 1188 | + if (pi->chan->mode == L2CAP_MODE_EXT_FLOWCTL) { |
---|
| 1189 | + sk->sk_state = BT_CONNECTED; |
---|
| 1190 | + pi->chan->state = BT_CONNECTED; |
---|
| 1191 | + __l2cap_ecred_conn_rsp_defer(pi->chan); |
---|
| 1192 | + } else if (bdaddr_type_is_le(pi->chan->src_type)) { |
---|
1000 | 1193 | sk->sk_state = BT_CONNECTED; |
---|
1001 | 1194 | pi->chan->state = BT_CONNECTED; |
---|
1002 | 1195 | __l2cap_le_connect_rsp_defer(pi->chan); |
---|
.. | .. |
---|
1115 | 1308 | struct l2cap_conn *conn; |
---|
1116 | 1309 | int err = 0; |
---|
1117 | 1310 | |
---|
1118 | | - BT_DBG("sock %p, sk %p", sock, sk); |
---|
| 1311 | + BT_DBG("sock %p, sk %p, how %d", sock, sk, how); |
---|
| 1312 | + |
---|
| 1313 | + /* 'how' parameter is mapped to sk_shutdown as follows: |
---|
| 1314 | + * SHUT_RD (0) --> RCV_SHUTDOWN (1) |
---|
| 1315 | + * SHUT_WR (1) --> SEND_SHUTDOWN (2) |
---|
| 1316 | + * SHUT_RDWR (2) --> SHUTDOWN_MASK (3) |
---|
| 1317 | + */ |
---|
| 1318 | + how++; |
---|
1119 | 1319 | |
---|
1120 | 1320 | if (!sk) |
---|
1121 | 1321 | return 0; |
---|
1122 | 1322 | |
---|
1123 | 1323 | lock_sock(sk); |
---|
1124 | 1324 | |
---|
1125 | | - if (sk->sk_shutdown) |
---|
| 1325 | + if ((sk->sk_shutdown & how) == how) |
---|
1126 | 1326 | goto shutdown_already; |
---|
1127 | 1327 | |
---|
1128 | 1328 | BT_DBG("Handling sock shutdown"); |
---|
.. | .. |
---|
1145 | 1345 | * has already been actioned to close the L2CAP |
---|
1146 | 1346 | * link such as by l2cap_disconnection_req(). |
---|
1147 | 1347 | */ |
---|
1148 | | - if (sk->sk_shutdown) |
---|
1149 | | - goto has_shutdown; |
---|
| 1348 | + if ((sk->sk_shutdown & how) == how) |
---|
| 1349 | + goto shutdown_matched; |
---|
1150 | 1350 | } |
---|
1151 | 1351 | |
---|
1152 | | - sk->sk_shutdown = SHUTDOWN_MASK; |
---|
| 1352 | + /* Try setting the RCV_SHUTDOWN bit, return early if SEND_SHUTDOWN |
---|
| 1353 | + * is already set |
---|
| 1354 | + */ |
---|
| 1355 | + if ((how & RCV_SHUTDOWN) && !(sk->sk_shutdown & RCV_SHUTDOWN)) { |
---|
| 1356 | + sk->sk_shutdown |= RCV_SHUTDOWN; |
---|
| 1357 | + if ((sk->sk_shutdown & how) == how) |
---|
| 1358 | + goto shutdown_matched; |
---|
| 1359 | + } |
---|
| 1360 | + |
---|
| 1361 | + sk->sk_shutdown |= SEND_SHUTDOWN; |
---|
1153 | 1362 | release_sock(sk); |
---|
1154 | 1363 | |
---|
1155 | 1364 | l2cap_chan_lock(chan); |
---|
.. | .. |
---|
1179 | 1388 | err = bt_sock_wait_state(sk, BT_CLOSED, |
---|
1180 | 1389 | sk->sk_lingertime); |
---|
1181 | 1390 | |
---|
1182 | | -has_shutdown: |
---|
| 1391 | +shutdown_matched: |
---|
1183 | 1392 | l2cap_chan_put(chan); |
---|
1184 | 1393 | sock_put(sk); |
---|
1185 | 1394 | |
---|
.. | .. |
---|
1207 | 1416 | |
---|
1208 | 1417 | bt_sock_unlink(&l2cap_sk_list, sk); |
---|
1209 | 1418 | |
---|
1210 | | - err = l2cap_sock_shutdown(sock, 2); |
---|
| 1419 | + err = l2cap_sock_shutdown(sock, SHUT_RDWR); |
---|
1211 | 1420 | chan = l2cap_pi(sk)->chan; |
---|
1212 | 1421 | |
---|
1213 | 1422 | l2cap_chan_hold(chan); |
---|
.. | .. |
---|
1483 | 1692 | return sk->sk_sndtimeo; |
---|
1484 | 1693 | } |
---|
1485 | 1694 | |
---|
| 1695 | +static struct pid *l2cap_sock_get_peer_pid_cb(struct l2cap_chan *chan) |
---|
| 1696 | +{ |
---|
| 1697 | + struct sock *sk = chan->data; |
---|
| 1698 | + |
---|
| 1699 | + return sk->sk_peer_pid; |
---|
| 1700 | +} |
---|
| 1701 | + |
---|
1486 | 1702 | static void l2cap_sock_suspend_cb(struct l2cap_chan *chan) |
---|
1487 | 1703 | { |
---|
1488 | 1704 | struct sock *sk = chan->data; |
---|
.. | .. |
---|
1517 | 1733 | .suspend = l2cap_sock_suspend_cb, |
---|
1518 | 1734 | .set_shutdown = l2cap_sock_set_shutdown_cb, |
---|
1519 | 1735 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, |
---|
| 1736 | + .get_peer_pid = l2cap_sock_get_peer_pid_cb, |
---|
1520 | 1737 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
---|
1521 | 1738 | .filter = l2cap_sock_filter, |
---|
1522 | 1739 | }; |
---|
.. | .. |
---|
1698 | 1915 | .recvmsg = l2cap_sock_recvmsg, |
---|
1699 | 1916 | .poll = bt_sock_poll, |
---|
1700 | 1917 | .ioctl = bt_sock_ioctl, |
---|
| 1918 | + .gettstamp = sock_gettstamp, |
---|
1701 | 1919 | .mmap = sock_no_mmap, |
---|
1702 | 1920 | .socketpair = sock_no_socketpair, |
---|
1703 | 1921 | .shutdown = l2cap_sock_shutdown, |
---|