Commit 7bc2444c authored by Marcel Holtmann's avatar Marcel Holtmann Committed by Marcel Holtmann

[Bluetooth] Add security callback to the core

To give higher layers like RFCOMM the possibility to use the Bluetooth
security mechanisms, they need a way to get feedback from the HCI core 
layer when they succeeded or failed. This patch introduces a callback
structure that can be used for this kind of notification.
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 0cf54fa6
...@@ -161,7 +161,9 @@ struct hci_conn { ...@@ -161,7 +161,9 @@ struct hci_conn {
extern struct hci_proto *hci_proto[]; extern struct hci_proto *hci_proto[];
extern struct list_head hci_dev_list; extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock; extern rwlock_t hci_dev_list_lock;
extern rwlock_t hci_cb_list_lock;
/* ----- Inquiry cache ----- */ /* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds #define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds
...@@ -491,6 +493,50 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status) ...@@ -491,6 +493,50 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status)
int hci_register_proto(struct hci_proto *hproto); int hci_register_proto(struct hci_proto *hproto);
int hci_unregister_proto(struct hci_proto *hproto); int hci_unregister_proto(struct hci_proto *hproto);
/* ----- HCI callbacks ----- */
struct hci_cb {
struct list_head list;
char *name;
void (*auth_cfm) (struct hci_conn *conn, __u8 status);
void (*encrypt_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
};
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head *p;
hci_proto_auth_cfm(conn, status);
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);
}
read_unlock_bh(&hci_cb_list_lock);
}
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
{
struct list_head *p;
hci_proto_encrypt_cfm(conn, status);
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);
}
read_unlock_bh(&hci_cb_list_lock);
}
int hci_register_cb(struct hci_cb *hcb);
int hci_unregister_cb(struct hci_cb *hcb);
int hci_register_notifier(struct notifier_block *nb); int hci_register_notifier(struct notifier_block *nb);
int hci_unregister_notifier(struct notifier_block *nb); int hci_unregister_notifier(struct notifier_block *nb);
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
#define BT_DBG(D...) #define BT_DBG(D...)
#endif #endif
#define VERSION "2.6" #define VERSION "2.7"
struct proc_dir_entry *proc_bt; struct proc_dir_entry *proc_bt;
EXPORT_SYMBOL(proc_bt); EXPORT_SYMBOL(proc_bt);
......
...@@ -65,6 +65,10 @@ rwlock_t hci_task_lock = RW_LOCK_UNLOCKED; ...@@ -65,6 +65,10 @@ rwlock_t hci_task_lock = RW_LOCK_UNLOCKED;
LIST_HEAD(hci_dev_list); LIST_HEAD(hci_dev_list);
rwlock_t hci_dev_list_lock = RW_LOCK_UNLOCKED; rwlock_t hci_dev_list_lock = RW_LOCK_UNLOCKED;
/* HCI callback list */
LIST_HEAD(hci_cb_list);
rwlock_t hci_cb_list_lock = RW_LOCK_UNLOCKED;
/* HCI protocols */ /* HCI protocols */
#define HCI_MAX_PROTO 2 #define HCI_MAX_PROTO 2
struct hci_proto *hci_proto[HCI_MAX_PROTO]; struct hci_proto *hci_proto[HCI_MAX_PROTO];
...@@ -930,6 +934,30 @@ int hci_unregister_proto(struct hci_proto *hp) ...@@ -930,6 +934,30 @@ int hci_unregister_proto(struct hci_proto *hp)
} }
EXPORT_SYMBOL(hci_unregister_proto); EXPORT_SYMBOL(hci_unregister_proto);
int hci_register_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
write_lock_bh(&hci_cb_list_lock);
list_add(&cb->list, &hci_cb_list);
write_unlock_bh(&hci_cb_list_lock);
return 0;
}
EXPORT_SYMBOL(hci_register_cb);
int hci_unregister_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
write_lock_bh(&hci_cb_list_lock);
list_del(&cb->list);
write_unlock_bh(&hci_cb_list_lock);
return 0;
}
EXPORT_SYMBOL(hci_unregister_cb);
static int hci_send_frame(struct sk_buff *skb) static int hci_send_frame(struct sk_buff *skb)
{ {
struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct hci_dev *hdev = (struct hci_dev *) skb->dev;
......
...@@ -739,7 +739,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -739,7 +739,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
conn->link_mode |= HCI_LM_AUTH; conn->link_mode |= HCI_LM_AUTH;
clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
hci_proto_auth_cfm(conn, ev->status); hci_auth_cfm(conn, ev->status);
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
if (!ev->status) { if (!ev->status) {
...@@ -751,7 +751,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -751,7 +751,7 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
sizeof(cp), &cp); sizeof(cp), &cp);
} else { } else {
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_proto_encrypt_cfm(conn, ev->status); hci_encrypt_cfm(conn, ev->status, 0x00);
} }
} }
} }
...@@ -780,7 +780,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -780,7 +780,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
} }
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
hci_proto_encrypt_cfm(conn, ev->status); hci_encrypt_cfm(conn, ev->status, ev->encrypt);
} }
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment