diff options
| author | Johan Hedberg <johan.hedberg@nokia.com> | 2006-03-13 20:54:47 +0000 | 
|---|---|---|
| committer | Johan Hedberg <johan.hedberg@nokia.com> | 2006-03-13 20:54:47 +0000 | 
| commit | 1477aa78883562b5d5e97e4ec6fa2d23216673c2 (patch) | |
| tree | d40e8420180c283e1af85997cfdedeb6bdab8ad3 | |
| parent | 1fe7ab081842276d8db73a44cc64c2115b618cc2 (diff) | |
More passkey handler functionality
| -rw-r--r-- | common/list.c | 13 | ||||
| -rw-r--r-- | common/list.h | 5 | ||||
| -rw-r--r-- | hcid/dbus-security.c | 221 | ||||
| -rw-r--r-- | hcid/dbus.c | 2 | ||||
| -rw-r--r-- | hcid/dbus.h | 6 | 
5 files changed, 215 insertions, 32 deletions
| diff --git a/common/list.c b/common/list.c index bda2b564..c6d8cb98 100644 --- a/common/list.c +++ b/common/list.c @@ -86,6 +86,19 @@ struct slist *slist_remove(struct slist *list, void *data)  	return list;  } +struct slist *slist_find(struct slist *list, const void *data, +			cmp_func_t cmp_func) +{ +	struct slist *l; + +	for (l = list; l != NULL; l = l->next) { +		if (!cmp_func(l->data, data)) +			return l; +	} + +	return NULL; +} +  void slist_free(struct slist *list)  {  	struct slist *l, *next; diff --git a/common/list.h b/common/list.h index b16bf946..1838370c 100644 --- a/common/list.h +++ b/common/list.h @@ -30,10 +30,15 @@ struct slist {  	struct slist *next;  }; +typedef int (*cmp_func_t)(const void *a, const void *b); +  struct slist *slist_append(struct slist *list, void *data);  struct slist *slist_remove(struct slist *list, void *data); +struct slist *slist_find(struct slist *list, const void *data, +			cmp_func_t cmp_func); +  void slist_free(struct slist *list);  #endif /* __LIST_H */ diff --git a/hcid/dbus-security.c b/hcid/dbus-security.c index f3113d14..7fe9e313 100644 --- a/hcid/dbus-security.c +++ b/hcid/dbus-security.c @@ -65,6 +65,165 @@ static void default_agent_exited(const char *name, void *data)  	default_agent = NULL;  } +static void passkey_agent_free(struct passkey_agent *agent) +{ +	if (!agent) +		return; +	if (agent->name) +		free(agent->name); +	if (agent->path) +		free(agent->path); +	if (agent->addr) +		free(agent->addr); +	free(agent); +} + +static struct passkey_agent *passkey_agent_new(const char *name, +					const char *path, const char *addr) +{ +	struct passkey_agent *agent; + +	agent = malloc(sizeof(struct passkey_agent)); +	if (!agent) +		return NULL; + +	memset(agent, 0, sizeof(struct passkey_agent)); + +	agent->name = strdup(name); +	if (!agent->name) +		goto mem_fail; + +	agent->path = strdup(path); +	if (!agent->path) +		goto mem_fail; + +	if (addr) { +		agent->addr = strdup(addr); +		if (!agent->addr) +			goto mem_fail; +	} + +	return agent; + +mem_fail: +	passkey_agent_free(agent); +	return NULL; +} + +static int agent_cmp(const struct passkey_agent *a, const struct passkey_agent *b) +{ +	int ret; + +	if (b->name) { +		if (!a->name) +			return -1; +		ret = strcmp(a->name, b->name); +		if (ret) +			return ret; +	} + +	if (b->path) { +		if (!a->path) +			return -1; +		ret = strcmp(a->path, b->path); +		if (ret) +			return ret; +	} + +	if (b->addr) { +		if (!a->addr) +			return -1; +		ret = strcmp(a->addr, b->addr); +		if (ret) +			return ret; +	} + +	return 0; +} + +static DBusHandlerResult register_agent(DBusConnection *conn, +					DBusMessage *msg, void *data) +{ +	char *path, *addr; +	struct passkey_agent *agent, ref; +	struct hci_dbus_data *adapter; +	DBusMessage *reply; + +	if (!data) { +		error("register_agent called without any adapter info!"); +		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	} + +	adapter = data; + +	if (!dbus_message_get_args(msg, NULL, +				DBUS_TYPE_STRING, &path, +				DBUS_TYPE_STRING, &addr, +				DBUS_TYPE_INVALID)) +		return error_invalid_arguments(conn, msg); + +	ref.name = (char *)dbus_message_get_sender(msg); +	ref.addr = addr; +	ref.path = path; + +	if (slist_find(adapter->passkey_agents, &ref, (cmp_func_t)agent_cmp)) +		return error_passkey_agent_already_exists(conn, msg); + +	agent = passkey_agent_new(ref.name, path, addr); +	if (!agent) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	reply = dbus_message_new_method_return(msg); +	if (!reply) { +		passkey_agent_free(agent); +		return DBUS_HANDLER_RESULT_NEED_MEMORY; +	} + +	adapter->passkey_agents = slist_append(adapter->passkey_agents, agent); + +	return send_reply_and_unref(conn, reply); +} + +static DBusHandlerResult unregister_agent(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	char *path, *addr; +	struct hci_dbus_data *adapter; +	struct slist *match; +	struct passkey_agent ref; +	DBusMessage *reply; + +	if (!data) { +		error("uregister_agent called without any adapter info!"); +		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	} + +	adapter = data; + +	if (!dbus_message_get_args(msg, NULL, +				DBUS_TYPE_STRING, &path, +				DBUS_TYPE_STRING, &addr, +				DBUS_TYPE_INVALID)) +		return error_invalid_arguments(conn, msg); + +	ref.name = (char *)dbus_message_get_sender(msg); +	ref.path = path; +	ref.addr = addr; + +	match = slist_find(adapter->passkey_agents, &ref, (cmp_func_t)agent_cmp); +	if (!match) +		return error_passkey_agent_does_not_exist(conn, msg); + +	adapter->passkey_agents = slist_remove(adapter->passkey_agents, match->data); +	passkey_agent_free(match->data); + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	return send_reply_and_unref(conn, reply); +} +  static DBusHandlerResult register_default_agent(DBusConnection *conn,  						DBusMessage *msg, void *data)  { @@ -79,20 +238,10 @@ static DBusHandlerResult register_default_agent(DBusConnection *conn,  				DBUS_TYPE_INVALID))  		return error_invalid_arguments(conn, msg); -	default_agent = malloc(sizeof(struct passkey_agent)); +	default_agent = passkey_agent_new(dbus_message_get_sender(msg), path, NULL);  	if (!default_agent)  		goto need_memory; -	memset(default_agent, 0, sizeof(struct passkey_agent)); - -	default_agent->name = strdup(dbus_message_get_sender(msg)); -	if (!default_agent->name) -		goto need_memory; - -	default_agent->path = strdup(path); -	if (!default_agent->path) -		goto need_memory; -  	reply = dbus_message_new_method_return(msg);  	if (!reply)  		goto need_memory; @@ -103,18 +252,11 @@ static DBusHandlerResult register_default_agent(DBusConnection *conn,  	info("Default passkey agent (%s, %s) registered",  			default_agent->name, default_agent->path); -	dbus_connection_send(conn, reply, NULL); -	dbus_message_unref(reply); - -	return DBUS_HANDLER_RESULT_HANDLED; +	return send_reply_and_unref(conn, reply);  need_memory:  	if (default_agent) { -		if (default_agent->name) -			free(default_agent->name); -		if (default_agent->path) -			free(default_agent->path); -		free(default_agent); +		passkey_agent_free(default_agent);  		default_agent = NULL;  	} @@ -151,20 +293,17 @@ static DBusHandlerResult unregister_default_agent(DBusConnection *conn,  	info("Default passkey agent (%s, %s) unregistered",  			default_agent->name, default_agent->path); -	free(default_agent->path); -	free(default_agent->name); -	free(default_agent); +	passkey_agent_free(default_agent);  	default_agent = NULL; -	dbus_connection_send(conn, reply, NULL); -	dbus_message_unref(reply); - -	return DBUS_HANDLER_RESULT_HANDLED; +	return send_reply_and_unref(conn, reply);  }  static struct service_data sec_services[] = {  	{ "RegisterDefaultPasskeyAgent",	register_default_agent		},  	{ "UnregisterDefaultPasskeyAgent",	unregister_default_agent	}, +	{ "RegisterPasskeyAgent",		register_agent			}, +	{ "UnregisterPasskeyAgent",		unregister_agent		},  	{ NULL, NULL }  }; @@ -299,7 +438,31 @@ DBusHandlerResult handle_security_method(DBusConnection *conn, DBusMessage *msg,  	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;  } -int call_default_passkey_agent(int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba) +int handle_passkey_request(int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba)  { -	return call_passkey_agent(default_agent, dev, path, sba, dba); +	struct passkey_agent *agent = default_agent; +	struct hci_dbus_data *adapter = NULL; +	struct slist *l; +	char addr[18]; +	void *data; + +	dbus_connection_get_object_path_data(get_dbus_connection(), path, &data); + +	if (!data) +		goto done; + +	adapter = data; + +	ba2str(dba, addr); + +	for (l = adapter->passkey_agents; l != NULL; l = l->next) { +		struct passkey_agent *a = l->data; +		if (!strcmp(a->addr, addr)) { +			agent = a; +			break; +		} +	} + +done: +	return call_passkey_agent(agent, dev, path, sba, dba);  } diff --git a/hcid/dbus.c b/hcid/dbus.c index 4efc7457..9341200e 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -433,7 +433,7 @@ void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)  	snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, hci_devid(addr)); -	call_default_passkey_agent(dev, path, sba, &ci->bdaddr); +	handle_passkey_request(dev, path, sba, &ci->bdaddr);  }  void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status) diff --git a/hcid/dbus.h b/hcid/dbus.h index 14011fa4..beb9accc 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -27,6 +27,7 @@  #include <stdint.h>  #include <dbus/dbus.h>  #include <bluetooth/bluetooth.h> +#include "list.h"  #define BASE_PATH		"/org/bluez"  #define BASE_INTERFACE		"org.bluez" @@ -76,9 +77,10 @@ struct hci_dbus_data {  	uint32_t timeout_hits;  	timeout_handler_func_t *timeout_handler;  	uint8_t mode;		/* scan mode */ -	uint8_t resolve_name;	/* send name on discover process */ +	int resolve_name;	/* send name on discover process */  	struct slist *discovered_devices;  	char *requestor_name;	/* requestor unique name */ +	struct slist *passkey_agents;  };  struct passkey_agent { @@ -130,7 +132,7 @@ DBusHandlerResult handle_security_method(DBusConnection *conn, DBusMessage *msg,  service_handler_func_t find_service_handler(struct service_data *services, DBusMessage *msg); -int call_default_passkey_agent(int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba); +int handle_passkey_request(int dev, const char *path, bdaddr_t *sba, bdaddr_t *dba);  static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusMessage *reply)  { | 
