diff options
author | Vinicius Costa Gomes <vinicius.gomes@openbossa.org> | 2011-08-19 20:06:51 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-09-21 11:58:11 -0400 |
commit | d26a23454813908a1bf0e2fd8c73233b22c6dbd7 (patch) | |
tree | 20a47fdba8e49371265684bc2ed2306d7c042195 /net/bluetooth/smp.c | |
parent | e2dcd113d15ef99d23498859e7006955b5367698 (diff) |
Bluetooth: Add a flag to indicate that SMP is going on
Add HCI_CONN_LE_SMP_PEND flag to indicate that SMP is pending
for that connection. This allows to have information that an SMP
procedure is going on for that connection.
We use the HCI_CONN_ENCRYPT_PEND to indicate that encryption
(HCI_LE_Start_Encryption) is pending for that connection.
While a SMP procedure is going on we hold an reference to the
connection, to avoid disconnections.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 44 |
1 files changed, 34 insertions, 10 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 20c82c7000ac..f0c67f62a08e 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -248,6 +248,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
248 | 248 | ||
249 | BT_DBG("conn %p", conn); | 249 | BT_DBG("conn %p", conn); |
250 | 250 | ||
251 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) | ||
252 | hci_conn_hold(conn->hcon); | ||
253 | |||
251 | conn->preq[0] = SMP_CMD_PAIRING_REQ; | 254 | conn->preq[0] = SMP_CMD_PAIRING_REQ; |
252 | memcpy(&conn->preq[1], req, sizeof(*req)); | 255 | memcpy(&conn->preq[1], req, sizeof(*req)); |
253 | skb_pull(skb, sizeof(*req)); | 256 | skb_pull(skb, sizeof(*req)); |
@@ -397,6 +400,9 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | |||
397 | memset(stk + conn->smp_key_size, 0, | 400 | memset(stk + conn->smp_key_size, 0, |
398 | SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size); | 401 | SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size); |
399 | 402 | ||
403 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | ||
404 | return SMP_UNSPECIFIED; | ||
405 | |||
400 | hci_le_start_enc(hcon, ediv, rand, stk); | 406 | hci_le_start_enc(hcon, ediv, rand, stk); |
401 | hcon->enc_key_size = conn->smp_key_size; | 407 | hcon->enc_key_size = conn->smp_key_size; |
402 | } else { | 408 | } else { |
@@ -430,9 +436,11 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
430 | 436 | ||
431 | BT_DBG("conn %p", conn); | 437 | BT_DBG("conn %p", conn); |
432 | 438 | ||
433 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | 439 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) |
434 | return 0; | 440 | return 0; |
435 | 441 | ||
442 | hci_conn_hold(hcon); | ||
443 | |||
436 | skb_pull(skb, sizeof(*rp)); | 444 | skb_pull(skb, sizeof(*rp)); |
437 | 445 | ||
438 | memset(&cp, 0, sizeof(cp)); | 446 | memset(&cp, 0, sizeof(cp)); |
@@ -443,8 +451,6 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
443 | 451 | ||
444 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 452 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
445 | 453 | ||
446 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
447 | |||
448 | return 0; | 454 | return 0; |
449 | } | 455 | } |
450 | 456 | ||
@@ -461,19 +467,13 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
461 | if (IS_ERR(hcon->hdev->tfm)) | 467 | if (IS_ERR(hcon->hdev->tfm)) |
462 | return 1; | 468 | return 1; |
463 | 469 | ||
464 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | ||
465 | return 0; | ||
466 | |||
467 | if (sec_level == BT_SECURITY_LOW) | 470 | if (sec_level == BT_SECURITY_LOW) |
468 | return 1; | 471 | return 1; |
469 | 472 | ||
470 | if (hcon->sec_level >= sec_level) | 473 | if (hcon->sec_level >= sec_level) |
471 | return 1; | 474 | return 1; |
472 | 475 | ||
473 | authreq = seclevel_to_authreq(sec_level); | ||
474 | |||
475 | if (hcon->link_mode & HCI_LM_MASTER) { | 476 | if (hcon->link_mode & HCI_LM_MASTER) { |
476 | struct smp_cmd_pairing cp; | ||
477 | struct link_key *key; | 477 | struct link_key *key; |
478 | 478 | ||
479 | key = hci_find_link_key_type(hcon->hdev, conn->dst, | 479 | key = hci_find_link_key_type(hcon->hdev, conn->dst, |
@@ -481,12 +481,28 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
481 | if (key) { | 481 | if (key) { |
482 | struct key_master_id *master = (void *) key->data; | 482 | struct key_master_id *master = (void *) key->data; |
483 | 483 | ||
484 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, | ||
485 | &hcon->pend)) | ||
486 | goto done; | ||
487 | |||
484 | hci_le_start_enc(hcon, master->ediv, master->rand, | 488 | hci_le_start_enc(hcon, master->ediv, master->rand, |
485 | key->val); | 489 | key->val); |
486 | hcon->enc_key_size = key->pin_len; | 490 | hcon->enc_key_size = key->pin_len; |
487 | 491 | ||
488 | goto done; | 492 | goto done; |
489 | } | 493 | } |
494 | } | ||
495 | |||
496 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) | ||
497 | return 0; | ||
498 | |||
499 | /* While SMP is going on */ | ||
500 | hci_conn_hold(hcon); | ||
501 | |||
502 | authreq = seclevel_to_authreq(sec_level); | ||
503 | |||
504 | if (hcon->link_mode & HCI_LM_MASTER) { | ||
505 | struct smp_cmd_pairing cp; | ||
490 | 506 | ||
491 | build_pairing_cmd(conn, &cp, NULL, authreq); | 507 | build_pairing_cmd(conn, &cp, NULL, authreq); |
492 | conn->preq[0] = SMP_CMD_PAIRING_REQ; | 508 | conn->preq[0] = SMP_CMD_PAIRING_REQ; |
@@ -501,7 +517,6 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
501 | 517 | ||
502 | done: | 518 | done: |
503 | hcon->pending_sec_level = sec_level; | 519 | hcon->pending_sec_level = sec_level; |
504 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
505 | 520 | ||
506 | return 0; | 521 | return 0; |
507 | } | 522 | } |
@@ -619,6 +634,9 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
619 | if (IS_ERR(conn->hcon->hdev->tfm)) | 634 | if (IS_ERR(conn->hcon->hdev->tfm)) |
620 | return PTR_ERR(conn->hcon->hdev->tfm); | 635 | return PTR_ERR(conn->hcon->hdev->tfm); |
621 | 636 | ||
637 | if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) | ||
638 | return 0; | ||
639 | |||
622 | rsp = (void *) &conn->prsp[1]; | 640 | rsp = (void *) &conn->prsp[1]; |
623 | 641 | ||
624 | /* The responder sends its keys first */ | 642 | /* The responder sends its keys first */ |
@@ -689,5 +707,11 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
689 | *keydist &= ~SMP_DIST_SIGN; | 707 | *keydist &= ~SMP_DIST_SIGN; |
690 | } | 708 | } |
691 | 709 | ||
710 | if (conn->hcon->out || force) { | ||
711 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); | ||
712 | del_timer(&conn->security_timer); | ||
713 | hci_conn_put(conn->hcon); | ||
714 | } | ||
715 | |||
692 | return 0; | 716 | return 0; |
693 | } | 717 | } |