--- include/service.h | 7 + src/connman.h | 6 - src/ipconfig.c | 108 --------------- src/service.c | 375 +++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 374 insertions(+), 122 deletions(-)
diff --git a/include/service.h b/include/service.h index 9de5b9c..8c0e892 100644 --- a/include/service.h +++ b/include/service.h @@ -84,6 +84,13 @@ enum connman_service_error { CONNMAN_SERVICE_ERROR_CONNECT_FAILED = 4, }; +enum connman_service_proxy_method { + CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN = 0, + CONNMAN_SERVICE_PROXY_METHOD_DIRECT = 1, + CONNMAN_SERVICE_PROXY_METHOD_MANUAL = 2, + CONNMAN_SERVICE_PROXY_METHOD_AUTO = 3, +}; + struct connman_service; struct connman_service *connman_service_create(void); diff --git a/src/connman.h b/src/connman.h index 3a546fe..59ef961 100644 --- a/src/connman.h +++ b/src/connman.h @@ -229,12 +229,6 @@ void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, enum connman_ipconfig_type type, DBusMessageIter *array); -void __connman_ipconfig_append_proxy(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter); -void __connman_ipconfig_append_proxyconfig(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter); -int __connman_ipconfig_set_proxyconfig(struct connman_ipconfig *ipconfig, - DBusMessageIter *array); void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); enum connman_ipconfig_method __connman_ipconfig_get_method( diff --git a/src/ipconfig.c b/src/ipconfig.c index 2b60e2d..8a67b41 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -74,7 +74,6 @@ struct connman_ipdevice { char *ipv4_gateway; char *ipv6_gateway; - char *proxy; char *pac; struct connman_ipconfig *config; @@ -305,7 +304,6 @@ static void free_ipdevice(gpointer data) free_address_list(ipdevice); g_free(ipdevice->ipv4_gateway); g_free(ipdevice->ipv6_gateway); - g_free(ipdevice->proxy); g_free(ipdevice->pac); g_free(ipdevice->address); @@ -1633,112 +1631,6 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, return 0; } -void __connman_ipconfig_append_proxy(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter) -{ - struct connman_ipdevice *ipdevice; - const char *method = "direct"; - - ipdevice = g_hash_table_lookup(ipdevice_hash, - GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) - goto done; - - if (ipdevice->pac == NULL) - goto done; - - method = "auto-config"; - - connman_dbus_dict_append_basic(iter, "URL", - DBUS_TYPE_STRING, &ipdevice->pac); - -done: - connman_dbus_dict_append_basic(iter, "Method", - DBUS_TYPE_STRING, &method); -} - -void __connman_ipconfig_append_proxyconfig(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter) -{ - struct connman_ipdevice *ipdevice; - const char *method = "auto"; - - ipdevice = g_hash_table_lookup(ipdevice_hash, - GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) - goto done; - - if (ipdevice->proxy == NULL) - goto done; - - method = ipdevice->proxy; - -done: - connman_dbus_dict_append_basic(iter, "Method", - DBUS_TYPE_STRING, &method); -} - -int __connman_ipconfig_set_proxyconfig(struct connman_ipconfig *ipconfig, - DBusMessageIter *array) -{ - struct connman_ipdevice *ipdevice; - DBusMessageIter dict; - const char *method; - - DBG("ipconfig %p", ipconfig); - - ipdevice = g_hash_table_lookup(ipdevice_hash, - GINT_TO_POINTER(ipconfig->index)); - if (ipdevice == NULL) - return -ENXIO; - - if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY) - return -EINVAL; - - dbus_message_iter_recurse(array, &dict); - - while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry; - const char *key; - int type; - - dbus_message_iter_recurse(&dict, &entry); - - if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) - return -EINVAL; - - dbus_message_iter_get_basic(&entry, &key); - dbus_message_iter_next(&entry); - - type = dbus_message_iter_get_arg_type(&entry); - - if (g_str_equal(key, "Method") == TRUE) { - if (type != DBUS_TYPE_STRING) - return -EINVAL; - - dbus_message_iter_get_basic(&entry, &method); - if (strlen(method) == 0) - method = NULL; - } - - dbus_message_iter_next(&dict); - } - - DBG("method %s", method); - - if (method == NULL) - return -EINVAL; - - if (g_str_equal(method, "auto") == FALSE && - g_str_equal(method, "direct") == FALSE) - return -EINVAL; - - g_free(ipdevice->proxy); - ipdevice->proxy = g_strdup(method); - - return 0; -} - void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig, DBusMessageIter *iter) { diff --git a/src/service.c b/src/service.c index 026778b..9db2708 100644 --- a/src/service.c +++ b/src/service.c @@ -100,6 +100,10 @@ struct connman_service { struct connman_stats stats; struct connman_stats stats_roaming; GHashTable *counter_table; + enum connman_service_proxy_method proxy; + char **proxies; + char **excludes; + char *pac; }; static void append_path(gpointer value, gpointer user_data) @@ -267,6 +271,34 @@ static enum connman_service_error string2error(const char *error) return CONNMAN_SERVICE_ERROR_UNKNOWN; } +static const char *proxymethod2string(enum connman_service_proxy_method method) +{ + switch (method) { + case CONNMAN_SERVICE_PROXY_METHOD_DIRECT: + return "direct"; + case CONNMAN_SERVICE_PROXY_METHOD_MANUAL: + return "manual"; + case CONNMAN_SERVICE_PROXY_METHOD_AUTO: + return "auto"; + case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN: + break; + } + + return NULL; +} + +static enum connman_service_proxy_method string2proxymethod(const char *method) +{ + if (!g_strcmp0(method, "direct")) + return CONNMAN_SERVICE_PROXY_METHOD_DIRECT; + else if (!g_strcmp0(method, "auto")) + return CONNMAN_SERVICE_PROXY_METHOD_AUTO; + else if (!g_strcmp0(method, "manual")) + return CONNMAN_SERVICE_PROXY_METHOD_MANUAL; + else + return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; +} + static connman_bool_t is_connecting(struct connman_service *service) { switch (service->state) { @@ -823,23 +855,116 @@ static void append_domainconfig(DBusMessageIter *iter, void *user_data) DBUS_TYPE_STRING, &service->domains[i]); } +static void append_proxies(DBusMessageIter *iter, void *user_data) +{ + struct connman_service *service = user_data; + int i; + + if (service->proxies == NULL) + return; + + for (i = 0; service->proxies[i]; i++) + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &service->proxies[i]); +} + +static void append_excludes(DBusMessageIter *iter, void *user_data) +{ + struct connman_service *service = user_data; + int i; + + if (service->excludes == NULL) + return; + + for (i = 0; service->excludes[i]; i++) + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &service->excludes[i]); +} + static void append_proxy(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; + const char *pac = NULL; + const char *method = proxymethod2string( + CONNMAN_SERVICE_PROXY_METHOD_DIRECT); + + DBG(""); if (is_connected(service) == FALSE) return; - if (service->ipconfig != NULL) - __connman_ipconfig_append_proxy(service->ipconfig, iter); + switch (service->proxy) { + case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN: + service->proxy = CONNMAN_SERVICE_PROXY_METHOD_DIRECT; + /* fall through */ + case CONNMAN_SERVICE_PROXY_METHOD_DIRECT: + goto done; + case CONNMAN_SERVICE_PROXY_METHOD_MANUAL: + connman_dbus_dict_append_array(iter, "Servers", + DBUS_TYPE_STRING, append_proxies, + service); + + connman_dbus_dict_append_array(iter, "Excludes", + DBUS_TYPE_STRING, append_excludes, + service); + break; + case CONNMAN_SERVICE_PROXY_METHOD_AUTO: + /* Maybe DHCP, or WPAD, has provided an url for a pac file */ + if (service->ipconfig != NULL) + pac = __connman_ipconfig_get_proxy_autoconfig( + service->ipconfig); + + if (service->pac == NULL && pac == NULL) + goto done; + + if (service->pac != NULL) + pac = service->pac; + + connman_dbus_dict_append_basic(iter, "URL", + DBUS_TYPE_STRING, &pac); + break; + } + + method = proxymethod2string(service->proxy); + +done: + connman_dbus_dict_append_basic(iter, "Method", + DBUS_TYPE_STRING, &method); } static void append_proxyconfig(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; + const char *method; - if (service->ipconfig != NULL) - __connman_ipconfig_append_proxyconfig(service->ipconfig, iter); + switch (service->proxy) { + case CONNMAN_SERVICE_PROXY_METHOD_DIRECT: + break; + case CONNMAN_SERVICE_PROXY_METHOD_MANUAL: + if (service->proxies != NULL) + connman_dbus_dict_append_array(iter, "Servers", + DBUS_TYPE_STRING, + append_proxies, service); + + if (service->excludes != NULL) + connman_dbus_dict_append_array(iter, "Excludes", + DBUS_TYPE_STRING, + append_excludes, service); + break; + case CONNMAN_SERVICE_PROXY_METHOD_AUTO: + if (service->pac != NULL) + connman_dbus_dict_append_basic(iter, "URL", + DBUS_TYPE_STRING, &service->pac); + break; + case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN: + service->proxy = CONNMAN_SERVICE_PROXY_METHOD_AUTO; + break; + } + + method = proxymethod2string(service->proxy); + + connman_dbus_dict_append_basic(iter, "Method", + DBUS_TYPE_STRING, &method); } static void append_provider(DBusMessageIter *iter, void *user_data) @@ -1464,6 +1589,179 @@ static DBusMessage *get_properties(DBusConnection *conn, return reply; } +static int update_proxy_configuration(struct connman_service *service, + DBusMessageIter *array) +{ + DBusMessageIter dict; + enum connman_service_proxy_method method; + GString *servers_str = NULL; + GString *excludes_str = NULL; + const char *url = NULL; + + method = CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; + + dbus_message_iter_recurse(array, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, variant; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) + goto error; + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != + DBUS_TYPE_VARIANT) + goto error; + + dbus_message_iter_recurse(&entry, &variant); + type = dbus_message_iter_get_arg_type(&variant); + + if (g_str_equal(key, "Method") == TRUE) { + const char *val; + + if (type != DBUS_TYPE_STRING) + goto error; + + dbus_message_iter_get_basic(&variant, &val); + method = string2proxymethod(val); + } else if (g_str_equal(key, "URL") == TRUE) { + if (type != DBUS_TYPE_STRING) + goto error; + + dbus_message_iter_get_basic(&variant, &url); + } else if (g_str_equal(key, "Servers") == TRUE) { + DBusMessageIter str_array; + + if (type != DBUS_TYPE_ARRAY) + goto error; + + servers_str = g_string_new(NULL); + if (servers_str == NULL) + goto error; + + dbus_message_iter_recurse(&variant, &str_array); + + while (dbus_message_iter_get_arg_type(&str_array) == + DBUS_TYPE_STRING) { + char *val = NULL; + + dbus_message_iter_get_basic(&str_array, &val); + + if (servers_str->len > 0) + g_string_append_printf(servers_str, + " %s", val); + else + g_string_append(servers_str, val); + + dbus_message_iter_next(&str_array); + } + } else if (g_str_equal(key, "Excludes") == TRUE) { + DBusMessageIter str_array; + + if (type != DBUS_TYPE_ARRAY) + goto error; + + excludes_str = g_string_new(NULL); + if (excludes_str == NULL) + goto error; + + dbus_message_iter_recurse(&variant, &str_array); + + while (dbus_message_iter_get_arg_type(&str_array) == + DBUS_TYPE_STRING) { + char *val = NULL; + + dbus_message_iter_get_basic(&str_array, &val); + + if (excludes_str->len > 0) + g_string_append_printf(excludes_str, + " %s", val); + else + g_string_append(excludes_str, val); + + dbus_message_iter_next(&str_array); + } + } + + dbus_message_iter_next(&dict); + } + + switch (method) { + case CONNMAN_SERVICE_PROXY_METHOD_DIRECT: + break; + case CONNMAN_SERVICE_PROXY_METHOD_MANUAL: + if (servers_str == NULL && service->proxies == NULL) + goto error; + + if (servers_str != NULL) { + g_strfreev(service->proxies); + + if (servers_str->len > 0) + service->proxies = g_strsplit_set( + servers_str->str, " ", 0); + else + service->proxies = NULL; + } + + if (excludes_str != NULL) { + g_strfreev(service->excludes); + + if (excludes_str->len > 0) + service->excludes = g_strsplit_set( + excludes_str->str, " ", 0); + else + service->excludes = NULL; + } + + if (service->proxies == NULL) + method = CONNMAN_SERVICE_PROXY_METHOD_DIRECT; + + break; + case CONNMAN_SERVICE_PROXY_METHOD_AUTO: + g_free(service->pac); + + if (url != NULL && strlen(url) > 0) + service->pac = g_strdup(url); + else + service->pac = NULL; + + /* if we are connected: + - if service->pac == NULL + - if __connman_ipconfig_get_proxy_autoconfig( + service->ipconfig) == NULL + --> We should start WPAD */ + + break; + case CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN: + goto error; + } + + if (servers_str != NULL) + g_string_free(servers_str, TRUE); + + if (excludes_str != NULL) + g_string_free(excludes_str, TRUE); + + service->proxy = method; + + return 0; + +error: + if (servers_str != NULL) + g_string_free(servers_str, TRUE); + + if (excludes_str != NULL) + g_string_free(excludes_str, TRUE); + + return -EINVAL; +} + static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -1668,11 +1966,11 @@ static DBusMessage *set_property(DBusConnection *conn, } else if (g_str_equal(name, "Proxy.Configuration") == TRUE) { int err; - if (service->ipconfig == NULL) - return __connman_error_invalid_property(msg); + if (type != DBUS_TYPE_ARRAY) + return __connman_error_invalid_arguments(msg); + + err = update_proxy_configuration(service, &value); - err = __connman_ipconfig_set_proxyconfig(service->ipconfig, - &value); if (err < 0) return __connman_error_failed(msg, -err); @@ -2246,9 +2544,12 @@ static void service_free(gpointer user_data) g_strfreev(service->nameservers); g_strfreev(service->domains); + g_strfreev(service->proxies); + g_strfreev(service->excludes); g_free(service->nameserver); g_free(service->domainname); + g_free(service->pac); g_free(service->mcc); g_free(service->mnc); g_free(service->apn); @@ -4001,6 +4302,31 @@ static int service_load(struct connman_service *service) service->domains = NULL; } + str = g_key_file_get_string(keyfile, + service->identifier, "Proxy.Method", NULL); + service->proxy = string2proxymethod(str); + + service->proxies = g_key_file_get_string_list(keyfile, + service->identifier, "Proxy.Servers", &length, NULL); + if (service->proxies != NULL && length == 0) { + g_strfreev(service->proxies); + service->proxies = NULL; + } + + service->excludes = g_key_file_get_string_list(keyfile, + service->identifier, "Proxy.Excludes", &length, NULL); + if (service->excludes != NULL && length == 0) { + g_strfreev(service->excludes); + service->excludes = NULL; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "Proxy.URL", NULL); + if (str != NULL) { + g_free(service->pac); + service->pac = str; + } + done: g_key_file_free(keyfile); @@ -4014,6 +4340,7 @@ static int service_save(struct connman_service *service) gchar *pathname, *data = NULL; gsize length; gchar *str; + const char *cst_str = NULL; int err = 0; DBG("service %p", service); @@ -4162,6 +4489,38 @@ update: g_key_file_remove_key(keyfile, service->identifier, "Domains", NULL); + cst_str = proxymethod2string(service->proxy); + if (str != NULL) + g_key_file_set_string(keyfile, service->identifier, + "Proxy.Method", str); + + if (service->proxies != NULL) { + guint len = g_strv_length(service->proxies); + + g_key_file_set_string_list(keyfile, service->identifier, + "Proxy.Servers", + (const gchar **) service->proxies, len); + } else + g_key_file_remove_key(keyfile, service->identifier, + "Proxy.Servers", NULL); + + if (service->excludes != NULL) { + guint len = g_strv_length(service->excludes); + + g_key_file_set_string_list(keyfile, service->identifier, + "Proxy.Excludes", + (const gchar **) service->excludes, len); + } else + g_key_file_remove_key(keyfile, service->identifier, + "Proxy.Excludes", NULL); + + if (service->pac != NULL && strlen(service->pac) > 0) + g_key_file_set_string(keyfile, service->identifier, + "Proxy.URL", service->pac); + else + g_key_file_remove_key(keyfile, service->identifier, + "Proxy.URL", NULL); + data = g_key_file_to_data(keyfile, &length, NULL); if (g_file_set_contents(pathname, data, length, NULL) == FALSE) -- 1.7.1 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman