|
From: Ulf H. <ul...@us...> - 2001-04-26 13:58:18
|
The following file was modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
sec_client.c 1.17 1.18=20=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
Added sec_man_get_cached_link_key, list handling for cached link keys.
Removed "magic" numbers
The diff of the modified file(s):
--- sec_client.c 2001/03/19 12:43:11 1.17
+++ sec_client.c 2001/04/26 13:58:18 1.18
@@ -96,10 +96,48 @@
#define SEC_MAN_SRV_SOCK "/tmp/sec_sock"
#endif
=20
+#define HCI_VALUE_RETURN_LINK_KEYS 0x15
+#define BD_ADDRESS_SIZE 6
+#define LINK_KEY_SIZE 16
+#define BUFFER_SIZE 256
#define MAX_EVENT_DATA_LENGTH 16
+#define MAX_LINKKEYLISTSIZE 255 /* for now */
=20
/****************** TYPE DEFINITION SECTION ******************************=
***/
=20
+typedef struct link_key_information_type {
+ unsigned char bd_addr[BD_ADDRESS_SIZE];
+ unsigned char link_key[LINK_KEY_SIZE];
+=09
+ struct link_key_information_type *prev;
+ struct link_key_information_type *next;
+} link_key_information_type;
+
+typedef struct link_key_list_type {
+ link_key_information_type *first;
+ link_key_information_type *last;
+ link_key_information_type *cur;
+ u32 count;
+} link_key_list_type;
+
+enum originator_types {
+ BT_SEC_MAN,
+ SEC_CLIENT,
+ KERNEL
+};=20
+
+struct security_query {
+ u16 request_type; /* out */
+ u32 request_value; /* out */
+ u8 remote_bd[BD_ADDRESS_SIZE];
+ /* out */
+ u8 event_param[MAX_EVENT_DATA_LENGTH];
+ /* out */
+ u8 originator; /* out/in BT_SEC_MAN, SEC_CLIENT or KERNEL*/
+ u32 originator_data; /* out/in con or rfcomm struct pointer */
+ u16 request_result; /* in */=09
+} security_query;
+
/****************** LOCAL FUNCTION DECLARATION SECTION *******************=
***/
=20
#ifdef __KERNEL__
@@ -122,10 +160,22 @@
static s32 sec_man_doquery(s32 fd, u8 *request);
#endif
=20
+
+void init_link_key_list(void);
+void free_link_key_list(void);
+link_key_information_type* create_link_key(unsigned char *bd_addr,
+ unsigned char *link_key_str);
+link_key_information_type* get_first_link_key(void);
+link_key_information_type* get_next_link_key(link_key_information_type* li=
nk_key);
+void insert_link_key(link_key_information_type *new_link_key);
+s32 delete_link_key(link_key_information_type *link_key);
+
/****************** GLOBAL VARIABLE DECLARATION SECTION ******************=
***/
=20
/****************** LOCAL VARIABLE DECLARATION SECTION *******************=
***/
=20
+static link_key_list_type link_key_list;
+
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
static struct wait_queue *sec_man_wq =3D NULL;
@@ -231,23 +281,6 @@
=20
#endif /* __KERNEL__ */
=20
-enum originator_types {
- BT_SEC_MAN,
- SEC_CLIENT,
- KERNEL
-};=20
-
-struct security_query {
- u16 request_type; /* out */
- u32 request_value; /* out */
- u8 remote_bd[6]; /* out */
- u8 event_param[MAX_EVENT_DATA_LENGTH];
- /* out */
- u8 originator; /* out/in BT_SEC_MAN, SEC_CLIENT or KERNEL*/
- u32 originator_data; /* out/in con or rfcomm struct pointer */
- u16 request_result; /* in */=09
-} security_query;
-
#ifndef __KERNEL__
static s32 sec_man_sock;
#endif
@@ -270,11 +303,135 @@
#ifndef __KERNEL__
sec_man_sock =3D open_socket(SEC_MAN_SRV_SOCK);
#endif
+ init_link_key_list();
=20
/* To indicate that nothing is ready */
security_query.originator =3D SEC_CLIENT;=20
}
=20
+void
+init_link_key_list(void)
+{
+ /* Init list */
+ link_key_list.first =3D NULL;
+ link_key_list.last =3D NULL;
+ link_key_list.cur =3D NULL;
+ link_key_list.count =3D 0;=09
+}
+
+void=20
+free_link_key_list(void)
+{
+ while (link_key_list.count)
+ delete_link_key(link_key_list.first);
+}=20
+
+link_key_information_type*=20
+create_link_key(unsigned char *bd_addr, unsigned char *link_key_str)
+{=20
+ link_key_information_type *link_key;
+
+ if (link_key_list.count =3D=3D MAX_LINKKEYLISTSIZE) {
+ D_ERR("Connection list full!\n");
+ return NULL;
+ }
+ /* Add check if already in list ?? or rely on that otherwhere ?*/
+=20=20
+ /* Allocate new element */
+ if ((link_key =3D kmalloc(sizeof *link_key, GFP_ATOMIC)) < 0) {
+ D_ERR(__FUNCTION__ ": could not allocate new link key element\n");
+ return NULL;
+ }
+=09
+ memcpy(link_key->bd_addr, bd_addr, BD_ADDRESS_SIZE);
+ memcpy(link_key->link_key, link_key_str, LINK_KEY_SIZE);
+
+ link_key->next =3D link_key;
+ link_key->prev =3D link_key;
+
+ return link_key;
+}
+
+link_key_information_type* get_first_link_key(void)
+{
+ return link_key_list.first;
+}
+
+link_key_information_type* get_next_link_key(link_key_information_type* li=
nk_key)
+{
+ if (link_key->next =3D=3D link_key_list.first)
+ return NULL;
+ else
+ return link_key->next;
+}
+
+void=20
+insert_link_key(link_key_information_type *new_link_key)
+{
+ link_key_information_type *old_link_key;
+
+ if (!link_key_list.count) {
+ /* Empty list */
+ D_PROC("Inserting into empty list\n");
+ link_key_list.first =3D new_link_key;=20
+ link_key_list.cur =3D new_link_key;
+ link_key_list.last =3D new_link_key;
+ link_key_list.count++;
+
+ new_link_key->next =3D link_key_list.first; /* Pos32 at itself */
+ new_link_key->prev =3D link_key_list.first;
+
+ return;
+ }
+=20=20
+ /* Not empty */
+ D_PROC("Inserting into list\n");
+=09
+ old_link_key =3D link_key_list.first; /* mark oldlink_key first */
+ new_link_key->next =3D old_link_key;
+ link_key_list.last->next =3D new_link_key;
+ old_link_key->prev =3D new_link_key;
+ new_link_key->prev =3D link_key_list.last;
+=20=20
+ link_key_list.cur =3D new_link_key; /* Set current to new element */
+ link_key_list.first =3D new_link_key; /* Set first to new element */
+ link_key_list.count++;
+}
+
+s32=20
+delete_link_key(link_key_information_type *link_key)
+{=20=20
+ if (link_key_list.count =3D=3D 1) {
+ /* Last element */
+ D_PROC("Deleting last element\n");
+=09=09
+ link_key_list.count--;
+ link_key_list.first =3D NULL;
+ link_key_list.cur =3D NULL;
+ link_key_list.last =3D NULL;
+ kfree(link_key);
+
+ return 0;
+ }
+
+ D_PROC("Deleting element in list\n");
+ link_key->prev->next =3D link_key->next; /* Take it out */
+ link_key->next->prev =3D link_key->prev;
+=20=20
+ if (link_key_list.first =3D=3D link_key) /* Update first pointer */
+ link_key_list.first =3D link_key->next;
+=20=20
+ if (link_key_list.last =3D=3D link_key) /* Update last pointer */
+ link_key_list.last =3D link_key->prev;
+=20=20
+ link_key_list.cur =3D link_key->next; /* Update cur pointer */
+ link_key_list.count--;
+=20=20
+ kfree(link_key);=20
+
+ return 0;=20=20
+}
+
#ifdef __KERNEL__
s32
sec_man_create_proc_file(void)
@@ -357,7 +514,7 @@
=20
security_query.request_type =3D user;
security_query.request_value =3D service_data;
- memcpy(security_query.remote_bd, bd_addr, 6);
+ memcpy(security_query.remote_bd, bd_addr, BD_ADDRESS_SIZE);
security_query.originator =3D BT_SEC_MAN;
security_query.originator_data =3D user_data;
security_query.request_result =3D GENERAL_FAILURE;
@@ -379,16 +536,29 @@
{
#define FNC "sec_man_event: "
=20
+ if (event =3D=3D HCI_VALUE_RETURN_LINK_KEYS)
+ {
+ /* Ok, link key has to be stored locally */
+ link_key_information_type *link_key;
+ unsigned char link_key_str[LINK_KEY_SIZE];
+=09=09
+ memcpy(link_key_str, param, LINK_KEY_SIZE);
+ link_key =3D create_link_key(bd_addr, link_key_str);
+ insert_link_key(link_key);
+ D_PROC("sec_man_event: Number of elements in list: %d\n", link_key_list.=
count);
+=09=09
+ }
+ else
+ {
#ifndef __KERNEL__
if (sec_man_sock < 0) {
/* What to do if no security manager present?? */
}
#endif
-
D_PROC("Called sec_man_event user:%d event:%02x\n", user, event);
security_query.request_type =3D user;
security_query.request_value =3D event;
- memcpy(security_query.remote_bd, bd_addr, 6);
+ memcpy(security_query.remote_bd, bd_addr, BD_ADDRESS_SIZE);
security_query.originator =3D BT_SEC_MAN;
=20
if (param_len > MAX_EVENT_DATA_LENGTH) {
@@ -407,10 +577,40 @@
#else
sec_man_doquery(sec_man_sock, (u8*) &security_query);
#endif
-=09
+ }
#undef FNC=09
}
=20
+void sec_man_get_cached_link_key(u8 *param)
+{
+ link_key_information_type *link_key;
+
+ link_key =3D get_first_link_key();
+=09=09=09
+ D_PROC("sec_man_get_cached_link_key: \n");
+=09=09=09
+ if (link_key !=3D NULL)
+ {
+ memcpy(param, link_key->bd_addr, BD_ADDRESS_SIZE);
+ memcpy(param + BD_ADDRESS_SIZE,
+ link_key->link_key,
+ LINK_KEY_SIZE);
+
+ D_PROC("Returning bd address %02x:%02x:%02x:%02x:%02x:%02x",
+ link_key->bd_addr[0],
+ link_key->bd_addr[1],
+ link_key->bd_addr[2],
+ link_key->bd_addr[3],
+ link_key->bd_addr[4],
+ link_key->bd_addr[5]);
+=09=09
+ delete_link_key(link_key);
+=09=09
+ } else {
+ memset(param, 0, BD_ADDRESS_SIZE + LINK_KEY_SIZE);
+ }
+}
+
/* -------------------- Local functions --------------------------- */
#ifndef __KERNEL__
int open_socket(char *name)
@@ -545,7 +745,7 @@
s32 sec_man_doquery(s32 fd, u8 *request)
{
s32 n;
- u8 tmpbuf[256];
+ u8 tmpbuf[BUFFER_SIZE];
struct security_query *sec_hdl;
=20
sec_hdl =3D (struct security_query*) (request);
@@ -553,7 +753,7 @@
syslog(LOG_INFO, "sec_man_doquery : sending request\n");
write(fd, request, sizeof(struct security_query));
=20=09
- n =3D read(fd, tmpbuf, 256);
+ n =3D read(fd, tmpbuf, BUFFER_SIZE);
=20=09
/* what if not all is written once */
=20
|