diff options
-rw-r--r-- | network/common.c | 4 | ||||
-rw-r--r-- | network/common.h | 5 | ||||
-rw-r--r-- | network/connection.c | 301 | ||||
-rw-r--r-- | network/connection.h | 10 | ||||
-rw-r--r-- | network/main.c | 78 | ||||
-rw-r--r-- | network/manager.c | 786 | ||||
-rw-r--r-- | network/network.conf | 4 |
7 files changed, 126 insertions, 1062 deletions
diff --git a/network/common.c b/network/common.c index f1dbe1c5..151e4810 100644 --- a/network/common.c +++ b/network/common.c @@ -49,10 +49,6 @@ static int ctl; static GSList *pids; -#define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" -#define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" -#define GN_UUID "00001117-0000-1000-8000-00805f9b34fb" - static struct { const char *name; /* Friendly name */ const char *uuid128; /* UUID 128 */ diff --git a/network/common.h b/network/common.h index e6aa90f6..cc154471 100644 --- a/network/common.h +++ b/network/common.h @@ -22,7 +22,10 @@ */ #define MAX_PATH_LENGTH 64 /* D-Bus path */ -#define NETWORK_PATH "/org/bluez/network" + +#define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" +#define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" +#define GN_UUID "00001117-0000-1000-8000-00805f9b34fb" int bnep_init(const char *panu_script, const char *gn_script, const char *nap_script); diff --git a/network/connection.c b/network/connection.c index d2fd85c2..3e99a865 100644 --- a/network/connection.c +++ b/network/connection.c @@ -52,6 +52,10 @@ #include "common.h" #include "connection.h" +#define NETWORK_PANU_INTERFACE "org.bluez.network.Peer" +#define NETWORK_GN_INTERFACE "org.bluez.network.Hub" +#define NETWORK_NAP_INTERFACE "org.bluez.network.Router" + typedef enum { CONNECTED, CONNECTING, @@ -60,13 +64,10 @@ typedef enum { struct network_conn { DBusMessage *msg; - bdaddr_t store; bdaddr_t src; bdaddr_t dst; char *path; /* D-Bus path */ char dev[16]; /* Interface name */ - char *name; /* Service Name */ - char *desc; /* Service Description*/ uint16_t id; /* Role: Service Class Identifier */ conn_state state; int sk; @@ -119,14 +120,33 @@ static inline DBusMessage *connection_attempt_failed(DBusMessage *msg, int err) err ? strerror(err) : "Connection attempt failed"); } +static const char *id2iface(uint16_t id) +{ + switch (id) { + case BNEP_SVC_PANU: + return NETWORK_PANU_INTERFACE; + break; + case BNEP_SVC_GN: + return NETWORK_GN_INTERFACE; + break; + case BNEP_SVC_NAP: + return NETWORK_NAP_INTERFACE; + break; + default: + return NULL; + } +} + static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct network_conn *nc = data; if (connection != NULL) { + const char *interface = id2iface(nc->id); + g_dbus_emit_signal(connection, nc->path, - NETWORK_CONNECTION_INTERFACE, + interface, "Disconnected", DBUS_TYPE_INVALID); } @@ -205,7 +225,7 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond, bnep_if_up(nc->dev, nc->id); g_dbus_emit_signal(connection, nc->path, - NETWORK_CONNECTION_INTERFACE, + id2iface(nc->id), "Connected", DBUS_TYPE_INVALID); @@ -297,68 +317,6 @@ failed: g_dbus_send_message(connection, reply); } -static DBusMessage *get_adapter(DBusConnection *conn, DBusMessage *msg, - void *data) -{ - struct network_conn *nc = data; - char addr[18]; - const char *paddr = addr; - - ba2str(&nc->src, addr); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &paddr, - DBUS_TYPE_INVALID); -} - -static DBusMessage *get_address(DBusConnection *conn, DBusMessage *msg, - void *data) -{ - struct network_conn *nc = data; - char addr[18]; - const char *paddr = addr; - - ba2str(&nc->dst, addr); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &paddr, - DBUS_TYPE_INVALID); -} - -static DBusMessage *get_uuid(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct network_conn *nc = data; - const char *uuid; - - uuid = bnep_uuid(nc->id); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INVALID); -} - -static DBusMessage *get_name(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct network_conn *nc = data; - - if (!nc->name) - return not_supported(msg); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &nc->name, - DBUS_TYPE_INVALID); -} - -static DBusMessage *get_description(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct network_conn *nc = data; - - if (!nc->desc) - return not_supported(msg); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &nc->desc, - DBUS_TYPE_INVALID); -} - static DBusMessage *get_interface(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -436,44 +394,6 @@ static DBusMessage *is_connected(DBusConnection *conn, DBUS_TYPE_INVALID); } -static DBusMessage *get_info(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct network_conn *nc = data; - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter dict; - const char *uuid; - char raddr[18]; - const char *paddr = raddr; - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - dbus_message_iter_append_dict_entry(&dict, "name", - DBUS_TYPE_STRING, &nc->name); - - uuid = bnep_uuid(nc->id); - dbus_message_iter_append_dict_entry(&dict, "uuid", - DBUS_TYPE_STRING, &uuid); - - ba2str(&nc->dst, raddr); - dbus_message_iter_append_dict_entry(&dict, "address", - DBUS_TYPE_STRING, &paddr); - - dbus_message_iter_close_container(&iter, &dict); - - return reply; -} - static void connection_free(struct network_conn *nc) { if (!nc) @@ -487,39 +407,28 @@ static void connection_free(struct network_conn *nc) bnep_kill_connection(&nc->dst); } - if (nc->name) - g_free(nc->name); - - if (nc->desc) - g_free(nc->desc); - g_free(nc); nc = NULL; } -static void connection_unregister(void *data) +static void path_unregister(void *data) { struct network_conn *nc = data; + const char *interface = id2iface(nc->id); - info("Unregistered connection path:%s", nc->path); + info("Unregistered interface %s on path %s", interface, nc->path); connections = g_slist_remove(connections, nc); connection_free(nc); } static GDBusMethodTable connection_methods[] = { - { "GetAdapter", "", "s", get_adapter }, - { "GetAddress", "", "s", get_address }, - { "GetUUID", "", "s", get_uuid }, - { "GetName", "", "s", get_name }, - { "GetDescription", "", "s", get_description }, { "GetInterface", "", "s", get_interface }, { "Connect", "", "s", connection_connect, G_DBUS_METHOD_FLAG_ASYNC }, { "CancelConnect", "", "", connection_cancel }, { "Disconnect", "", "", connection_disconnect }, { "IsConnected", "", "b", is_connected }, - { "GetInfo", "", "a{sv}",get_info }, { } }; @@ -529,12 +438,20 @@ static GDBusSignalTable connection_signals[] = { { } }; +void connection_unregister(const char *path, uint16_t id) +{ + const char *interface = id2iface(id); + + g_dbus_unregister_interface(connection, path, interface); +} + int connection_register(const char *path, bdaddr_t *src, bdaddr_t *dst, - uint16_t id, const char *name, const char *desc) + uint16_t id) { struct network_conn *nc; bdaddr_t default_src; int dev_id; + const char *interface; if (!path) return -EINVAL; @@ -545,164 +462,32 @@ int connection_register(const char *path, bdaddr_t *src, bdaddr_t *dst, return -1; nc = g_new0(struct network_conn, 1); + interface = id2iface(id); if (g_dbus_register_interface(connection, path, - NETWORK_CONNECTION_INTERFACE, + interface, connection_methods, connection_signals, NULL, - nc, connection_unregister) == FALSE) { - error("D-Bus failed to register %s interface", - NETWORK_CONNECTION_INTERFACE); + nc, path_unregister) == FALSE) { + error("D-Bus failed to register %s interface", interface); return -1; } nc->path = g_strdup(path); - bacpy(&nc->store, src); - bacpy(&nc->src, &default_src); + bacpy(&nc->src, src); bacpy(&nc->dst, dst); nc->id = id; - nc->name = g_strdup(name); - nc->desc = g_strdup(desc); memset(nc->dev, 0, 16); strncpy(nc->dev, prefix, strlen(prefix)); nc->state = DISCONNECTED; connections = g_slist_append(connections, nc); - info("Registered connection path:%s", path); + info("Registered interface %s on path %s", interface, path); return 0; } -int connection_store(const char *path, gboolean default_path) -{ - struct network_conn *nc; - const char *role; - char key[32], *value; - char filename[PATH_MAX + 1]; - char src_addr[18], dst_addr[18]; - int len, err; - GSList *l; - - l = g_slist_find_custom(connections, path, find_connection); - if (!l) - return -ENOENT; - - nc = l->data; - if (!nc->name || !nc->desc) - return -EINVAL; - - /* FIXME: name and desc validation - remove ':' */ - - ba2str(&nc->dst, dst_addr); - role = bnep_name(nc->id); - snprintf(key, 32, "%s#%s", dst_addr, role); - - ba2str(&nc->store, src_addr); - create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "network"); - create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - if (default_path) - err = textfile_put(filename, "default", key); - else { - len = strlen(nc->name) + strlen(nc->desc) + 2; - value = g_malloc0(len); - snprintf(value, len, "%s:%s", nc->name, nc->desc); - err = textfile_put(filename, key, value); - g_free(value); - } - - return err; -} - -int connection_find_data(const char *path, const char *pattern) -{ - struct network_conn *nc; - char addr[18], key[32]; - const char *role; - GSList *l; - - l = g_slist_find_custom(connections, path, find_connection); - if (!l) - return -1; - - nc = l->data; - if (strcasecmp(pattern, nc->dev) == 0) - return 0; - - if (strcasecmp(pattern, nc->name) == 0) - return 0; - - ba2str(&nc->dst, addr); - - if (strcasecmp(pattern, addr) == 0) - return 0; - - role = bnep_name(nc->id); - snprintf(key, 32, "%s#%s", addr, role); - - if (strcasecmp(pattern, key) == 0) - return 0; - - return -1; -} - -gboolean connection_has_pending(const char *path) -{ - struct network_conn *nc; - GSList *l; - - l = g_slist_find_custom(connections, path, find_connection); - if (!l) - return FALSE; - - nc = l->data; - - return (nc->state == CONNECTING); -} - -int connection_remove_stored(const char *path) -{ - struct network_conn *nc; - const char *role; - char key[32]; - char filename[PATH_MAX + 1]; - char src_addr[18], dst_addr[18]; - int err; - GSList *l; - - l = g_slist_find_custom(connections, path, find_connection); - if (!l) - return -ENOENT; - - nc = l->data; - - ba2str(&nc->dst, dst_addr); - role = bnep_name(nc->id); - snprintf(key, 32, "%s#%s", dst_addr, role); - - ba2str(&nc->store, src_addr); - create_name(filename, PATH_MAX, STORAGEDIR, src_addr, "network"); - - err = textfile_del(filename, key); - - return err; -} - -gboolean connection_is_connected(const char *path) -{ - struct network_conn *nc; - GSList *l; - - l = g_slist_find_custom(connections, path, find_connection); - if (!l) - return FALSE; - - nc = l->data; - - return (nc->state == CONNECTED); -} - int connection_init(DBusConnection *conn, const char *iface_prefix) { connection = dbus_connection_ref(conn); diff --git a/network/connection.h b/network/connection.h index fd15e816..1bbc460f 100644 --- a/network/connection.h +++ b/network/connection.h @@ -21,14 +21,8 @@ * */ -#define NETWORK_CONNECTION_INTERFACE "org.bluez.network.Connection" - int connection_init(DBusConnection *conn, const char *iface_prefix); void connection_exit(); int connection_register(const char *path, bdaddr_t *src, bdaddr_t *dst, - uint16_t id, const char *name, const char *desc); -int connection_store(const char *path, gboolean default_path); -int connection_remove_stored(const char *path); -int connection_find_data(const char *path, const char *pattern); -gboolean connection_has_pending(const char *path); -gboolean connection_is_connected(const char *path); + uint16_t id); +void connection_unregister(const char *path, uint16_t id); diff --git a/network/main.c b/network/main.c index 4fcf5192..e4220928 100644 --- a/network/main.c +++ b/network/main.c @@ -41,76 +41,6 @@ #define GN_IFACE "pan0" #define NAP_IFACE "pan1" -#define PANU_UUID "00001115-0000-1000-8000-00805f9b34fb" -#define NAP_UUID "00001116-0000-1000-8000-00805f9b34fb" -#define GN_UUID "00001117-0000-1000-8000-00805f9b34fb" - -#define NETWORK_INTERFACE "org.bluez.Network" - -static DBusMessage *network_connect(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - const char *target, *device = "bnep0"; - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &target, - DBUS_TYPE_INVALID) == FALSE) - return NULL; - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &device, - DBUS_TYPE_INVALID); -} - -static DBusMessage *network_disconnect(DBusConnection *conn, - DBusMessage *msg, void *user_data) -{ - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_INVALID) == FALSE) - return NULL; - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static GDBusMethodTable network_methods[] = { - { "Connect", "s", "s", network_connect }, - { "Disconnect", "", "", network_disconnect }, - { } -}; - -static GDBusSignalTable network_signals[] = { - { "Connected", "ss" }, - { "Disconnected", "s" }, - { } -}; - -static DBusConnection *conn; - -static int network_probe(struct btd_device *device, GSList *records) -{ - const gchar *path = device_get_path(device); - DBG("path %s", path); - - if (g_dbus_register_interface(conn, path, NETWORK_INTERFACE, - network_methods, network_signals, NULL, - device, NULL) == FALSE) - return -1; - - return 0; -} - -static void network_remove(struct btd_device *device) -{ - const gchar *path = device_get_path(device); - DBG("path %s", path); - - g_dbus_unregister_interface(conn, path, NETWORK_INTERFACE); -} - -static struct btd_device_driver network_driver = { - .name = "network", - .uuids = BTD_UUIDS(PANU_UUID, NAP_UUID, GN_UUID), - .probe = network_probe, - .remove = network_remove, -}; - static struct network_conf conf = { .connection_enabled = TRUE, .server_enabled = TRUE, @@ -230,6 +160,8 @@ done: static int network_init(void) { + DBusConnection *conn; + conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); if (conn == NULL) return -EIO; @@ -241,18 +173,12 @@ static int network_init(void) return -EIO; } - btd_register_device_driver(&network_driver); - return 0; } static void network_exit(void) { - btd_unregister_device_driver(&network_driver); - network_manager_exit(); - - dbus_connection_unref(conn); } BLUETOOTH_PLUGIN_DEFINE("network", network_init, network_exit) diff --git a/network/manager.c b/network/manager.c index dd23b58d..27573101 100644 --- a/network/manager.c +++ b/network/manager.c @@ -45,8 +45,8 @@ #include "textfile.h" #include "glib-helper.h" -#define NETWORK_MANAGER_INTERFACE "org.bluez.network.Manager" - +#include "../hcid/adapter.h" +#include "../hcid/device.h" #include "error.h" #include "bridge.h" #include "manager.h" @@ -54,578 +54,10 @@ #define MAX_NAME_SIZE 256 -struct pending_reply { - DBusConnection *conn; - DBusMessage *msg; - bdaddr_t src; /* Source address */ - bdaddr_t dst; /* Destination address */ - char *addr; /* Destination address */ - char *path; /* D-Bus object path */ - char *adapter_path; /* Default adapter path */ - uint16_t id; /* Role */ -}; - static struct network_conf *conf = NULL;/* Network service configuration */ -static GSList *server_paths = NULL; /* Network registered servers paths */ -static GSList *connection_paths = NULL; /* Network registered connections paths */ -static int default_index = -1; /* Network default connection path index */ -static int net_uid = 0; /* Network objects identifier */ static DBusConnection *connection = NULL; -static void pending_reply_free(struct pending_reply *pr) -{ - if (pr->addr) - g_free(pr->addr); - if (pr->path) - g_free(pr->path); - if (pr->adapter_path) - g_free(pr->adapter_path); - if (pr->msg) - dbus_message_unref(pr->msg); - if (pr->conn) - dbus_connection_unref(pr->conn); -} - -static inline DBusMessage *does_not_exist(DBusMessage *msg) -{ - return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExists", - "No such connection"); -} - -static inline DBusMessage *already_exists(DBusMessage *msg) -{ - return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExists", - "Connection already exists"); -} - -static inline DBusMessage *not_supported(DBusMessage *msg) -{ - return g_dbus_create_error(msg, ERROR_INTERFACE ".NotSupported", - "Not supported"); -} - -static inline DBusMessage *connection_is_busy(DBusMessage *msg) -{ - return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", - "Connection is Busy"); -} - -static inline DBusMessage *adapter_not_available(DBusMessage *msg) -{ - return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", - "Adapter not available"); -} - -static void create_path(DBusConnection *conn, DBusMessage *msg, - const char *path, const char *sname) -{ - /* emit signal when it is a new path */ - if (sname) { - g_dbus_emit_signal(conn, NETWORK_PATH, - NETWORK_MANAGER_INTERFACE, - sname, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - } - - g_dbus_send_reply(conn, msg, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); -} - -static DBusMessage *list_paths(DBusConnection *conn, DBusMessage *msg, - GSList *list) -{ - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter array_iter; - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING_AS_STRING, &array_iter); - - for (; list; list = list->next) { - dbus_message_iter_append_basic(&array_iter, - DBUS_TYPE_STRING, - &list->data); - } - - dbus_message_iter_close_container(&iter, &array_iter); - - return reply; -} - -static const char *last_connection_used(DBusConnection *conn) -{ - const char *path = NULL; - GSList *l; - int i; - - for (i = g_slist_length (connection_paths) -1; i > -1; i--) { - path = g_slist_nth_data (connection_paths, i); - if (connection_is_connected(path)) - break; - } - - /* No connection connected fallback to last connection */ - if (i == -1) { - l = g_slist_last(connection_paths); - path = l->data; - } - - return path; -} - -static DBusMessage *remove_path(DBusConnection *conn, - DBusMessage *msg, GSList **list, - const char *sname) -{ - const char *path; - GSList *l; - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID) == FALSE) - return NULL; - - l = g_slist_find_custom(*list, path, (GCompareFunc) strcmp); - if (!l) - return does_not_exist(msg); - - /* Remove references from the storage */ - if (*list == connection_paths) { - if (connection_has_pending(path)) - return connection_is_busy(msg); - - connection_remove_stored(path); - /* Reset default connection */ - if (l == g_slist_nth(*list, default_index)) { - const char *dpath; - - dpath = last_connection_used(conn); - connection_store(dpath, TRUE); - } - } - - g_free(l->data); - *list = g_slist_remove(*list, l->data); - - g_dbus_emit_signal(conn, NETWORK_PATH, - NETWORK_MANAGER_INTERFACE, - sname, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - - g_dbus_unregister_interface(conn, path, NETWORK_CONNECTION_INTERFACE); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static void records_cb(sdp_list_t *recs, int err, gpointer data) -{ - struct pending_reply *pr = data; - int len; - sdp_data_t *d; - sdp_record_t *rec = NULL; - char name[MAX_NAME_SIZE], *desc = NULL; - - if (err < 0) { - error_connection_attempt_failed(pr->conn, pr->msg, -err); - goto fail; - } - - if (!recs || !recs->data) { - error_not_supported(pr->conn, pr->msg); - error("Invalid PAN service record"); - goto fail; - } - - rec = recs->data; - - /* Concat remote name and service name */ - memset(name, 0, MAX_NAME_SIZE); - if (read_remote_name(&pr->src, &pr->dst, name, MAX_NAME_SIZE) < 0) - len = 0; - else - len = strlen(name); - - d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); - if (d) { - snprintf(name + len, MAX_NAME_SIZE - len, - len ? " (%.*s)" : "%.*s", d->unitSize, d->val.str); - } - - /* Extract service description from record */ - d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY); - if (d) { - desc = g_new0(char, d->unitSize); - snprintf(desc, d->unitSize, "%.*s", - d->unitSize, d->val.str); - } - - sdp_list_free(recs, (sdp_free_func_t) sdp_record_free); - - if (connection_register(pr->path, &pr->src, &pr->dst, pr->id, name, - desc) < 0) { - error_failed(pr->conn, pr->msg, "D-Bus path registration failed"); - goto fail; - } - - connection_store(pr->path, FALSE); - connection_paths = g_slist_append(connection_paths, g_strdup(pr->path)); - - create_path(pr->conn, pr->msg, pr->path, "ConnectionCreated"); - -fail: - g_free(desc); - pending_reply_free(pr); -} - -static DBusMessage *list_servers(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - return list_paths(conn, msg, server_paths); -} - -static DBusMessage *find_server(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *pattern; - const char *path; - GSList *list; - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID) == FALSE) - return NULL; - - for (list = server_paths; list; list = list->next) { - path = (const char *) list->data; - if (server_find_data(path, pattern) == 0) - break; - } - - if (list == NULL) - return does_not_exist(msg); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); -} - -static DBusMessage *list_connections(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - return list_paths(conn, msg, connection_paths); -} - -static GSList *find_connection_pattern(DBusConnection *conn, - const char *pattern) -{ - const char *path; - GSList *list; - - if (pattern == NULL) - return NULL; - - for (list = connection_paths; list; list = list->next) { - path = (const char *) list->data; - if (connection_find_data(path, pattern) == 0) - break; - } - - return list; -} - -static DBusMessage *find_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *pattern; - const char *path; - GSList *list; - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID) == FALSE) - return NULL; - - list = find_connection_pattern(conn, pattern); - if (list == NULL) - return does_not_exist(msg); - - path = list->data; - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); -} - -static DBusMessage *create_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct pending_reply *pr; - const char *addr; - const char *str; - bdaddr_t src; - uint16_t id; - int dev_id, err; - char key[32]; - GSList *l; - uuid_t uuid; - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr, - DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == FALSE) - return NULL; - - id = bnep_service_id(str); - if (id != BNEP_SVC_GN && id != BNEP_SVC_NAP && id != BNEP_SVC_PANU) - return not_supported(msg); - - snprintf(key, 32, "%s#%s", addr, bnep_name(id)); - - /* Checks if the connection was already been made */ - for (l = connection_paths; l; l = l->next) { - if (connection_find_data(l->data, key) == 0) - return already_exists(msg); - } - - bacpy(&src, BDADDR_ANY); - dev_id = hci_get_route(&src); - if (dev_id < 0 || hci_devba(dev_id, &src) < 0) - return adapter_not_available(msg); - - pr = g_new0(struct pending_reply, 1); - - /* FIXME just to maintain compatibility */ - pr->adapter_path = g_strdup_printf("/org/bluez/hci%d", dev_id); - if (!pr->adapter_path) { - pending_reply_free (pr); - return adapter_not_available(msg); - } - - pr->conn = dbus_connection_ref(conn); - pr->msg = dbus_message_ref(msg); - bacpy(&pr->src, &src); - str2ba(addr, &pr->dst); - pr->addr = g_strdup(addr); - pr->id = id; - pr->path = g_new0(char, MAX_PATH_LENGTH); - snprintf(pr->path, MAX_PATH_LENGTH, - NETWORK_PATH "/connection%d", net_uid++); - - sdp_uuid16_create(&uuid, pr->id); - err = bt_search_service(&pr->src, &pr->dst, &uuid, records_cb, pr, - NULL); - if (err < 0) { - pending_reply_free(pr); - return not_supported(msg); - } - - return NULL; -} - -static DBusMessage *remove_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - return remove_path(conn, msg, &connection_paths, "ConnectionRemoved"); -} - -static DBusMessage *last_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *path; - - if (connection_paths == NULL || - g_slist_length(connection_paths) == 0) - return does_not_exist(msg); - - path = last_connection_used(conn); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); -} - -static DBusMessage *default_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *path; - - if (connection_paths == NULL || - g_slist_length (connection_paths) == 0) - return does_not_exist(msg); - - path = g_slist_nth_data (connection_paths, default_index); - - if (path == NULL) { - path = last_connection_used(conn); - connection_store(path, TRUE); - } - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); -} - -static DBusMessage *change_default_connection(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - const char *path; - const char *pattern; - GSList *list; - - if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID) == FALSE) - return NULL; - - if (connection_paths == NULL || - g_slist_length(connection_paths) == 0) - return does_not_exist(msg); - - list = g_slist_find_custom(connection_paths, pattern, - (GCompareFunc) strcmp); - - /* Find object path via pattern */ - if (list == NULL) { - list = find_connection_pattern(conn, pattern); - if (list == NULL) - return does_not_exist(msg); - - path = list->data; - } else - path = list->data; - - default_index = g_slist_position(connection_paths, list); - connection_store(path, TRUE); - - g_dbus_emit_signal(connection, NETWORK_PATH, - NETWORK_MANAGER_INTERFACE, - "DefaultConnectionChanged", - DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); - - return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &path, - DBUS_TYPE_INVALID); -} - -static void manager_unregister(void *data) -{ - info("Unregistered manager path"); - - if (server_paths) { - g_slist_foreach(server_paths, (GFunc) g_free, NULL); - g_slist_free(server_paths); - server_paths = NULL; - } - - if (connection_paths) { - g_slist_foreach(connection_paths, (GFunc) g_free, NULL); - g_slist_free(connection_paths); - connection_paths = NULL; - } - - bnep_kill_all_connections(); -} - -static void parse_stored_connection(char *key, char *value, void *data) -{ - bdaddr_t dst, *src = data; - char path[MAX_PATH_LENGTH]; - char addr[18]; - const char *ptr; - char *name; - int len, id; - - /* Format: XX:XX:XX:XX:XX:XX#{NAP, GN} name:description */ - - /* Parsing the key: address#role */ - ptr = strchr(key, '#'); - - /* Empty address or invalid len */ - if (!ptr || ((ptr - key) != 17)) - return; - - memset(addr, 0, 18); - strncpy(addr, key, 17); - str2ba(addr, &dst); - - /* Empty role */ - if (++ptr == NULL) - return; - - if (strcasecmp("nap", ptr) == 0) - id = BNEP_SVC_NAP; - else if (strcasecmp("gn", ptr) == 0) - id = BNEP_SVC_GN; - else if (strcasecmp("panu", ptr) == 0) - id = BNEP_SVC_PANU; - else - return; - - snprintf(path, MAX_PATH_LENGTH, - NETWORK_PATH "/connection%d", net_uid++); - - /* Parsing the value: name and description */ - ptr = strchr(value, ':'); - - /* Empty name */ - if (!ptr) - return; - - len = ptr-value; - name = g_malloc0(len + 1); - strncpy(name, value, len); - - /* Empty description */ - if (++ptr == NULL) { - g_free(name); - return; - } - - if (connection_register(path, src, &dst, id, name, ptr) == 0) { - char *rpath = g_strdup(path); - connection_paths = g_slist_append(connection_paths, rpath); - } - - g_free(name); -} - -static void register_connections_stored(const char *adapter) -{ - char filename[PATH_MAX + 1]; - char *pattern; - struct stat st; - GSList *list; - bdaddr_t src; - bdaddr_t default_src; - int dev_id; - - create_name(filename, PATH_MAX, STORAGEDIR, adapter, "network"); - - str2ba(adapter, &src); - - if (stat(filename, &st) < 0) - return; - - if (!(st.st_mode & __S_IFREG)) - return; - - textfile_foreach(filename, parse_stored_connection, &src); - - /* Check default connection for current default adapter */ - bacpy(&default_src, BDADDR_ANY); - dev_id = hci_get_route(&default_src); - if (dev_id < 0 || hci_devba(dev_id, &default_src) < 0) - return; - - if (bacmp(&default_src, &src) != 0) - return; - - pattern = textfile_get(filename, "default"); - if (!pattern) - return; - - list = find_connection_pattern(connection, pattern); - if (!list) - return; - default_index = g_slist_position(connection_paths, list); -} - static void register_server(uint16_t id) { char path[MAX_PATH_LENGTH]; @@ -637,10 +69,6 @@ static void register_server(uint16_t id) snprintf(path, MAX_PATH_LENGTH, NETWORK_PATH "/%s", bnep_name(id)); - if (g_slist_find_custom(server_paths, path, - (GCompareFunc) strcmp)) - return; - bacpy(&src, BDADDR_ANY); dev_id = hci_get_route(&src); if (dev_id < 0 || hci_devba(dev_id, &src)) @@ -650,133 +78,90 @@ static void register_server(uint16_t id) return; server_store(path); - - server_paths = g_slist_append(server_paths, g_strdup(path)); } -static void register_servers_stored(const char *adapter, const char *profile) +static int network_probe(struct btd_device *device, uint16_t id) { - char filename[PATH_MAX + 1]; - char path[MAX_PATH_LENGTH]; - uint16_t id; - struct stat s; - bdaddr_t src; + struct adapter *adapter = device_get_adapter(device); + const gchar *path = device_get_path(device); + const char *source, *destination; + bdaddr_t src, dst; - if (strcmp(profile, "nap") == 0) - id = BNEP_SVC_NAP; - else if (strcmp(profile, "gn") == 0) - id = BNEP_SVC_GN; - else - id = BNEP_SVC_PANU; + DBG("path %s", path); - create_name(filename, PATH_MAX, STORAGEDIR, adapter, profile); + source = adapter->address; + destination = device_get_address(device); - str2ba(adapter, &src); + str2ba(source, &src); + str2ba(destination, &dst); - if (stat (filename, &s) == 0 && (s.st_mode & __S_IFREG)) { - snprintf(path, MAX_PATH_LENGTH, NETWORK_PATH "/%s", profile); - if (server_register_from_file(path, &src, id, filename) == 0) { - server_paths = g_slist_append(server_paths, - g_strdup(path)); - } - } + return connection_register(path, &src, &dst, id); } -static void register_stored(void) +static int panu_probe(struct btd_device *device, GSList *records) { - char dirname[PATH_MAX + 1]; - struct dirent *de; - DIR *dir; - - snprintf(dirname, PATH_MAX, "%s", STORAGEDIR); + return network_probe(device, BNEP_SVC_PANU); +} - dir = opendir(dirname); - if (!dir) - return; +static int gn_probe(struct btd_device *device, GSList *records) +{ + return network_probe(device, BNEP_SVC_GN); +} - while ((de = readdir(dir)) != NULL) { - if (!isdigit(de->d_name[0])) - continue; +static int nap_probe(struct btd_device *device, GSList *records) +{ + return network_probe(device, BNEP_SVC_NAP); +} - /* Connection objects */ - if (conf->connection_enabled) - register_connections_stored(de->d_name); +static void network_remove(struct btd_device *device, uint16_t id) +{ + const gchar *path = device_get_path(device); - /* Server objects */ - if (conf->server_enabled) { - /* NAP objects */ - register_servers_stored(de->d_name, "nap"); + DBG("path %s", path); - /* GN objects */ - register_servers_stored(de->d_name, "gn"); + connection_unregister(path, id); +} - /* PANU objects */ - register_servers_stored(de->d_name, "panu"); - } - } +static void panu_remove(struct btd_device *device) +{ + network_remove(device, BNEP_SVC_PANU); +} - closedir(dir); +static void gn_remove(struct btd_device *device) +{ + network_remove(device, BNEP_SVC_GN); } -static GDBusMethodTable connection_methods[] = { - { "ListConnections", "", "as", list_connections }, - { "FindConnection", "s", "s", find_connection }, - { "CreateConnection", "ss", "s", create_connection, - G_DBUS_METHOD_FLAG_ASYNC }, - { "RemoveConnection", "s", "", remove_connection }, - { "LastConnection", "", "s", last_connection }, - { "DefaultConnection", "", "s", default_connection }, - { "ChangeDefaultConnection", "s", "s", change_default_connection }, - { } -}; +static void nap_remove(struct btd_device *device) +{ + network_remove(device, BNEP_SVC_NAP); +} -static GDBusSignalTable connection_signals[] = { - { "ConnectionCreated", "s" }, - { "ConnectionRemoved", "s" }, - { "DefaultConnectionChanged", "s" }, - { } +static struct btd_device_driver network_panu_driver = { + .name = "network-panu", + .uuids = BTD_UUIDS(PANU_UUID), + .probe = panu_probe, + .remove = panu_remove, }; -static GDBusMethodTable server_methods[] = { - { "ListServers", "", "as", list_servers }, - { "FindServer", "s", "s", find_server }, - { } +static struct btd_device_driver network_gn_driver = { + .name = "network-gn", + .uuids = BTD_UUIDS(GN_UUID), + .probe = gn_probe, + .remove = gn_remove, }; -static GDBusMethodTable manager_methods[] = { - { "ListServers", "", "as", list_servers }, - { "FindServer", "s", "s", find_server }, - { "ListConnections", "", "as", list_connections }, - { "FindConnection", "s", "s", find_connection }, - { "CreateConnection", "ss", "s", create_connection, - G_DBUS_METHOD_FLAG_ASYNC }, - { "RemoveConnection", "s", "", remove_connection }, - { "LastConnection", "", "s", last_connection }, - { "DefaultConnection", "", "s", default_connection }, - { "ChangeDefaultConnection", "s", "s", change_default_connection }, - { } +static struct btd_device_driver network_nap_driver = { + .name = "network-nap", + .uuids = BTD_UUIDS(NAP_UUID), + .probe = nap_probe, + .remove = nap_remove, }; int network_manager_init(DBusConnection *conn, struct network_conf *service_conf) { - GDBusMethodTable *methods = NULL; - GDBusSignalTable *signals = NULL; - conf = service_conf; - if (conf->server_enabled && conf->connection_enabled) { - methods = manager_methods; - signals = connection_signals; - } else if (conf->connection_enabled) { - methods = connection_methods; - signals = connection_signals; - } else if (conf->server_enabled) - methods = server_methods; - else { - error ("All interfaces were disabled"); - return -1; - } - if (bnep_init(conf->panu_script, conf->gn_script, conf->nap_script)) { error("Can't init bnep module"); return -1; @@ -788,41 +173,29 @@ int network_manager_init(DBusConnection *conn, struct network_conf *service_conf * (setup connection request) contains the destination service * field that defines which service the source is connecting to. */ - if (conf->server_enabled) { - if (bridge_init(conf->gn_iface, conf->nap_iface) < 0) { - error("Can't init bridge module"); - return -1; - } - - if (server_init(conn, conf->iface_prefix, conf->security) < 0) - return -1; - } - - if (conf->connection_enabled) { - if (connection_init(conn, conf->iface_prefix) < 0) - return -1; - } - - if (g_dbus_register_interface(conn, NETWORK_PATH, - NETWORK_MANAGER_INTERFACE, - methods, signals, NULL, - NULL, manager_unregister) == FALSE) { - error("Failed to register %s interface to %s", - NETWORK_MANAGER_INTERFACE, NETWORK_PATH); + if (bridge_init(conf->gn_iface, conf->nap_iface) < 0) { + error("Can't init bridge module"); return -1; } - connection = dbus_connection_ref(conn); - - info("Registered manager path:%s", NETWORK_PATH); - - register_stored(); + if (server_init(conn, conf->iface_prefix, conf->security) < 0) + return -1; /* Register PANU, GN and NAP servers if they don't exist */ + /* FIXME: server should be registered as adapter driver */ register_server(BNEP_SVC_PANU); register_server(BNEP_SVC_GN); register_server(BNEP_SVC_NAP); + if (connection_init(conn, conf->iface_prefix) < 0) + return -1; + + btd_register_device_driver(&network_panu_driver); + btd_register_device_driver(&network_gn_driver); + btd_register_device_driver(&network_nap_driver); + + connection = dbus_connection_ref(conn); + return 0; } @@ -831,11 +204,12 @@ void network_manager_exit(void) if (conf->server_enabled) server_exit(); - if (conf->connection_enabled) + if (conf->connection_enabled) { + btd_unregister_device_driver(&network_panu_driver); + btd_unregister_device_driver(&network_gn_driver); + btd_unregister_device_driver(&network_nap_driver); connection_exit(); - - g_dbus_unregister_interface(connection, NETWORK_PATH, - NETWORK_MANAGER_INTERFACE); + } dbus_connection_unref(connection); connection = NULL; @@ -843,13 +217,3 @@ void network_manager_exit(void) bnep_cleanup(); bridge_cleanup(); } - -static inline int create_filename(char *buf, size_t size, - bdaddr_t *bdaddr, const char *name) -{ - char addr[18]; - - ba2str(bdaddr, addr); - - return create_name(buf, size, STORAGEDIR, addr, name); -} diff --git a/network/network.conf b/network/network.conf index 8677bd7b..4c24c8d8 100644 --- a/network/network.conf +++ b/network/network.conf @@ -4,10 +4,6 @@ # particular interface [General] -# If we want to disable support for specific services -# Defaults to supporting all implemented services -#Disable=Connection,Server - # Disable link encryption: default=false #DisableSecurity=true |