Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 134717
b: refs/heads/master
c: 8c1b235
h: refs/heads/master
i:
  134715: bb79b38
v: v3
  • Loading branch information
Marcel Holtmann committed Feb 27, 2009
1 parent 6521260 commit 11efc0f
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 192 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: c89b6e6bda4c8021195778f47567d0cc9dbfe7ec
refs/heads/master: 8c1b235594fbab9a13240a1dac12ea9fd99b6440
9 changes: 9 additions & 0 deletions trunk/include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@
#define SOL_SCO 17
#define SOL_RFCOMM 18

#define BT_SECURITY 4
struct bt_security {
__u8 level;
};
#define BT_SECURITY_SDP 0
#define BT_SECURITY_LOW 1
#define BT_SECURITY_MEDIUM 2
#define BT_SECURITY_HIGH 3

#define BT_DEFER_SETUP 7

#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
Expand Down
56 changes: 33 additions & 23 deletions trunk/include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ struct hci_conn {
__u16 link_policy;
__u32 link_mode;
__u8 auth_type;
__u8 sec_level;
__u8 power_save;
unsigned long pend;

Expand Down Expand Up @@ -325,12 +326,11 @@ int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);

struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_auth(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);

void hci_conn_enter_active_mode(struct hci_conn *conn);
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
Expand Down Expand Up @@ -470,26 +470,25 @@ void hci_conn_del_sysfs(struct hci_conn *conn);

/* ----- HCI protocols ----- */
struct hci_proto {
char *name;
char *name;
unsigned int id;
unsigned long flags;

void *priv;

int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
int (*connect_cfm) (struct hci_conn *conn, __u8 status);
int (*disconn_ind) (struct hci_conn *conn, __u8 reason);
int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
int (*auth_cfm) (struct hci_conn *conn, __u8 status);
int (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
};

static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
{
register struct hci_proto *hp;
int mask = 0;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->connect_ind)
mask |= hp->connect_ind(hdev, bdaddr, type);
Expand Down Expand Up @@ -530,27 +529,33 @@ static inline void hci_proto_disconn_ind(struct hci_conn *conn, __u8 reason)
static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
{
register struct hci_proto *hp;
__u8 encrypt;

if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return;

encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->auth_cfm)
hp->auth_cfm(conn, status);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->auth_cfm)
hp->auth_cfm(conn, status);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
}

static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
{
register struct hci_proto *hp;

hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->encrypt_cfm)
hp->encrypt_cfm(conn, status, encrypt);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);

hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->encrypt_cfm)
hp->encrypt_cfm(conn, status, encrypt);
if (hp && hp->security_cfm)
hp->security_cfm(conn, status, encrypt);
}

int hci_register_proto(struct hci_proto *hproto);
Expand All @@ -562,23 +567,28 @@ struct hci_cb {

char *name;

void (*auth_cfm) (struct hci_conn *conn, __u8 status);
void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};

static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head *p;
__u8 encrypt;

hci_proto_auth_cfm(conn, status);

if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return;

encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;

read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->auth_cfm)
cb->auth_cfm(conn, status);
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
read_unlock_bh(&hci_cb_list_lock);
}
Expand All @@ -592,8 +602,8 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encr
read_lock_bh(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->encrypt_cfm)
cb->encrypt_cfm(conn, status, encrypt);
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
read_unlock_bh(&hci_cb_list_lock);
}
Expand Down
45 changes: 30 additions & 15 deletions trunk/net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ EXPORT_SYMBOL(hci_get_route);

/* Create SCO or ACL connection.
* Device _must_ be locked */
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
{
struct hci_conn *acl;
struct hci_conn *sco;
Expand All @@ -340,6 +340,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
hci_conn_hold(acl);

if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
acl->sec_level = sec_level;
acl->auth_type = auth_type;
hci_acl_connect(acl);
}
Expand Down Expand Up @@ -385,16 +386,17 @@ int hci_conn_check_link_mode(struct hci_conn *conn)
EXPORT_SYMBOL(hci_conn_check_link_mode);

/* Authenticate remote device */
int hci_conn_auth(struct hci_conn *conn)
static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level)
{
BT_DBG("conn %p", conn);

if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
if (!(conn->auth_type & 0x01)) {
conn->auth_type |= 0x01;
conn->link_mode &= ~HCI_LM_AUTH;
}
}
if (sec_level > conn->sec_level)
conn->link_mode &= ~HCI_LM_AUTH;

conn->sec_level = sec_level;

if (sec_level == BT_SECURITY_HIGH)
conn->auth_type |= 0x01;

if (conn->link_mode & HCI_LM_AUTH)
return 1;
Expand All @@ -405,31 +407,42 @@ int hci_conn_auth(struct hci_conn *conn)
hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
}

return 0;
}
EXPORT_SYMBOL(hci_conn_auth);

/* Enable encryption */
int hci_conn_encrypt(struct hci_conn *conn)
/* Enable security */
int hci_conn_security(struct hci_conn *conn, __u8 sec_level)
{
BT_DBG("conn %p", conn);

if (sec_level == BT_SECURITY_SDP)
return 1;

if (sec_level == BT_SECURITY_LOW) {
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0)
return hci_conn_auth(conn, sec_level);
else
return 1;
}

if (conn->link_mode & HCI_LM_ENCRYPT)
return hci_conn_auth(conn);
return hci_conn_auth(conn, sec_level);

if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return 0;

if (hci_conn_auth(conn)) {
if (hci_conn_auth(conn, sec_level)) {
struct hci_cp_set_conn_encrypt cp;
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT,
sizeof(cp), &cp);
}

return 0;
}
EXPORT_SYMBOL(hci_conn_encrypt);
EXPORT_SYMBOL(hci_conn_security);

/* Change link key */
int hci_conn_change_link_key(struct hci_conn *conn)
Expand All @@ -442,12 +455,13 @@ int hci_conn_change_link_key(struct hci_conn *conn)
hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY,
sizeof(cp), &cp);
}

return 0;
}
EXPORT_SYMBOL(hci_conn_change_link_key);

/* Switch role */
int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
{
BT_DBG("conn %p", conn);

Expand All @@ -460,6 +474,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
cp.role = role;
hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
}

return 0;
}
EXPORT_SYMBOL(hci_conn_switch_role);
Expand Down
3 changes: 2 additions & 1 deletion trunk/net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1601,7 +1601,8 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b

if (conn->state == BT_CONFIG) {
if (!ev->status && hdev->ssp_mode > 0 &&
conn->ssp_mode > 0 && conn->out) {
conn->ssp_mode > 0 && conn->out &&
conn->sec_level != BT_SECURITY_SDP) {
struct hci_cp_auth_requested cp;
cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
Expand Down
Loading

0 comments on commit 11efc0f

Please sign in to comment.