diff options
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r-- | net/bluetooth/hci_conn.c | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index a4a789f24c8d..98f97a1e9bbb 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -325,7 +325,7 @@ EXPORT_SYMBOL(hci_get_route); | |||
325 | 325 | ||
326 | /* Create SCO or ACL connection. | 326 | /* Create SCO or ACL connection. |
327 | * Device _must_ be locked */ | 327 | * Device _must_ be locked */ |
328 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type) | 328 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type) |
329 | { | 329 | { |
330 | struct hci_conn *acl; | 330 | struct hci_conn *acl; |
331 | struct hci_conn *sco; | 331 | struct hci_conn *sco; |
@@ -340,6 +340,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 | |||
340 | hci_conn_hold(acl); | 340 | hci_conn_hold(acl); |
341 | 341 | ||
342 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { | 342 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) { |
343 | acl->sec_level = sec_level; | ||
343 | acl->auth_type = auth_type; | 344 | acl->auth_type = auth_type; |
344 | hci_acl_connect(acl); | 345 | hci_acl_connect(acl); |
345 | } | 346 | } |
@@ -385,16 +386,17 @@ int hci_conn_check_link_mode(struct hci_conn *conn) | |||
385 | EXPORT_SYMBOL(hci_conn_check_link_mode); | 386 | EXPORT_SYMBOL(hci_conn_check_link_mode); |
386 | 387 | ||
387 | /* Authenticate remote device */ | 388 | /* Authenticate remote device */ |
388 | int hci_conn_auth(struct hci_conn *conn) | 389 | static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level) |
389 | { | 390 | { |
390 | BT_DBG("conn %p", conn); | 391 | BT_DBG("conn %p", conn); |
391 | 392 | ||
392 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) { | 393 | if (sec_level > conn->sec_level) |
393 | if (!(conn->auth_type & 0x01)) { | 394 | conn->link_mode &= ~HCI_LM_AUTH; |
394 | conn->auth_type |= 0x01; | 395 | |
395 | conn->link_mode &= ~HCI_LM_AUTH; | 396 | conn->sec_level = sec_level; |
396 | } | 397 | |
397 | } | 398 | if (sec_level == BT_SECURITY_HIGH) |
399 | conn->auth_type |= 0x01; | ||
398 | 400 | ||
399 | if (conn->link_mode & HCI_LM_AUTH) | 401 | if (conn->link_mode & HCI_LM_AUTH) |
400 | return 1; | 402 | return 1; |
@@ -405,31 +407,42 @@ int hci_conn_auth(struct hci_conn *conn) | |||
405 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, | 407 | hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, |
406 | sizeof(cp), &cp); | 408 | sizeof(cp), &cp); |
407 | } | 409 | } |
410 | |||
408 | return 0; | 411 | return 0; |
409 | } | 412 | } |
410 | EXPORT_SYMBOL(hci_conn_auth); | ||
411 | 413 | ||
412 | /* Enable encryption */ | 414 | /* Enable security */ |
413 | int hci_conn_encrypt(struct hci_conn *conn) | 415 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level) |
414 | { | 416 | { |
415 | BT_DBG("conn %p", conn); | 417 | BT_DBG("conn %p", conn); |
416 | 418 | ||
419 | if (sec_level == BT_SECURITY_SDP) | ||
420 | return 1; | ||
421 | |||
422 | if (sec_level == BT_SECURITY_LOW) { | ||
423 | if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) | ||
424 | return hci_conn_auth(conn, sec_level); | ||
425 | else | ||
426 | return 1; | ||
427 | } | ||
428 | |||
417 | if (conn->link_mode & HCI_LM_ENCRYPT) | 429 | if (conn->link_mode & HCI_LM_ENCRYPT) |
418 | return hci_conn_auth(conn); | 430 | return hci_conn_auth(conn, sec_level); |
419 | 431 | ||
420 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) | 432 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) |
421 | return 0; | 433 | return 0; |
422 | 434 | ||
423 | if (hci_conn_auth(conn)) { | 435 | if (hci_conn_auth(conn, sec_level)) { |
424 | struct hci_cp_set_conn_encrypt cp; | 436 | struct hci_cp_set_conn_encrypt cp; |
425 | cp.handle = cpu_to_le16(conn->handle); | 437 | cp.handle = cpu_to_le16(conn->handle); |
426 | cp.encrypt = 1; | 438 | cp.encrypt = 1; |
427 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, | 439 | hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, |
428 | sizeof(cp), &cp); | 440 | sizeof(cp), &cp); |
429 | } | 441 | } |
442 | |||
430 | return 0; | 443 | return 0; |
431 | } | 444 | } |
432 | EXPORT_SYMBOL(hci_conn_encrypt); | 445 | EXPORT_SYMBOL(hci_conn_security); |
433 | 446 | ||
434 | /* Change link key */ | 447 | /* Change link key */ |
435 | int hci_conn_change_link_key(struct hci_conn *conn) | 448 | int hci_conn_change_link_key(struct hci_conn *conn) |
@@ -442,12 +455,13 @@ int hci_conn_change_link_key(struct hci_conn *conn) | |||
442 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, | 455 | hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, |
443 | sizeof(cp), &cp); | 456 | sizeof(cp), &cp); |
444 | } | 457 | } |
458 | |||
445 | return 0; | 459 | return 0; |
446 | } | 460 | } |
447 | EXPORT_SYMBOL(hci_conn_change_link_key); | 461 | EXPORT_SYMBOL(hci_conn_change_link_key); |
448 | 462 | ||
449 | /* Switch role */ | 463 | /* Switch role */ |
450 | int hci_conn_switch_role(struct hci_conn *conn, uint8_t role) | 464 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role) |
451 | { | 465 | { |
452 | BT_DBG("conn %p", conn); | 466 | BT_DBG("conn %p", conn); |
453 | 467 | ||
@@ -460,6 +474,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role) | |||
460 | cp.role = role; | 474 | cp.role = role; |
461 | hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); | 475 | hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp); |
462 | } | 476 | } |
477 | |||
463 | return 0; | 478 | return 0; |
464 | } | 479 | } |
465 | EXPORT_SYMBOL(hci_conn_switch_role); | 480 | EXPORT_SYMBOL(hci_conn_switch_role); |