X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Felement.c;h=e4fd6f3ca6e5e97c239122221daa4eca63135134;hb=7260b267094d37ef067ed21a0252df361096148a;hp=3c072ee777b838e010274a09c2d3583a142948f2;hpb=fb0fb9058f300222717a025e6f8a0c7a030bf303;p=connman diff --git a/src/element.c b/src/element.c index 3c072ee..e4fd6f3 100644 --- a/src/element.c +++ b/src/element.c @@ -40,57 +40,6 @@ static gchar *device_filter = NULL; static gboolean started = FALSE; -static struct { - enum connman_property_id id; - int type; - const char *name; - const void *value; -} propid_table[] = { - { CONNMAN_PROPERTY_ID_IPV4_METHOD, - DBUS_TYPE_STRING, "IPv4.Method", "dhcp" }, - { CONNMAN_PROPERTY_ID_IPV4_ADDRESS, - DBUS_TYPE_STRING, "IPv4.Address" }, - { CONNMAN_PROPERTY_ID_IPV4_NETMASK, - DBUS_TYPE_STRING, "IPv4.Netmask" }, - { CONNMAN_PROPERTY_ID_IPV4_GATEWAY, - DBUS_TYPE_STRING, "IPv4.Gateway" }, - { CONNMAN_PROPERTY_ID_IPV4_BROADCAST, - DBUS_TYPE_STRING, "IPv4.Broadcast" }, - { CONNMAN_PROPERTY_ID_IPV4_NAMESERVER, - DBUS_TYPE_STRING, "IPv4.Nameserver" }, - - { CONNMAN_PROPERTY_ID_WIFI_SECURITY, - DBUS_TYPE_STRING, "WiFi.Security" }, - { CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE, - DBUS_TYPE_STRING, "WiFi.Passphrase" }, - - { } -}; - -static int propid2type(enum connman_property_id id) -{ - int i; - - for (i = 0; propid_table[i].name; i++) { - if (propid_table[i].id == id) - return propid_table[i].type; - } - - return DBUS_TYPE_INVALID; -} - -static const char *propid2name(enum connman_property_id id) -{ - int i; - - for (i = 0; propid_table[i].name; i++) { - if (propid_table[i].id == id) - return propid_table[i].name; - } - - return NULL; -} - static const char *type2string(enum connman_element_type type) { switch (type) { @@ -127,56 +76,6 @@ static const char *type2string(enum connman_element_type type) return NULL; } -static const char *subtype2string(enum connman_element_subtype type) -{ - switch (type) { - case CONNMAN_ELEMENT_SUBTYPE_UNKNOWN: - return "unknown"; - case CONNMAN_ELEMENT_SUBTYPE_FAKE: - return "fake"; - case CONNMAN_ELEMENT_SUBTYPE_ETHERNET: - return "ethernet"; - case CONNMAN_ELEMENT_SUBTYPE_WIFI: - return "wifi"; - case CONNMAN_ELEMENT_SUBTYPE_WIMAX: - return "wimax"; - case CONNMAN_ELEMENT_SUBTYPE_CELLULAR: - return "cellular"; - case CONNMAN_ELEMENT_SUBTYPE_BLUETOOTH: - return "bluetooth"; - } - - return NULL; -} - -const char *__connman_element_policy2string(enum connman_element_policy policy) -{ - switch (policy) { - case CONNMAN_ELEMENT_POLICY_UNKNOWN: - return "unknown"; - case CONNMAN_ELEMENT_POLICY_IGNORE: - return "ignore"; - case CONNMAN_ELEMENT_POLICY_AUTO: - return "auto"; - case CONNMAN_ELEMENT_POLICY_ASK: - return "ask"; - } - - return NULL; -} - -enum connman_element_policy __connman_element_string2policy(const char *policy) -{ - if (strcasecmp(policy, "ignore") == 0) - return CONNMAN_ELEMENT_POLICY_IGNORE; - else if (strcasecmp(policy, "auto") == 0) - return CONNMAN_ELEMENT_POLICY_AUTO; - else if (strcasecmp(policy, "ask") == 0) - return CONNMAN_ELEMENT_POLICY_ASK; - else - return CONNMAN_ELEMENT_POLICY_UNKNOWN; -} - const char *__connman_ipv4_method2string(enum connman_ipv4_method method) { switch (method) { @@ -205,116 +104,6 @@ enum connman_ipv4_method __connman_ipv4_string2method(const char *method) return CONNMAN_IPV4_METHOD_UNKNOWN; } -static void append_property(DBusMessageIter *dict, - struct connman_property *property) -{ - if (property->value == NULL) - return; - - switch (property->type) { - case DBUS_TYPE_ARRAY: - connman_dbus_dict_append_array(dict, property->name, - property->subtype, &property->value, property->size); - break; - case DBUS_TYPE_STRING: - connman_dbus_dict_append_variant(dict, property->name, - property->type, &property->value); - break; - default: - connman_dbus_dict_append_variant(dict, property->name, - property->type, property->value); - break; - } -} - -static void add_common_properties(struct connman_element *element, - DBusMessageIter *dict) -{ - const char *address = NULL, *netmask = NULL, *gateway = NULL; - GSList *list; - - connman_element_get_value(element, - CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address); - connman_element_get_value(element, - CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask); - connman_element_get_value(element, - CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway); - - if (element->priority > 0) - connman_dbus_dict_append_variant(dict, "Priority", - DBUS_TYPE_UINT16, &element->priority); - - if (address != NULL) - connman_dbus_dict_append_variant(dict, "IPv4.Address", - DBUS_TYPE_STRING, &address); - if (netmask != NULL) - connman_dbus_dict_append_variant(dict, "IPv4.Netmask", - DBUS_TYPE_STRING, &netmask); - if (gateway != NULL) - connman_dbus_dict_append_variant(dict, "IPv4.Gateway", - DBUS_TYPE_STRING, &gateway); - - if (element->wifi.security != NULL) { - const char *passphrase = ""; - - connman_dbus_dict_append_variant(dict, "WiFi.Security", - DBUS_TYPE_STRING, &element->wifi.security); - - if (element->wifi.passphrase != NULL) - passphrase = element->wifi.passphrase; - - connman_dbus_dict_append_variant(dict, "WiFi.Passphrase", - DBUS_TYPE_STRING, &passphrase); - } - - __connman_element_lock(element); - - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - append_property(dict, property); - } - - __connman_element_unlock(element); -} - -#if 0 -static void set_common_property(struct connman_element *element, - const char *name, DBusMessageIter *value) -{ - GSList *list; - - if (g_str_equal(name, "Priority") == TRUE) { - dbus_message_iter_get_basic(value, &element->priority); - return; - } - - __connman_element_lock(element); - - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - const char *str; - - if (g_str_equal(property->name, name) == FALSE) - continue; - - if (property->flags & CONNMAN_PROPERTY_FLAG_STATIC) - continue; - - property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE; - - if (property->type == DBUS_TYPE_STRING) { - dbus_message_iter_get_basic(value, &str); - g_free(property->value); - property->value = g_strdup(str); - } else - property->value = NULL; - } - - __connman_element_unlock(element); -} -#endif - static void emit_element_signal(DBusConnection *conn, const char *member, struct connman_element *element) { @@ -336,180 +125,6 @@ static void emit_element_signal(DBusConnection *conn, const char *member, g_dbus_send_message(conn, signal); } -static void emit_enabled_signal(DBusConnection *conn, - struct connman_element *element) -{ - DBusMessage *signal; - DBusMessageIter entry, value; - const char *iface, *key; - - DBG("conn %p", conn); - - if (element == NULL) - return; - - switch (element->type) { - case CONNMAN_ELEMENT_TYPE_CONNECTION: - iface = CONNMAN_CONNECTION_INTERFACE; - key = "Default"; - break; - default: - return; - } - - signal = dbus_message_new_signal(element->path, - iface, "PropertyChanged"); - if (signal == NULL) - return; - - dbus_message_iter_init_append(signal, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_BOOLEAN_AS_STRING, &value); - dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, - &element->enabled); - dbus_message_iter_close_container(&entry, &value); - - g_dbus_send_message(conn, signal); -} - -static DBusMessage *do_enable(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - - DBG("conn %p", conn); - - if (element->enabled == TRUE) - return __connman_error_failed(msg); - - if (element->driver && element->driver->enable) { - DBG("Calling enable callback"); - if (element->driver->enable(element) < 0) - return __connman_error_failed(msg); - } - - element->enabled = TRUE; - - emit_enabled_signal(connection, element); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static DBusMessage *do_disable(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - - DBG("conn %p", conn); - - if (element->enabled == FALSE) - return __connman_error_failed(msg); - - if (element->driver && element->driver->disable) { - DBG("Calling disable callback"); - if (element->driver->disable(element) < 0) - return __connman_error_failed(msg); - } - - element->enabled = FALSE; - - emit_enabled_signal(connection, element); - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static DBusMessage *connection_get_properties(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessage *reply; - DBusMessageIter array, dict; - const char *str; - - DBG("conn %p", conn); - - reply = dbus_message_new_method_return(msg); - if (reply == NULL) - return NULL; - - dbus_message_iter_init_append(reply, &array); - - dbus_message_iter_open_container(&array, 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); - - str = subtype2string(element->subtype); - if (str != NULL) - connman_dbus_dict_append_variant(&dict, "Type", - DBUS_TYPE_STRING, &str); - - if (element->devname != NULL) - connman_dbus_dict_append_variant(&dict, "Interface", - DBUS_TYPE_STRING, &element->devname); - - if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIFI || - element->subtype == CONNMAN_ELEMENT_SUBTYPE_WIMAX) - connman_dbus_dict_append_variant(&dict, "Strength", - DBUS_TYPE_BYTE, &element->strength); - - connman_dbus_dict_append_variant(&dict, "Default", - DBUS_TYPE_BOOLEAN, &element->enabled); - - add_common_properties(element, &dict); - - dbus_message_iter_close_container(&array, &dict); - - return reply; -} - -static DBusMessage *connection_set_property(DBusConnection *conn, - DBusMessage *msg, void *data) -{ - struct connman_element *element = data; - DBusMessageIter iter, value; - const char *name; - - DBG("conn %p", conn); - - if (dbus_message_iter_init(msg, &iter) == FALSE) - return __connman_error_invalid_arguments(msg); - - dbus_message_iter_get_basic(&iter, &name); - dbus_message_iter_next(&iter); - dbus_message_iter_recurse(&iter, &value); - - if (__connman_security_check_privileges(msg) < 0) - return __connman_error_permission_denied(msg); - - if (g_str_equal(name, "Default") == TRUE) { - dbus_bool_t enabled; - - dbus_message_iter_get_basic(&value, &enabled); - - if (enabled == TRUE) - return do_enable(conn, msg, element); - else - return do_disable(conn, msg, element); - } - - return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); -} - -static GDBusMethodTable connection_methods[] = { - { "GetProperties", "", "a{sv}", connection_get_properties }, - { "SetProperty", "sv", "", connection_set_property }, - { }, -}; - -static GDBusSignalTable element_signals[] = { - { "PropertyChanged", "sv" }, - { }, -}; - struct foreach_data { enum connman_element_type type; element_cb_t callback; @@ -657,6 +272,91 @@ int __connman_element_count(struct connman_element *element, return data.count; } +static struct connman_network *__connman_element_get_network(struct connman_element *element) +{ + if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK && + element->network != NULL) + return element->network; + + if (element->parent == NULL) + return NULL; + + return __connman_element_get_network(element->parent); +} + +struct connman_service *__connman_element_get_service(struct connman_element *element) +{ + struct connman_service *service = NULL; + struct connman_network *network; + struct connman_device *device; + enum connman_device_type type; + + device = __connman_element_get_device(element); + if (device == NULL) + return NULL; + + type = connman_device_get_type(device); + + switch (type) { + case CONNMAN_DEVICE_TYPE_UNKNOWN: + case CONNMAN_DEVICE_TYPE_VENDOR: + case CONNMAN_DEVICE_TYPE_BLUETOOTH: + case CONNMAN_DEVICE_TYPE_GPS: + case CONNMAN_DEVICE_TYPE_HSO: + case CONNMAN_DEVICE_TYPE_NOZOMI: + case CONNMAN_DEVICE_TYPE_HUAWEI: + case CONNMAN_DEVICE_TYPE_NOVATEL: + break; + case CONNMAN_DEVICE_TYPE_ETHERNET: + service = __connman_service_lookup_from_device(device); + break; + case CONNMAN_DEVICE_TYPE_WIFI: + case CONNMAN_DEVICE_TYPE_WIMAX: + network = __connman_element_get_network(element); + if (network == NULL) + return NULL; + service = __connman_service_lookup_from_network(network); + break; + } + + return service; +} + +struct connman_device *__connman_element_get_device(struct connman_element *element) +{ + if (element->type == CONNMAN_ELEMENT_TYPE_DEVICE && + element->device != NULL) + return element->device; + + if (element->parent == NULL) + return NULL; + + return __connman_element_get_device(element->parent); +} + +const char *__connman_element_get_device_path(struct connman_element *element) +{ + struct connman_device *device; + + device = __connman_element_get_device(element); + if (device == NULL) + return NULL; + + return connman_device_get_path(device); +} + +const char *__connman_element_get_network_path(struct connman_element *element) +{ + if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK && + element->network != NULL) + return element->path; + + if (element->parent == NULL) + return NULL; + + return __connman_element_get_network_path(element->parent); +} + static gint compare_priority(gconstpointer a, gconstpointer b) { const struct connman_driver *driver1 = a; @@ -671,33 +371,13 @@ static gboolean match_driver(struct connman_element *element, if (element->type == CONNMAN_ELEMENT_TYPE_ROOT) return FALSE; - if (element->type != driver->type && - driver->type != CONNMAN_ELEMENT_TYPE_UNKNOWN) - return FALSE; - - if (element->subtype == driver->subtype || - driver->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN) + if (element->type == driver->type || + driver->type == CONNMAN_ELEMENT_TYPE_UNKNOWN) return TRUE; return FALSE; } -static void enable_element(struct connman_element *element) -{ - if (element->type != CONNMAN_ELEMENT_TYPE_DEVICE) - return; - - if (element->policy != CONNMAN_ELEMENT_POLICY_AUTO) - return; - - if (element->driver && element->driver->enable) { - if (element->driver->enable(element) == 0) { - element->enabled = TRUE; - emit_enabled_signal(connection, element); - } - } -} - static gboolean probe_driver(GNode *node, gpointer data) { struct connman_element *element = node->data; @@ -712,8 +392,6 @@ static gboolean probe_driver(GNode *node, gpointer data) __connman_element_lock(element); element->driver = driver; __connman_element_unlock(element); - - enable_element(element); } return FALSE; @@ -762,22 +440,6 @@ int connman_driver_register(struct connman_driver *driver) return 0; } -static void disable_element(struct connman_element *element) -{ - if (element->policy != CONNMAN_ELEMENT_POLICY_AUTO) - return; - - if (element->enabled == FALSE) - return; - - if (element->driver && element->driver->disable) { - if (element->driver->disable(element) == 0) { - element->enabled = FALSE; - emit_enabled_signal(connection, element); - } - } -} - static gboolean remove_driver(GNode *node, gpointer data) { struct connman_element *element = node->data; @@ -786,8 +448,6 @@ static gboolean remove_driver(GNode *node, gpointer data) DBG("element %p name %s", element, element->name); if (element->driver == driver) { - disable_element(element); - if (driver->remove) driver->remove(element); @@ -816,6 +476,35 @@ void connman_driver_unregister(struct connman_driver *driver) G_TRAVERSE_ALL, -1, remove_driver, driver); } +static void unregister_property(gpointer data) +{ + struct connman_property *property = data; + + DBG("property %p", property); + + g_free(property->value); + g_free(property); +} + +void __connman_element_initialize(struct connman_element *element) +{ + DBG("element %p", element); + + element->refcount = 1; + + element->name = NULL; + element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN; + element->state = CONNMAN_ELEMENT_STATE_UNKNOWN; + element->error = CONNMAN_ELEMENT_ERROR_UNKNOWN; + element->index = -1; + element->enabled = FALSE; + + element->configuring = FALSE; + + element->properties = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, unregister_property); +} + /** * connman_element_create: * @name: element name @@ -835,15 +524,7 @@ struct connman_element *connman_element_create(const char *name) DBG("element %p", element); - element->refcount = 1; - - element->name = g_strdup(name); - element->type = CONNMAN_ELEMENT_TYPE_UNKNOWN; - element->subtype = CONNMAN_ELEMENT_SUBTYPE_UNKNOWN; - element->state = CONNMAN_ELEMENT_STATE_CLOSED; - element->policy = CONNMAN_ELEMENT_POLICY_AUTO; - element->index = -1; - element->enabled = FALSE; + __connman_element_initialize(element); return element; } @@ -860,24 +541,11 @@ struct connman_element *connman_element_ref(struct connman_element *element) static void free_properties(struct connman_element *element) { - GSList *list; - DBG("element %p name %s", element, element->name); __connman_element_lock(element); - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) - g_free(property->value); - - g_free(property->name); - g_free(property); - } - - g_slist_free(element->properties); - + g_hash_table_destroy(element->properties); element->properties = NULL; __connman_element_unlock(element); @@ -899,14 +567,13 @@ void connman_element_unref(struct connman_element *element) g_free(element->ipv4.broadcast); g_free(element->ipv4.nameserver); g_free(element->devname); - g_free(element->devpath); g_free(element->path); g_free(element->name); g_free(element); } } -int connman_element_add_static_property(struct connman_element *element, +static int set_static_property(struct connman_element *element, const char *name, int type, const void *value) { struct connman_property *property; @@ -920,10 +587,8 @@ int connman_element_add_static_property(struct connman_element *element, if (property == NULL) return -ENOMEM; - property->flags = CONNMAN_PROPERTY_FLAG_STATIC; - property->id = CONNMAN_PROPERTY_ID_INVALID; - property->name = g_strdup(name); - property->type = type; + property->id = CONNMAN_PROPERTY_ID_INVALID; + property->type = type; DBG("name %s type %d value %p", name, type, value); @@ -938,300 +603,57 @@ int connman_element_add_static_property(struct connman_element *element, break; } - __connman_element_lock(element); - element->properties = g_slist_append(element->properties, property); - __connman_element_unlock(element); - - return 0; -} - -static void emit_property_changed(DBusConnection *conn, - struct connman_element *element, - const char *name, int type, const void *data) -{ - DBusMessage *signal; - DBusMessageIter entry, value; - const char *iface, *sig; - - DBG("conn %p", conn); - - switch (element->type) { - case CONNMAN_ELEMENT_TYPE_CONNECTION: - iface = CONNMAN_CONNECTION_INTERFACE; - break; - default: - return; - } - - signal = dbus_message_new_signal(element->path, - iface, "PropertyChanged"); - if (signal == NULL) - return; - - dbus_message_iter_init_append(signal, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &name); - - switch (type) { - case DBUS_TYPE_STRING: - sig = DBUS_TYPE_STRING_AS_STRING; - break; - case DBUS_TYPE_BYTE: - sig = DBUS_TYPE_BYTE_AS_STRING; - break; - default: - sig = DBUS_TYPE_VARIANT_AS_STRING; - break; - } - - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - sig, &value); - dbus_message_iter_append_basic(&value, type, data); - dbus_message_iter_close_container(&entry, &value); - - g_dbus_send_message(conn, signal); -} - -int connman_element_set_static_property(struct connman_element *element, - const char *name, int type, const void *value) -{ - GSList *list; - - DBG("element %p name %s", element, element->name); - - if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_BYTE) - return -EINVAL; - - __connman_element_lock(element); - - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (g_str_equal(property->name, name) == FALSE) - continue; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC)) - continue; - - property->type = type; - g_free(property->value); - - switch (type) { - case DBUS_TYPE_STRING: - property->value = g_strdup(*((const char **) value)); - break; - case DBUS_TYPE_BYTE: - property->value = g_try_malloc(1); - if (property->value != NULL) - memcpy(property->value, value, 1); - break; - } - } - - __connman_element_unlock(element); - - emit_property_changed(connection, element, name, type, value); - - return 0; -} - -int connman_element_add_static_array_property(struct connman_element *element, - const char *name, int type, const void *value, int len) -{ - struct connman_property *property; - - DBG("element %p name %s", element, element->name); - - if (type != DBUS_TYPE_BYTE) - return -EINVAL; - - property = g_try_new0(struct connman_property, 1); - if (property == NULL) - return -ENOMEM; - - property->flags = CONNMAN_PROPERTY_FLAG_STATIC; - property->id = CONNMAN_PROPERTY_ID_INVALID; - property->name = g_strdup(name); - property->type = DBUS_TYPE_ARRAY; - property->subtype = type; - - DBG("name %s type %d value %p", name, type, value); - - switch (type) { - case DBUS_TYPE_BYTE: - property->value = g_try_malloc(len); - if (property->value != NULL) { - memcpy(property->value, - *((const unsigned char **) value), len); - property->size = len; - } - break; - } - - __connman_element_lock(element); - element->properties = g_slist_append(element->properties, property); - __connman_element_unlock(element); - - return 0; -} - -static void *get_reference_value(struct connman_element *element, - enum connman_property_id id) -{ - GSList *list; - - DBG("element %p name %s", element, element->name); - - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (property->id != id) - continue; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) - return property->value; - } - - if (element->parent == NULL) - return NULL; - - return get_reference_value(element->parent, id); -} - -static void set_reference_properties(struct connman_element *element) -{ - GSList *list; - - DBG("element %p name %s", element, element->name); - - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_REFERENCE)) - continue; - - property->value = get_reference_value(element->parent, - property->id); - } -} - -static struct connman_property *create_property(struct connman_element *element, - enum connman_property_id id) -{ - struct connman_property *property; - GSList *list; - - DBG("element %p name %s", element, element->name); - - __connman_element_lock(element); - - for (list = element->properties; list; list = list->next) { - property = list->data; - - if (property->id == id) - goto unlock; - } - - property = g_try_new0(struct connman_property, 1); - if (property == NULL) - goto unlock; - - property->flags = CONNMAN_PROPERTY_FLAG_REFERENCE; - property->id = id; - property->name = g_strdup(propid2name(id)); - property->type = propid2type(id); - - if (property->name == NULL) { - g_free(property); - property = NULL; - goto unlock; - } + __connman_element_lock(element); - element->properties = g_slist_append(element->properties, property); + g_hash_table_replace(element->properties, g_strdup(name), property); -unlock: __connman_element_unlock(element); - return property; + return 0; } -static void create_default_properties(struct connman_element *element) +static int set_static_array_property(struct connman_element *element, + const char *name, int type, const void *value, int len) { struct connman_property *property; - int i; DBG("element %p name %s", element, element->name); - for (i = 0; propid_table[i].name; i++) { - DBG("property %s", propid_table[i].name); + if (type != DBUS_TYPE_BYTE) + return -EINVAL; - property = create_property(element, propid_table[i].id); + property = g_try_new0(struct connman_property, 1); + if (property == NULL) + return -ENOMEM; - property->flags &= ~CONNMAN_PROPERTY_FLAG_REFERENCE; + property->id = CONNMAN_PROPERTY_ID_INVALID; + property->type = DBUS_TYPE_ARRAY; + property->subtype = type; - if (propid_table[i].type != DBUS_TYPE_STRING) - continue; + DBG("name %s type %d value %p", name, type, value); - if (propid_table[i].value) - property->value = g_strdup(propid_table[i].value); - else - property->value = g_strdup(""); + switch (type) { + case DBUS_TYPE_BYTE: + property->value = g_try_malloc(len); + if (property->value != NULL) { + memcpy(property->value, + *((const unsigned char **) value), len); + property->size = len; + } + break; } -} - -static int define_properties_valist(struct connman_element *element, - va_list args) -{ - enum connman_property_id id; - - DBG("element %p name %s", element, element->name); - - id = va_arg(args, enum connman_property_id); - while (id != CONNMAN_PROPERTY_ID_INVALID) { - - DBG("property %d", id); + __connman_element_lock(element); - create_property(element, id); + g_hash_table_replace(element->properties, g_strdup(name), property); - id = va_arg(args, enum connman_property_id); - } + __connman_element_unlock(element); return 0; } -/** - * connman_element_define_properties: - * @element: an element - * @varargs: list of property identifiers - * - * Define the valid properties for an element. - * - * Returns: %0 on success - */ -int connman_element_define_properties(struct connman_element *element, ...) -{ - va_list args; - int err; - - DBG("element %p name %s", element, element->name); - - va_start(args, element); - - err = define_properties_valist(element, args); - - va_end(args); - - return err; -} - -int connman_element_create_property(struct connman_element *element, - const char *name, int type) -{ - return -EIO; -} - -int connman_element_set_property(struct connman_element *element, +#if 0 +static int set_property(struct connman_element *element, enum connman_property_id id, const void *value) { switch (id) { @@ -1265,24 +687,13 @@ int connman_element_set_property(struct connman_element *element, element->ipv4.nameserver = g_strdup(*((const char **) value)); __connman_element_unlock(element); break; - case CONNMAN_PROPERTY_ID_WIFI_SECURITY: - __connman_element_lock(element); - g_free(element->wifi.security); - element->wifi.security = g_strdup(*((const char **) value)); - __connman_element_unlock(element); - break; - case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE: - __connman_element_lock(element); - g_free(element->wifi.passphrase); - element->wifi.passphrase = g_strdup(*((const char **) value)); - __connman_element_unlock(element); - break; default: return -EINVAL; } return 0; } +#endif int connman_element_get_value(struct connman_element *element, enum connman_property_id id, void *value) @@ -1291,6 +702,14 @@ int connman_element_get_value(struct connman_element *element, return -EINVAL; switch (id) { + case CONNMAN_PROPERTY_ID_IPV4_METHOD: + if (element->ipv4.method == CONNMAN_IPV4_METHOD_UNKNOWN) + return connman_element_get_value(element->parent, + id, value); + __connman_element_lock(element); + *((const char **) value) = __connman_ipv4_method2string(element->ipv4.method); + __connman_element_unlock(element); + break; case CONNMAN_PROPERTY_ID_IPV4_ADDRESS: if (element->ipv4.address == NULL) return connman_element_get_value(element->parent, @@ -1331,22 +750,6 @@ int connman_element_get_value(struct connman_element *element, *((char **) value) = element->ipv4.nameserver; __connman_element_unlock(element); break; - case CONNMAN_PROPERTY_ID_WIFI_SECURITY: - if (element->wifi.security == NULL) - return connman_element_get_value(element->parent, - id, value); - __connman_element_lock(element); - *((char **) value) = element->wifi.security; - __connman_element_unlock(element); - break; - case CONNMAN_PROPERTY_ID_WIFI_PASSPHRASE: - if (element->wifi.passphrase == NULL) - return connman_element_get_value(element->parent, - id, value); - __connman_element_lock(element); - *((char **) value) = element->wifi.passphrase; - __connman_element_unlock(element); - break; default: return -EINVAL; } @@ -1354,60 +757,53 @@ int connman_element_get_value(struct connman_element *element, return 0; } -gboolean connman_element_get_static_property(struct connman_element *element, +static gboolean get_static_property(struct connman_element *element, const char *name, void *value) { - GSList *list; + struct connman_property *property; gboolean found = FALSE; DBG("element %p name %s", element, element->name); __connman_element_lock(element); - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC)) - continue; - - if (g_str_equal(property->name, name) == TRUE) { - switch (property->type) { - case DBUS_TYPE_STRING: - *((char **) value) = property->value; - found = TRUE; - break; - } + property = g_hash_table_lookup(element->properties, name); + if (property != NULL) { + switch (property->type) { + case DBUS_TYPE_STRING: + *((char **) value) = property->value; + found = TRUE; + break; + case DBUS_TYPE_BYTE: + memcpy(value, property->value, 1); + found = TRUE; break; } } __connman_element_unlock(element); + if (found == FALSE && element->parent != NULL) + return get_static_property(element->parent, name, value); + return found; } -gboolean connman_element_get_static_array_property(struct connman_element *element, - const char *name, void *value, int *len) +static gboolean get_static_array_property(struct connman_element *element, + const char *name, void *value, unsigned int *len) { - GSList *list; + struct connman_property *property; gboolean found = FALSE; DBG("element %p name %s", element, element->name); __connman_element_lock(element); - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC)) - continue; - - if (g_str_equal(property->name, name) == TRUE) { - *((char **) value) = property->value; - *len = property->size; - found = TRUE; - break; - } + property = g_hash_table_lookup(element->properties, name); + if (property != NULL) { + *((char **) value) = property->value; + *len = property->size; + found = TRUE; } __connman_element_unlock(element); @@ -1415,74 +811,228 @@ gboolean connman_element_get_static_array_property(struct connman_element *eleme return found; } -gboolean connman_element_match_static_property(struct connman_element *element, +#if 0 +static gboolean match_static_property(struct connman_element *element, const char *name, const void *value) { - GSList *list; + struct connman_property *property; gboolean result = FALSE; DBG("element %p name %s", element, element->name); __connman_element_lock(element); - for (list = element->properties; list; list = list->next) { - struct connman_property *property = list->data; - - if (!(property->flags & CONNMAN_PROPERTY_FLAG_STATIC)) - continue; - - if (g_str_equal(property->name, name) == FALSE) - continue; - + property = g_hash_table_lookup(element->properties, name); + if (property != NULL) { if (property->type == DBUS_TYPE_STRING) result = g_str_equal(property->value, *((const char **) value)); - - if (result == TRUE) - break; } __connman_element_unlock(element); return result; } +#endif -static void append_connections(DBusMessageIter *entry) +/** + * connman_element_set_string: + * @element: element structure + * @key: unique identifier + * @value: string value + * + * Set string value for specific key + */ +int connman_element_set_string(struct connman_element *element, + const char *key, const char *value) { - DBusMessageIter value, iter; - const char *key = "Connections"; + return set_static_property(element, key, DBUS_TYPE_STRING, &value); +} - dbus_message_iter_append_basic(entry, DBUS_TYPE_STRING, &key); +/** + * connman_element_get_string: + * @element: element structure + * @key: unique identifier + * + * Get string value for specific key + */ +const char *connman_element_get_string(struct connman_element *element, + const char *key) +{ + const char *value; - dbus_message_iter_open_container(entry, DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING, - &value); + if (get_static_property(element, key, &value) == FALSE) + return NULL; - dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY, - DBUS_TYPE_OBJECT_PATH_AS_STRING, &iter); - __connman_element_list(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION, &iter); - dbus_message_iter_close_container(&value, &iter); + return value; +} - dbus_message_iter_close_container(entry, &value); +/** + * connman_element_set_uint8: + * @element: element structure + * @key: unique identifier + * @value: integer value + * + * Set integer value for specific key + */ +int connman_element_set_uint8(struct connman_element *element, + const char *key, connman_uint8_t value) +{ + return set_static_property(element, key, DBUS_TYPE_BYTE, &value); } -static void emit_connections_signal(DBusConnection *conn) +/** + * connman_element_get_uint8: + * @element: element structure + * @key: unique identifier + * + * Get integer value for specific key + */ +connman_uint8_t connman_element_get_uint8(struct connman_element *element, + const char *key) { - DBusMessage *signal; - DBusMessageIter entry; + connman_uint8_t value; - DBG("conn %p", conn); + if (get_static_property(element, key, &value) == FALSE) + return 0; - signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, "PropertyChanged"); - if (signal == NULL) - return; + return value; +} - dbus_message_iter_init_append(signal, &entry); +/** + * connman_element_set_blob: + * @element: element structure + * @key: unique identifier + * @data: blob data + * @size: blob size + * + * Set binary blob value for specific key + */ +int connman_element_set_blob(struct connman_element *element, + const char *key, const void *data, unsigned int size) +{ + return set_static_array_property(element, key, + DBUS_TYPE_BYTE, &data, size); +} - append_connections(&entry); +/** + * connman_element_get_blob: + * @element: element structure + * @key: unique identifier + * @size: pointer to blob size + * + * Get binary blob value for specific key + */ +const void *connman_element_get_blob(struct connman_element *element, + const char *key, unsigned int *size) +{ + void *value; - g_dbus_send_message(conn, signal); + if (get_static_array_property(element, key, &value, size) == FALSE) + return NULL; + + return value; +} + +int __connman_element_append_ipv4(struct connman_element *element, + DBusMessageIter *dict) +{ + const char *method = NULL; + const char *address = NULL, *netmask = NULL, *gateway = NULL; + + connman_element_get_value(element, + CONNMAN_PROPERTY_ID_IPV4_METHOD, &method); + + connman_element_get_value(element, + CONNMAN_PROPERTY_ID_IPV4_ADDRESS, &address); + connman_element_get_value(element, + CONNMAN_PROPERTY_ID_IPV4_NETMASK, &netmask); + connman_element_get_value(element, + CONNMAN_PROPERTY_ID_IPV4_GATEWAY, &gateway); + + if (method != NULL) + connman_dbus_dict_append_variant(dict, "IPv4.Method", + DBUS_TYPE_STRING, &method); + + if (address != NULL) + connman_dbus_dict_append_variant(dict, "IPv4.Address", + DBUS_TYPE_STRING, &address); + + if (netmask != NULL) + connman_dbus_dict_append_variant(dict, "IPv4.Netmask", + DBUS_TYPE_STRING, &netmask); + + if (gateway != NULL) + connman_dbus_dict_append_variant(dict, "IPv4.Gateway", + DBUS_TYPE_STRING, &gateway); + + return 0; +} + +int __connman_element_set_ipv4(struct connman_element *element, + const char *name, DBusMessageIter *value) +{ + int type; + + type = dbus_message_iter_get_arg_type(value); + + if (g_str_equal(name, "IPv4.Method") == TRUE) { + enum connman_ipv4_method method; + const char *str; + + if (type != DBUS_TYPE_STRING) + return -EINVAL; + + dbus_message_iter_get_basic(value, &str); + method = __connman_ipv4_string2method(str); + if (method == CONNMAN_IPV4_METHOD_UNKNOWN) + return -EINVAL; + + if (method == element->ipv4.method) + return -EALREADY; + + element->ipv4.method = method; + + connman_element_update(element); + } else if (g_str_equal(name, "IPv4.Address") == TRUE) { + const char *address; + + if (type != DBUS_TYPE_STRING) + return -EINVAL; + + dbus_message_iter_get_basic(value, &address); + + g_free(element->ipv4.address); + element->ipv4.address = g_strdup(address); + + connman_element_update(element); + } else if (g_str_equal(name, "IPv4.Netmask") == TRUE) { + const char *netmask; + + if (type != DBUS_TYPE_STRING) + return -EINVAL; + + dbus_message_iter_get_basic(value, &netmask); + + g_free(element->ipv4.netmask); + element->ipv4.netmask = g_strdup(netmask); + + connman_element_update(element); + } else if (g_str_equal(name, "IPv4.Gateway") == TRUE) { + const char *gateway; + + if (type != DBUS_TYPE_STRING) + return -EINVAL; + + dbus_message_iter_get_basic(value, &gateway); + + g_free(element->ipv4.gateway); + element->ipv4.gateway = g_strdup(gateway); + + connman_element_update(element); + } + + return 0; } static void append_state(DBusMessageIter *entry, const char *state) @@ -1515,20 +1065,16 @@ static void emit_state_change(DBusConnection *conn, const char *state) append_state(&entry, state); g_dbus_send_message(conn, signal); -} -static void set_signal_strength(struct connman_element *connection) -{ - struct connman_element *element = connection; + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "StateChanged"); + if (signal == NULL) + return; - while (element != NULL) { - if (element->type == CONNMAN_ELEMENT_TYPE_NETWORK) { - connection->strength = element->strength; - break; - } + dbus_message_iter_init_append(signal, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &state); - element = element->parent; - } + g_dbus_send_message(conn, signal); } static void probe_element(struct connman_element *element) @@ -1549,8 +1095,6 @@ static void probe_element(struct connman_element *element) __connman_element_lock(element); element->driver = driver; __connman_element_unlock(element); - - enable_element(element); break; } } @@ -1568,9 +1112,6 @@ static void register_element(gpointer data, gpointer user_data) node = g_node_find(element_root, G_PRE_ORDER, G_TRAVERSE_ALL, element->parent); basepath = element->parent->path; - - if (element->subtype == CONNMAN_ELEMENT_SUBTYPE_UNKNOWN) - element->subtype = element->parent->subtype; } else { element->parent = element_root->data; @@ -1580,26 +1121,31 @@ static void register_element(gpointer data, gpointer user_data) element->path = g_strdup_printf("%s/%s", basepath, element->name); - set_reference_properties(element); - __connman_element_unlock(element); DBG("element %p path %s", element, element->path); g_node_append_data(node, element); + if (element->type == CONNMAN_ELEMENT_TYPE_DHCP) { + element->parent->configuring = TRUE; + + if (__connman_element_count(NULL, + CONNMAN_ELEMENT_TYPE_CONNECTION) == 0) + emit_state_change(connection, "connecting"); + } + if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION) { - if (g_dbus_register_interface(connection, element->path, - CONNMAN_CONNECTION_INTERFACE, - connection_methods, element_signals, - NULL, element, NULL) == FALSE) - connman_error("Failed to register %s connection", - element->path); - else { - set_signal_strength(element); - emit_connections_signal(connection); - emit_state_change(connection, "online"); + struct connman_element *parent = element->parent; + + while (parent) { + parent->configuring = FALSE; + parent = parent->parent; } + + if (__connman_element_count(NULL, + CONNMAN_ELEMENT_TYPE_CONNECTION) == 1) + emit_state_change(connection, "online"); } emit_element_signal(connection, "ElementAdded", element); @@ -1650,6 +1196,9 @@ int connman_element_register(struct connman_element *element, } } + if (element->type == CONNMAN_ELEMENT_TYPE_DHCP) + element->ipv4.method = CONNMAN_IPV4_METHOD_DHCP; + element->parent = parent; __connman_element_unlock(element); @@ -1673,8 +1222,6 @@ static gboolean remove_element(GNode *node, gpointer user_data) g_node_unlink(node); if (element->driver) { - disable_element(element); - if (element->driver->remove) element->driver->remove(element); @@ -1690,10 +1237,6 @@ static gboolean remove_element(GNode *node, gpointer user_data) if (__connman_element_count(NULL, CONNMAN_ELEMENT_TYPE_CONNECTION) == 0) emit_state_change(connection, "offline"); - emit_connections_signal(connection); - - g_dbus_unregister_interface(connection, element->path, - CONNMAN_CONNECTION_INTERFACE); } emit_element_signal(connection, "ElementRemoved", element); @@ -1732,22 +1275,12 @@ void connman_element_unregister_children(struct connman_element *element) static gboolean update_element(GNode *node, gpointer user_data) { struct connman_element *element = node->data; - struct connman_element *root = user_data; DBG("element %p name %s", element, element->name); if (element->driver && element->driver->update) element->driver->update(element); - if (element->type == CONNMAN_ELEMENT_TYPE_CONNECTION && - root->type == CONNMAN_ELEMENT_TYPE_NETWORK) { - if (element->strength != root->strength) { - element->strength = root->strength; - emit_property_changed(connection, element, "Strength", - DBUS_TYPE_BYTE, &element->strength); - } - } - emit_element_signal(connection, "ElementUpdated", element); return FALSE; @@ -1774,12 +1307,41 @@ int connman_element_set_enabled(struct connman_element *element, element->enabled = enabled; - emit_enabled_signal(connection, element); + connman_element_update(element); return 0; } -int __connman_element_init(DBusConnection *conn, const char *device) +/** + * connman_element_set_error: + * @element: element structure + * @error: error identifier + * + * Set error state and specific error identifier + */ +void connman_element_set_error(struct connman_element *element, + enum connman_element_error error) +{ + struct connman_service *service; + + DBG("element %p error %d", element, error); + + if (element->type == CONNMAN_ELEMENT_TYPE_ROOT) + return; + + element->state = CONNMAN_ELEMENT_STATE_ERROR; + element->error = error; + + if (element->driver && element->driver->change) + element->driver->change(element); + + service = __connman_element_get_service(element); + __connman_service_indicate_state(service, + CONNMAN_SERVICE_STATE_FAILURE); +} + +int __connman_element_init(DBusConnection *conn, const char *device, + const char *nodevice) { struct connman_element *element; @@ -1796,10 +1358,10 @@ int __connman_element_init(DBusConnection *conn, const char *device) element->path = g_strdup("/"); element->type = CONNMAN_ELEMENT_TYPE_ROOT; - create_default_properties(element); - element_root = g_node_new(element); + __connman_notifier_init(); + __connman_service_init(); __connman_network_init(); __connman_device_init(); @@ -1832,7 +1394,10 @@ void __connman_element_start(void) started = TRUE; + __connman_storage_init_device(); + __connman_connection_init(); + __connman_ipv4_init(); __connman_detect_init(); } @@ -1841,6 +1406,7 @@ void __connman_element_stop(void) DBG(""); __connman_detect_cleanup(); + __connman_ipv4_cleanup(); __connman_connection_cleanup(); } @@ -1851,8 +1417,6 @@ static gboolean free_driver(GNode *node, gpointer data) DBG("element %p name %s", element, element->name); if (element->driver) { - disable_element(element); - if (element->driver->remove) element->driver->remove(element); @@ -1882,6 +1446,8 @@ void __connman_element_cleanup(void) __connman_device_cleanup(); __connman_network_cleanup(); + __connman_service_cleanup(); + __connman_notifier_cleanup(); g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, free_driver, NULL);