Commit f5d37008 authored by Slava Monich's avatar Slava Monich

[connman] Added net.connman.Manager.CreateService method. JB#37538

Arguments:

  s     service type (optional)
  s     device identifier (optional)
  s     network identifier (optional)
  a(ss) service settings (essentially, the settings file)

Returns:

  o     the service path

Only "wifi" service type is currently allowed. If the device
identifier is missing, the first available device is assumed.
If the network identifier is missing, it's generated from "SSID"
and "Security" settings.

Settings may contain the same keys that you can find in the
service settings file.
parent c7cbb9ff
......@@ -383,13 +383,6 @@ static GString *wifi_bss_ident_append_suffix(GString *str, GSupplicantBSS *bss)
return str;
}
static char *wifi_bss_ident_suffix(GSupplicantBSS *bss)
{
GString *str = g_string_sized_new(18);
return g_string_free(wifi_bss_ident_append_suffix(str, bss), FALSE);
}
static char *wifi_bss_ident(struct wifi_bss *bss_data)
{
GString *str;
......@@ -1512,8 +1505,7 @@ static void wifi_device_tp_free(struct wifi_device_tp *tp)
static void wifi_device_bss_add(struct wifi_device *dev, GSupplicantBSS *bss);
static void wifi_device_autoscan_perform(struct wifi_device *dev);
static void wifi_device_active_scan_perform(struct wifi_device *dev);
static void wifi_device_active_scan_schedule(struct wifi_device *dev,
GSupplicantBSS *bss);
static void wifi_device_active_scan_schedule(struct wifi_device *dev);
static void wifi_device_set_state(struct wifi_device *dev,
WIFI_DEVICE_STATE state);
......@@ -1858,7 +1850,7 @@ static gboolean wifi_device_autoscan_repeat(gpointer data)
* perform active scan.
*/
if (wifi_device_have_hidden_networks(dev)) {
wifi_device_active_scan_schedule(dev, NULL);
wifi_device_active_scan_schedule(dev);
}
wifi_device_autoscan_request(dev);
......@@ -1958,51 +1950,23 @@ static void wifi_device_active_scan_add(struct wifi_device *dev, GBytes *ssid)
(char*)g_bytes_get_data(ssid, NULL));
}
static void wifi_device_check_hidden_network(struct wifi_device *dev,
const char *name)
static void wifi_device_hidden_network_cb(struct connman_service *service,
void *data)
{
GKeyFile *file = connman_storage_load_service(name);
if (file) {
if (g_key_file_get_boolean(file, name, "Favorite", NULL) &&
g_key_file_get_boolean(file, name, "Hidden", NULL)) {
char *hex = g_key_file_get_string(file, name,
"SSID", NULL);
GBytes *ssid;
if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_WIFI &&
__connman_service_is_really_hidden(service)) {
struct wifi_device *dev = data;
GBytes* ssid = __connman_service_get_ssid(service);
if (hex) g_strstrip(hex);
ssid = gutil_hex2bytes(hex, -1);
if (ssid) {
wifi_device_active_scan_add(dev, ssid);
g_bytes_unref(ssid);
}
g_free(hex);
if (ssid) {
wifi_device_active_scan_add(dev, ssid);
}
g_key_file_unref(file);
}
}
static void wifi_device_active_scan_schedule(struct wifi_device *dev,
GSupplicantBSS *bss)
static void wifi_device_active_scan_schedule(struct wifi_device *dev)
{
gchar **services;
services = connman_storage_get_services();
if (services) {
int i;
char *suffix = bss ? wifi_bss_ident_suffix(bss) : NULL;
for (i = 0; services[i]; i++) {
const char *name = services[i];
if (g_str_has_prefix(name, WIFI_SERVICE_PREFIX) &&
(!suffix || g_str_has_suffix(name, suffix))) {
wifi_device_check_hidden_network(dev, name);
}
}
g_strfreev(services);
g_free(suffix);
}
__connman_service_foreach(wifi_device_hidden_network_cb, dev);
wifi_device_scan_check(dev);
}
......@@ -2400,7 +2364,7 @@ static void wifi_device_bss_add_3(struct wifi_device *dev,
connect->user_data = NULL;
wifi_hidden_connect_free(connect);
} else if (!ssid || !g_bytes_get_size(ssid)) {
wifi_device_active_scan_schedule(dev, bss);
wifi_device_active_scan_schedule(dev);
}
}
......@@ -2562,7 +2526,7 @@ static int wifi_device_scan(struct wifi_device *dev,
return (-EALREADY);
} else if (!ssid || !ssid_len) {
if (wifi_device_have_hidden_networks(dev)) {
wifi_device_active_scan_schedule(dev, NULL);
wifi_device_active_scan_schedule(dev);
}
DBG("restarting autoscan");
wifi_device_autoscan_restart(dev);
......@@ -3288,7 +3252,7 @@ static void wifi_device_update_screen_state(struct wifi_device *dev)
DBG("screen %sactive", active ? "" : "in");
dev->screen_active = active;
if (active) {
wifi_device_active_scan_schedule(dev, NULL);
wifi_device_active_scan_schedule(dev);
wifi_device_autoscan_restart(dev);
}
}
......
......@@ -622,6 +622,8 @@ bool __connman_network_get_weakness(struct connman_network *network);
int __connman_config_init();
void __connman_config_cleanup(void);
void __connman_service_foreach(void (*fn) (struct connman_service *service,
void *user_data), void *user_data);
void __connman_service_list_struct(DBusMessageIter *iter);
int __connman_config_load_service(GKeyFile *keyfile, const char *group,
......@@ -684,6 +686,8 @@ void __connman_service_list_struct(DBusMessageIter *iter);
int __connman_service_compare(const struct connman_service *a,
const struct connman_service *b);
const char *__connman_service_create(enum connman_service_type type,
const char *ident, GKeyFile *settings);
struct connman_service *__connman_service_lookup_from_index(int index);
struct connman_service *__connman_service_lookup_from_ident(const char *identifier);
......@@ -759,6 +763,8 @@ void __connman_service_return_error(struct connman_service *service,
int __connman_service_provision_changed(const char *ident);
void __connman_service_set_config(struct connman_service *service,
const char *file_id, const char *section);
bool __connman_service_is_really_hidden(struct connman_service *service);
GBytes *__connman_service_get_ssid(struct connman_service *service);
gboolean __connman_service_update_value_from_network(
struct connman_service *service,
struct connman_network *network, const char *key);
......
......@@ -24,6 +24,7 @@
#endif
#include <errno.h>
#include <ctype.h>
#include <gdbus.h>
......@@ -32,6 +33,9 @@
#include "connman.h"
#include <gsupplicant_util.h>
#include <gutil_misc.h>
static bool connman_state_idle;
static dbus_bool_t sessionmode;
......@@ -211,8 +215,7 @@ static DBusMessage *get_peers(DBusConnection *conn,
return NULL;
__connman_dbus_append_objpath_dict_array(reply,
append_peer_structs, NULL);
append_peer_structs, NULL);
return reply;
}
......@@ -315,16 +318,213 @@ static DBusMessage *unregister_counter(DBusConnection *conn,
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
static DBusMessage *reset_counters(DBusConnection *conn, DBusMessage *msg, void *data)
static DBusMessage *reset_counters(DBusConnection *conn, DBusMessage *msg,
void *data)
{
const char *type = NULL;
DBG("conn %p", conn);
dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &type,
DBUS_TYPE_INVALID);
__connman_service_counter_reset_all(type);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
/* This key is checked only if the first CreateService argument is empty */
#define SERVICE_KEY_TYPE "Type"
/* These should match the ones defined in service.c */
#define SERVICE_KEY_NAME "Name"
#define SERVICE_KEY_SSID "SSID"
#define SERVICE_KEY_SECURITY "Security"
static DBusMessage *create_service(DBusConnection *conn, DBusMessage *msg,
void *data)
{
DBG("conn %p", conn);
DBusMessage *reply;
DBusMessageIter iter, array, entry;
enum connman_service_type service_type;
GKeyFile *settings;
const char *device_ident, *network_ident, *type = NULL, *name = NULL;
char *ident, *p, *tmp_name = NULL;
/* N.B. The caller has checked the signature */
dbus_message_iter_init(msg, &iter);
dbus_message_iter_get_basic(&iter, &type);
dbus_message_iter_next(&iter);
dbus_message_iter_get_basic(&iter, &device_ident);
dbus_message_iter_next(&iter);
dbus_message_iter_get_basic(&iter, &network_ident);
dbus_message_iter_next(&iter);
/* If service type is missing, pull it from the settings */
if (!type || !type[0]) {
dbus_message_iter_recurse(&iter, &array);
while (dbus_message_iter_get_arg_type(&array) ==
DBUS_TYPE_STRUCT) {
const char *key = NULL;
const char *type;
dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID);
dbus_message_iter_recurse(&array, &entry);
dbus_message_iter_get_basic(&entry, &key);
dbus_message_iter_next(&entry);
if (!g_strcmp0(key, SERVICE_KEY_TYPE)) {
dbus_message_iter_get_basic(&entry, &type);
break;
}
dbus_message_iter_next(&array);
}
}
if (type && type[0]) {
/* Check the service type (only wifi is supported for now) */
service_type = __connman_service_string2type(type);
if (service_type == CONNMAN_SERVICE_TYPE_UNKNOWN) {
DBG("unknown device type %s", type);
return __connman_error_invalid_arguments(msg);
} else if (service_type != CONNMAN_SERVICE_TYPE_WIFI) {
DBG("unsupported device type %s", type);
return __connman_error_not_supported(msg);
}
} else {
/* No device type given, assume wifi */
service_type = CONNMAN_SERVICE_TYPE_WIFI;
}
__connman_service_counter_reset_all(type);
/*
* If no device identifier is given, assume the first device
* of this type.
*/
if (!device_ident || !device_ident[0]) {
struct connman_device *device =
__connman_device_find_device(service_type);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
if (!device) {
DBG("no devices of type %s", type);
return __connman_error_invalid_arguments(msg);
}
device_ident = connman_device_get_ident(device);
}
/*
* If no network identifier is provided, deduce one from ssid
* and security (we have to assume wifi here)
*/
if (network_ident && network_ident[0]) {
ident = g_strconcat(type, "_", device_ident, "_",
network_ident, NULL);
} else {
const char *ssid = NULL, *security = NULL, *ptr;
dbus_message_iter_recurse(&iter, &array);
while (dbus_message_iter_get_arg_type(&array) ==
DBUS_TYPE_STRUCT && !(ssid && security)) {
const char *key = NULL;
dbus_message_iter_recurse(&array, &entry);
dbus_message_iter_get_basic(&entry, &key);
dbus_message_iter_next(&entry);
if (!g_strcmp0(key, SERVICE_KEY_SSID)) {
dbus_message_iter_get_basic(&entry, &ssid);
} else if (!g_strcmp0(key, SERVICE_KEY_SECURITY)) {
dbus_message_iter_get_basic(&entry, &security);
}
dbus_message_iter_next(&array);
}
if (!ssid || !security) {
DBG("missing security and/or ssid");
return __connman_error_invalid_arguments(msg);
}
if (__connman_service_string2security(security) ==
CONNMAN_SERVICE_SECURITY_UNKNOWN) {
DBG("invalid security %s", security);
return __connman_error_invalid_arguments(msg);
}
for (ptr = ssid; *ptr; ptr++) {
if (!isxdigit(*ptr)) {
DBG("invalid ssid %s", ssid);
return __connman_error_invalid_arguments(msg);
}
}
if ((ptr - ssid) & 1) {
DBG("invalid ssid length");
return __connman_error_invalid_arguments(msg);
}
ident = g_strconcat(type, "_", device_ident, "_",
ssid, "_managed_", security, NULL);
}
/* Lowercase the identifier */
p = g_utf8_strdown(ident, -1);
if (p) {
g_free(ident);
ident = p;
}
/* Decode settings */
settings = g_key_file_new();
dbus_message_iter_recurse(&iter, &array);
while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
const char *key, *value;
dbus_message_iter_recurse(&array, &entry);
dbus_message_iter_get_basic(&entry, &key);
dbus_message_iter_next(&entry);
dbus_message_iter_get_basic(&entry, &value);
g_key_file_set_string(settings, ident, key, value);
dbus_message_iter_next(&array);
/* Find the name in the process of filling the keyfile */
if (!g_strcmp0(key, SERVICE_KEY_NAME)) {
name = value;
}
}
/* If there's no name, generate one (again, this is wifi specific) */
if (!name) {
char *str = g_key_file_get_string(settings, ident,
SERVICE_KEY_SSID, NULL);
GBytes* ssid = gutil_hex2bytes(str, -1);
if (ssid) {
name = tmp_name = gsupplicant_utf8_from_bytes(ssid);
g_bytes_unref(ssid);
}
g_free(str);
}
if (name) {
const char *path;
/* Actually create the service (or update the existing one) */
DBG("%s \"%s\"", ident, name);
path = __connman_service_create(service_type, ident, settings);
if (path) {
DBG("%s", path);
reply = g_dbus_create_reply(msg,
DBUS_TYPE_OBJECT_PATH, &path,
DBUS_TYPE_INVALID);
} else {
/* Passing zero to get the generic Failed error */
reply = __connman_error_failed(msg, 0);
}
} else {
DBG("can't generate service name");
reply = __connman_error_invalid_arguments(msg);
}
g_key_file_unref(settings);
g_free(ident);
return reply;
}
static DBusMessage *create_session(DBusConnection *conn,
......@@ -550,9 +750,16 @@ static const GDBusMethodTable manager_methods[] = {
{ GDBUS_METHOD("UnregisterCounter",
GDBUS_ARGS({ "path", "o" }), NULL,
unregister_counter) },
{ GDBUS_METHOD("ResetCounters",
GDBUS_ARGS({ "type", "s" }), NULL,
reset_counters) },
{ GDBUS_METHOD("ResetCounters",
GDBUS_ARGS({ "type", "s" }), NULL,
reset_counters) },
{ GDBUS_METHOD("CreateService",
GDBUS_ARGS({ "service_type", "s" },
{ "device_ident", "s" },
{ "network_ident", "s" },
{ "settings", "a(ss)" }),
GDBUS_ARGS({ "service", "o" }),
create_service) },
{ GDBUS_ASYNC_METHOD("CreateSession",
GDBUS_ARGS({ "settings", "a{sv}" },
{ "notifier", "o" }),
......
This diff is collapsed.
......@@ -37,7 +37,7 @@ BuildRequires: pkgconfig(libglibutil) >= 1.0.21
BuildRequires: pkgconfig(libdbuslogserver-dbus)
BuildRequires: pkgconfig(libdbusaccess) >= 1.0.3
BuildRequires: pkgconfig(libmce-glib)
BuildRequires: pkgconfig(libgsupplicant) >= 1.0.4
BuildRequires: pkgconfig(libgsupplicant) >= 1.0.6
BuildRequires: ppp-devel
%description
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment