diff options
author | Vinicius Costa Gomes <vinicius.gomes@openbossa.org> | 2011-01-26 19:42:57 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-06-13 15:05:34 -0400 |
commit | f1cb9af557dd8fb5d98fbcc4b5d3eb9d6d235af7 (patch) | |
tree | e2701e2cecfbf5cea1a079a7a87f8bfe020b7598 /net/bluetooth/smp.c | |
parent | 9b3d67405b17d61ba8be9d824222fb410f487b8a (diff) |
Bluetooth: Add support for resuming socket when SMP is finished
This adds support for resuming the user space traffic when SMP
negotiation is complete.
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 | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 69839797b7dc..da46d76fc13d 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -336,9 +336,13 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
336 | { | 336 | { |
337 | struct smp_cmd_security_req *rp = (void *) skb->data; | 337 | struct smp_cmd_security_req *rp = (void *) skb->data; |
338 | struct smp_cmd_pairing cp; | 338 | struct smp_cmd_pairing cp; |
339 | struct hci_conn *hcon = conn->hcon; | ||
339 | 340 | ||
340 | BT_DBG("conn %p", conn); | 341 | BT_DBG("conn %p", conn); |
341 | 342 | ||
343 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | ||
344 | return; | ||
345 | |||
342 | skb_pull(skb, sizeof(*rp)); | 346 | skb_pull(skb, sizeof(*rp)); |
343 | memset(&cp, 0, sizeof(cp)); | 347 | memset(&cp, 0, sizeof(cp)); |
344 | 348 | ||
@@ -353,6 +357,20 @@ static void smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
353 | memcpy(&conn->preq[1], &cp, sizeof(cp)); | 357 | memcpy(&conn->preq[1], &cp, sizeof(cp)); |
354 | 358 | ||
355 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 359 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
360 | |||
361 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
362 | } | ||
363 | |||
364 | static __u8 seclevel_to_authreq(__u8 level) | ||
365 | { | ||
366 | switch (level) { | ||
367 | case BT_SECURITY_HIGH: | ||
368 | /* For now we don't support bonding */ | ||
369 | return SMP_AUTH_MITM; | ||
370 | |||
371 | default: | ||
372 | return SMP_AUTH_NONE; | ||
373 | } | ||
356 | } | 374 | } |
357 | 375 | ||
358 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | 376 | int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) |
@@ -365,21 +383,16 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
365 | if (IS_ERR(hcon->hdev->tfm)) | 383 | if (IS_ERR(hcon->hdev->tfm)) |
366 | return 1; | 384 | return 1; |
367 | 385 | ||
368 | switch (sec_level) { | 386 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) |
369 | case BT_SECURITY_MEDIUM: | 387 | return 0; |
370 | /* Encrypted, no MITM protection */ | ||
371 | authreq = HCI_AT_NO_BONDING_MITM; | ||
372 | break; | ||
373 | 388 | ||
374 | case BT_SECURITY_HIGH: | 389 | if (sec_level == BT_SECURITY_LOW) |
375 | /* Bonding, MITM protection */ | 390 | return 1; |
376 | authreq = HCI_AT_GENERAL_BONDING_MITM; | ||
377 | break; | ||
378 | 391 | ||
379 | case BT_SECURITY_LOW: | 392 | if (hcon->sec_level >= sec_level) |
380 | default: | ||
381 | return 1; | 393 | return 1; |
382 | } | 394 | |
395 | authreq = seclevel_to_authreq(sec_level); | ||
383 | 396 | ||
384 | if (hcon->link_mode & HCI_LM_MASTER) { | 397 | if (hcon->link_mode & HCI_LM_MASTER) { |
385 | struct smp_cmd_pairing cp; | 398 | struct smp_cmd_pairing cp; |
@@ -400,6 +413,9 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
400 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); | 413 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); |
401 | } | 414 | } |
402 | 415 | ||
416 | hcon->pending_sec_level = sec_level; | ||
417 | set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend); | ||
418 | |||
403 | return 0; | 419 | return 0; |
404 | } | 420 | } |
405 | 421 | ||