diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 21 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 214 | ||||
-rw-r--r-- | net/bluetooth/hidp/hidp.h | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 34 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 2 |
8 files changed, 188 insertions, 101 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1edfdf4c095b..f6348e078aa4 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #define BT_DBG(D...) | 49 | #define BT_DBG(D...) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #define VERSION "2.12" | 52 | #define VERSION "2.13" |
53 | 53 | ||
54 | /* Bluetooth sockets */ | 54 | /* Bluetooth sockets */ |
55 | #define BT_MAX_PROTO 8 | 55 | #define BT_MAX_PROTO 8 |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ca8d05245ca0..b7002429f152 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route); | |||
330 | 330 | ||
331 | /* Create SCO or ACL connection. | 331 | /* Create SCO or ACL connection. |
332 | * Device _must_ be locked */ | 332 | * Device _must_ be locked */ |
333 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | 333 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) |
334 | { | 334 | { |
335 | struct hci_conn *acl; | 335 | struct hci_conn *acl; |
336 | struct hci_conn *sco; | 336 | struct hci_conn *sco; |
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
344 | 344 | ||
345 | hci_conn_hold(acl); | 345 | hci_conn_hold(acl); |
346 | 346 | ||
347 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) | 347 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { |
348 | acl->auth_type = auth_type; | ||
348 | hci_acl_connect(acl); | 349 | hci_acl_connect(acl); |
350 | } | ||
349 | 351 | ||
350 | if (type == ACL_LINK) | 352 | if (type == ACL_LINK) |
351 | return acl; | 353 | return acl; |
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
374 | } | 376 | } |
375 | EXPORT_SYMBOL(hci_connect); | 377 | EXPORT_SYMBOL(hci_connect); |
376 | 378 | ||
379 | /* Check link security requirement */ | ||
380 | int hci_conn_check_link_mode(struct hci_conn *conn) | ||
381 | { | ||
382 | BT_DBG("conn %p", conn); | ||
383 | |||
384 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 && | ||
385 | !(conn->link_mode & HCI_LM_ENCRYPT)) | ||
386 | return 0; | ||
387 | |||
388 | return 1; | ||
389 | } | ||
390 | EXPORT_SYMBOL(hci_conn_check_link_mode); | ||
391 | |||
377 | /* Authenticate remote device */ | 392 | /* Authenticate remote device */ |
378 | int hci_conn_auth(struct hci_conn *conn) | 393 | int hci_conn_auth(struct hci_conn *conn) |
379 | { | 394 | { |
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn) | |||
381 | 396 | ||
382 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { | 397 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { |
383 | if (!(conn->auth_type & 0x01)) { | 398 | if (!(conn->auth_type & 0x01)) { |
384 | conn->auth_type = HCI_AT_GENERAL_BONDING_MITM; | 399 | conn->auth_type |= 0x01; |
385 | conn->link_mode &= ~HCI_LM_AUTH; | 400 | conn->link_mode &= ~HCI_LM_AUTH; |
386 | } | 401 | } |
387 | } | 402 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f5b21cb93699..278a3ace14f6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -164,6 +164,9 @@ static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev * | |||
164 | { | 164 | { |
165 | int ret; | 165 | int ret; |
166 | 166 | ||
167 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
168 | return -ENETDOWN; | ||
169 | |||
167 | /* Serialize all requests */ | 170 | /* Serialize all requests */ |
168 | hci_req_lock(hdev); | 171 | hci_req_lock(hdev); |
169 | ret = __hci_request(hdev, req, opt, timeout); | 172 | ret = __hci_request(hdev, req, opt, timeout); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0e3db289f4be..ad7a553d7713 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1605 | 1605 | ||
1606 | if (conn->state == BT_CONFIG) { | 1606 | if (conn->state == BT_CONFIG) { |
1607 | if (!ev->status && hdev->ssp_mode > 0 && | 1607 | if (!ev->status && hdev->ssp_mode > 0 && |
1608 | conn->ssp_mode > 0) { | 1608 | conn->ssp_mode > 0 && conn->out) { |
1609 | if (conn->out) { | 1609 | struct hci_cp_auth_requested cp; |
1610 | struct hci_cp_auth_requested cp; | 1610 | cp.handle = ev->handle; |
1611 | cp.handle = ev->handle; | 1611 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, |
1612 | hci_send_cmd(hdev, | ||
1613 | HCI_OP_AUTH_REQUESTED, | ||
1614 | sizeof(cp), &cp); | 1612 | sizeof(cp), &cp); |
1615 | } | ||
1616 | } else { | 1613 | } else { |
1617 | conn->state = BT_CONNECTED; | 1614 | conn->state = BT_CONNECTED; |
1618 | hci_proto_connect_cfm(conn, ev->status); | 1615 | hci_proto_connect_cfm(conn, ev->status); |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 96434d774c84..acdeab3d9807 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -578,7 +578,7 @@ static int hidp_session(void *arg) | |||
578 | if (session->hid) { | 578 | if (session->hid) { |
579 | if (session->hid->claimed & HID_CLAIMED_INPUT) | 579 | if (session->hid->claimed & HID_CLAIMED_INPUT) |
580 | hidinput_disconnect(session->hid); | 580 | hidinput_disconnect(session->hid); |
581 | hid_free_device(session->hid); | 581 | hid_destroy_device(session->hid); |
582 | } | 582 | } |
583 | 583 | ||
584 | /* Wakeup user-space polling for socket errors */ | 584 | /* Wakeup user-space polling for socket errors */ |
@@ -623,9 +623,15 @@ static struct device *hidp_get_device(struct hidp_session *session) | |||
623 | static int hidp_setup_input(struct hidp_session *session, | 623 | static int hidp_setup_input(struct hidp_session *session, |
624 | struct hidp_connadd_req *req) | 624 | struct hidp_connadd_req *req) |
625 | { | 625 | { |
626 | struct input_dev *input = session->input; | 626 | struct input_dev *input; |
627 | int i; | 627 | int i; |
628 | 628 | ||
629 | input = input_allocate_device(); | ||
630 | if (!input) | ||
631 | return -ENOMEM; | ||
632 | |||
633 | session->input = input; | ||
634 | |||
629 | input_set_drvdata(input, session); | 635 | input_set_drvdata(input, session); |
630 | 636 | ||
631 | input->name = "Bluetooth HID Boot Protocol Device"; | 637 | input->name = "Bluetooth HID Boot Protocol Device"; |
@@ -677,67 +683,114 @@ static void hidp_close(struct hid_device *hid) | |||
677 | { | 683 | { |
678 | } | 684 | } |
679 | 685 | ||
680 | static const struct { | 686 | static int hidp_parse(struct hid_device *hid) |
681 | __u16 idVendor; | 687 | { |
682 | __u16 idProduct; | 688 | struct hidp_session *session = hid->driver_data; |
683 | unsigned quirks; | 689 | struct hidp_connadd_req *req = session->req; |
684 | } hidp_blacklist[] = { | 690 | unsigned char *buf; |
685 | /* Apple wireless Mighty Mouse */ | 691 | int ret; |
686 | { 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL }, | ||
687 | 692 | ||
688 | { } /* Terminating entry */ | 693 | buf = kmalloc(req->rd_size, GFP_KERNEL); |
689 | }; | 694 | if (!buf) |
695 | return -ENOMEM; | ||
696 | |||
697 | if (copy_from_user(buf, req->rd_data, req->rd_size)) { | ||
698 | kfree(buf); | ||
699 | return -EFAULT; | ||
700 | } | ||
701 | |||
702 | ret = hid_parse_report(session->hid, buf, req->rd_size); | ||
703 | |||
704 | kfree(buf); | ||
705 | |||
706 | if (ret) | ||
707 | return ret; | ||
708 | |||
709 | session->req = NULL; | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | static int hidp_start(struct hid_device *hid) | ||
715 | { | ||
716 | struct hidp_session *session = hid->driver_data; | ||
717 | struct hid_report *report; | ||
690 | 718 | ||
691 | static void hidp_setup_quirks(struct hid_device *hid) | 719 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT]. |
720 | report_list, list) | ||
721 | hidp_send_report(session, report); | ||
722 | |||
723 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT]. | ||
724 | report_list, list) | ||
725 | hidp_send_report(session, report); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static void hidp_stop(struct hid_device *hid) | ||
692 | { | 731 | { |
693 | unsigned int n; | 732 | struct hidp_session *session = hid->driver_data; |
733 | |||
734 | skb_queue_purge(&session->ctrl_transmit); | ||
735 | skb_queue_purge(&session->intr_transmit); | ||
694 | 736 | ||
695 | for (n = 0; hidp_blacklist[n].idVendor; n++) | 737 | if (hid->claimed & HID_CLAIMED_INPUT) |
696 | if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) && | 738 | hidinput_disconnect(hid); |
697 | hidp_blacklist[n].idProduct == le16_to_cpu(hid->product)) | 739 | hid->claimed = 0; |
698 | hid->quirks = hidp_blacklist[n].quirks; | ||
699 | } | 740 | } |
700 | 741 | ||
701 | static void hidp_setup_hid(struct hidp_session *session, | 742 | static struct hid_ll_driver hidp_hid_driver = { |
743 | .parse = hidp_parse, | ||
744 | .start = hidp_start, | ||
745 | .stop = hidp_stop, | ||
746 | .open = hidp_open, | ||
747 | .close = hidp_close, | ||
748 | .hidinput_input_event = hidp_hidinput_event, | ||
749 | }; | ||
750 | |||
751 | static int hidp_setup_hid(struct hidp_session *session, | ||
702 | struct hidp_connadd_req *req) | 752 | struct hidp_connadd_req *req) |
703 | { | 753 | { |
704 | struct hid_device *hid = session->hid; | 754 | struct hid_device *hid; |
705 | struct hid_report *report; | ||
706 | bdaddr_t src, dst; | 755 | bdaddr_t src, dst; |
756 | int ret; | ||
707 | 757 | ||
708 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); | 758 | hid = hid_allocate_device(); |
709 | baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); | 759 | if (IS_ERR(hid)) { |
760 | ret = PTR_ERR(session->hid); | ||
761 | goto err; | ||
762 | } | ||
710 | 763 | ||
764 | session->hid = hid; | ||
765 | session->req = req; | ||
711 | hid->driver_data = session; | 766 | hid->driver_data = session; |
712 | 767 | ||
713 | hid->country = req->country; | 768 | baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); |
769 | baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); | ||
714 | 770 | ||
715 | hid->bus = BUS_BLUETOOTH; | 771 | hid->bus = BUS_BLUETOOTH; |
716 | hid->vendor = req->vendor; | 772 | hid->vendor = req->vendor; |
717 | hid->product = req->product; | 773 | hid->product = req->product; |
718 | hid->version = req->version; | 774 | hid->version = req->version; |
775 | hid->country = req->country; | ||
719 | 776 | ||
720 | strncpy(hid->name, req->name, 128); | 777 | strncpy(hid->name, req->name, 128); |
721 | strncpy(hid->phys, batostr(&src), 64); | 778 | strncpy(hid->phys, batostr(&src), 64); |
722 | strncpy(hid->uniq, batostr(&dst), 64); | 779 | strncpy(hid->uniq, batostr(&dst), 64); |
723 | 780 | ||
724 | hid->dev = hidp_get_device(session); | 781 | hid->dev.parent = hidp_get_device(session); |
725 | 782 | hid->ll_driver = &hidp_hid_driver; | |
726 | hid->hid_open = hidp_open; | ||
727 | hid->hid_close = hidp_close; | ||
728 | |||
729 | hid->hidinput_input_event = hidp_hidinput_event; | ||
730 | 783 | ||
731 | hidp_setup_quirks(hid); | 784 | ret = hid_add_device(hid); |
785 | if (ret) | ||
786 | goto err_hid; | ||
732 | 787 | ||
733 | list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) | 788 | return 0; |
734 | hidp_send_report(session, report); | 789 | err_hid: |
735 | 790 | hid_destroy_device(hid); | |
736 | list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list) | 791 | session->hid = NULL; |
737 | hidp_send_report(session, report); | 792 | err: |
738 | 793 | return ret; | |
739 | if (hidinput_connect(hid) == 0) | ||
740 | hid->claimed |= HID_CLAIMED_INPUT; | ||
741 | } | 794 | } |
742 | 795 | ||
743 | int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) | 796 | int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) |
@@ -757,38 +810,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
757 | 810 | ||
758 | BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size); | 811 | BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size); |
759 | 812 | ||
760 | if (req->rd_size > 0) { | ||
761 | unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL); | ||
762 | |||
763 | if (!buf) { | ||
764 | kfree(session); | ||
765 | return -ENOMEM; | ||
766 | } | ||
767 | |||
768 | if (copy_from_user(buf, req->rd_data, req->rd_size)) { | ||
769 | kfree(buf); | ||
770 | kfree(session); | ||
771 | return -EFAULT; | ||
772 | } | ||
773 | |||
774 | session->hid = hid_parse_report(buf, req->rd_size); | ||
775 | |||
776 | kfree(buf); | ||
777 | |||
778 | if (!session->hid) { | ||
779 | kfree(session); | ||
780 | return -EINVAL; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | if (!session->hid) { | ||
785 | session->input = input_allocate_device(); | ||
786 | if (!session->input) { | ||
787 | kfree(session); | ||
788 | return -ENOMEM; | ||
789 | } | ||
790 | } | ||
791 | |||
792 | down_write(&hidp_session_sem); | 813 | down_write(&hidp_session_sem); |
793 | 814 | ||
794 | s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst); | 815 | s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst); |
@@ -816,15 +837,18 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, | |||
816 | session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); | 837 | session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); |
817 | session->idle_to = req->idle_to; | 838 | session->idle_to = req->idle_to; |
818 | 839 | ||
819 | if (session->input) { | 840 | if (req->rd_size > 0) { |
841 | err = hidp_setup_hid(session, req); | ||
842 | if (err && err != -ENODEV) | ||
843 | goto err_skb; | ||
844 | } | ||
845 | |||
846 | if (!session->hid) { | ||
820 | err = hidp_setup_input(session, req); | 847 | err = hidp_setup_input(session, req); |
821 | if (err < 0) | 848 | if (err < 0) |
822 | goto failed; | 849 | goto err_skb; |
823 | } | 850 | } |
824 | 851 | ||
825 | if (session->hid) | ||
826 | hidp_setup_hid(session, req); | ||
827 | |||
828 | __hidp_link_session(session); | 852 | __hidp_link_session(session); |
829 | 853 | ||
830 | hidp_set_timer(session); | 854 | hidp_set_timer(session); |
@@ -850,17 +874,16 @@ unlink: | |||
850 | 874 | ||
851 | __hidp_unlink_session(session); | 875 | __hidp_unlink_session(session); |
852 | 876 | ||
853 | if (session->input) { | 877 | if (session->input) |
854 | input_unregister_device(session->input); | 878 | input_unregister_device(session->input); |
855 | session->input = NULL; /* don't try to free it here */ | 879 | if (session->hid) |
856 | } | 880 | hid_destroy_device(session->hid); |
857 | 881 | err_skb: | |
882 | skb_queue_purge(&session->ctrl_transmit); | ||
883 | skb_queue_purge(&session->intr_transmit); | ||
858 | failed: | 884 | failed: |
859 | up_write(&hidp_session_sem); | 885 | up_write(&hidp_session_sem); |
860 | 886 | ||
861 | if (session->hid) | ||
862 | hid_free_device(session->hid); | ||
863 | |||
864 | input_free_device(session->input); | 887 | input_free_device(session->input); |
865 | kfree(session); | 888 | kfree(session); |
866 | return err; | 889 | return err; |
@@ -950,18 +973,43 @@ int hidp_get_conninfo(struct hidp_conninfo *ci) | |||
950 | return err; | 973 | return err; |
951 | } | 974 | } |
952 | 975 | ||
976 | static const struct hid_device_id hidp_table[] = { | ||
977 | { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) }, | ||
978 | { } | ||
979 | }; | ||
980 | |||
981 | static struct hid_driver hidp_driver = { | ||
982 | .name = "generic-bluetooth", | ||
983 | .id_table = hidp_table, | ||
984 | }; | ||
985 | |||
953 | static int __init hidp_init(void) | 986 | static int __init hidp_init(void) |
954 | { | 987 | { |
988 | int ret; | ||
989 | |||
955 | l2cap_load(); | 990 | l2cap_load(); |
956 | 991 | ||
957 | BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION); | 992 | BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION); |
958 | 993 | ||
959 | return hidp_init_sockets(); | 994 | ret = hid_register_driver(&hidp_driver); |
995 | if (ret) | ||
996 | goto err; | ||
997 | |||
998 | ret = hidp_init_sockets(); | ||
999 | if (ret) | ||
1000 | goto err_drv; | ||
1001 | |||
1002 | return 0; | ||
1003 | err_drv: | ||
1004 | hid_unregister_driver(&hidp_driver); | ||
1005 | err: | ||
1006 | return ret; | ||
960 | } | 1007 | } |
961 | 1008 | ||
962 | static void __exit hidp_exit(void) | 1009 | static void __exit hidp_exit(void) |
963 | { | 1010 | { |
964 | hidp_cleanup_sockets(); | 1011 | hidp_cleanup_sockets(); |
1012 | hid_unregister_driver(&hidp_driver); | ||
965 | } | 1013 | } |
966 | 1014 | ||
967 | module_init(hidp_init); | 1015 | module_init(hidp_init); |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index 343fb0566b3e..e503c89057ad 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
@@ -151,6 +151,8 @@ struct hidp_session { | |||
151 | 151 | ||
152 | struct sk_buff_head ctrl_transmit; | 152 | struct sk_buff_head ctrl_transmit; |
153 | struct sk_buff_head intr_transmit; | 153 | struct sk_buff_head intr_transmit; |
154 | |||
155 | struct hidp_connadd_req *req; | ||
154 | }; | 156 | }; |
155 | 157 | ||
156 | static inline void hidp_schedule(struct hidp_session *session) | 158 | static inline void hidp_schedule(struct hidp_session *session) |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 3396d5bdef1c..9610a9c85b98 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -55,7 +55,7 @@ | |||
55 | #define BT_DBG(D...) | 55 | #define BT_DBG(D...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define VERSION "2.10" | 58 | #define VERSION "2.11" |
59 | 59 | ||
60 | static u32 l2cap_feat_mask = 0x0000; | 60 | static u32 l2cap_feat_mask = 0x0000; |
61 | 61 | ||
@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk) | |||
778 | struct l2cap_conn *conn; | 778 | struct l2cap_conn *conn; |
779 | struct hci_conn *hcon; | 779 | struct hci_conn *hcon; |
780 | struct hci_dev *hdev; | 780 | struct hci_dev *hdev; |
781 | __u8 auth_type; | ||
781 | int err = 0; | 782 | int err = 0; |
782 | 783 | ||
783 | BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); | 784 | BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm); |
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk) | |||
789 | 790 | ||
790 | err = -ENOMEM; | 791 | err = -ENOMEM; |
791 | 792 | ||
792 | hcon = hci_connect(hdev, ACL_LINK, dst); | 793 | if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH || |
794 | l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT || | ||
795 | l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) { | ||
796 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
797 | auth_type = HCI_AT_NO_BONDING_MITM; | ||
798 | else | ||
799 | auth_type = HCI_AT_GENERAL_BONDING_MITM; | ||
800 | } else { | ||
801 | if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) | ||
802 | auth_type = HCI_AT_NO_BONDING; | ||
803 | else | ||
804 | auth_type = HCI_AT_GENERAL_BONDING; | ||
805 | } | ||
806 | |||
807 | hcon = hci_connect(hdev, ACL_LINK, dst, auth_type); | ||
793 | if (!hcon) | 808 | if (!hcon) |
794 | goto done; | 809 | goto done; |
795 | 810 | ||
@@ -1553,10 +1568,10 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1553 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 1568 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
1554 | struct l2cap_conn_rsp rsp; | 1569 | struct l2cap_conn_rsp rsp; |
1555 | struct sock *sk, *parent; | 1570 | struct sock *sk, *parent; |
1556 | int result, status = 0; | 1571 | int result, status = L2CAP_CS_NO_INFO; |
1557 | 1572 | ||
1558 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); | 1573 | u16 dcid = 0, scid = __le16_to_cpu(req->scid); |
1559 | __le16 psm = req->psm; | 1574 | __le16 psm = req->psm; |
1560 | 1575 | ||
1561 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); | 1576 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); |
1562 | 1577 | ||
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
1567 | goto sendresp; | 1582 | goto sendresp; |
1568 | } | 1583 | } |
1569 | 1584 | ||
1585 | /* Check if the ACL is secure enough (if not SDP) */ | ||
1586 | if (psm != cpu_to_le16(0x0001) && | ||
1587 | !hci_conn_check_link_mode(conn->hcon)) { | ||
1588 | result = L2CAP_CR_SEC_BLOCK; | ||
1589 | goto response; | ||
1590 | } | ||
1591 | |||
1570 | result = L2CAP_CR_NO_MEM; | 1592 | result = L2CAP_CR_NO_MEM; |
1571 | 1593 | ||
1572 | /* Check for backlog size */ | 1594 | /* Check for backlog size */ |
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status) | |||
2224 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2246 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2225 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2247 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2226 | rsp.result = cpu_to_le16(result); | 2248 | rsp.result = cpu_to_le16(result); |
2227 | rsp.status = cpu_to_le16(0); | 2249 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
2228 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2250 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2229 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2251 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2230 | } | 2252 | } |
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
2296 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); | 2318 | rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid); |
2297 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); | 2319 | rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); |
2298 | rsp.result = cpu_to_le16(result); | 2320 | rsp.result = cpu_to_le16(result); |
2299 | rsp.status = cpu_to_le16(0); | 2321 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
2300 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 2322 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
2301 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 2323 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
2302 | } | 2324 | } |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index a16011fedc1d..0cc91e6da76d 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -200,7 +200,7 @@ static int sco_connect(struct sock *sk) | |||
200 | else | 200 | else |
201 | type = SCO_LINK; | 201 | type = SCO_LINK; |
202 | 202 | ||
203 | hcon = hci_connect(hdev, type, dst); | 203 | hcon = hci_connect(hdev, type, dst, HCI_AT_NO_BONDING); |
204 | if (!hcon) | 204 | if (!hcon) |
205 | goto done; | 205 | goto done; |
206 | 206 | ||