Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266356
b: refs/heads/master
c: 85a8eef
h: refs/heads/master
v: v3
  • Loading branch information
John W. Linville committed Sep 27, 2011
1 parent 9d64a19 commit 3ac5d3f
Show file tree
Hide file tree
Showing 15 changed files with 539 additions and 288 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6b661895a195f244097a60d4d4c9f09983d7efc7
refs/heads/master: 85a8eefdc9ee5ec222fb146a4df5d67c306488c4
10 changes: 10 additions & 0 deletions trunk/include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,16 @@ struct hci_rp_read_bd_addr {
bdaddr_t bdaddr;
} __packed;

#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
struct hci_cp_write_page_scan_activity {
__le16 interval;
__le16 window;
} __packed;

#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
#define PAGE_SCAN_TYPE_STANDARD 0x00
#define PAGE_SCAN_TYPE_INTERLACED 0x01

#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct hci_cp_le_set_event_mask {
__u8 mask[8];
Expand Down
25 changes: 21 additions & 4 deletions trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,6 @@ struct hci_dev {

__u16 init_last_cmd;

struct crypto_blkcipher *tfm;

struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
struct list_head blacklist;
Expand Down Expand Up @@ -348,6 +346,7 @@ enum {
HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND,
HCI_CONN_SCO_SETUP_PEND,
HCI_CONN_LE_SMP_PEND,
};

static inline void hci_conn_hash_init(struct hci_dev *hdev)
Expand Down Expand Up @@ -395,6 +394,22 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
}
}

static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
{
struct hci_conn_hash *h = &hdev->conn_hash;
switch (type) {
case ACL_LINK:
return h->acl_num;
case LE_LINK:
return h->le_num;
case SCO_LINK:
case ESCO_LINK:
return h->sco_num;
default:
return 0;
}
}

static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16 handle)
{
Expand Down Expand Up @@ -475,7 +490,7 @@ static inline void hci_conn_put(struct hci_conn *conn)
{
if (atomic_dec_and_test(&conn->refcnt)) {
unsigned long timeo;
if (conn->type == ACL_LINK) {
if (conn->type == ACL_LINK || conn->type == LE_LINK) {
del_timer(&conn->idle_timer);
if (conn->state == BT_CONNECTED) {
timeo = msecs_to_jiffies(conn->disc_timeout);
Expand Down Expand Up @@ -838,7 +853,7 @@ int mgmt_powered(u16 index, u8 powered);
int mgmt_discoverable(u16 index, u8 discoverable);
int mgmt_connectable(u16 index, u8 connectable);
int mgmt_new_key(u16 index, struct link_key *key, u8 persistent);
int mgmt_connected(u16 index, bdaddr_t *bdaddr);
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type);
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
Expand All @@ -858,6 +873,8 @@ int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
u8 *eir);
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
int mgmt_discovering(u16 index, u8 discovering);
int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr);
int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr);

/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
Expand Down
8 changes: 1 addition & 7 deletions trunk/include/net/bluetooth/l2cap.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,14 +409,8 @@ struct l2cap_conn {

__u8 disc_reason;

__u8 preq[7]; /* SMP Pairing Request */
__u8 prsp[7]; /* SMP Pairing Response */
__u8 prnd[16]; /* SMP Pairing Random */
__u8 pcnf[16]; /* SMP Pairing Confirm */
__u8 tk[16]; /* SMP Temporary Key */
__u8 smp_key_size;

struct timer_list security_timer;
struct smp_chan *smp_chan;

struct list_head chan_l;
rwlock_t chan_lock;
Expand Down
16 changes: 16 additions & 0 deletions trunk/include/net/bluetooth/mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ struct mgmt_cp_unblock_device {
bdaddr_t bdaddr;
} __packed;

#define MGMT_OP_SET_FAST_CONNECTABLE 0x001F
struct mgmt_cp_set_fast_connectable {
__u8 enable;
} __packed;

#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
Expand Down Expand Up @@ -249,6 +254,7 @@ struct mgmt_ev_new_key {
#define MGMT_EV_CONNECTED 0x000B
struct mgmt_ev_connected {
bdaddr_t bdaddr;
__u8 link_type;
} __packed;

#define MGMT_EV_DISCONNECTED 0x000C
Expand Down Expand Up @@ -301,3 +307,13 @@ struct mgmt_ev_remote_name {
} __packed;

#define MGMT_EV_DISCOVERING 0x0014

#define MGMT_EV_DEVICE_BLOCKED 0x0015
struct mgmt_ev_device_blocked {
bdaddr_t bdaddr;
} __packed;

#define MGMT_EV_DEVICE_UNBLOCKED 0x0016
struct mgmt_ev_device_unblocked {
bdaddr_t bdaddr;
} __packed;
17 changes: 17 additions & 0 deletions trunk/include/net/bluetooth/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,26 @@ struct smp_cmd_security_req {
#define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16

struct smp_chan {
struct l2cap_conn *conn;
u8 preq[7]; /* SMP Pairing Request */
u8 prsp[7]; /* SMP Pairing Response */
u8 prnd[16]; /* SMP Pairing Random (local) */
u8 rrnd[16]; /* SMP Pairing Random (remote) */
u8 pcnf[16]; /* SMP Pairing Confirm */
u8 tk[16]; /* SMP Temporary Key */
u8 smp_key_size;
struct crypto_blkcipher *tfm;
struct work_struct confirm;
struct work_struct random;

};

/* SMP Commands */
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);

void smp_chan_destroy(struct l2cap_conn *conn);

#endif /* __SMP_H */
2 changes: 1 addition & 1 deletion trunk/net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
cp.handle = cpu_to_le16(conn->handle);
memcpy(cp.ltk, ltk, sizeof(cp.ltk));
cp.ediv = ediv;
memcpy(cp.rand, rand, sizeof(rand));
memcpy(cp.rand, rand, sizeof(cp.rand));

hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
}
Expand Down
57 changes: 23 additions & 34 deletions trunk/net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1312,59 +1312,41 @@ int hci_blacklist_clear(struct hci_dev *hdev)
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct bdaddr_list *entry;
int err;

if (bacmp(bdaddr, BDADDR_ANY) == 0)
return -EBADF;

hci_dev_lock_bh(hdev);

if (hci_blacklist_lookup(hdev, bdaddr)) {
err = -EEXIST;
goto err;
}
if (hci_blacklist_lookup(hdev, bdaddr))
return -EEXIST;

entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
if (!entry) {
err = -ENOMEM;
goto err;
}
if (!entry)
return -ENOMEM;

bacpy(&entry->bdaddr, bdaddr);

list_add(&entry->list, &hdev->blacklist);

err = 0;

err:
hci_dev_unlock_bh(hdev);
return err;
return mgmt_device_blocked(hdev->id, bdaddr);
}

int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct bdaddr_list *entry;
int err = 0;

hci_dev_lock_bh(hdev);

if (bacmp(bdaddr, BDADDR_ANY) == 0) {
hci_blacklist_clear(hdev);
goto done;
return hci_blacklist_clear(hdev);
}

entry = hci_blacklist_lookup(hdev, bdaddr);
if (!entry) {
err = -ENOENT;
goto done;
return -ENOENT;
}

list_del(&entry->list);
kfree(entry);

done:
hci_dev_unlock_bh(hdev);
return err;
return mgmt_device_unblocked(hdev->id, bdaddr);
}

static void hci_clear_adv_cache(unsigned long arg)
Expand Down Expand Up @@ -1523,11 +1505,6 @@ int hci_register_dev(struct hci_dev *hdev)
if (!hdev->workqueue)
goto nomem;

hdev->tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(hdev->tfm))
BT_INFO("Failed to load transform for ecb(aes): %ld",
PTR_ERR(hdev->tfm));

hci_register_sysfs(hdev);

hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
Expand Down Expand Up @@ -1576,9 +1553,6 @@ int hci_unregister_dev(struct hci_dev *hdev)
!test_bit(HCI_SETUP, &hdev->flags))
mgmt_index_removed(hdev->id);

if (!IS_ERR(hdev->tfm))
crypto_free_blkcipher(hdev->tfm);

hci_notify(hdev, HCI_DEV_UNREG);

if (hdev->rfkill) {
Expand Down Expand Up @@ -2074,6 +2048,9 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
min = c->sent;
conn = c;
}

if (hci_conn_num(hdev, type) == num)
break;
}

if (conn) {
Expand Down Expand Up @@ -2131,6 +2108,9 @@ static inline void hci_sched_acl(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

if (!hci_conn_num(hdev, ACL_LINK))
return;

if (!test_bit(HCI_RAW, &hdev->flags)) {
/* ACL tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
Expand Down Expand Up @@ -2162,6 +2142,9 @@ static inline void hci_sched_sco(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

if (!hci_conn_num(hdev, SCO_LINK))
return;

while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, &quote))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
BT_DBG("skb %p len %d", skb, skb->len);
Expand All @@ -2182,6 +2165,9 @@ static inline void hci_sched_esco(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

if (!hci_conn_num(hdev, ESCO_LINK))
return;

while (hdev->sco_cnt && (conn = hci_low_sent(hdev, ESCO_LINK, &quote))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
BT_DBG("skb %p len %d", skb, skb->len);
Expand All @@ -2202,6 +2188,9 @@ static inline void hci_sched_le(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

if (!hci_conn_num(hdev, LE_LINK))
return;

if (!test_bit(HCI_RAW, &hdev->flags)) {
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
Expand Down
16 changes: 8 additions & 8 deletions trunk/net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,16 +898,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
if (!cp)
return;

hci_dev_lock(hdev);

if (cp->enable == 0x01) {
del_timer(&hdev->adv_timer);

hci_dev_lock(hdev);
hci_adv_entries_clear(hdev);
hci_dev_unlock(hdev);
} else if (cp->enable == 0x00) {
mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
}

hci_dev_unlock(hdev);
}

static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
Expand Down Expand Up @@ -1103,9 +1102,10 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev,
return 0;

/* Only request authentication for SSP connections or non-SSP
* devices with sec_level HIGH */
* devices with sec_level HIGH or if MITM protection is requested */
if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
conn->pending_sec_level != BT_SECURITY_HIGH)
conn->pending_sec_level != BT_SECURITY_HIGH &&
!(conn->auth_type & 0x01))
return 0;

return 1;
Expand Down Expand Up @@ -1412,7 +1412,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn->state = BT_CONFIG;
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
mgmt_connected(hdev->id, &ev->bdaddr);
mgmt_connected(hdev->id, &ev->bdaddr, conn->type);
} else
conn->state = BT_CONNECTED;

Expand Down Expand Up @@ -2816,7 +2816,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
goto unlock;
}

mgmt_connected(hdev->id, &ev->bdaddr);
mgmt_connected(hdev->id, &ev->bdaddr, conn->type);

conn->sec_level = BT_SECURITY_LOW;
conn->handle = __le16_to_cpu(ev->handle);
Expand Down
Loading

0 comments on commit 3ac5d3f

Please sign in to comment.