diff options
Diffstat (limited to 'net/bluetooth/sco.c')
-rw-r--r-- | net/bluetooth/sco.c | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 46fd8bf9a690..51ae0c3e470a 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -195,7 +195,7 @@ static int sco_connect(struct sock *sk) | |||
195 | else | 195 | else |
196 | type = SCO_LINK; | 196 | type = SCO_LINK; |
197 | 197 | ||
198 | hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING); | 198 | hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING); |
199 | if (!hcon) | 199 | if (!hcon) |
200 | goto done; | 200 | goto done; |
201 | 201 | ||
@@ -668,7 +668,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, char | |||
668 | return err; | 668 | return err; |
669 | } | 669 | } |
670 | 670 | ||
671 | static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | 671 | static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) |
672 | { | 672 | { |
673 | struct sock *sk = sock->sk; | 673 | struct sock *sk = sock->sk; |
674 | struct sco_options opts; | 674 | struct sco_options opts; |
@@ -723,6 +723,31 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char | |||
723 | return err; | 723 | return err; |
724 | } | 724 | } |
725 | 725 | ||
726 | static int sco_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | ||
727 | { | ||
728 | struct sock *sk = sock->sk; | ||
729 | int len, err = 0; | ||
730 | |||
731 | BT_DBG("sk %p", sk); | ||
732 | |||
733 | if (level == SOL_SCO) | ||
734 | return sco_sock_getsockopt_old(sock, optname, optval, optlen); | ||
735 | |||
736 | if (get_user(len, optlen)) | ||
737 | return -EFAULT; | ||
738 | |||
739 | lock_sock(sk); | ||
740 | |||
741 | switch (optname) { | ||
742 | default: | ||
743 | err = -ENOPROTOOPT; | ||
744 | break; | ||
745 | } | ||
746 | |||
747 | release_sock(sk); | ||
748 | return err; | ||
749 | } | ||
750 | |||
726 | static int sco_sock_release(struct socket *sock) | 751 | static int sco_sock_release(struct socket *sock) |
727 | { | 752 | { |
728 | struct sock *sk = sock->sk; | 753 | struct sock *sk = sock->sk; |
@@ -832,10 +857,30 @@ done: | |||
832 | /* ----- SCO interface with lower layer (HCI) ----- */ | 857 | /* ----- SCO interface with lower layer (HCI) ----- */ |
833 | static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) | 858 | static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) |
834 | { | 859 | { |
860 | register struct sock *sk; | ||
861 | struct hlist_node *node; | ||
862 | int lm = 0; | ||
863 | |||
864 | if (type != SCO_LINK && type != ESCO_LINK) | ||
865 | return 0; | ||
866 | |||
835 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | 867 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); |
836 | 868 | ||
837 | /* Always accept connection */ | 869 | /* Find listening sockets */ |
838 | return HCI_LM_ACCEPT; | 870 | read_lock(&sco_sk_list.lock); |
871 | sk_for_each(sk, node, &sco_sk_list.head) { | ||
872 | if (sk->sk_state != BT_LISTEN) | ||
873 | continue; | ||
874 | |||
875 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || | ||
876 | !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | ||
877 | lm |= HCI_LM_ACCEPT; | ||
878 | break; | ||
879 | } | ||
880 | } | ||
881 | read_unlock(&sco_sk_list.lock); | ||
882 | |||
883 | return lm; | ||
839 | } | 884 | } |
840 | 885 | ||
841 | static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | 886 | static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) |
@@ -857,7 +902,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | |||
857 | return 0; | 902 | return 0; |
858 | } | 903 | } |
859 | 904 | ||
860 | static int sco_disconn_ind(struct hci_conn *hcon, __u8 reason) | 905 | static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) |
861 | { | 906 | { |
862 | BT_DBG("hcon %p reason %d", hcon, reason); | 907 | BT_DBG("hcon %p reason %d", hcon, reason); |
863 | 908 | ||
@@ -940,7 +985,7 @@ static struct hci_proto sco_hci_proto = { | |||
940 | .id = HCI_PROTO_SCO, | 985 | .id = HCI_PROTO_SCO, |
941 | .connect_ind = sco_connect_ind, | 986 | .connect_ind = sco_connect_ind, |
942 | .connect_cfm = sco_connect_cfm, | 987 | .connect_cfm = sco_connect_cfm, |
943 | .disconn_ind = sco_disconn_ind, | 988 | .disconn_cfm = sco_disconn_cfm, |
944 | .recv_scodata = sco_recv_scodata | 989 | .recv_scodata = sco_recv_scodata |
945 | }; | 990 | }; |
946 | 991 | ||