connman_bool_t favorite;
unsigned int order;
char *name;
+ char *passphrase;
struct connman_device *device;
+ struct connman_network *network;
};
static void append_path(gpointer value, gpointer user_data)
static void state_changed(struct connman_service *service)
{
DBusMessage *signal;
- DBusMessageIter entry;
- const char *str;
+ DBusMessageIter entry, value;
+ const char *str, *key = "State";
if (service->path == NULL)
return;
return;
dbus_message_iter_init_append(signal, &entry);
- connman_dbus_dict_append_variant(&entry, "State",
- DBUS_TYPE_STRING, &str);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_STRING_AS_STRING, &value);
+ dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
+ dbus_message_iter_close_container(&entry, &value);
+
g_dbus_send_message(connection, signal);
}
connman_dbus_dict_append_variant(&dict, "Name",
DBUS_TYPE_STRING, &service->name);
+ if (service->passphrase != NULL &&
+ __connman_security_check_privilege(msg,
+ CONNMAN_SECURITY_PRIVILEGE_SECRET) == 0)
+ connman_dbus_dict_append_variant(&dict, "Passphrase",
+ DBUS_TYPE_STRING, &service->passphrase);
+
dbus_message_iter_close_container(&array, &dict);
return reply;
}
+static DBusMessage *set_property(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct connman_service *service = data;
+ DBusMessageIter iter, value;
+ const char *name;
+ int type;
+
+ 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_privilege(msg,
+ CONNMAN_SECURITY_PRIVILEGE_MODIFY) < 0)
+ return __connman_error_permission_denied(msg);
+
+ type = dbus_message_iter_get_arg_type(&value);
+
+ if (g_str_equal(name, "Passphrase") == TRUE) {
+ const char *passphrase;
+
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ if (__connman_security_check_privilege(msg,
+ CONNMAN_SECURITY_PRIVILEGE_SECRET) < 0)
+ return __connman_error_permission_denied(msg);
+
+ dbus_message_iter_get_basic(&value, &passphrase);
+
+ g_free(service->passphrase);
+ service->passphrase = g_strdup(passphrase);
+
+ if (service->network != NULL)
+ connman_network_set_string(service->network,
+ "WiFi.Passphrase", service->passphrase);
+ }
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
static DBusMessage *connect_service(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct connman_service *service = data;
+ if (service->network != NULL) {
+ int err;
+
+ err = connman_network_connect(service->network);
+ if (err < 0 && err != -EINPROGRESS)
+ return __connman_error_failed(msg);
+
+ service->state = CONNMAN_SERVICE_STATE_ASSOCIATION;
+
+ state_changed(service);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+
if (service->device != NULL) {
+ if (service->favorite == FALSE)
+ return __connman_error_no_carrier(msg);
+
if (__connman_device_connect(service->device) < 0)
return __connman_error_failed(msg);
service->state = CONNMAN_SERVICE_STATE_READY;
state_changed(service);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
return __connman_error_not_supported(msg);
{
struct connman_service *service = data;
+ if (service->network != NULL) {
+ int err;
+
+ err = __connman_network_disconnect(service->network);
+ if (err < 0 && err != -EINPROGRESS)
+ return __connman_error_failed(msg);
+
+ service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
+
+ state_changed(service);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+
if (service->device != NULL) {
+ if (service->favorite == FALSE)
+ return __connman_error_no_carrier(msg);
+
if (__connman_device_connect(service->device) < 0)
return __connman_error_failed(msg);
service->state = CONNMAN_SERVICE_STATE_IDLE;
state_changed(service);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
return __connman_error_not_supported(msg);
if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
return __connman_error_not_supported(msg);
+ if (service->network != NULL) {
+ int err;
+
+ err = __connman_network_disconnect(service->network);
+ if (err < 0 && err != -EINPROGRESS)
+ return __connman_error_failed(msg);
+
+ service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
+
+ state_changed(service);
+ }
+
connman_service_set_favorite(service, FALSE);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static GDBusMethodTable service_methods[] = {
- { "GetProperties", "", "a{sv}", get_properties },
- { "Connect", "", "", connect_service },
- { "Disconnect", "", "", disconnect_service },
- { "Remove", "", "", remove_service },
- { "MoveBefore", "o", "", move_before },
- { "MoveAfter", "o", "", move_after },
+ { "GetProperties", "", "a{sv}", get_properties },
+ { "SetProperty", "sv", "", set_property },
+ { "Connect", "", "", connect_service },
+ { "Disconnect", "", "", disconnect_service },
+ { "Remove", "", "", remove_service },
+ { "MoveBefore", "o", "", move_before },
+ { "MoveAfter", "o", "", move_after },
{ },
};
g_free(path);
}
+ if (service->network != NULL)
+ connman_network_unref(service->network);
+
g_free(service->name);
+ g_free(service->passphrase);
g_free(service->identifier);
g_free(service);
}
int __connman_service_set_carrier(struct connman_service *service,
connman_bool_t carrier)
{
+ DBG("service %p carrier %d", service, carrier);
+
if (service == NULL)
return -EINVAL;
int __connman_service_indicate_configuration(struct connman_service *service)
{
+ DBG("service %p", service);
+
if (service == NULL)
return -EINVAL;
return 0;
}
+int __connman_service_ready(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ if (service == NULL)
+ return -EINVAL;
+
+ service->state = CONNMAN_SERVICE_STATE_READY;
+
+ state_changed(service);
+
+ return 0;
+}
+
+int __connman_service_disconnect(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ if (service == NULL)
+ return -EINVAL;
+
+ service->state = CONNMAN_SERVICE_STATE_DISCONNECT;
+
+ state_changed(service);
+
+ return 0;
+}
+
/**
* connman_service_lookup:
* @identifier: service identifier
{
const char *path = __connman_profile_active();
+ DBG("service %p", service);
+
if (service->path != NULL)
return -EALREADY;
service->path = g_strdup_printf("%s/%s", path, service->identifier);
+ DBG("path %s", service->path);
+
g_dbus_register_interface(connection, service->path,
CONNMAN_SERVICE_INTERFACE,
service_methods, service_signals,
/**
* connman_service_lookup_from_network:
- * @device: device structure
+ * @network: network structure
*
* Look up a service by network (reference count will not be increased)
*/
struct connman_service *__connman_service_lookup_from_network(struct connman_network *network)
{
struct connman_service *service;
+ const char *group;
char *name;
- name = g_strdup_printf("%s_%s", __connman_network_get_type(network),
- __connman_network_get_group(network));
+ group = __connman_network_get_group(network);
+ if (group == NULL)
+ return NULL;
+
+ name = g_strdup_printf("%s_%s",
+ __connman_network_get_type(network), group);
service = connman_service_lookup(name);
return CONNMAN_SERVICE_TYPE_UNKNOWN;
}
+static enum connman_service_mode convert_wifi_mode(const char *mode)
+{
+ if (mode == NULL)
+ return CONNMAN_SERVICE_MODE_UNKNOWN;
+ else if (g_str_equal(mode, "managed") == TRUE)
+ return CONNMAN_SERVICE_MODE_MANAGED;
+ else if (g_str_equal(mode, "adhoc") == TRUE)
+ return CONNMAN_SERVICE_MODE_ADHOC;
+ else
+ return CONNMAN_SERVICE_MODE_UNKNOWN;
+}
+
+static enum connman_service_mode convert_wifi_security(const char *security)
+{
+ if (security == NULL)
+ return CONNMAN_SERVICE_SECURITY_UNKNOWN;
+ else if (g_str_equal(security, "none") == TRUE)
+ return CONNMAN_SERVICE_SECURITY_NONE;
+ else if (g_str_equal(security, "wep") == TRUE)
+ return CONNMAN_SERVICE_SECURITY_WEP;
+ else if (g_str_equal(security, "wpa") == TRUE)
+ return CONNMAN_SERVICE_SECURITY_WPA;
+ else if (g_str_equal(security, "wpa2") == TRUE)
+ return CONNMAN_SERVICE_SECURITY_WPA2;
+ else
+ return CONNMAN_SERVICE_SECURITY_UNKNOWN;
+}
+
+static void update_from_network(struct connman_service *service,
+ struct connman_network *network)
+{
+ connman_uint8_t strength = service->strength;
+ GSequenceIter *iter;
+ const char *str;
+
+ str = connman_network_get_string(network, "Name");
+ if (str != NULL) {
+ g_free(service->name);
+ service->name = g_strdup(str);
+ }
+
+ service->strength = connman_network_get_uint8(network, "Strength");
+
+ str = connman_network_get_string(network, "WiFi.Mode");
+ service->mode = convert_wifi_mode(str);
+
+ str = connman_network_get_string(network, "WiFi.Security");
+ service->security = convert_wifi_security(str);
+
+ if (service->strength > strength && service->network != NULL) {
+ connman_network_unref(service->network);
+ service->network = NULL;
+ }
+
+ if (service->network == NULL) {
+ service->network = connman_network_ref(network);
+
+ str = connman_network_get_string(network, "WiFi.Passphrase");
+ if (str != NULL) {
+ g_free(service->passphrase);
+ service->passphrase = g_strdup(str);
+ }
+ }
+
+ iter = g_hash_table_lookup(service_hash, service->identifier);
+ if (iter != NULL)
+ g_sequence_sort_changed(iter, service_compare, NULL);
+}
+
/**
* connman_service_create_from_network:
- * @device: device structure
+ * @network: network structure
*
* Look up service by network and if not found, create one
*/
struct connman_service *__connman_service_create_from_network(struct connman_network *network)
{
struct connman_service *service;
+ const char *group;
char *name;
- name = g_strdup_printf("%s_%s", __connman_network_get_type(network),
- __connman_network_get_group(network));
+ group = __connman_network_get_group(network);
+ if (group == NULL)
+ return NULL;
+
+ name = g_strdup_printf("%s_%s",
+ __connman_network_get_type(network), group);
service = connman_service_get(name);
if (service == NULL)
goto done;
if (service->path != NULL) {
+ update_from_network(service, network);
+
+ __connman_profile_changed();
+
connman_service_put(service);
service = NULL;
goto done;
service->type = convert_network_type(network);
+ update_from_network(service, network);
+
service_register(service);
done: