[PATCH 6to4 v1 4/6] service: Create 6to4 tunnel if enabled.
--- src/connman.h |1 + src/ipv4.c|5 + src/service.c | 56 3 files changed, 62 insertions(+), 0 deletions(-) diff --git a/src/connman.h b/src/connman.h index 08bd7a9..24816a0 100644 --- a/src/connman.h +++ b/src/connman.h @@ -466,6 +466,7 @@ struct connman_ipconfig *__connman_service_get_ip4config( struct connman_service *service); struct connman_ipconfig *__connman_service_get_ip6config( struct connman_service *service); +connman_bool_t __connman_service_6to4_enabled(struct connman_service *service); const char *__connman_service_get_ident(struct connman_service *service); const char *__connman_service_get_path(struct connman_service *service); unsigned int __connman_service_get_order(struct connman_service *service); diff --git a/src/ipv4.c b/src/ipv4.c index f6e436c..8cbeaf3 100644 --- a/src/ipv4.c +++ b/src/ipv4.c @@ -99,6 +99,9 @@ static int ipv4_probe(struct connman_element *element) __connman_ipconfig_set_element_ipv6_gateway( ipconfig, connection); + if (__connman_service_6to4_enabled(service) == TRUE) + __connman_6to4_probe(address); + if (connman_element_register(connection, element) 0) connman_element_unref(connection); @@ -148,6 +151,8 @@ static void ipv4_remove(struct connman_element *element) AF_INET, address, peer, prefixlen, broadcast) 0)) DBG(address removal failed); + __connman_6to4_remove(); + connman_element_unref(element); } diff --git a/src/service.c b/src/service.c index 7751dc0..ff9a1af 100644 --- a/src/service.c +++ b/src/service.c @@ -108,6 +108,7 @@ struct connman_service { char **excludes; char *pac; connman_bool_t wps; + connman_bool_t enabled_6to4; }; static void append_path(gpointer value, gpointer user_data) @@ -1622,6 +1623,9 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_dbus_dict_append_dict(dict, IPv6.Configuration, append_ipv6config, service); + connman_dbus_dict_append_basic(dict, 6to4, + DBUS_TYPE_BOOLEAN, service-enabled_6to4); + connman_dbus_dict_append_array(dict, Nameservers, DBUS_TYPE_STRING, append_dns, service); @@ -1817,6 +1821,21 @@ void __connman_service_set_passphrase(struct connman_service *service, __connman_storage_save_service(service); } +connman_bool_t __connman_service_6to4_enabled(struct connman_service *service) +{ + enum connman_ipconfig_method method; + + if (service == NULL) + return FALSE; + + method = __connman_ipconfig_get_method(service-ipconfig_ipv6); + if (method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || + method == CONNMAN_IPCONFIG_METHOD_OFF) + return FALSE; + + return service-enabled_6to4; +} + static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -2313,6 +2332,31 @@ static DBusMessage *set_property(DBusConnection *conn, ipv4, ipv6); __connman_storage_save_service(service); + } else if (g_str_equal(name, 6to4) == TRUE) { + connman_bool_t six2four; + + if (type != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(value, six2four); + + if (service-enabled_6to4 == six2four) + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + service-enabled_6to4 = six2four; + if (service-enabled_6to4 == TRUE) { + if (__connman_service_6to4_enabled(service) == TRUE) { + struct connman_ipaddress *address; + address = + __connman_ipconfig_get_system_address( + service-ipconfig_ipv4); + if (address) + __connman_6to4_probe(address-local); + } + } else + __connman_6to4_remove(); + + __connman_storage_save_service(service); } else return __connman_error_invalid_property(msg); @@ -4821,6 +4865,8 @@ static int service_load(struct connman_service *service) case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_ETHERNET: + service-enabled_6to4 = g_key_file_get_boolean(keyfile, +
[PATCH 6to4 v1 2/6] ipconfig: Add function to return the system address pointer.
--- src/connman.h |2 ++ src/ipconfig.c |9 + 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/src/connman.h b/src/connman.h index 6202db3..5014291 100644 --- a/src/connman.h +++ b/src/connman.h @@ -253,6 +253,8 @@ void __connman_ipconfig_set_element_ipv6_gateway( int __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, struct connman_element *parent); int __connman_ipconfig_set_address(struct connman_ipconfig *ipconfig); +struct connman_ipaddress *__connman_ipconfig_get_system_address( + struct connman_ipconfig *ipconfig); int __connman_ipconfig_clear_address(struct connman_ipconfig *ipconfig); unsigned char __connman_ipconfig_netmask_prefix_len(const char *netmask); diff --git a/src/ipconfig.c b/src/ipconfig.c index 1fb8281..7396645 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1129,6 +1129,15 @@ enum connman_ipconfig_method __connman_ipconfig_get_method(struct connman_ipconf return ipconfig-method; } +struct connman_ipaddress *__connman_ipconfig_get_system_address( + struct connman_ipconfig *ipconfig) +{ + if (ipconfig == NULL) + return NULL; + + return ipconfig-system; +} + /** * connman_ipconfig_bind: * @ipconfig: ipconfig structure -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v1 0/6] Create 6to4 tunnel automatically if enabled
Hi, the following patches create 6to4 tunnel automatically if enabled for a given service, IPv6 is enabled and device has public IP address. Regards, Jukka Jukka Rissanen (6): doc: Add comment about 6to4 tunnelling. ipconfig: Add function to return the system address pointer. 6to4: Add 6to4 tunnel support. service: Create 6to4 tunnel if enabled. test: Add support for 6to4 tunnel status printing. test: Add support for enabling/disabling 6to4 tunnel. Makefile.am |2 +- doc/service-api.txt |9 + src/6to4.c | 569 +++ src/connman.h |6 + src/ipconfig.c |9 + src/ipv4.c |5 + src/service.c | 56 + test/list-services |2 +- test/test-connman | 28 +++ 9 files changed, 684 insertions(+), 2 deletions(-) create mode 100644 src/6to4.c ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v1 1/6] doc: Add comment about 6to4 tunnelling.
--- doc/service-api.txt |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/doc/service-api.txt b/doc/service-api.txt index b3e758e..35e03a6 100644 --- a/doc/service-api.txt +++ b/doc/service-api.txt @@ -386,6 +386,15 @@ Properties string State [readonly] until the new configuration has been successfully installed. + boolean 6to4 [readwrite] + + If set to true, the service will create 6to4 + tunnel if the service IPv4 address is not private. + Default value is false meaning that 6to4 tunnel is + not created. Only one tunnel is created even if + there are more than one active service that have + public IPv4 address. + dict Proxy [readonly] string Method [readonly] -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v2] ipconfig: Enable IPv6 privacy extension for autoconf addresses.
This is described in RFC 3041 and RFC 4941 --- src/ipconfig.c | 64 1 files changed, 64 insertions(+), 0 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 1fb8281..f6af4c4 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -79,6 +79,7 @@ struct connman_ipdevice { struct connman_ipconfig *config_ipv6; gboolean ipv6_enabled; + int ipv6_privacy; }; static GHashTable *ipdevice_hash = NULL; @@ -352,6 +353,65 @@ static void set_ipv6_state(gchar *ifname, gboolean enable) fclose(f); } +static int get_ipv6_privacy(gchar *ifname) +{ + gchar *path; + FILE *f; + int value = 0; + + if (ifname == NULL) + return value; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return value; + + f = fopen(path, r); + + g_free(path); + + if (f != NULL) { + if (fscanf(f, %d, value) = 0) + value = 0; + fclose(f); + } + + return value; +} + +/* Enable the IPv6 privacy extension for stateless address autoconfiguration. + * This is described in RFC 3041 and RFC 4941 + */ +static void set_ipv6_privacy(gchar *ifname, int value) +{ + gchar *path; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return; + + if (value 0) + value = 0; + + f = fopen(path, r+); + + g_free(path); + + if (f == NULL) + return; + + fprintf(f, %d, value); + fclose(f); +} + static void free_ipdevice(gpointer data) { struct connman_ipdevice *ipdevice = data; @@ -377,6 +437,7 @@ static void free_ipdevice(gpointer data) g_free(ipdevice-address); set_ipv6_state(ipdevice-ifname, ipdevice-ipv6_enabled); + set_ipv6_privacy(ipdevice-ifname, ipdevice-ipv6_privacy); g_free(ipdevice-ifname); g_free(ipdevice); @@ -474,6 +535,7 @@ void __connman_ipconfig_newlink(int index, unsigned short type, ipdevice-type = type; ipdevice-ipv6_enabled = get_ipv6_state(ipdevice-ifname); + ipdevice-ipv6_privacy = get_ipv6_privacy(ipdevice-ifname); ipdevice-address = g_strdup(address); @@ -1610,6 +1672,8 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) if (ipdevice == NULL) return; + set_ipv6_privacy(ipdevice-ifname, 2); + set_ipv6_state(ipdevice-ifname, TRUE); } -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH] ipconfig: Never return or set system wide IPv6 status value.
--- src/ipconfig.c | 18 +- 1 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 1fb8281..f8ca414 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -299,13 +299,13 @@ static gboolean get_ipv6_state(gchar *ifname) int disabled; gchar *path; FILE *f; - gboolean enabled = FALSE; + gboolean enabled = TRUE; if (ifname == NULL) - path = g_strdup(/proc/sys/net/ipv6/conf/all/disable_ipv6); - else - path = g_strdup_printf( - /proc/sys/net/ipv6/conf/%s/disable_ipv6, ifname); + return enabled; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/disable_ipv6, + ifname); if (path == NULL) return enabled; @@ -329,10 +329,10 @@ static void set_ipv6_state(gchar *ifname, gboolean enable) FILE *f; if (ifname == NULL) - path = g_strdup(/proc/sys/net/ipv6/conf/all/disable_ipv6); - else - path = g_strdup_printf( - /proc/sys/net/ipv6/conf/%s/disable_ipv6, ifname); + return; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/disable_ipv6, + ifname); if (path == NULL) return; -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v3] ipconfig: Enable IPv6 privacy extension for autoconf addresses.
This is described in RFC 3041 and RFC 4941 --- src/ipconfig.c | 66 1 files changed, 66 insertions(+), 0 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 1fb8281..0f676d3 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -79,6 +79,7 @@ struct connman_ipdevice { struct connman_ipconfig *config_ipv6; gboolean ipv6_enabled; + int ipv6_privacy; }; static GHashTable *ipdevice_hash = NULL; @@ -352,6 +353,67 @@ static void set_ipv6_state(gchar *ifname, gboolean enable) fclose(f); } +static int get_ipv6_privacy(gchar *ifname) +{ + gchar *path; + FILE *f; + int value; + + if (ifname == NULL) + return 0; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return 0; + + f = fopen(path, r); + + g_free(path); + + if (f == NULL) + return 0; + + if (fscanf(f, %d, value) = 0) + value = 0; + + fclose(f); + + return value; +} + +/* Enable the IPv6 privacy extension for stateless address autoconfiguration. + * This is described in RFC 3041 and RFC 4941 + */ +static void set_ipv6_privacy(gchar *ifname, int value) +{ + gchar *path; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return; + + if (value 0) + value = 0; + + f = fopen(path, r+); + + g_free(path); + + if (f == NULL) + return; + + fprintf(f, %d, value); + fclose(f); +} + static void free_ipdevice(gpointer data) { struct connman_ipdevice *ipdevice = data; @@ -377,6 +439,7 @@ static void free_ipdevice(gpointer data) g_free(ipdevice-address); set_ipv6_state(ipdevice-ifname, ipdevice-ipv6_enabled); + set_ipv6_privacy(ipdevice-ifname, ipdevice-ipv6_privacy); g_free(ipdevice-ifname); g_free(ipdevice); @@ -474,6 +537,7 @@ void __connman_ipconfig_newlink(int index, unsigned short type, ipdevice-type = type; ipdevice-ipv6_enabled = get_ipv6_state(ipdevice-ifname); + ipdevice-ipv6_privacy = get_ipv6_privacy(ipdevice-ifname); ipdevice-address = g_strdup(address); @@ -1610,6 +1674,8 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) if (ipdevice == NULL) return; + set_ipv6_privacy(ipdevice-ifname, 2); + set_ipv6_state(ipdevice-ifname, TRUE); } -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH v3] ipconfig: Enable IPv6 privacy extension for autoconf addresses.
Hi David, ... but while ConnMan is driving the device we *always* use this horrid 'privacy' mode when IPv6 is enabled? What kind of problems there is with the privacy mode? Regards, Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH] ipconfig: Enable IPv6 properly when loading and if method is AUTO or MANUAL.
--- Hi, This fixes the issue when ipconfig IPv6 method is AUTO and config is loaded during connman startup, now depending on timing it is possible that IPv4 address is not loaded at all. This can happen easily for WLAN connections, ethernet connections will probably work ok without the patch. The IPv6 disabling must also not done during the loading so that if multiple configs are loaded, those ones that have IPv6 method OFF will not block IPv6 networking from those that have method set to AUTO. Regards, Jukka src/ipconfig.c | 17 ++--- 1 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 14edb3d..28f77a6 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1856,23 +1856,10 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, ipconfig-method = CONNMAN_IPCONFIG_METHOD_OFF; if (ipconfig-type == CONNMAN_IPCONFIG_TYPE_IPV6) { - if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_OFF) - disable_ipv6(ipconfig); - else if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO || + if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO || ipconfig-method == CONNMAN_IPCONFIG_METHOD_MANUAL) { - enable_ipv6(ipconfig); __connman_ipconfig_enable(ipconfig); - - if (ipconfig-ops_data) { - struct connman_service *service = - ipconfig-ops_data; - struct connman_network *network; - network = __connman_service_get_network( - service); - if (network) - __connman_network_set_ipconfig(network, - NULL, ipconfig); - } + enable_ipv6(ipconfig); } } -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v2] ipconfig: Toggle interface IPv6 status if IPv6 ipconfig is enabled or disabled.
This is done so that if service is disconnected, the kernel created autoconf routes need to be cleared also. That can be done easiest by disabling IPv6 for that interface. The disabling of IPv6 is only done for autoconfigured interfaces. When service is connected, the IPv6 is enabled for the used interface. --- Hi, this is the second version of the patch. No code changes, just fixed the changelog to describe the problem properly. Regards, Jukka src/ipconfig.c | 61 ++- 1 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 14edb3d..62d3766 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1351,6 +1351,34 @@ const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipc return ipdevice-pac; } +static void disable_ipv6(struct connman_ipconfig *ipconfig) +{ + struct connman_ipdevice *ipdevice; + + DBG(); + + ipdevice = g_hash_table_lookup(ipdevice_hash, + GINT_TO_POINTER(ipconfig-index)); + if (ipdevice == NULL) + return; + + set_ipv6_state(ipdevice-ifname, FALSE); +} + +static void enable_ipv6(struct connman_ipconfig *ipconfig) +{ + struct connman_ipdevice *ipdevice; + + DBG(); + + ipdevice = g_hash_table_lookup(ipdevice_hash, + GINT_TO_POINTER(ipconfig-index)); + if (ipdevice == NULL) + return; + + set_ipv6_state(ipdevice-ifname, TRUE); +} + int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) { struct connman_ipdevice *ipdevice; @@ -1376,6 +1404,7 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) if (ipdevice-config_ipv6 == ipconfig) return -EALREADY; type = CONNMAN_IPCONFIG_TYPE_IPV6; + enable_ipv6(ipconfig); } else return -EINVAL; @@ -1459,6 +1488,10 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig) if (ipdevice-config_ipv6 == ipconfig) { ipconfig_list = g_list_remove(ipconfig_list, ipconfig); + if (ipdevice-config_ipv6-method == + CONNMAN_IPCONFIG_METHOD_AUTO) + disable_ipv6(ipdevice-config_ipv6); + connman_ipaddress_clear(ipdevice-config_ipv6-system); connman_ipconfig_unref(ipdevice-config_ipv6); ipdevice-config_ipv6 = NULL; @@ -1662,34 +1695,6 @@ void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, DBUS_TYPE_STRING, ipconfig-address-gateway); } -static void disable_ipv6(struct connman_ipconfig *ipconfig) -{ - struct connman_ipdevice *ipdevice; - - DBG(); - - ipdevice = g_hash_table_lookup(ipdevice_hash, - GINT_TO_POINTER(ipconfig-index)); - if (ipdevice == NULL) - return; - - set_ipv6_state(ipdevice-ifname, FALSE); -} - -static void enable_ipv6(struct connman_ipconfig *ipconfig) -{ - struct connman_ipdevice *ipdevice; - - DBG(); - - ipdevice = g_hash_table_lookup(ipdevice_hash, - GINT_TO_POINTER(ipconfig-index)); - if (ipdevice == NULL) - return; - - set_ipv6_state(ipdevice-ifname, TRUE); -} - int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, DBusMessageIter *array) { -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH privacy v2 0/3] Enable/disable IPv6 privacy extension
Hi, this is the v2 of the IPv6 privacy patch. This version makes the privacy setting configurable. The privacy setting can be changed in service API via IPv6.Configuration property. I used the same values for privacy setting as described in the kernel documentation Documentation/networking/ip-sysctl.txt file so that the mapping between those two is simple. By default the privacy setting is 1, meaning it is enabled but public addresses are prefered over temporary ones. The privacy value is only written to kernel if IPv6 method is AUTO. Note that the kernel might not activate the privacy mode immediately, it seems to require that interface goes down before activation. Same thing happens if privacy mode is disabled, the temporary addresses do not disappear until the interface is taken down. At least this was happening in my test system with kernel 2.6.32. Regards, Jukka Jukka Rissanen (3): doc: Add description about IPv6 privacy setting. ipconfig: Enable IPv6 privacy extension for autoconf addresses. test: Enable or disable IPv6 privacy extension. doc/service-api.txt | 18 src/ipconfig.c | 113 -- test/set-ipv6-method | 18 +--- 3 files changed, 138 insertions(+), 11 deletions(-) ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH privacy v2 2/3] ipconfig: Enable IPv6 privacy extension for autoconf addresses.
--- src/ipconfig.c | 113 ++-- 1 files changed, 109 insertions(+), 4 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 1fb8281..481133b 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -51,6 +51,8 @@ struct connman_ipconfig { enum connman_ipconfig_method method; struct connman_ipaddress *address; struct connman_ipaddress *system; + + int ipv6_privacy; }; struct connman_ipdevice { @@ -79,6 +81,7 @@ struct connman_ipdevice { struct connman_ipconfig *config_ipv6; gboolean ipv6_enabled; + int ipv6_privacy; }; static GHashTable *ipdevice_hash = NULL; @@ -352,6 +355,67 @@ static void set_ipv6_state(gchar *ifname, gboolean enable) fclose(f); } +static int get_ipv6_privacy(gchar *ifname) +{ + gchar *path; + FILE *f; + int value; + + if (ifname == NULL) + return 0; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return 0; + + f = fopen(path, r); + + g_free(path); + + if (f == NULL) + return 0; + + if (fscanf(f, %d, value) = 0) + value = 0; + + fclose(f); + + return value; +} + +/* Enable the IPv6 privacy extension for stateless address autoconfiguration. + * The privacy extension is described in RFC 3041 and RFC 4941 + */ +static void set_ipv6_privacy(gchar *ifname, int value) +{ + gchar *path; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return; + + if (value 0) + value = 0; + + f = fopen(path, r+); + + g_free(path); + + if (f == NULL) + return; + + fprintf(f, %d, value); + fclose(f); +} + static void free_ipdevice(gpointer data) { struct connman_ipdevice *ipdevice = data; @@ -377,6 +441,7 @@ static void free_ipdevice(gpointer data) g_free(ipdevice-address); set_ipv6_state(ipdevice-ifname, ipdevice-ipv6_enabled); + set_ipv6_privacy(ipdevice-ifname, ipdevice-ipv6_privacy); g_free(ipdevice-ifname); g_free(ipdevice); @@ -474,6 +539,7 @@ void __connman_ipconfig_newlink(int index, unsigned short type, ipdevice-type = type; ipdevice-ipv6_enabled = get_ipv6_state(ipdevice-ifname); + ipdevice-ipv6_privacy = get_ipv6_privacy(ipdevice-ifname); ipdevice-address = g_strdup(address); @@ -926,6 +992,7 @@ static struct connman_ipconfig *create_ipv6config(int index) ipv6config-index = index; ipv6config-type = CONNMAN_IPCONFIG_TYPE_IPV6; ipv6config-method = CONNMAN_IPCONFIG_METHOD_AUTO; + ipv6config-ipv6_privacy = 1; ipv6config-address = connman_ipaddress_alloc(AF_INET6); if (ipv6config-address == NULL) { @@ -1496,6 +1563,9 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, if (ipconfig-system-gateway != NULL) connman_dbus_dict_append_basic(iter, Gateway, DBUS_TYPE_STRING, ipconfig-system-gateway); + + connman_dbus_dict_append_basic(iter, Privacy, + DBUS_TYPE_INT32, ipconfig-ipv6_privacy); } void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, @@ -1536,6 +1606,9 @@ void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, if (ipconfig-address-gateway != NULL) connman_dbus_dict_append_basic(iter, Gateway, DBUS_TYPE_STRING, ipconfig-address-gateway); + + connman_dbus_dict_append_basic(iter, Privacy, + DBUS_TYPE_INT32, ipconfig-ipv6_privacy); } void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, @@ -1610,6 +1683,9 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) if (ipdevice == NULL) return; + if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO) + set_ipv6_privacy(ipdevice-ifname, ipconfig-ipv6_privacy); + set_ipv6_state(ipdevice-ifname, TRUE); } @@ -1618,8 +1694,8 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, { enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; const char *address = NULL, *netmask = NULL, *gateway = NULL, - *prefix_length_string = NULL; - int prefix_length = 0; + *prefix_length_string = NULL, *privacy_string = NULL; + int prefix_length = 0, privacy = 1; DBusMessageIter dict; DBG(ipconfig %p, ipconfig); @@ -1678,12 +1754,24 @@ int
[PATCH privacy v2 3/3] test: Enable or disable IPv6 privacy extension.
--- test/set-ipv6-method | 18 +++--- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/test/set-ipv6-method b/test/set-ipv6-method index 274e89b..c0b251e 100755 --- a/test/set-ipv6-method +++ b/test/set-ipv6-method @@ -4,7 +4,7 @@ import sys import dbus def print_usage(): - print Usage: %s service off|manual|auto [address [prefixlen] [gateway]] % (sys.argv[0]) + print Usage: %s service off|manual|auto [address [prefixlen] [gateway]] [privacy] % (sys.argv[0]) if (len(sys.argv) 3): print_usage() @@ -20,12 +20,16 @@ properties = service.GetProperties() print Setting method %s for %s % (sys.argv[2], sys.argv[1]) ipv6_configuration = { Method: sys.argv[2] } -if (len(sys.argv) 3): - ipv6_configuration[Address] = sys.argv[3] -if (len(sys.argv) 4): - ipv6_configuration[PrefixLength] = sys.argv[4] -if (len(sys.argv) 5): - ipv6_configuration[Gateway] = sys.argv[5] +if sys.argv[2] == auto: + if (len(sys.argv) 3): + ipv6_configuration[Privacy] = sys.argv[3] +else: + if (len(sys.argv) 3): + ipv6_configuration[Address] = sys.argv[3] + if (len(sys.argv) 4): + ipv6_configuration[PrefixLength] = sys.argv[4] + if (len(sys.argv) 5): + ipv6_configuration[Gateway] = sys.argv[5] service.SetProperty(IPv6.Configuration, ipv6_configuration) print New IPv6.Configuration: , ipv6_configuration -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH privacy v2 1/3] doc: Add description about IPv6 privacy setting.
--- doc/service-api.txt | 18 ++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/doc/service-api.txt b/doc/service-api.txt index b3e758e..55c5b6e 100644 --- a/doc/service-api.txt +++ b/doc/service-api.txt @@ -375,6 +375,24 @@ Properties string State [readonly] The current configured IPv6 gateway. + int32 Privacy [readonly] + + Enable or disable IPv6 privacy extension + that is described in RFC 4941. The value + has only meaning if Method is set to auto. + + Value = 0 means that privacy extension is + disabled and normal autoconf addresses are + used. + Value 1 means that privacy extension is + enabled and system prefers to use public + addresses over temporary addresses. + Value = 2 means that privacy extension is + enabled and system prefers temporary addresses + over public addresses. + + Default value is 1. + dict IPv6.Configuration [readwrite] Same values as IPv6 property. The IPv6 represents -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: Memory Leaks When Using Statistics (was Re: [PATCH 1/1]: Fix Memory-map and Double-free Errors in Statistics Handling (was Re: Connman-0.67 Crashes and/or Hangs on Start-up))
Hi Grant, On 17 February 2011 20:10, Grant Erickson maratho...@gmail.com wrote: To isolate the leaks, I systematically eliminated processes from the system until I was left with: - syslogd - klogd - wpa_supplicant - dbus-daemon - connmand I have run connmand under valgrind and it reports memory leaks in gsupplicant code. I sent earlier some memoryleak patches in various parts of connman but unfortunately I have lately had no time to find out where the latest supplicant leaks are. Regards, Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v2 0/7] Create 6to4 tunnel automatically if enabled
Hi, the v2 patch checks if the tunnel has internet connectivity. Only change to v1 is the patch #7 which adds the connectivity check. The check is done by trying to connect to ipv6.google.com:80 via the tunnel. The google host was choosen as it only provides connectivity via IPv6. This could be changed to connman.net when it provides the same kind of service. The IPv6 address of the host is resolved by async DNS so that mainloop is not blocked. The timeouts I used were 10 sec for DNS query and 2 sec for connection test but these can be tweaked of course. Any comments or suggestions? Regards, Jukka Jukka Rissanen (7): doc: Add comment about 6to4 tunnelling. ipconfig: Add function to return the system address pointer. 6to4: Add 6to4 tunnel support. service: Create 6to4 tunnel if enabled. test: Add support for 6to4 tunnel status printing. test: Add support for enabling/disabling 6to4 tunnel. 6to4: Check the connectivity via tunnel after creating it. Makefile.am | 10 +- configure.ac|4 + doc/service-api.txt |9 + src/6to4.c | 789 +++ src/connman.h |6 + src/ipconfig.c |9 + src/ipv4.c |5 + src/service.c | 56 test/list-services |2 +- test/test-connman | 28 ++ 10 files changed, 912 insertions(+), 6 deletions(-) create mode 100644 src/6to4.c ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v2 1/7] doc: Add comment about 6to4 tunnelling.
--- doc/service-api.txt |9 + 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/doc/service-api.txt b/doc/service-api.txt index 9695059..c662aaf 100644 --- a/doc/service-api.txt +++ b/doc/service-api.txt @@ -377,6 +377,15 @@ Properties string State [readonly] until the new configuration has been successfully installed. + boolean 6to4 [readwrite] + + If set to true, the service will create 6to4 + tunnel if the service IPv4 address is not private. + Default value is false meaning that 6to4 tunnel is + not created. Only one tunnel is created even if + there are more than one active service that have + public IPv4 address. + dict Proxy [readonly] string Method [readonly] -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v2 3/7] 6to4: Add 6to4 tunnel support.
--- Makefile.am |2 +- src/6to4.c| 569 + src/connman.h |3 + 3 files changed, 573 insertions(+), 1 deletions(-) create mode 100644 src/6to4.c diff --git a/Makefile.am b/Makefile.am index 144fcc5..8f13f56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,7 +77,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \ src/wifi.c src/storage.c src/dbus.c src/config.c \ src/technology.c src/counter.c src/location.c \ src/session.c src/tethering.c src/wpad.c src/wispr.c \ - src/stats.c src/iptables.c src/dnsproxy.c + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @CAPNG_LIBS@ @XTABLES_LIBS@ -lresolv -ldl diff --git a/src/6to4.c b/src/6to4.c new file mode 100644 index 000..b07eeed --- /dev/null +++ b/src/6to4.c @@ -0,0 +1,569 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include stdio.h +#include string.h +#include sys/socket.h +#include netinet/in.h +#include arpa/inet.h +#include net/if.h +#include linux/ip.h +#include linux/if_tunnel.h +#include linux/netlink.h +#include linux/rtnetlink.h +#include sys/ioctl.h +#include unistd.h + +#include connman.h +#include connman/log.h + +static int tunnel_created; + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) + +#ifndef IP_DF +#define IP_DF 0x4000 /* Flag: Don't Fragment */ +#endif + +struct rtnl_handle { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +/* Note that addattr32(), addattr_l(), rtnl_close(), rtnl_open() and + * rtnl_talk() are from libnetlink.c that is found in iproute2 package + * and copyright by Alexey Kuznetsov et al. + */ +static int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *rta; + if (NLMSG_ALIGN(n-nlmsg_len) + len (unsigned int)maxlen) { + DBG(Error! max allowed bound %d exceeded, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, 4); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + len; + + return 0; +} + +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, + const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len) + (unsigned int)maxlen) { + DBG(addattr_l message exceeded bound of %d, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static void rtnl_close(struct rtnl_handle *rth) +{ + if (rth-fd = 0) { + close(rth-fd); + rth-fd = -1; + } +} + +static int rtnl_open(struct rtnl_handle *rth) +{ + socklen_t addr_len; + int sndbuf = 32768; + int rcvbuf = 32768; + + memset(rth, 0, sizeof(*rth)); + + rth-fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (rth-fd 0) { + DBG(Cannot open netlink socket: %s, strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_SNDBUF, sndbuf, + sizeof(sndbuf)) 0) { + DBG(SO_SNDBUF: %s, strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_RCVBUF, rcvbuf, + sizeof(rcvbuf)) 0) { + DBG(SO_RCVBUF: %s, strerror(errno)); + return -1; + } + + memset(rth-local, 0, sizeof(rth-local)); + rth-local.nl_family = AF_NETLINK;
[PATCH 6to4 v2 4/7] service: Create 6to4 tunnel if enabled.
--- src/connman.h |1 + src/ipv4.c|5 + src/service.c | 56 3 files changed, 62 insertions(+), 0 deletions(-) diff --git a/src/connman.h b/src/connman.h index a8ef170..0d90b6b 100644 --- a/src/connman.h +++ b/src/connman.h @@ -481,6 +481,7 @@ struct connman_ipconfig *__connman_service_get_ip4config( struct connman_service *service); struct connman_ipconfig *__connman_service_get_ip6config( struct connman_service *service); +connman_bool_t __connman_service_6to4_enabled(struct connman_service *service); const char *__connman_service_get_ident(struct connman_service *service); const char *__connman_service_get_path(struct connman_service *service); unsigned int __connman_service_get_order(struct connman_service *service); diff --git a/src/ipv4.c b/src/ipv4.c index e77b8ee..1ab0338 100644 --- a/src/ipv4.c +++ b/src/ipv4.c @@ -103,6 +103,9 @@ static int ipv4_probe(struct connman_element *element) if (err 0) return err; + if (__connman_service_6to4_enabled(service) == TRUE) + __connman_6to4_probe(address); + return 0; } @@ -152,6 +155,8 @@ static void ipv4_remove(struct connman_element *element) AF_INET, address, peer, prefixlen, broadcast) 0)) DBG(address removal failed); + __connman_6to4_remove(); + connman_element_unref(element); } diff --git a/src/service.c b/src/service.c index 9a0d499..7293354 100644 --- a/src/service.c +++ b/src/service.c @@ -103,6 +103,7 @@ struct connman_service { char **excludes; char *pac; connman_bool_t wps; + connman_bool_t enabled_6to4; }; static void append_path(gpointer value, gpointer user_data) @@ -1649,6 +1650,9 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_dbus_dict_append_dict(dict, IPv6.Configuration, append_ipv6config, service); + connman_dbus_dict_append_basic(dict, 6to4, + DBUS_TYPE_BOOLEAN, service-enabled_6to4); + connman_dbus_dict_append_array(dict, Nameservers, DBUS_TYPE_STRING, append_dns, service); @@ -1851,6 +1855,21 @@ void __connman_service_set_passphrase(struct connman_service *service, __connman_storage_save_service(service); } +connman_bool_t __connman_service_6to4_enabled(struct connman_service *service) +{ + enum connman_ipconfig_method method; + + if (service == NULL) + return FALSE; + + method = __connman_ipconfig_get_method(service-ipconfig_ipv6); + if (method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || + method == CONNMAN_IPCONFIG_METHOD_OFF) + return FALSE; + + return service-enabled_6to4; +} + static DBusMessage *get_properties(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -2281,6 +2300,31 @@ static DBusMessage *set_property(DBusConnection *conn, ipv4, ipv6); __connman_storage_save_service(service); + } else if (g_str_equal(name, 6to4) == TRUE) { + connman_bool_t six2four; + + if (type != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(value, six2four); + + if (service-enabled_6to4 == six2four) + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + + service-enabled_6to4 = six2four; + if (service-enabled_6to4 == TRUE) { + if (__connman_service_6to4_enabled(service) == TRUE) { + struct connman_ipaddress *address; + address = + __connman_ipconfig_get_system_address( + service-ipconfig_ipv4); + if (address) + __connman_6to4_probe(address-local); + } + } else + __connman_6to4_remove(); + + __connman_storage_save_service(service); } else return __connman_error_invalid_property(msg); @@ -4756,6 +4800,8 @@ static int service_load(struct connman_service *service) case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: case CONNMAN_SERVICE_TYPE_ETHERNET: + service-enabled_6to4 = g_key_file_get_boolean(keyfile, + service-identifier, 6to4, NULL); case CONNMAN_SERVICE_TYPE_GPS: case CONNMAN_SERVICE_TYPE_VPN: case CONNMAN_SERVICE_TYPE_GADGET: @@ -4830,6
[PATCH 6to4 v2 5/7] test: Add support for 6to4 tunnel status printing.
--- test/list-services |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/test/list-services b/test/list-services index 3ae6a4d..20295b1 100755 --- a/test/list-services +++ b/test/list-services @@ -50,7 +50,7 @@ for path in properties[Services]: val = extract_list(properties[key]) elif key in [Favorite, Immutable, AutoConnect, LoginRequired, SetupRequired, - PassphraseRequired]: + PassphraseRequired, 6to4]: if properties[key] == dbus.Boolean(1): val = true else: -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH v2] ipconfig: Enable IPv6 properly when loading config and disable IPv6 properly when connecting service.
--- Hi, this sets the IPv6 status correctly by - enabling IPv6 when service config is loaded and method is AUTO or MANUAL - and disabling IPv6 when service is connected and method is OFF Regards, Jukka include/ipconfig.h |1 + src/ipconfig.c | 25 ++--- src/service.c |7 +++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/include/ipconfig.h b/include/ipconfig.h index 9bc97d5..7d62330 100644 --- a/include/ipconfig.h +++ b/include/ipconfig.h @@ -95,6 +95,7 @@ int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig, enum connman_ipconfig_method method); void connman_ipconfig_bind(struct connman_ipconfig *ipconfig, struct connman_ipaddress *ipaddress); +void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig); #ifdef __cplusplus } diff --git a/src/ipconfig.c b/src/ipconfig.c index 62d3766..6511370 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1379,6 +1379,14 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) set_ipv6_state(ipdevice-ifname, TRUE); } +void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig) +{ + if (ipconfig == NULL || ipconfig-type != CONNMAN_IPCONFIG_TYPE_IPV6) + return; + + disable_ipv6(ipconfig); +} + int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig) { struct connman_ipdevice *ipdevice; @@ -1861,23 +1869,10 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig, ipconfig-method = CONNMAN_IPCONFIG_METHOD_OFF; if (ipconfig-type == CONNMAN_IPCONFIG_TYPE_IPV6) { - if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_OFF) - disable_ipv6(ipconfig); - else if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO || + if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO || ipconfig-method == CONNMAN_IPCONFIG_METHOD_MANUAL) { - enable_ipv6(ipconfig); __connman_ipconfig_enable(ipconfig); - - if (ipconfig-ops_data) { - struct connman_service *service = - ipconfig-ops_data; - struct connman_network *network; - network = __connman_service_get_network( - service); - if (network) - __connman_network_set_ipconfig(network, - NULL, ipconfig); - } + enable_ipv6(ipconfig); } } diff --git a/src/service.c b/src/service.c index 9a0d499..1696e5a 100644 --- a/src/service.c +++ b/src/service.c @@ -3319,6 +3319,7 @@ int __connman_service_indicate_state(struct connman_service *service, if (state == CONNMAN_SERVICE_STATE_READY) { enum connman_service_proxy_method proxy_config; + enum connman_ipconfig_method method; set_reconnect_state(service, TRUE); @@ -3371,6 +3372,12 @@ int __connman_service_indicate_state(struct connman_service *service, } default_changed(); + + method = __connman_ipconfig_get_method(service-ipconfig_ipv6); + if (method == CONNMAN_IPCONFIG_METHOD_OFF) + __connman_ipconfig_disable_ipv6( + service-ipconfig_ipv6); + } else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) { __connman_location_finish(service); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6routes v1 1/2] rtnl: Catch IPv6 route netlink messages.
--- src/rtnl.c | 122 +++ 1 files changed, 97 insertions(+), 25 deletions(-) diff --git a/src/rtnl.c b/src/rtnl.c index 5b09ca4..42b1632 100644 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -633,7 +633,7 @@ static void process_deladdr(unsigned char family, unsigned char prefixlen, prefixlen, ip_string); } -static void extract_route(struct rtmsg *msg, int bytes, int *index, +static void extract_ipv4_route(struct rtmsg *msg, int bytes, int *index, struct in_addr *dst, struct in_addr *gateway) { @@ -658,30 +658,79 @@ static void extract_route(struct rtmsg *msg, int bytes, int *index, } } +static void extract_ipv6_route(struct rtmsg *msg, int bytes, int *index, + struct in6_addr *dst, + struct in6_addr *gateway) +{ + struct rtattr *attr; + + for (attr = RTM_RTA(msg); RTA_OK(attr, bytes); + attr = RTA_NEXT(attr, bytes)) { + switch (attr-rta_type) { + case RTA_DST: + if (dst != NULL) + *dst = *((struct in6_addr *) RTA_DATA(attr)); + break; + case RTA_GATEWAY: + if (gateway != NULL) + *gateway = + *((struct in6_addr *) RTA_DATA(attr)); + break; + case RTA_OIF: + if (index != NULL) + *index = *((int *) RTA_DATA(attr)); + break; + } + } +} + static void process_newroute(unsigned char family, unsigned char scope, struct rtmsg *msg, int bytes) { GSList *list; - struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - char dststr[16], gatewaystr[16]; + char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN]; int index = -1; - if (family != AF_INET) - return; + if (family == AF_INET) { + struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - extract_route(msg, bytes, index, dst, gateway); + extract_ipv4_route(msg, bytes, index, dst, gateway); - inet_ntop(family, dst, dststr, sizeof(dststr)); - inet_ntop(family, gateway, gatewaystr, sizeof(gatewaystr)); + inet_ntop(family, dst, dststr, sizeof(dststr)); + inet_ntop(family, gateway, gatewaystr, sizeof(gatewaystr)); - __connman_ipconfig_newroute(index, family, scope, dststr, gatewaystr); + __connman_ipconfig_newroute(index, family, scope, dststr, + gatewaystr); - /* skip host specific routes */ - if (scope != RT_SCOPE_UNIVERSE + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE !(scope == RT_SCOPE_LINK dst.s_addr == INADDR_ANY)) - return; + return; - if (dst.s_addr != INADDR_ANY) + if (dst.s_addr != INADDR_ANY) + return; + + } else if (family == AF_INET6) { + struct in6_addr dst = IN6ADDR_ANY_INIT, + gateway = IN6ADDR_ANY_INIT; + + extract_ipv6_route(msg, bytes, index, dst, gateway); + + inet_ntop(family, dst, dststr, sizeof(dststr)); + inet_ntop(family, gateway, gatewaystr, sizeof(gatewaystr)); + + __connman_ipconfig_newroute(index, family, scope, dststr, + gatewaystr); + + /* skip host specific routes */ + if (scope != RT_SCOPE_UNIVERSE + !(scope == RT_SCOPE_LINK + IN6_IS_ADDR_UNSPECIFIED(dst))) + return; + + if (!IN6_IS_ADDR_UNSPECIFIED(dst)) + return; + } else return; for (list = rtnl_list; list; list = list-next) { @@ -696,26 +745,49 @@ static void process_delroute(unsigned char family, unsigned char scope, struct rtmsg *msg, int bytes) { GSList *list; - struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - char dststr[16], gatewaystr[16]; + char dststr[INET6_ADDRSTRLEN], gatewaystr[INET6_ADDRSTRLEN]; int index = -1; - if (family != AF_INET) - return; + if (family == AF_INET) { + struct in_addr dst = { INADDR_ANY }, gateway = { INADDR_ANY }; - extract_route(msg, bytes,
[PATCH ipv6routes v1 0/2] Catch IPv6 default gw messages
Hi, here is some preliminary work for IPv6 route handling. The patch catches IPv6 route additions and deletions and updates ipconfig accordingly. Regards, Jukka Jukka Rissanen (2): rtnl: Catch IPv6 route netlink messages. ipconfig: Catch IPv6 default route creation and deletion. src/ipconfig.c | 16 +--- src/rtnl.c | 122 --- 2 files changed, 107 insertions(+), 31 deletions(-) ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6routes v1 2/2] ipconfig: Catch IPv6 default route creation and deletion.
--- src/ipconfig.c | 16 ++-- 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 62d3766..59dd987 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -720,7 +720,8 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, if (ipdevice == NULL) return; - if (scope == 0 g_strcmp0(dst, 0.0.0.0) == 0) { + if (scope == 0 (g_strcmp0(dst, 0.0.0.0) == 0 || + g_strcmp0(dst, ::) == 0)) { GSList *list; GList *config_list; @@ -734,7 +735,7 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, ipdevice-config_ipv6-system-gateway = g_strdup(gateway); } - } else { + } else if (family == AF_INET) { g_free(ipdevice-ipv4_gateway); ipdevice-ipv4_gateway = g_strdup(gateway); @@ -744,7 +745,8 @@ void __connman_ipconfig_newroute(int index, int family, unsigned char scope, ipdevice-config_ipv4-system-gateway = g_strdup(gateway); } - } + } else + return; for (list = ipdevice-address_list; list; list = list-next) { struct connman_ipaddress *ipaddress = list-data; @@ -784,7 +786,8 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, if (ipdevice == NULL) return; - if (scope == 0 g_strcmp0(dst, 0.0.0.0) == 0) { + if (scope == 0 (g_strcmp0(dst, 0.0.0.0) == 0 || + g_strcmp0(dst, ::) == 0)) { GSList *list; GList *config_list; @@ -797,7 +800,7 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, g_free(ipdevice-config_ipv6-system-gateway); ipdevice-config_ipv6-system-gateway = NULL; } - } else { + } else if (family == AF_INET) { g_free(ipdevice-ipv4_gateway); ipdevice-ipv4_gateway = NULL; @@ -806,7 +809,8 @@ void __connman_ipconfig_delroute(int index, int family, unsigned char scope, g_free(ipdevice-config_ipv4-system-gateway); ipdevice-config_ipv4-system-gateway = NULL; } - } + } else + return; for (list = ipdevice-address_list; list; list = list-next) { struct connman_ipaddress *ipaddress = list-data; -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v3 0/7] Create 6to4 tunnel automatically if enabled
Hi, The v3 patch moves 6to4 property to IPv4 dict. The v2 patch checks if the tunnel has internet connectivity. The check is done by trying to connect to ipv6.google.com:80 via the tunnel. The google host was choosen as it only provides connectivity via IPv6. This could be changed to connman.net when it provides the same kind of service. The IPv6 address of the host is resolved by async DNS so that mainloop is not blocked. The timeouts I used were 10 sec for DNS query and 2 sec for connection test but these can be tweaked of course. Regards, Jukka Jukka Rissanen (7): doc: Add description about 6to4 tunnelling. ipconfig: Add function to return the system address pointer. 6to4: Add 6to4 tunnel support. service: Create 6to4 tunnel if enabled. test: Add support for 6to4 tunnel status printing. test: Add support for enabling/disabling 6to4 tunnel. 6to4: Check the connectivity via tunnel after creating it. Makefile.am | 10 +- configure.ac|4 + doc/service-api.txt | 11 + src/6to4.c | 789 +++ src/connman.h |9 +- src/ipconfig.c | 25 ++- src/ipv4.c |5 + src/service.c | 61 - test/list-services |8 +- test/test-connman | 37 +++ 10 files changed, 947 insertions(+), 12 deletions(-) create mode 100644 src/6to4.c ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v3 3/7] 6to4: Add 6to4 tunnel support.
--- Makefile.am |2 +- src/6to4.c| 569 + src/connman.h |3 + 3 files changed, 573 insertions(+), 1 deletions(-) create mode 100644 src/6to4.c diff --git a/Makefile.am b/Makefile.am index 144fcc5..8f13f56 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,7 +77,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \ src/wifi.c src/storage.c src/dbus.c src/config.c \ src/technology.c src/counter.c src/location.c \ src/session.c src/tethering.c src/wpad.c src/wispr.c \ - src/stats.c src/iptables.c src/dnsproxy.c + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @CAPNG_LIBS@ @XTABLES_LIBS@ -lresolv -ldl diff --git a/src/6to4.c b/src/6to4.c new file mode 100644 index 000..b07eeed --- /dev/null +++ b/src/6to4.c @@ -0,0 +1,569 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include stdio.h +#include string.h +#include sys/socket.h +#include netinet/in.h +#include arpa/inet.h +#include net/if.h +#include linux/ip.h +#include linux/if_tunnel.h +#include linux/netlink.h +#include linux/rtnetlink.h +#include sys/ioctl.h +#include unistd.h + +#include connman.h +#include connman/log.h + +static int tunnel_created; + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) + +#ifndef IP_DF +#define IP_DF 0x4000 /* Flag: Don't Fragment */ +#endif + +struct rtnl_handle { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +/* Note that addattr32(), addattr_l(), rtnl_close(), rtnl_open() and + * rtnl_talk() are from libnetlink.c that is found in iproute2 package + * and copyright by Alexey Kuznetsov et al. + */ +static int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *rta; + if (NLMSG_ALIGN(n-nlmsg_len) + len (unsigned int)maxlen) { + DBG(Error! max allowed bound %d exceeded, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, 4); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + len; + + return 0; +} + +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, + const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len) + (unsigned int)maxlen) { + DBG(addattr_l message exceeded bound of %d, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static void rtnl_close(struct rtnl_handle *rth) +{ + if (rth-fd = 0) { + close(rth-fd); + rth-fd = -1; + } +} + +static int rtnl_open(struct rtnl_handle *rth) +{ + socklen_t addr_len; + int sndbuf = 32768; + int rcvbuf = 32768; + + memset(rth, 0, sizeof(*rth)); + + rth-fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (rth-fd 0) { + DBG(Cannot open netlink socket: %s, strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_SNDBUF, sndbuf, + sizeof(sndbuf)) 0) { + DBG(SO_SNDBUF: %s, strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_RCVBUF, rcvbuf, + sizeof(rcvbuf)) 0) { + DBG(SO_RCVBUF: %s, strerror(errno)); + return -1; + } + + memset(rth-local, 0, sizeof(rth-local)); + rth-local.nl_family = AF_NETLINK;
[PATCH 6to4 v3 5/7] test: Add support for 6to4 tunnel status printing.
--- test/list-services |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/test/list-services b/test/list-services index 3ae6a4d..bfb0f73 100755 --- a/test/list-services +++ b/test/list-services @@ -12,7 +12,13 @@ def extract_values(values): if key in [Servers, Excludes]: val += extract_list(values[key]) else: - val += str(values[key]) + if key in [6to4]: + if values[key] == dbus.Boolean(1): + val += true + else: + val += false + else: + val += str(values[key]) val += } return val -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v3 6/7] test: Add support for enabling/disabling 6to4 tunnel.
--- test/test-connman | 37 + 1 files changed, 37 insertions(+), 0 deletions(-) diff --git a/test/test-connman b/test/test-connman index 9a855fb..c297cf7 100755 --- a/test/test-connman +++ b/test/test-connman @@ -18,6 +18,7 @@ if len(sys.argv) 2: print connect service print disconnect service print remove service + print 6to4 service [on|off] print print scan [type] print enable type @@ -170,6 +171,42 @@ elif sys.argv[1] in [remove]: except dbus.DBusException, error: print %s: %s % (error._dbus_error_name, error.message) +elif sys.argv[1] == 6to4: + if (len(sys.argv) 3): + print Need at least service parameter + sys.exit(1) + + path = /profile/default/ + sys.argv[2] + + service = dbus.Interface(bus.get_object(net.connman, path), + net.connman.Service) + properties = service.GetProperties() + + if (len(sys.argv) 3): + flag = sys.argv[3].strip().lower() + six2four = dbus.Boolean(flag not in ['false', 'off', 'f', 'n', '0']) + + ipv4_config = properties[IPv4.Configuration] + ipv4_configuration = { Method : str(ipv4_config[Method]) } + ipv4_configuration[6to4] = str(six2four) + if Address in ipv4_config.keys(): + ipv4_configuration[Address] = str(ipv4_config[Address]) + if Netmask in ipv4_config.keys(): + ipv4_configuration[Netmask] = str(ipv4_config[Netmask]) + if Gateway in ipv4_config.keys(): + ipv4_configuration[Gateway] = str(ipv4_config[Gateway]) + service.SetProperty(IPv4.Configuration, ipv4_configuration) + + print 6to4 tunnelling set to %s for %s % (six2four, sys.argv[2]) + else: + ipv4_configuration = properties[IPv4.Configuration] + if 6to4 in ipv4_configuration.keys(): + six2four = ipv4_configuration[6to4] + else: + six2four = dbus.Boolean(0) + + print 6to4 tunnelling set to %s for %s % (six2four, sys.argv[2]) + elif sys.argv[1] == scan: if len(sys.argv) 2: manager.RequestScan(sys.argv[2]) -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH privacy v3 2/3] ipconfig: Support IPv6 privacy extension for autoconf addresses.
--- src/ipconfig.c | 141 +-- 1 files changed, 135 insertions(+), 6 deletions(-) diff --git a/src/ipconfig.c b/src/ipconfig.c index 6511370..5d4e755 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -51,6 +51,8 @@ struct connman_ipconfig { enum connman_ipconfig_method method; struct connman_ipaddress *address; struct connman_ipaddress *system; + + int ipv6_privacy_config; }; struct connman_ipdevice { @@ -79,6 +81,7 @@ struct connman_ipdevice { struct connman_ipconfig *config_ipv6; gboolean ipv6_enabled; + int ipv6_privacy; }; static GHashTable *ipdevice_hash = NULL; @@ -352,6 +355,67 @@ static void set_ipv6_state(gchar *ifname, gboolean enable) fclose(f); } +static int get_ipv6_privacy(gchar *ifname) +{ + gchar *path; + FILE *f; + int value; + + if (ifname == NULL) + return 0; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return 0; + + f = fopen(path, r); + + g_free(path); + + if (f == NULL) + return 0; + + if (fscanf(f, %d, value) = 0) + value = 0; + + fclose(f); + + return value; +} + +/* Enable the IPv6 privacy extension for stateless address autoconfiguration. + * The privacy extension is described in RFC 3041 and RFC 4941 + */ +static void set_ipv6_privacy(gchar *ifname, int value) +{ + gchar *path; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf(/proc/sys/net/ipv6/conf/%s/use_tempaddr, + ifname); + + if (path == NULL) + return; + + if (value 0) + value = 0; + + f = fopen(path, r+); + + g_free(path); + + if (f == NULL) + return; + + fprintf(f, %d, value); + fclose(f); +} + static void free_ipdevice(gpointer data) { struct connman_ipdevice *ipdevice = data; @@ -377,6 +441,7 @@ static void free_ipdevice(gpointer data) g_free(ipdevice-address); set_ipv6_state(ipdevice-ifname, ipdevice-ipv6_enabled); + set_ipv6_privacy(ipdevice-ifname, ipdevice-ipv6_privacy); g_free(ipdevice-ifname); g_free(ipdevice); @@ -474,6 +539,7 @@ void __connman_ipconfig_newlink(int index, unsigned short type, ipdevice-type = type; ipdevice-ipv6_enabled = get_ipv6_state(ipdevice-ifname); + ipdevice-ipv6_privacy = get_ipv6_privacy(ipdevice-ifname); ipdevice-address = g_strdup(address); @@ -1030,6 +1096,7 @@ static struct connman_ipconfig *create_ipv6config(int index) ipv6config-index = index; ipv6config-type = CONNMAN_IPCONFIG_TYPE_IPV6; ipv6config-method = CONNMAN_IPCONFIG_METHOD_AUTO; + ipv6config-ipv6_privacy_config = 0; ipv6config-address = connman_ipaddress_alloc(AF_INET6); if (ipv6config-address == NULL) { @@ -1376,6 +1443,10 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) if (ipdevice == NULL) return; + if (ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO) + set_ipv6_privacy(ipdevice-ifname, + ipconfig-ipv6_privacy_config); + set_ipv6_state(ipdevice-ifname, TRUE); } @@ -1545,6 +1616,30 @@ enum connman_ipconfig_method __connman_ipconfig_string2method(const char *method return CONNMAN_IPCONFIG_METHOD_UNKNOWN; } +static const char *privacy2string(int privacy) +{ + if (privacy = 0) + return disabled; + else if (privacy == 1) + return enabled; + else if (privacy 1) + return prefered; + + return disabled; +} + +static int string2privacy(const char *privacy) +{ + if (g_strcmp0(privacy, disabled) == 0) + return 0; + else if (g_strcmp0(privacy, enabled) == 0) + return 1; + else if (g_strcmp0(privacy, prefered) == 0) + return 2; + else + return 0; +} + void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, DBusMessageIter *iter) { @@ -1587,7 +1682,7 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, DBusMessageIter *iter) { - const char *str; + const char *str, *privacy; DBG(); @@ -1614,12 +1709,16 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, if (ipconfig-system-gateway != NULL) connman_dbus_dict_append_basic(iter, Gateway,
[PATCH privacy v3 3/3] test: Enable or disable IPv6 privacy extension.
--- test/set-ipv6-method | 18 +++--- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/test/set-ipv6-method b/test/set-ipv6-method index 274e89b..c0b251e 100755 --- a/test/set-ipv6-method +++ b/test/set-ipv6-method @@ -4,7 +4,7 @@ import sys import dbus def print_usage(): - print Usage: %s service off|manual|auto [address [prefixlen] [gateway]] % (sys.argv[0]) + print Usage: %s service off|manual|auto [address [prefixlen] [gateway]] [privacy] % (sys.argv[0]) if (len(sys.argv) 3): print_usage() @@ -20,12 +20,16 @@ properties = service.GetProperties() print Setting method %s for %s % (sys.argv[2], sys.argv[1]) ipv6_configuration = { Method: sys.argv[2] } -if (len(sys.argv) 3): - ipv6_configuration[Address] = sys.argv[3] -if (len(sys.argv) 4): - ipv6_configuration[PrefixLength] = sys.argv[4] -if (len(sys.argv) 5): - ipv6_configuration[Gateway] = sys.argv[5] +if sys.argv[2] == auto: + if (len(sys.argv) 3): + ipv6_configuration[Privacy] = sys.argv[3] +else: + if (len(sys.argv) 3): + ipv6_configuration[Address] = sys.argv[3] + if (len(sys.argv) 4): + ipv6_configuration[PrefixLength] = sys.argv[4] + if (len(sys.argv) 5): + ipv6_configuration[Gateway] = sys.argv[5] service.SetProperty(IPv6.Configuration, ipv6_configuration) print New IPv6.Configuration: , ipv6_configuration -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 01/10] doc: Add description about 6to4 tunnelling.
--- doc/service-api.txt | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/doc/service-api.txt b/doc/service-api.txt index 65554a2..e13808e 100644 --- a/doc/service-api.txt +++ b/doc/service-api.txt @@ -332,6 +332,16 @@ Properties string State [readonly] The current configured IPv4 gateway. + boolean 6to4 [readonly] + + If true, the service created 6to4 + tunnel if the service IPv4 address is not + private and autoconfiguration does not work. + Only one tunnel is created even if there are + more than one active service that have public + IPv4 address. Tunnel is only created if it + provides internet connectivity. + dict IPv4.Configuration [readwrite] Same values as IPv4 property. The IPv4 represents -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 00/10] 6to4 tunneling support
Hi, this is v4 of the 6to4 tunneling support and many things have been changed in this version like: - 6to4 tunnel setting in service is read only i.e., it cannot be manipulated via dbus any longer - generic tunnel creation added to inet.c - IPv6 router solicitation / advertisement handling in inet.c - IPv6 support is added to gweb - gweb is used when checking connectivity through tunnel - tunnel is only created if we have a public IP address, the IPv6 is enabled and method is auto, we have not received autoconfigured ip address and internet connectivity via tunnel works ok The patch set is only tested via simulation (by commenting out various checks in the code) as I could not find such a crappy network anywhere, so there might be some problems left in the code. There is one issue when using gweb to check the connectivity via tunnel. As the network interface to be used is not set in gweb, we are just hoping that the routing in the device forces the check go through tunnel. Regards, Jukka Jukka Rissanen (10): doc: Add description about 6to4 tunnelling. inet: MTU and tunnel setup functions added. inet: Add routines to send IPv6 router solicitation message. gweb: Add support for connecting to IPv6 host. 6to4: Add 6to4 tunnel support. 6to4: Check the connectivity via tunnel after creating it. service: Create/remove 6to4 tunnel. 6to4: Check if the 6to4 tunnel is active or not. service: Return 6to4 tunnel status to dbus caller. test: Add support for 6to4 tunnel status printing. Makefile.am |2 +- doc/service-api.txt | 10 + gweb/gweb.c | 29 ++- include/inet.h | 11 + src/6to4.c | 563 +++ src/connman.h |4 + src/dhcp.c |4 + src/inet.c | 386 +++- src/service.c | 12 +- test/list-services |8 +- 10 files changed, 1015 insertions(+), 14 deletions(-) create mode 100644 src/6to4.c ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 03/10] inet: Add routines to send IPv6 router solicitation message.
--- include/inet.h |8 ++ src/inet.c | 315 2 files changed, 323 insertions(+), 0 deletions(-) diff --git a/include/inet.h b/include/inet.h index 9a9411d..3ed19c4 100644 --- a/include/inet.h +++ b/include/inet.h @@ -25,6 +25,8 @@ #include arpa/inet.h #include linux/netlink.h #include linux/rtnetlink.h +#include netinet/ip6.h +#include netinet/icmp6.h #include connman/device.h #include connman/ipconfig.h @@ -76,6 +78,12 @@ int connman_inet_remove_from_bridge(int index, const char *bridge); int connman_inet_set_mtu(int index, int mtu); int connman_inet_setup_tunnel(char *tunnel, int mtu); +typedef void (*connman_inet_rs_cb_t) (struct nd_router_advert *reply, + void *user_data); + +int connman_inet_ipv6_send_rs(int index, int timeout, + connman_inet_rs_cb_t callback, void *user_data); + #ifdef __cplusplus } #endif diff --git a/src/inet.c b/src/inet.c index 858d34c..40d8a8d 100644 --- a/src/inet.c +++ b/src/inet.c @@ -4,6 +4,10 @@ * * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. * + * Portions (IPv6 router solicitation handling from MIPL project) are + * Copyright 2003-2005 Go-Core Project and 2003-2006 Helsinki University of + * Technology + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -37,6 +41,7 @@ #include net/ethernet.h #include net/if.h #include net/if_arp.h +#include netinet/icmp6.h #include connman.h @@ -1261,3 +1266,313 @@ done: close(sk); return err; } + +struct rs_cb_data { + GIOChannel *channel; + connman_inet_rs_cb_t callback; + struct sockaddr_in6 addr; + guint rs_timeout; + void *user_data; +}; + +#define CMSG_BUF_LEN 512 +#define IN6ADDR_ALL_NODES_MC_INIT \ + { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */ +#define IN6ADDR_ALL_ROUTERS_MC_INIT \ + { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */ + +static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT; +static const struct in6_addr in6addr_all_routers_mc = + IN6ADDR_ALL_ROUTERS_MC_INIT; + +/* from netinet/in.h */ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +static void rs_cleanup(struct rs_cb_data *data) +{ + g_io_channel_shutdown(data-channel, TRUE, NULL); + g_io_channel_unref(data-channel); + data-channel = 0; + + if (data-rs_timeout 0) + g_source_remove(data-rs_timeout); + + g_free(data); +} + +static gboolean rs_timeout_cb(gpointer user_data) +{ + struct rs_cb_data *data = user_data; + + DBG(user data %p, user_data); + + if (data == NULL) + return FALSE; + + if (data-callback != NULL) + data-callback(NULL, data-user_data); + + data-rs_timeout = 0; + rs_cleanup(data); + return FALSE; +} + +static int icmpv6_recv(int fd, gpointer user_data) +{ + struct msghdr mhdr; + struct iovec iov; + unsigned char chdr[CMSG_BUF_LEN]; + unsigned char buf[1540]; + struct rs_cb_data *data = user_data; + struct nd_router_advert *hdr; + struct sockaddr_in6 saddr; + ssize_t len; + + DBG(); + + iov.iov_len = sizeof(buf); + iov.iov_base = buf; + + mhdr.msg_name = (void *)saddr; + mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = CMSG_BUF_LEN; + + len = recvmsg(fd, mhdr, 0); + if (len 0) { + data-callback(NULL, data-user_data); + return -errno; + } + + hdr = (struct nd_router_advert *)buf; + if (hdr-nd_ra_code != 0) + return 0; + + data-callback(hdr, data-user_data); + rs_cleanup(data); + + return len; +} + +static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + int fd, ret; + + DBG(); + + if (cond (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + fd = g_io_channel_unix_get_fd(chan); + ret = icmpv6_recv(fd, data); + if (ret == 0) + return TRUE; + + return FALSE; +} + +/* Adapted from RFC 1071 C Implementation Example */ +static uint16_t csum(const void *phdr, const void *data, socklen_t datalen) +{ + register unsigned long sum = 0; + socklen_t count; + uint16_t *addr; + int i; + + /* caller must make sure datalen is even */ + + addr = (uint16_t *)phdr; +
[PATCH 6to4 v4 02/10] inet: MTU and tunnel setup functions added.
--- include/inet.h |3 ++ src/inet.c | 71 ++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/include/inet.h b/include/inet.h index 9ba7781..9a9411d 100644 --- a/include/inet.h +++ b/include/inet.h @@ -73,6 +73,9 @@ int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway); int connman_inet_add_to_bridge(int index, const char *bridge); int connman_inet_remove_from_bridge(int index, const char *bridge); +int connman_inet_set_mtu(int index, int mtu); +int connman_inet_setup_tunnel(char *tunnel, int mtu); + #ifdef __cplusplus } #endif diff --git a/src/inet.c b/src/inet.c index 2f287f6..858d34c 100644 --- a/src/inet.c +++ b/src/inet.c @@ -35,8 +35,8 @@ #include arpa/inet.h #include net/route.h #include net/ethernet.h -#include linux/if_arp.h -#include linux/wireless.h +#include net/if.h +#include net/if_arp.h #include connman.h @@ -1194,3 +1194,70 @@ int connman_inet_add_to_bridge(int index, const char *bridge) return 0; } + +int connman_inet_set_mtu(int index, int mtu) +{ + struct ifreq ifr; + int sk, err; + + sk = socket(AF_INET, SOCK_DGRAM, 0); + if (sk 0) + return sk; + + memset(ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = index; + + err = ioctl(sk, SIOCGIFNAME, ifr); + if (err == 0) { + ifr.ifr_mtu = mtu; + err = ioctl(sk, SIOCSIFMTU, ifr); + } + + close(sk); + return err; +} + +int connman_inet_setup_tunnel(char *tunnel, int mtu) +{ + struct ifreq ifr; + int sk, err, index; + __u32 mask; + __u32 flags; + + if (tunnel == NULL) + return -EINVAL; + + sk = socket(AF_INET, SOCK_DGRAM, 0); + if (sk 0) + return sk; + + index = if_nametoindex(tunnel); + + err = connman_inet_set_mtu(index, mtu); + if (err 0) + return err; + else if (err) + goto done; + + memset(ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, tunnel, IFNAMSIZ); + err = ioctl(sk, SIOCGIFFLAGS, ifr); + if (err) + goto done; + + mask = IFF_UP; + flags = IFF_UP; + + if ((ifr.ifr_flags ^ flags) mask) { + ifr.ifr_flags = ~mask; + ifr.ifr_flags |= mask flags; + err = ioctl(sk, SIOCSIFFLAGS, ifr); + if (err) + connman_error(SIOCSIFFLAGS failed: %s, + strerror(errno)); + } + +done: + close(sk); + return err; +} -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 05/10] 6to4: Add 6to4 tunnel support.
--- Makefile.am |2 +- src/6to4.c| 498 + src/connman.h |3 + 3 files changed, 502 insertions(+), 1 deletions(-) create mode 100644 src/6to4.c diff --git a/Makefile.am b/Makefile.am index 3ad1ee9..95aefc7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,7 +77,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \ src/wifi.c src/storage.c src/dbus.c src/config.c \ src/technology.c src/counter.c src/location.c \ src/session.c src/tethering.c src/wpad.c src/wispr.c \ - src/stats.c src/iptables.c src/dnsproxy.c + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @CAPNG_LIBS@ @XTABLES_LIBS@ -lresolv -ldl diff --git a/src/6to4.c b/src/6to4.c new file mode 100644 index 000..68472e6 --- /dev/null +++ b/src/6to4.c @@ -0,0 +1,498 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * + * Portions copyright by Alexey Kuznetsov et al. from iproute2 package. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include stdio.h +#include string.h +#include sys/socket.h +#include netinet/in.h +#include arpa/inet.h +#include net/if.h +#include linux/ip.h +#include linux/if_tunnel.h +#include linux/netlink.h +#include linux/rtnetlink.h +#include sys/ioctl.h +#include unistd.h + +#include connman.h +#include connman/log.h +#include connman/ipconfig.h + +static int tunnel_created; +static int tunnel_pending; +static char *tunnel_ip_address; + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) + +#ifndef IP_DF +#define IP_DF 0x4000 /* Flag: Don't Fragment */ +#endif + +struct rtnl_handle { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +static int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *rta; + if (NLMSG_ALIGN(n-nlmsg_len) + len (unsigned int)maxlen) { + DBG(Error! max allowed bound %d exceeded, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, 4); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + len; + + return 0; +} + +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, + const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len) + (unsigned int)maxlen) { + DBG(addattr_l message exceeded bound of %d, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static void rtnl_close(struct rtnl_handle *rth) +{ + if (rth-fd = 0) { + close(rth-fd); + rth-fd = -1; + } +} + +static int rtnl_open(struct rtnl_handle *rth) +{ + socklen_t addr_len; + int sndbuf = 1024; + + memset(rth, 0, sizeof(*rth)); + + rth-fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (rth-fd 0) { + connman_error(Can not open netlink socket: %s, + strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_SNDBUF, sndbuf, + sizeof(sndbuf)) 0) { + connman_error(SO_SNDBUF: %s, strerror(errno)); + return -1; + } + + memset(rth-local, 0, sizeof(rth-local)); + rth-local.nl_family = AF_NETLINK; + rth-local.nl_groups = 0; + + if (bind(rth-fd, (struct sockaddr *)rth-local, + sizeof(rth-local)) 0) { + connman_error(Can not bind
[PATCH 6to4 v4 06/10] 6to4: Check the connectivity via tunnel after creating it.
--- src/6to4.c | 47 ++- 1 files changed, 46 insertions(+), 1 deletions(-) diff --git a/src/6to4.c b/src/6to4.c index 68472e6..52a0c53 100644 --- a/src/6to4.c +++ b/src/6to4.c @@ -41,10 +41,15 @@ #include connman.h #include connman/log.h #include connman/ipconfig.h +#include gweb/gweb.h static int tunnel_created; static int tunnel_pending; static char *tunnel_ip_address; +static GWeb *web; +static guint web_request_id; + +#define STATUS_URL http://ipv6.google.com/; #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) @@ -359,6 +364,35 @@ done: return ret; } +static gboolean unref_web(gpointer user_data) +{ + g_web_unref(web); + return FALSE; +} + +static gboolean web_result(GWebResult *result, gpointer user_data) +{ + guint16 status; + + if (web_request_id == 0) + return FALSE; + + status = g_web_result_get_status(result); + + DBG(status %u, status); + + if (status = 400 status 500) + tunnel_destroy(); + else + tunnel_pending = 0; + + web_request_id = 0; + + g_timeout_add_seconds(1, unref_web, NULL); + + return FALSE; +} + static int init_6to4(struct in_addr *ip4addr) { unsigned int a, b, c, d; @@ -392,7 +426,18 @@ static int init_6to4(struct in_addr *ip4addr) if (ret) goto error; - tunnel_pending = 0; + /* We try to verify that connectivity through tunnel works ok. +*/ + web = g_web_new(0); + if (web == NULL) + goto error; + + g_web_set_accept(web, NULL); + g_web_set_user_agent(web, ConnMan/%s, VERSION); + g_web_set_close_connection(web, TRUE); + + web_request_id = g_web_request_get(web, STATUS_URL, web_result, NULL); + return 0; error: -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 09/10] service: Return 6to4 tunnel status to dbus caller.
--- src/service.c | 10 +- 1 files changed, 9 insertions(+), 1 deletions(-) diff --git a/src/service.c b/src/service.c index 29d6af5..77e16a5 100644 --- a/src/service.c +++ b/src/service.c @@ -987,8 +987,16 @@ static void append_ipv4(DBusMessageIter *iter, void *user_data) if (is_connected_state(service, service-state_ipv4) == FALSE) return; - if (service-ipconfig_ipv4 != NULL) + if (service-ipconfig_ipv4 != NULL) { + int status; + __connman_ipconfig_append_ipv4(service-ipconfig_ipv4, iter); + + status = __connman_6to4_check(service-ipconfig_ipv4); + if (status = 0) + connman_dbus_dict_append_basic(iter, 6to4, + DBUS_TYPE_BOOLEAN, status); + } } static void append_ipv6(DBusMessageIter *iter, void *user_data) -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 08/10] 6to4: Check if the 6to4 tunnel is active or not.
--- src/6to4.c| 20 src/connman.h |1 + 2 files changed, 21 insertions(+), 0 deletions(-) diff --git a/src/6to4.c b/src/6to4.c index 52a0c53..8593e71 100644 --- a/src/6to4.c +++ b/src/6to4.c @@ -541,3 +541,23 @@ void __connman_6to4_remove(struct connman_ipconfig *ip4config) if (tunnel_created) tunnel_destroy(); } + +int __connman_6to4_check(struct connman_ipconfig *ip4config) +{ + const char *address; + + if (ip4config == NULL || tunnel_created == 0 || + tunnel_pending == 1) + return -1; + + DBG(tunnel ip address %s, tunnel_ip_address); + + address = __connman_ipconfig_get_local(ip4config); + if (address == NULL) + return -1; + + if (g_strcmp0(address, tunnel_ip_address) == 0) + return 1; + + return 0; +} diff --git a/src/connman.h b/src/connman.h index b3a45f0..a4ebbbe 100644 --- a/src/connman.h +++ b/src/connman.h @@ -639,3 +639,4 @@ void __connman_dnsproxy_flush(void); int __connman_6to4_probe(struct connman_service *service); void __connman_6to4_remove(struct connman_ipconfig *ipconfig); +int __connman_6to4_check(struct connman_ipconfig *ipconfig); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 07/10] service: Create/remove 6to4 tunnel.
--- src/dhcp.c|4 src/service.c |2 ++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/dhcp.c b/src/dhcp.c index 6fda67d..dd7c498 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -73,6 +73,8 @@ static void dhcp_invalid(struct connman_dhcp *dhcp) if (ipconfig == NULL) return; + __connman_6to4_remove(ipconfig); + __connman_service_set_domainname(service, NULL); __connman_service_set_pac(service, NULL); __connman_service_timeserver_remove(service, dhcp-timeserver); @@ -211,6 +213,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) dhcp_valid(dhcp); + __connman_6to4_probe(service); + g_free(address); g_free(netmask); g_free(gateway); diff --git a/src/service.c b/src/service.c index ece29fd..29d6af5 100644 --- a/src/service.c +++ b/src/service.c @@ -3875,6 +3875,8 @@ int __connman_service_disconnect(struct connman_service *service) if (err 0 err != -EINPROGRESS) return err; + __connman_6to4_remove(service-ipconfig_ipv4); + if (service-ipconfig_ipv4) __connman_ipconfig_set_proxy_autoconfig(service-ipconfig_ipv4, NULL); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v4 10/10] test: Add support for 6to4 tunnel status printing.
--- test/list-services |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/test/list-services b/test/list-services index 3ae6a4d..bfb0f73 100755 --- a/test/list-services +++ b/test/list-services @@ -12,7 +12,13 @@ def extract_values(values): if key in [Servers, Excludes]: val += extract_list(values[key]) else: - val += str(values[key]) + if key in [6to4]: + if values[key] == dbus.Boolean(1): + val += true + else: + val += false + else: + val += str(values[key]) val += } return val -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 2/9] inet: MTU and tunnel setup functions added.
--- include/inet.h |3 ++ src/inet.c | 71 ++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/include/inet.h b/include/inet.h index 9ba7781..9a9411d 100644 --- a/include/inet.h +++ b/include/inet.h @@ -73,6 +73,9 @@ int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway); int connman_inet_add_to_bridge(int index, const char *bridge); int connman_inet_remove_from_bridge(int index, const char *bridge); +int connman_inet_set_mtu(int index, int mtu); +int connman_inet_setup_tunnel(char *tunnel, int mtu); + #ifdef __cplusplus } #endif diff --git a/src/inet.c b/src/inet.c index 2f287f6..858d34c 100644 --- a/src/inet.c +++ b/src/inet.c @@ -35,8 +35,8 @@ #include arpa/inet.h #include net/route.h #include net/ethernet.h -#include linux/if_arp.h -#include linux/wireless.h +#include net/if.h +#include net/if_arp.h #include connman.h @@ -1194,3 +1194,70 @@ int connman_inet_add_to_bridge(int index, const char *bridge) return 0; } + +int connman_inet_set_mtu(int index, int mtu) +{ + struct ifreq ifr; + int sk, err; + + sk = socket(AF_INET, SOCK_DGRAM, 0); + if (sk 0) + return sk; + + memset(ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = index; + + err = ioctl(sk, SIOCGIFNAME, ifr); + if (err == 0) { + ifr.ifr_mtu = mtu; + err = ioctl(sk, SIOCSIFMTU, ifr); + } + + close(sk); + return err; +} + +int connman_inet_setup_tunnel(char *tunnel, int mtu) +{ + struct ifreq ifr; + int sk, err, index; + __u32 mask; + __u32 flags; + + if (tunnel == NULL) + return -EINVAL; + + sk = socket(AF_INET, SOCK_DGRAM, 0); + if (sk 0) + return sk; + + index = if_nametoindex(tunnel); + + err = connman_inet_set_mtu(index, mtu); + if (err 0) + return err; + else if (err) + goto done; + + memset(ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, tunnel, IFNAMSIZ); + err = ioctl(sk, SIOCGIFFLAGS, ifr); + if (err) + goto done; + + mask = IFF_UP; + flags = IFF_UP; + + if ((ifr.ifr_flags ^ flags) mask) { + ifr.ifr_flags = ~mask; + ifr.ifr_flags |= mask flags; + err = ioctl(sk, SIOCSIFFLAGS, ifr); + if (err) + connman_error(SIOCSIFFLAGS failed: %s, + strerror(errno)); + } + +done: + close(sk); + return err; +} -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 3/9] inet: Add routines to send IPv6 router solicitation message.
--- include/inet.h |8 ++ src/inet.c | 315 2 files changed, 323 insertions(+), 0 deletions(-) diff --git a/include/inet.h b/include/inet.h index 9a9411d..3ed19c4 100644 --- a/include/inet.h +++ b/include/inet.h @@ -25,6 +25,8 @@ #include arpa/inet.h #include linux/netlink.h #include linux/rtnetlink.h +#include netinet/ip6.h +#include netinet/icmp6.h #include connman/device.h #include connman/ipconfig.h @@ -76,6 +78,12 @@ int connman_inet_remove_from_bridge(int index, const char *bridge); int connman_inet_set_mtu(int index, int mtu); int connman_inet_setup_tunnel(char *tunnel, int mtu); +typedef void (*connman_inet_rs_cb_t) (struct nd_router_advert *reply, + void *user_data); + +int connman_inet_ipv6_send_rs(int index, int timeout, + connman_inet_rs_cb_t callback, void *user_data); + #ifdef __cplusplus } #endif diff --git a/src/inet.c b/src/inet.c index 858d34c..40d8a8d 100644 --- a/src/inet.c +++ b/src/inet.c @@ -4,6 +4,10 @@ * * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. * + * Portions (IPv6 router solicitation handling from MIPL project) are + * Copyright 2003-2005 Go-Core Project and 2003-2006 Helsinki University of + * Technology + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -37,6 +41,7 @@ #include net/ethernet.h #include net/if.h #include net/if_arp.h +#include netinet/icmp6.h #include connman.h @@ -1261,3 +1266,313 @@ done: close(sk); return err; } + +struct rs_cb_data { + GIOChannel *channel; + connman_inet_rs_cb_t callback; + struct sockaddr_in6 addr; + guint rs_timeout; + void *user_data; +}; + +#define CMSG_BUF_LEN 512 +#define IN6ADDR_ALL_NODES_MC_INIT \ + { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */ +#define IN6ADDR_ALL_ROUTERS_MC_INIT \ + { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */ + +static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT; +static const struct in6_addr in6addr_all_routers_mc = + IN6ADDR_ALL_ROUTERS_MC_INIT; + +/* from netinet/in.h */ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +static void rs_cleanup(struct rs_cb_data *data) +{ + g_io_channel_shutdown(data-channel, TRUE, NULL); + g_io_channel_unref(data-channel); + data-channel = 0; + + if (data-rs_timeout 0) + g_source_remove(data-rs_timeout); + + g_free(data); +} + +static gboolean rs_timeout_cb(gpointer user_data) +{ + struct rs_cb_data *data = user_data; + + DBG(user data %p, user_data); + + if (data == NULL) + return FALSE; + + if (data-callback != NULL) + data-callback(NULL, data-user_data); + + data-rs_timeout = 0; + rs_cleanup(data); + return FALSE; +} + +static int icmpv6_recv(int fd, gpointer user_data) +{ + struct msghdr mhdr; + struct iovec iov; + unsigned char chdr[CMSG_BUF_LEN]; + unsigned char buf[1540]; + struct rs_cb_data *data = user_data; + struct nd_router_advert *hdr; + struct sockaddr_in6 saddr; + ssize_t len; + + DBG(); + + iov.iov_len = sizeof(buf); + iov.iov_base = buf; + + mhdr.msg_name = (void *)saddr; + mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = CMSG_BUF_LEN; + + len = recvmsg(fd, mhdr, 0); + if (len 0) { + data-callback(NULL, data-user_data); + return -errno; + } + + hdr = (struct nd_router_advert *)buf; + if (hdr-nd_ra_code != 0) + return 0; + + data-callback(hdr, data-user_data); + rs_cleanup(data); + + return len; +} + +static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + int fd, ret; + + DBG(); + + if (cond (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + fd = g_io_channel_unix_get_fd(chan); + ret = icmpv6_recv(fd, data); + if (ret == 0) + return TRUE; + + return FALSE; +} + +/* Adapted from RFC 1071 C Implementation Example */ +static uint16_t csum(const void *phdr, const void *data, socklen_t datalen) +{ + register unsigned long sum = 0; + socklen_t count; + uint16_t *addr; + int i; + + /* caller must make sure datalen is even */ + + addr = (uint16_t *)phdr; +
[PATCH 6to4 v5 1/9] doc: Add description about 6to4 tunnelling.
--- doc/service-api.txt |6 +- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/doc/service-api.txt b/doc/service-api.txt index 65554a2..7e87e6e 100644 --- a/doc/service-api.txt +++ b/doc/service-api.txt @@ -347,12 +347,16 @@ Propertiesstring State [readonly] string Method [readonly] - Possible values are auto, manual + Possible values are auto, manual, 6to4 and off. The value fixed indicates an IP address that can not be modified. For example cellular networks return fixed information. + The value 6to4 is returned if 6to4 tunnel + is created by connman. The tunnel can only be + created if method was set to auto by the + user. User cannot set the method to 6to4. string Address [readonly] -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 5/9] 6to4: Add 6to4 tunnel support.
--- Makefile.am |2 +- src/6to4.c| 498 + src/connman.h |3 + 3 files changed, 502 insertions(+), 1 deletions(-) create mode 100644 src/6to4.c diff --git a/Makefile.am b/Makefile.am index 3ad1ee9..95aefc7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,7 +77,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \ src/wifi.c src/storage.c src/dbus.c src/config.c \ src/technology.c src/counter.c src/location.c \ src/session.c src/tethering.c src/wpad.c src/wispr.c \ - src/stats.c src/iptables.c src/dnsproxy.c + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @CAPNG_LIBS@ @XTABLES_LIBS@ -lresolv -ldl diff --git a/src/6to4.c b/src/6to4.c new file mode 100644 index 000..68472e6 --- /dev/null +++ b/src/6to4.c @@ -0,0 +1,498 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * + * Portions copyright by Alexey Kuznetsov et al. from iproute2 package. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include stdio.h +#include string.h +#include sys/socket.h +#include netinet/in.h +#include arpa/inet.h +#include net/if.h +#include linux/ip.h +#include linux/if_tunnel.h +#include linux/netlink.h +#include linux/rtnetlink.h +#include sys/ioctl.h +#include unistd.h + +#include connman.h +#include connman/log.h +#include connman/ipconfig.h + +static int tunnel_created; +static int tunnel_pending; +static char *tunnel_ip_address; + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) + +#ifndef IP_DF +#define IP_DF 0x4000 /* Flag: Don't Fragment */ +#endif + +struct rtnl_handle { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +static int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *rta; + if (NLMSG_ALIGN(n-nlmsg_len) + len (unsigned int)maxlen) { + DBG(Error! max allowed bound %d exceeded, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, 4); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + len; + + return 0; +} + +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, + const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len) + (unsigned int)maxlen) { + DBG(addattr_l message exceeded bound of %d, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static void rtnl_close(struct rtnl_handle *rth) +{ + if (rth-fd = 0) { + close(rth-fd); + rth-fd = -1; + } +} + +static int rtnl_open(struct rtnl_handle *rth) +{ + socklen_t addr_len; + int sndbuf = 1024; + + memset(rth, 0, sizeof(*rth)); + + rth-fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (rth-fd 0) { + connman_error(Can not open netlink socket: %s, + strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_SNDBUF, sndbuf, + sizeof(sndbuf)) 0) { + connman_error(SO_SNDBUF: %s, strerror(errno)); + return -1; + } + + memset(rth-local, 0, sizeof(rth-local)); + rth-local.nl_family = AF_NETLINK; + rth-local.nl_groups = 0; + + if (bind(rth-fd, (struct sockaddr *)rth-local, + sizeof(rth-local)) 0) { + connman_error(Can not bind
[PATCH 6to4 v5 6/9] 6to4: Check the connectivity via tunnel after creating it.
--- src/6to4.c | 47 ++- 1 files changed, 46 insertions(+), 1 deletions(-) diff --git a/src/6to4.c b/src/6to4.c index 68472e6..52a0c53 100644 --- a/src/6to4.c +++ b/src/6to4.c @@ -41,10 +41,15 @@ #include connman.h #include connman/log.h #include connman/ipconfig.h +#include gweb/gweb.h static int tunnel_created; static int tunnel_pending; static char *tunnel_ip_address; +static GWeb *web; +static guint web_request_id; + +#define STATUS_URL http://ipv6.google.com/; #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) @@ -359,6 +364,35 @@ done: return ret; } +static gboolean unref_web(gpointer user_data) +{ + g_web_unref(web); + return FALSE; +} + +static gboolean web_result(GWebResult *result, gpointer user_data) +{ + guint16 status; + + if (web_request_id == 0) + return FALSE; + + status = g_web_result_get_status(result); + + DBG(status %u, status); + + if (status = 400 status 500) + tunnel_destroy(); + else + tunnel_pending = 0; + + web_request_id = 0; + + g_timeout_add_seconds(1, unref_web, NULL); + + return FALSE; +} + static int init_6to4(struct in_addr *ip4addr) { unsigned int a, b, c, d; @@ -392,7 +426,18 @@ static int init_6to4(struct in_addr *ip4addr) if (ret) goto error; - tunnel_pending = 0; + /* We try to verify that connectivity through tunnel works ok. +*/ + web = g_web_new(0); + if (web == NULL) + goto error; + + g_web_set_accept(web, NULL); + g_web_set_user_agent(web, ConnMan/%s, VERSION); + g_web_set_close_connection(web, TRUE); + + web_request_id = g_web_request_get(web, STATUS_URL, web_result, NULL); + return 0; error: -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 4/9] gweb: Add support for connecting to IPv6 host.
--- gweb/gweb.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) diff --git a/gweb/gweb.c b/gweb/gweb.c index f3c8a7e..1bb1c70 100644 --- a/gweb/gweb.c +++ b/gweb/gweb.c @@ -31,6 +31,7 @@ #include string.h #include sys/socket.h #include arpa/inet.h +#include netdb.h #include giognutls.h #include gresolv.h @@ -63,6 +64,7 @@ struct web_session { char *host; uint16_t port; unsigned long flags; + struct addrinfo *addr; char *content_type; @@ -168,6 +170,9 @@ static void free_session(struct web_session *session) g_free(session-host); g_free(session-address); + if (session-addr != NULL) + freeaddrinfo(session-addr); + g_free(session); } @@ -881,10 +886,9 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, static int connect_session_transport(struct web_session *session) { GIOFlags flags; - struct sockaddr_in sin; int sk; - sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + sk = socket(session-addr-ai_family, SOCK_STREAM, IPPROTO_TCP); if (sk 0) return -EIO; @@ -910,12 +914,8 @@ static int connect_session_transport(struct web_session *session) g_io_channel_set_close_on_unref(session-transport_channel, TRUE); - memset(sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(session-port); - sin.sin_addr.s_addr = inet_addr(session-address); - - if (connect(sk, (struct sockaddr *) sin, sizeof(sin)) 0) { + if (connect(sk, session-addr-ai_addr, + session-addr-ai_addrlen) 0) { if (errno != EINPROGRESS) { close(sk); return -EIO; @@ -1048,6 +1048,8 @@ static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data) { struct web_session *session = user_data; + struct addrinfo hints; + int ret; if (results == NULL || results[0] == NULL) { call_result_func(session, 404); @@ -1056,7 +1058,16 @@ static void resolv_result(GResolvResultStatus status, debug(session-web, address %s, results[0]); - if (inet_aton(results[0], NULL) == 0) { + memset(hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + + if (session-addr != NULL) { + freeaddrinfo(session-addr); + session-addr = NULL; + } + + ret = getaddrinfo(results[0], NULL, hints, session-addr); + if (ret != 0 || session-addr == NULL) { call_result_func(session, 400); return; } -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 7/9] service: Create/remove 6to4 tunnel.
--- src/dhcp.c|4 src/service.c |2 ++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/dhcp.c b/src/dhcp.c index 6fda67d..dd7c498 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -73,6 +73,8 @@ static void dhcp_invalid(struct connman_dhcp *dhcp) if (ipconfig == NULL) return; + __connman_6to4_remove(ipconfig); + __connman_service_set_domainname(service, NULL); __connman_service_set_pac(service, NULL); __connman_service_timeserver_remove(service, dhcp-timeserver); @@ -211,6 +213,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) dhcp_valid(dhcp); + __connman_6to4_probe(service); + g_free(address); g_free(netmask); g_free(gateway); diff --git a/src/service.c b/src/service.c index ece29fd..29d6af5 100644 --- a/src/service.c +++ b/src/service.c @@ -3875,6 +3875,8 @@ int __connman_service_disconnect(struct connman_service *service) if (err 0 err != -EINPROGRESS) return err; + __connman_6to4_remove(service-ipconfig_ipv4); + if (service-ipconfig_ipv4) __connman_ipconfig_set_proxy_autoconfig(service-ipconfig_ipv4, NULL); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 8/9] 6to4: Check if the 6to4 tunnel is active or not.
--- src/6to4.c| 20 src/connman.h |1 + 2 files changed, 21 insertions(+), 0 deletions(-) diff --git a/src/6to4.c b/src/6to4.c index 52a0c53..8593e71 100644 --- a/src/6to4.c +++ b/src/6to4.c @@ -541,3 +541,23 @@ void __connman_6to4_remove(struct connman_ipconfig *ip4config) if (tunnel_created) tunnel_destroy(); } + +int __connman_6to4_check(struct connman_ipconfig *ip4config) +{ + const char *address; + + if (ip4config == NULL || tunnel_created == 0 || + tunnel_pending == 1) + return -1; + + DBG(tunnel ip address %s, tunnel_ip_address); + + address = __connman_ipconfig_get_local(ip4config); + if (address == NULL) + return -1; + + if (g_strcmp0(address, tunnel_ip_address) == 0) + return 1; + + return 0; +} diff --git a/src/connman.h b/src/connman.h index b3a45f0..a4ebbbe 100644 --- a/src/connman.h +++ b/src/connman.h @@ -639,3 +639,4 @@ void __connman_dnsproxy_flush(void); int __connman_6to4_probe(struct connman_service *service); void __connman_6to4_remove(struct connman_ipconfig *ipconfig); +int __connman_6to4_check(struct connman_ipconfig *ipconfig); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH 6to4 v5 9/9] service: Return 6to4 tunnel status to dbus caller.
--- src/connman.h |3 ++- src/ipconfig.c |9 - src/service.c |3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/connman.h b/src/connman.h index a4ebbbe..47f3c89 100644 --- a/src/connman.h +++ b/src/connman.h @@ -247,7 +247,8 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter); + DBusMessageIter *iter, + struct connman_ipconfig *ip4config); void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, diff --git a/src/ipconfig.c b/src/ipconfig.c index 9f0d5d9..15cc9ce 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1693,7 +1693,8 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, } void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter) + DBusMessageIter *iter, + struct connman_ipconfig *ipconfig_ipv4) { const char *str, *privacy; @@ -1706,6 +1707,12 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, if (str == NULL) return; + if (ipconfig_ipv4 != NULL + ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO) { + if (__connman_6to4_check(ipconfig_ipv4) == 1) + str = 6to4; + } + connman_dbus_dict_append_basic(iter, Method, DBUS_TYPE_STRING, str); if (ipconfig-system == NULL) diff --git a/src/service.c b/src/service.c index 29d6af5..36f7d64 100644 --- a/src/service.c +++ b/src/service.c @@ -1002,7 +1002,8 @@ static void append_ipv6(DBusMessageIter *iter, void *user_data) return; if (service-ipconfig_ipv6 != NULL) - __connman_ipconfig_append_ipv6(service-ipconfig_ipv6, iter); + __connman_ipconfig_append_ipv6(service-ipconfig_ipv6, iter, + service-ipconfig_ipv4); } static void append_ipv4config(DBusMessageIter *iter, void *user_data) -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH 6to4 v5 3/9] inet: Add routines to send IPv6 router solicitation message.
Hi Marcel, On 17 March 2011 09:29, Marcel Holtmann mar...@holtmann.org wrote: Hi Jukka, diff --git a/src/inet.c b/src/inet.c index 858d34c..40d8a8d 100644 --- a/src/inet.c +++ b/src/inet.c @@ -4,6 +4,10 @@ * * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. * + * Portions (IPv6 router solicitation handling from MIPL project) are + * Copyright 2003-2005 Go-Core Project and 2003-2006 Helsinki University of + * Technology + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. what is the license of the code from Go-Core Project and Helsinki University? We need to ensure that it is compatible with GPLv2 license we use in ConnMan. Please provide pointers to the original code. + * Portions (IPv6 router solicitation handling from MIPL project) are + * Copyright 2003-2005 Go-Core Project and 2003-2006 Helsinki University of + * Technology and have GPLv2 license. Original code can be found at + * git://linux-ipv6.org/gitroot/mipv6-daemon.git or + * http://www.linux-ipv6.org/gitweb/gitweb.cgi?p=gitroot/mipv6-daemon.git;a=blob;f=src/ndisc.c + * Would something like this be ok? The linux-ipv6.org git repo seems to be corrupt as I cannot clone it but web interface still works. Regards, Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH 6to4 v5 3/9] inet: Add routines to send IPv6 router solicitation message.
Hi Marcel, On 17 March 2011 18:50, Marcel Holtmann mar...@holtmann.org wrote: Hi Jukka, you don't have to go this much over board with this. I just needed to double check by myself that we are GPLv2 compatible before going any further with this patch. Ok, I just wanted to be exact :) Please have the origin note and a link to the file in the commit message of your patch for reference. And for the headers just add the appropriate copyright: * Copyright 2003-2005 Go-Core Project * Copyright 2003-2006 Helsinki University of Technology That is clearly enough for us. Good, that is now done for inet.c and iproute2 stuff in 6to4.c Samuel, should I send a new patchset version or should I wait if you have any comments about the other patches in the set? Regards, Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 0/9] 6to4 tunneling support
Hi, v6: - copyright notice fixed in 6to4.c and inet.c (patches #3 and #5 fixed) - IPv6 router solicitation function in inet.c is now available to connman core only (affects patches #3 and #5) v5: - the 6to4 tunnel status is returned via IPv6.Method (patch #9 reworked) - removed test script modifications (removed patch #10) - doc updated (patch #1 updated) v4: - 6to4 tunnel setting in service is read only i.e., it cannot be manipulated via dbus any longer - generic tunnel creation added to inet.c - IPv6 router solicitation / advertisement handling in inet.c - IPv6 support is added to gweb - gweb is used when checking connectivity through tunnel - tunnel is only created if we have a public IP address, the IPv6 is enabled and method is auto, we have not received autoconfigured ip address and internet connectivity via tunnel works ok The patch set is only tested via simulation (by commenting out various checks in the code) as I could not find such a crappy network anywhere, so there might be some problems left in the code. There is one issue when using gweb to check the connectivity via tunnel. As the network interface to be used is not set in gweb, we are just hoping that the routing in the device forces the check go through tunnel. Regards, Jukka Jukka Rissanen (9): doc: Add description about 6to4 tunnelling. inet: MTU and tunnel setup functions added. inet: Add routines to send IPv6 router solicitation message. gweb: Add support for connecting to IPv6 host. 6to4: Add 6to4 tunnel support. 6to4: Check the connectivity via tunnel after creating it. service: Create/remove 6to4 tunnel. 6to4: Check if the 6to4 tunnel is active or not. service: Return 6to4 tunnel status to dbus caller. Makefile.am |2 +- doc/service-api.txt |6 +- gweb/gweb.c | 29 ++- include/inet.h |3 + src/6to4.c | 562 +++ src/connman.h | 16 ++- src/dhcp.c |4 + src/inet.c | 384 ++- src/ipconfig.c |9 +- src/service.c |5 +- 10 files changed, 1004 insertions(+), 16 deletions(-) create mode 100644 src/6to4.c ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 1/9] doc: Add description about 6to4 tunnelling.
--- doc/service-api.txt |6 +- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/doc/service-api.txt b/doc/service-api.txt index 65554a2..7e87e6e 100644 --- a/doc/service-api.txt +++ b/doc/service-api.txt @@ -347,12 +347,16 @@ Propertiesstring State [readonly] string Method [readonly] - Possible values are auto, manual + Possible values are auto, manual, 6to4 and off. The value fixed indicates an IP address that can not be modified. For example cellular networks return fixed information. + The value 6to4 is returned if 6to4 tunnel + is created by connman. The tunnel can only be + created if method was set to auto by the + user. User cannot set the method to 6to4. string Address [readonly] -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 3/9] inet: Add routines to send IPv6 router solicitation message.
IPv6 router solicitation handling is from MIPL project. Original code can be found at git://linux-ipv6.org/gitroot/mipv6-daemon.git and http://www.linux-ipv6.org/gitweb/gitweb.cgi?p=gitroot/mipv6-daemon.git;a=blob;f=src/ndisc.c --- src/connman.h |9 ++ src/inet.c| 313 + 2 files changed, 322 insertions(+), 0 deletions(-) diff --git a/src/connman.h b/src/connman.h index 42bf2e6..6150064 100644 --- a/src/connman.h +++ b/src/connman.h @@ -110,6 +110,15 @@ int __connman_inet_modify_address(int cmd, int flags, int index, int family, unsigned char prefixlen, const char *broadcast); +#include netinet/ip6.h +#include netinet/icmp6.h + +typedef void (*__connman_inet_rs_cb_t) (struct nd_router_advert *reply, + void *user_data); + +int __connman_inet_ipv6_send_rs(int index, int timeout, + __connman_inet_rs_cb_t callback, void *user_data); + #include connman/wifi.h #include connman/rfkill.h diff --git a/src/inet.c b/src/inet.c index 8609d9e..5e5d9cc 100644 --- a/src/inet.c +++ b/src/inet.c @@ -3,6 +3,8 @@ * Connection Manager * * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. + * Copyright (C) 2003-2005 Go-Core Project + * Copyright (C) 2003-2006 Helsinki University of Technology * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -37,6 +39,7 @@ #include net/ethernet.h #include net/if.h #include net/if_arp.h +#include netinet/icmp6.h #include connman.h @@ -1261,3 +1264,313 @@ done: close(sk); return err; } + +struct rs_cb_data { + GIOChannel *channel; + __connman_inet_rs_cb_t callback; + struct sockaddr_in6 addr; + guint rs_timeout; + void *user_data; +}; + +#define CMSG_BUF_LEN 512 +#define IN6ADDR_ALL_NODES_MC_INIT \ + { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1 } } } /* ff02::1 */ +#define IN6ADDR_ALL_ROUTERS_MC_INIT \ + { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff02::2 */ + +static const struct in6_addr in6addr_all_nodes_mc = IN6ADDR_ALL_NODES_MC_INIT; +static const struct in6_addr in6addr_all_routers_mc = + IN6ADDR_ALL_ROUTERS_MC_INIT; + +/* from netinet/in.h */ +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; + +static void rs_cleanup(struct rs_cb_data *data) +{ + g_io_channel_shutdown(data-channel, TRUE, NULL); + g_io_channel_unref(data-channel); + data-channel = 0; + + if (data-rs_timeout 0) + g_source_remove(data-rs_timeout); + + g_free(data); +} + +static gboolean rs_timeout_cb(gpointer user_data) +{ + struct rs_cb_data *data = user_data; + + DBG(user data %p, user_data); + + if (data == NULL) + return FALSE; + + if (data-callback != NULL) + data-callback(NULL, data-user_data); + + data-rs_timeout = 0; + rs_cleanup(data); + return FALSE; +} + +static int icmpv6_recv(int fd, gpointer user_data) +{ + struct msghdr mhdr; + struct iovec iov; + unsigned char chdr[CMSG_BUF_LEN]; + unsigned char buf[1540]; + struct rs_cb_data *data = user_data; + struct nd_router_advert *hdr; + struct sockaddr_in6 saddr; + ssize_t len; + + DBG(); + + iov.iov_len = sizeof(buf); + iov.iov_base = buf; + + mhdr.msg_name = (void *)saddr; + mhdr.msg_namelen = sizeof(struct sockaddr_in6); + mhdr.msg_iov = iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = CMSG_BUF_LEN; + + len = recvmsg(fd, mhdr, 0); + if (len 0) { + data-callback(NULL, data-user_data); + return -errno; + } + + hdr = (struct nd_router_advert *)buf; + if (hdr-nd_ra_code != 0) + return 0; + + data-callback(hdr, data-user_data); + rs_cleanup(data); + + return len; +} + +static gboolean icmpv6_event(GIOChannel *chan, GIOCondition cond, + gpointer data) +{ + int fd, ret; + + DBG(); + + if (cond (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + fd = g_io_channel_unix_get_fd(chan); + ret = icmpv6_recv(fd, data); + if (ret == 0) + return TRUE; + + return FALSE; +} + +/* Adapted from RFC 1071 C Implementation Example */ +static uint16_t csum(const void *phdr, const void *data, socklen_t datalen) +{ + register unsigned long sum = 0; + socklen_t count; + uint16_t *addr; + int i; + + /* caller must make sure datalen is even */
[6to4 v6 2/9] inet: MTU and tunnel setup functions added.
--- include/inet.h |3 ++ src/inet.c | 71 ++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/include/inet.h b/include/inet.h index 9ba7781..9a9411d 100644 --- a/include/inet.h +++ b/include/inet.h @@ -73,6 +73,9 @@ int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway); int connman_inet_add_to_bridge(int index, const char *bridge); int connman_inet_remove_from_bridge(int index, const char *bridge); +int connman_inet_set_mtu(int index, int mtu); +int connman_inet_setup_tunnel(char *tunnel, int mtu); + #ifdef __cplusplus } #endif diff --git a/src/inet.c b/src/inet.c index fa768fb..8609d9e 100644 --- a/src/inet.c +++ b/src/inet.c @@ -35,8 +35,8 @@ #include arpa/inet.h #include net/route.h #include net/ethernet.h -#include linux/if_arp.h -#include linux/wireless.h +#include net/if.h +#include net/if_arp.h #include connman.h @@ -1194,3 +1194,70 @@ int connman_inet_add_to_bridge(int index, const char *bridge) return 0; } + +int connman_inet_set_mtu(int index, int mtu) +{ + struct ifreq ifr; + int sk, err; + + sk = socket(AF_INET, SOCK_DGRAM, 0); + if (sk 0) + return sk; + + memset(ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = index; + + err = ioctl(sk, SIOCGIFNAME, ifr); + if (err == 0) { + ifr.ifr_mtu = mtu; + err = ioctl(sk, SIOCSIFMTU, ifr); + } + + close(sk); + return err; +} + +int connman_inet_setup_tunnel(char *tunnel, int mtu) +{ + struct ifreq ifr; + int sk, err, index; + __u32 mask; + __u32 flags; + + if (tunnel == NULL) + return -EINVAL; + + sk = socket(AF_INET, SOCK_DGRAM, 0); + if (sk 0) + return sk; + + index = if_nametoindex(tunnel); + + err = connman_inet_set_mtu(index, mtu); + if (err 0) + return err; + else if (err) + goto done; + + memset(ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, tunnel, IFNAMSIZ); + err = ioctl(sk, SIOCGIFFLAGS, ifr); + if (err) + goto done; + + mask = IFF_UP; + flags = IFF_UP; + + if ((ifr.ifr_flags ^ flags) mask) { + ifr.ifr_flags = ~mask; + ifr.ifr_flags |= mask flags; + err = ioctl(sk, SIOCSIFFLAGS, ifr); + if (err) + connman_error(SIOCSIFFLAGS failed: %s, + strerror(errno)); + } + +done: + close(sk); + return err; +} -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 4/9] gweb: Add support for connecting to IPv6 host.
--- gweb/gweb.c | 29 - 1 files changed, 20 insertions(+), 9 deletions(-) diff --git a/gweb/gweb.c b/gweb/gweb.c index f3c8a7e..1bb1c70 100644 --- a/gweb/gweb.c +++ b/gweb/gweb.c @@ -31,6 +31,7 @@ #include string.h #include sys/socket.h #include arpa/inet.h +#include netdb.h #include giognutls.h #include gresolv.h @@ -63,6 +64,7 @@ struct web_session { char *host; uint16_t port; unsigned long flags; + struct addrinfo *addr; char *content_type; @@ -168,6 +170,9 @@ static void free_session(struct web_session *session) g_free(session-host); g_free(session-address); + if (session-addr != NULL) + freeaddrinfo(session-addr); + g_free(session); } @@ -881,10 +886,9 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, static int connect_session_transport(struct web_session *session) { GIOFlags flags; - struct sockaddr_in sin; int sk; - sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + sk = socket(session-addr-ai_family, SOCK_STREAM, IPPROTO_TCP); if (sk 0) return -EIO; @@ -910,12 +914,8 @@ static int connect_session_transport(struct web_session *session) g_io_channel_set_close_on_unref(session-transport_channel, TRUE); - memset(sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(session-port); - sin.sin_addr.s_addr = inet_addr(session-address); - - if (connect(sk, (struct sockaddr *) sin, sizeof(sin)) 0) { + if (connect(sk, session-addr-ai_addr, + session-addr-ai_addrlen) 0) { if (errno != EINPROGRESS) { close(sk); return -EIO; @@ -1048,6 +1048,8 @@ static void resolv_result(GResolvResultStatus status, char **results, gpointer user_data) { struct web_session *session = user_data; + struct addrinfo hints; + int ret; if (results == NULL || results[0] == NULL) { call_result_func(session, 404); @@ -1056,7 +1058,16 @@ static void resolv_result(GResolvResultStatus status, debug(session-web, address %s, results[0]); - if (inet_aton(results[0], NULL) == 0) { + memset(hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + + if (session-addr != NULL) { + freeaddrinfo(session-addr); + session-addr = NULL; + } + + ret = getaddrinfo(results[0], NULL, hints, session-addr); + if (ret != 0 || session-addr == NULL) { call_result_func(session, 400); return; } -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 5/9] 6to4: Add 6to4 tunnel support.
Netlink support routines taken from iproute2 package. Iproute2 source code can be found at git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git --- Makefile.am |2 +- src/6to4.c| 497 + src/connman.h |3 + 3 files changed, 501 insertions(+), 1 deletions(-) create mode 100644 src/6to4.c diff --git a/Makefile.am b/Makefile.am index 3ad1ee9..95aefc7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -77,7 +77,7 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \ src/wifi.c src/storage.c src/dbus.c src/config.c \ src/technology.c src/counter.c src/location.c \ src/session.c src/tethering.c src/wpad.c src/wispr.c \ - src/stats.c src/iptables.c src/dnsproxy.c + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ @CAPNG_LIBS@ @XTABLES_LIBS@ -lresolv -ldl diff --git a/src/6to4.c b/src/6to4.c new file mode 100644 index 000..767c866 --- /dev/null +++ b/src/6to4.c @@ -0,0 +1,497 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Copyright (C) Alexey Kuznetsov et al. from iproute2 package. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include config.h +#endif + +#include stdio.h +#include string.h +#include sys/socket.h +#include netinet/in.h +#include arpa/inet.h +#include net/if.h +#include linux/ip.h +#include linux/if_tunnel.h +#include linux/netlink.h +#include linux/rtnetlink.h +#include sys/ioctl.h +#include unistd.h + +#include connman.h +#include connman/log.h +#include connman/ipconfig.h + +static int tunnel_created; +static int tunnel_pending; +static char *tunnel_ip_address; + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) + +#ifndef IP_DF +#define IP_DF 0x4000 /* Flag: Don't Fragment */ +#endif + +struct rtnl_handle { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +static int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *rta; + if (NLMSG_ALIGN(n-nlmsg_len) + len (unsigned int)maxlen) { + DBG(Error! max allowed bound %d exceeded, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, 4); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + len; + + return 0; +} + +static int addattr_l(struct nlmsghdr *n, int maxlen, int type, + const void *data, int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len) + (unsigned int)maxlen) { + DBG(addattr_l message exceeded bound of %d, maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta-rta_type = type; + rta-rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n-nlmsg_len = NLMSG_ALIGN(n-nlmsg_len) + RTA_ALIGN(len); + + return 0; +} + +static void rtnl_close(struct rtnl_handle *rth) +{ + if (rth-fd = 0) { + close(rth-fd); + rth-fd = -1; + } +} + +static int rtnl_open(struct rtnl_handle *rth) +{ + socklen_t addr_len; + int sndbuf = 1024; + + memset(rth, 0, sizeof(*rth)); + + rth-fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (rth-fd 0) { + connman_error(Can not open netlink socket: %s, + strerror(errno)); + return -1; + } + + if (setsockopt(rth-fd, SOL_SOCKET, SO_SNDBUF, sndbuf, + sizeof(sndbuf)) 0) { + connman_error(SO_SNDBUF: %s, strerror(errno)); + return -1; + } + + memset(rth-local, 0, sizeof(rth-local)); + rth-local.nl_family = AF_NETLINK; + rth-local.nl_groups = 0; +
[6to4 v6 6/9] 6to4: Check the connectivity via tunnel after creating it.
--- src/6to4.c | 47 ++- 1 files changed, 46 insertions(+), 1 deletions(-) diff --git a/src/6to4.c b/src/6to4.c index 767c866..e6815a0 100644 --- a/src/6to4.c +++ b/src/6to4.c @@ -40,10 +40,15 @@ #include connman.h #include connman/log.h #include connman/ipconfig.h +#include gweb/gweb.h static int tunnel_created; static int tunnel_pending; static char *tunnel_ip_address; +static GWeb *web; +static guint web_request_id; + +#define STATUS_URL http://ipv6.google.com/; #define NLMSG_TAIL(nmsg) \ ((struct rtattr *) (((void *)(nmsg)) + NLMSG_ALIGN((nmsg)-nlmsg_len))) @@ -358,6 +363,35 @@ done: return ret; } +static gboolean unref_web(gpointer user_data) +{ + g_web_unref(web); + return FALSE; +} + +static gboolean web_result(GWebResult *result, gpointer user_data) +{ + guint16 status; + + if (web_request_id == 0) + return FALSE; + + status = g_web_result_get_status(result); + + DBG(status %u, status); + + if (status = 400 status 500) + tunnel_destroy(); + else + tunnel_pending = 0; + + web_request_id = 0; + + g_timeout_add_seconds(1, unref_web, NULL); + + return FALSE; +} + static int init_6to4(struct in_addr *ip4addr) { unsigned int a, b, c, d; @@ -391,7 +425,18 @@ static int init_6to4(struct in_addr *ip4addr) if (ret) goto error; - tunnel_pending = 0; + /* We try to verify that connectivity through tunnel works ok. +*/ + web = g_web_new(0); + if (web == NULL) + goto error; + + g_web_set_accept(web, NULL); + g_web_set_user_agent(web, ConnMan/%s, VERSION); + g_web_set_close_connection(web, TRUE); + + web_request_id = g_web_request_get(web, STATUS_URL, web_result, NULL); + return 0; error: -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 7/9] service: Create/remove 6to4 tunnel.
--- src/dhcp.c|4 src/service.c |2 ++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/src/dhcp.c b/src/dhcp.c index 3106c3d..03a2b90 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -73,6 +73,8 @@ static void dhcp_invalid(struct connman_dhcp *dhcp) if (ipconfig == NULL) return; + __connman_6to4_remove(ipconfig); + __connman_service_set_domainname(service, NULL); __connman_service_set_pac(service, NULL); __connman_service_timeserver_remove(service, dhcp-timeserver); @@ -289,6 +291,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) if (ip_change == TRUE) dhcp_valid(dhcp); + __connman_6to4_probe(service); + g_free(address); g_free(netmask); g_free(gateway); diff --git a/src/service.c b/src/service.c index f4b15f0..b147551 100644 --- a/src/service.c +++ b/src/service.c @@ -3887,6 +3887,8 @@ int __connman_service_disconnect(struct connman_service *service) if (err 0 err != -EINPROGRESS) return err; + __connman_6to4_remove(service-ipconfig_ipv4); + if (service-ipconfig_ipv4) __connman_ipconfig_set_proxy_autoconfig(service-ipconfig_ipv4, NULL); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 8/9] 6to4: Check if the 6to4 tunnel is active or not.
--- src/6to4.c| 20 src/connman.h |1 + 2 files changed, 21 insertions(+), 0 deletions(-) diff --git a/src/6to4.c b/src/6to4.c index e6815a0..3877bfb 100644 --- a/src/6to4.c +++ b/src/6to4.c @@ -540,3 +540,23 @@ void __connman_6to4_remove(struct connman_ipconfig *ip4config) if (tunnel_created) tunnel_destroy(); } + +int __connman_6to4_check(struct connman_ipconfig *ip4config) +{ + const char *address; + + if (ip4config == NULL || tunnel_created == 0 || + tunnel_pending == 1) + return -1; + + DBG(tunnel ip address %s, tunnel_ip_address); + + address = __connman_ipconfig_get_local(ip4config); + if (address == NULL) + return -1; + + if (g_strcmp0(address, tunnel_ip_address) == 0) + return 1; + + return 0; +} diff --git a/src/connman.h b/src/connman.h index 1ca73ed..d466b21 100644 --- a/src/connman.h +++ b/src/connman.h @@ -648,3 +648,4 @@ void __connman_dnsproxy_flush(void); int __connman_6to4_probe(struct connman_service *service); void __connman_6to4_remove(struct connman_ipconfig *ipconfig); +int __connman_6to4_check(struct connman_ipconfig *ipconfig); -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[6to4 v6 9/9] service: Return 6to4 tunnel status to dbus caller.
--- src/connman.h |3 ++- src/ipconfig.c |9 - src/service.c |3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/connman.h b/src/connman.h index d466b21..01dca1b 100644 --- a/src/connman.h +++ b/src/connman.h @@ -256,7 +256,8 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, void __connman_ipconfig_append_ipv4config(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter); + DBusMessageIter *iter, + struct connman_ipconfig *ip4config); void __connman_ipconfig_append_ipv6config(struct connman_ipconfig *ipconfig, DBusMessageIter *iter); int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, diff --git a/src/ipconfig.c b/src/ipconfig.c index 0599a73..22dd03b 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1701,7 +1701,8 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, } void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, - DBusMessageIter *iter) + DBusMessageIter *iter, + struct connman_ipconfig *ipconfig_ipv4) { const char *str, *privacy; @@ -1714,6 +1715,12 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, if (str == NULL) return; + if (ipconfig_ipv4 != NULL + ipconfig-method == CONNMAN_IPCONFIG_METHOD_AUTO) { + if (__connman_6to4_check(ipconfig_ipv4) == 1) + str = 6to4; + } + connman_dbus_dict_append_basic(iter, Method, DBUS_TYPE_STRING, str); if (ipconfig-system == NULL) diff --git a/src/service.c b/src/service.c index b147551..ae1f6fd 100644 --- a/src/service.c +++ b/src/service.c @@ -1002,7 +1002,8 @@ static void append_ipv6(DBusMessageIter *iter, void *user_data) return; if (service-ipconfig_ipv6 != NULL) - __connman_ipconfig_append_ipv6(service-ipconfig_ipv6, iter); + __connman_ipconfig_append_ipv6(service-ipconfig_ipv6, iter, + service-ipconfig_ipv4); } static void append_ipv4config(DBusMessageIter *iter, void *user_data) -- 1.7.0.4 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 00/13] ipv6 gw: Fix route and gateway handling for IPv6
Hi, here are some patches to fix route and gateway handling for static and autoconfigured IPv6 addresses. Description of patches: 01 - Error print enhancement 02,03 - Very minor indentation fixes 04 - Functions for setting and clearing IPv6 gateway address, needed by patch #07 05 - Set routes to IPv6 nameservers properly 06 - Association state was not set for IPv6 07 - Fix gateway handling for IPv6 08 - Setup gateways for manual IPv6 configs 09 - Added function to remove IP address from interface without removing the address from internal structures. This is needed by patch #10 10 - Remove address from interface 11 - Enable IPv6 support function. This is needed by patch #12 12 - Remove IPv6 autoconfigured addresses and routes by disabling IPv6 temporarily. This is done so that kernel can do the hard work for us as it will remove all autoconfigured address automagically when IPv6 is disabled. 13 - Mark the IPv6 gateway handling as done Jukka Jukka Rissanen (13): inet: Changed error prints to print the error string. inet: Fixed indentation. service: Fixed indentation. inet: Added support functions for setting and clearing IPv6 gateway address. service: Set and clear IPv6 nameserver addresses properly. network: Add IPv6 associating state. connection: Separate IPv4 and IPv6 gateway and routing handling. network: Set manual IPv6 state and gateway. ipconfig: Added function to remove address from interface. network: Clear interface addresses after removing gateway address. ipconfig: Added function to enable IPv6. network: Clear IPv6 autoconfigured routes when disconnected. TODO: IPv6 gateway handling done. TODO | 10 - include/inet.h |2 + include/ipconfig.h |2 + src/connection.c | 495 src/connman.h | 12 +- src/inet.c | 106 +++- src/ipconfig.c | 56 +-- src/network.c | 43 - src/service.c | 56 +- 9 files changed, 624 insertions(+), 158 deletions(-) ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 01/13] inet: Changed error prints to print the error string.
--- src/inet.c | 12 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/inet.c b/src/inet.c index e3adb7e..c55af06 100644 --- a/src/inet.c +++ b/src/inet.c @@ -783,7 +783,8 @@ int connman_inet_del_ipv6_network_route(int index, const char *host, close(sk); out: if (err 0) - connman_error(Del IPv6 host route error); + connman_error(Del IPv6 host route error (%s), + strerror(errno)); return err; } @@ -833,7 +834,8 @@ int connman_inet_add_ipv6_network_route(int index, const char *host, close(sk); out: if (err 0) - connman_error(Set IPv6 host route error); + connman_error(Set IPv6 host route error (%s), + strerror(errno)); return err; } @@ -875,7 +877,8 @@ int connman_inet_set_ipv6_gateway_address(int index, const char *gateway) close(sk); out: if (err 0) - connman_error(Set default IPv6 gateway error); + connman_error(Set default IPv6 gateway error (%s), + strerror(errno)); return err; } @@ -911,7 +914,8 @@ int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway) close(sk); out: if (err 0) - connman_error(Clear default IPv6 gateway error); + connman_error(Clear default IPv6 gateway error (%s), + strerror(errno)); return err; } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 02/13] inet: Fixed indentation.
--- src/inet.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/inet.c b/src/inet.c index c55af06..05ead31 100644 --- a/src/inet.c +++ b/src/inet.c @@ -796,7 +796,7 @@ int connman_inet_del_ipv6_host_route(int index, const char *host) int connman_inet_add_ipv6_network_route(int index, const char *host, const char *gateway, - unsigned char prefix_len) + unsigned char prefix_len) { struct in6_rtmsg rt; int sk, err; -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 06/13] network: Add IPv6 associating state.
--- src/network.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 88b8ad8..1693109 100644 --- a/src/network.c +++ b/src/network.c @@ -657,6 +657,9 @@ int connman_network_set_associating(struct connman_network *network, __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_ASSOCIATION, CONNMAN_IPCONFIG_TYPE_IPV4); + __connman_service_indicate_state(service, + CONNMAN_SERVICE_STATE_ASSOCIATION, + CONNMAN_IPCONFIG_TYPE_IPV6); } return 0; -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 05/13] service: Set and clear IPv6 nameserver addresses properly.
--- src/service.c | 56 +--- 1 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/service.c b/src/service.c index eca4ef2..216fa47 100644 --- a/src/service.c +++ b/src/service.c @@ -26,6 +26,7 @@ #include errno.h #include stdio.h #include string.h +#include netdb.h #include gdbus.h #include connman.h @@ -611,22 +612,63 @@ void __connman_service_nameserver_clear(struct connman_service *service) static void nameserver_add_routes(int index, char **nameservers, const char *gw) { - int i; + int i, ret, family; + struct addrinfo hints; + struct addrinfo *addr; for (i = 0; nameservers[i] != NULL; i++) { - if (connman_inet_compare_subnet(index, nameservers[i])) + memset(hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + addr = NULL; + + ret = getaddrinfo(nameservers[i], NULL, hints, addr); + if (ret == EAI_NONAME) + family = AF_INET; /* use the IPv4 as a default */ + else if (ret != 0) continue; + else + family = addr-ai_family; + + if (family == AF_INET) { + if (connman_inet_compare_subnet(index, + nameservers[i]) != TRUE) + connman_inet_add_host_route(index, + nameservers[i], gw); + } else if (family == AF_INET6) + connman_inet_add_ipv6_host_route(index, + nameservers[i], gw); - connman_inet_add_host_route(index, nameservers[i], gw); + freeaddrinfo(addr); } } static void nameserver_del_routes(int index, char **nameservers) { - int i; + int i, ret, family; + struct addrinfo hints; + struct addrinfo *addr; + + for (i = 0; nameservers[i] != NULL; i++) { + memset(hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + addr = NULL; + + ret = getaddrinfo(nameservers[i], NULL, hints, addr); + if (ret == EAI_NONAME) + family = AF_INET; /* use the IPv4 as a default */ + else if (ret != 0) + continue; + else + family = addr-ai_family; - for (i = 0; nameservers[i] != NULL; i++) - connman_inet_del_host_route(index, nameservers[i]); + if (family == AF_INET) + connman_inet_del_host_route(index, nameservers[i]); + else if (family == AF_INET6) + connman_inet_del_ipv6_host_route(index, + nameservers[i]); + + freeaddrinfo(addr); + } } void __connman_service_nameserver_add_routes(struct connman_service *service, -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 09/13] ipconfig: Added function to remove address from interface.
--- src/connman.h |1 + src/ipconfig.c | 30 -- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/connman.h b/src/connman.h index 7e22b78..9e28837 100644 --- a/src/connman.h +++ b/src/connman.h @@ -249,6 +249,7 @@ enum connman_ipconfig_method __connman_ipconfig_get_method( int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig); int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig); +int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig); int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig); void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig); unsigned char __connman_ipconfig_netmask_prefix_len(const char *netmask); diff --git a/src/ipconfig.c b/src/ipconfig.c index c8466d9..4d74ca8 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1401,6 +1401,34 @@ int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig) case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_DHCP: case CONNMAN_IPCONFIG_METHOD_MANUAL: + err = __connman_ipconfig_address_unset(ipconfig); + connman_ipaddress_clear(ipconfig-address); + + return err; + } + + return 0; +} + +int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig) +{ + int err; + + DBG(); + + if (ipconfig == NULL) + return 0; + + DBG(method %d, ipconfig-method); + + switch (ipconfig-method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_AUTO: + break; + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_DHCP: + case CONNMAN_IPCONFIG_METHOD_MANUAL: if (ipconfig-type == CONNMAN_IPCONFIG_TYPE_IPV4) err = connman_inet_clear_address(ipconfig-index, ipconfig-address); @@ -1412,8 +1440,6 @@ int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig) else err = -EINVAL; - connman_ipaddress_clear(ipconfig-address); - return err; } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 10/13] network: Clear interface addresses after removing gateway address.
--- src/network.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 4abcb09..0ae77ca 100644 --- a/src/network.c +++ b/src/network.c @@ -1101,6 +1101,9 @@ static gboolean set_connected(gpointer user_data) __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); + __connman_ipconfig_address_unset(ipconfig_ipv4); + __connman_ipconfig_address_unset(ipconfig_ipv6); + __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 11/13] ipconfig: Added function to enable IPv6.
--- include/ipconfig.h |1 + src/ipconfig.c |8 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/include/ipconfig.h b/include/ipconfig.h index 8980a78..34463eb 100644 --- a/include/ipconfig.h +++ b/include/ipconfig.h @@ -99,6 +99,7 @@ void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig, int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig, enum connman_ipconfig_method method); void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig); +void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig); #ifdef __cplusplus } diff --git a/src/ipconfig.c b/src/ipconfig.c index 4d74ca8..454d5d5 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1516,6 +1516,14 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) set_ipv6_state(ipdevice-ifname, TRUE); } +void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig) +{ + if (ipconfig == NULL || ipconfig-type != CONNMAN_IPCONFIG_TYPE_IPV6) + return; + + enable_ipv6(ipconfig); +} + void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig) { if (ipconfig == NULL || ipconfig-type != CONNMAN_IPCONFIG_TYPE_IPV6) -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 12/13] network: Clear IPv6 autoconfigured routes when disconnected.
--- src/network.c | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 0ae77ca..ac7bd07 100644 --- a/src/network.c +++ b/src/network.c @@ -1104,6 +1104,17 @@ static gboolean set_connected(gpointer user_data) __connman_ipconfig_address_unset(ipconfig_ipv4); __connman_ipconfig_address_unset(ipconfig_ipv6); + /* +* Special handling for IPv6 autoconfigured address. +* The simplest way to remove autoconfigured routes is to +* disable IPv6 temporarily so that kernel will do the cleanup +* automagically. +*/ + if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) { + __connman_ipconfig_disable_ipv6(ipconfig_ipv6); + __connman_ipconfig_enable_ipv6(ipconfig_ipv6); + } + __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw 13/13] TODO: IPv6 gateway handling done.
--- TODO | 10 -- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/TODO b/TODO index 7420ba0..8937041 100644 --- a/TODO +++ b/TODO @@ -64,16 +64,6 @@ Core not all driver (especially WiFi ones) implement runtime PM hooks. -- IPv6 gateway handling - - Priority: Medium - Complexity: C4 - - We should be able to switch between IPv6 only services and thus - change the default IPv6 gateway on the fly. For that we need to - improve the connection.c code to properly handle IPv6 gateways. - - - IP ranges allocation and check Priority: High -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH ipv6 gw 10/13] network: Clear interface addresses after removing gateway address.
Hi Samuel, On 06/21/2011 07:11 PM, Samuel Ortiz wrote: Hi Jukka, On Mon, Jun 20, 2011 at 02:05:26PM +0300, Jukka Rissanen wrote: --- src/network.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 4abcb09..0ae77ca 100644 --- a/src/network.c +++ b/src/network.c @@ -1101,6 +1101,9 @@ static gboolean set_connected(gpointer user_data) __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); + __connman_ipconfig_address_unset(ipconfig_ipv4); + __connman_ipconfig_address_unset(ipconfig_ipv6); + So we're already calling ipconfig_address_remove() from service.c and also from dhcp.c. Why do we need this ? Yes, the __connman_service_disconnect() will call the __connman_ipconfig_address_remove() but when changing the service, the __connman_service_disconnect() is not called at all. This means that the code path is different if you just disconnect a service and if you change from one service to another although the end result is the same i.e., the service is disconnected. The new __connman_ipconfig_address_unset() differs in small detail from __connman_ipconfig_address_remove(). The _unset() does not call connman_ipaddress_clear() so that we do not remove addresses from internal structures. Clearing the ipaddress from ipconfig caused problems if done at this stage of the call flow (sorry, I do not remember the details). Btw, the changelog would be the right place to explain why we do need those calls. Very true, I try to do better next time :) Cheers, Samuel. Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
Re: [PATCH ipv6 gw 07/13] connection: Separate IPv4 and IPv6 gateway and routing handling.
Hi Samuel, On 06/21/2011 07:10 PM, Samuel Ortiz wrote: Hi Jukka, On Mon, Jun 20, 2011 at 02:05:23PM +0300, Jukka Rissanen wrote: --- include/ipconfig.h |1 + src/connection.c | 495 src/connman.h |9 +- src/ipconfig.c | 18 +- src/network.c |3 +- 5 files changed, 397 insertions(+), 129 deletions(-) Pretty good patch, I have one comment though: Thanks, I tried to test the patch as well as possible but my test setup is quite limited atm so I could not test the VPN connectivity for example. -static struct gateway_data *find_gateway(int index, const char *gateway) +static struct gateway_data *find_gateway(int index, const char *gateway, + struct gateway_config **config) Couldn't this one simply return a struct gateway_config * ? Yes, you are right. I can fix that. Cheers, Samuel. Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 05/13] service: Set and clear IPv6 nameserver addresses properly.
--- src/service.c | 56 +--- 1 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/service.c b/src/service.c index 3f6df36..7f55bbf 100644 --- a/src/service.c +++ b/src/service.c @@ -26,6 +26,7 @@ #include errno.h #include stdio.h #include string.h +#include netdb.h #include gdbus.h #include connman.h @@ -611,22 +612,63 @@ void __connman_service_nameserver_clear(struct connman_service *service) static void nameserver_add_routes(int index, char **nameservers, const char *gw) { - int i; + int i, ret, family; + struct addrinfo hints; + struct addrinfo *addr; for (i = 0; nameservers[i] != NULL; i++) { - if (connman_inet_compare_subnet(index, nameservers[i])) + memset(hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + addr = NULL; + + ret = getaddrinfo(nameservers[i], NULL, hints, addr); + if (ret == EAI_NONAME) + family = AF_INET; /* use the IPv4 as a default */ + else if (ret != 0) continue; + else + family = addr-ai_family; + + if (family == AF_INET) { + if (connman_inet_compare_subnet(index, + nameservers[i]) != TRUE) + connman_inet_add_host_route(index, + nameservers[i], gw); + } else if (family == AF_INET6) + connman_inet_add_ipv6_host_route(index, + nameservers[i], gw); - connman_inet_add_host_route(index, nameservers[i], gw); + freeaddrinfo(addr); } } static void nameserver_del_routes(int index, char **nameservers) { - int i; + int i, ret, family; + struct addrinfo hints; + struct addrinfo *addr; + + for (i = 0; nameservers[i] != NULL; i++) { + memset(hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_NUMERICHOST; + addr = NULL; + + ret = getaddrinfo(nameservers[i], NULL, hints, addr); + if (ret == EAI_NONAME) + family = AF_INET; /* use the IPv4 as a default */ + else if (ret != 0) + continue; + else + family = addr-ai_family; - for (i = 0; nameservers[i] != NULL; i++) - connman_inet_del_host_route(index, nameservers[i]); + if (family == AF_INET) + connman_inet_del_host_route(index, nameservers[i]); + else if (family == AF_INET6) + connman_inet_del_ipv6_host_route(index, + nameservers[i]); + + freeaddrinfo(addr); + } } void __connman_service_nameserver_add_routes(struct connman_service *service, -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 04/13] inet: Added support functions for setting and clearing IPv6 gateway address.
--- include/inet.h |2 + src/inet.c | 92 2 files changed, 94 insertions(+), 0 deletions(-) diff --git a/include/inet.h b/include/inet.h index 19f4455..1aa23ea 100644 --- a/include/inet.h +++ b/include/inet.h @@ -69,6 +69,8 @@ int connman_inet_del_ipv6_network_route(int index, const char *host, int connman_inet_del_ipv6_host_route(int index, const char *host); int connman_inet_set_ipv6_gateway_address(int index, const char *gateway); int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway); +int connman_inet_set_ipv6_gateway_interface(int index); +int connman_inet_clear_ipv6_gateway_interface(int index); int connman_inet_add_to_bridge(int index, const char *bridge); int connman_inet_remove_from_bridge(int index, const char *bridge); diff --git a/src/inet.c b/src/inet.c index 05ead31..d898650 100644 --- a/src/inet.c +++ b/src/inet.c @@ -1014,6 +1014,52 @@ int connman_inet_set_gateway_interface(int index) return err; } +int connman_inet_set_ipv6_gateway_interface(int index) +{ + struct ifreq ifr; + struct rtentry rt; + struct sockaddr_in6 addr; + const struct in6_addr any = IN6ADDR_ANY_INIT; + int sk, err; + + DBG(); + + sk = socket(PF_INET6, SOCK_DGRAM, 0); + if (sk 0) + return -1; + + memset(ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = index; + + if (ioctl(sk, SIOCGIFNAME, ifr) 0) { + close(sk); + return -1; + } + + DBG(ifname %s, ifr.ifr_name); + + memset(rt, 0, sizeof(rt)); + rt.rt_flags = RTF_UP; + + memset(addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = any; + + memcpy(rt.rt_genmask, addr, sizeof(rt.rt_genmask)); + memcpy(rt.rt_dst, addr, sizeof(rt.rt_dst)); + memcpy(rt.rt_gateway, addr, sizeof(rt.rt_gateway)); + + rt.rt_dev = ifr.ifr_name; + + err = ioctl(sk, SIOCADDRT, rt); + if (err 0) + connman_error(Setting default interface route failed (%s), + strerror(errno)); + close(sk); + + return err; +} + int connman_inet_clear_gateway_address(int index, const char *gateway) { struct ifreq ifr; @@ -1110,6 +1156,52 @@ int connman_inet_clear_gateway_interface(int index) return err; } +int connman_inet_clear_ipv6_gateway_interface(int index) +{ + struct ifreq ifr; + struct rtentry rt; + struct sockaddr_in6 addr; + const struct in6_addr any = IN6ADDR_ANY_INIT; + int sk, err; + + DBG(); + + sk = socket(PF_INET6, SOCK_DGRAM, 0); + if (sk 0) + return -1; + + memset(ifr, 0, sizeof(ifr)); + ifr.ifr_ifindex = index; + + if (ioctl(sk, SIOCGIFNAME, ifr) 0) { + close(sk); + return -1; + } + + DBG(ifname %s, ifr.ifr_name); + + memset(rt, 0, sizeof(rt)); + rt.rt_flags = RTF_UP; + + memset(addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr = any; + + memcpy(rt.rt_genmask, addr, sizeof(rt.rt_genmask)); + memcpy(rt.rt_dst, addr, sizeof(rt.rt_dst)); + memcpy(rt.rt_gateway, addr, sizeof(rt.rt_gateway)); + + rt.rt_dev = ifr.ifr_name; + + err = ioctl(sk, SIOCDELRT, rt); + if (err 0) + connman_error(Removing default interface route failed (%s), + strerror(errno)); + close(sk); + + return err; +} + connman_bool_t connman_inet_compare_subnet(int index, const char *host) { struct ifreq ifr; -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 06/13] network: Add IPv6 associating state.
--- src/network.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 88b8ad8..1693109 100644 --- a/src/network.c +++ b/src/network.c @@ -657,6 +657,9 @@ int connman_network_set_associating(struct connman_network *network, __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_ASSOCIATION, CONNMAN_IPCONFIG_TYPE_IPV4); + __connman_service_indicate_state(service, + CONNMAN_SERVICE_STATE_ASSOCIATION, + CONNMAN_IPCONFIG_TYPE_IPV6); } return 0; -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 08/13] network: Set manual IPv6 state and gateway.
--- src/network.c | 23 +++ 1 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/network.c b/src/network.c index acc374f..4abcb09 100644 --- a/src/network.c +++ b/src/network.c @@ -960,6 +960,8 @@ static int manual_ipv6_set(struct connman_network *network, struct connman_service *service; int err; + DBG(network %p ipv6 %p, network, ipconfig_ipv6); + service = __connman_service_lookup_from_network(network); if (service == NULL) return -EINVAL; @@ -971,10 +973,23 @@ static int manual_ipv6_set(struct connman_network *network, return err; } - /* -* READY state will be indicated by IPV4 setting -* gateway will be set by IPV4 setting -*/ + err = __connman_ipconfig_gateway_add(ipconfig_ipv6); + if (err 0) + return err; + + __connman_connection_gateway_activate(service, + CONNMAN_IPCONFIG_TYPE_IPV6); + + __connman_device_increase_connections(network-device); + + __connman_device_set_network(network-device, network); + + connman_device_set_disconnected(network-device, FALSE); + + network-connecting = FALSE; + + __connman_service_set_ipconfig_ready(service, + CONNMAN_IPCONFIG_TYPE_IPV6); return 0; } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 07/13] connection: Separate IPv4 and IPv6 gateway and routing handling.
--- include/ipconfig.h |1 + src/connection.c | 495 +++- src/connman.h |9 +- src/ipconfig.c | 18 +- src/network.c |3 +- 5 files changed, 393 insertions(+), 133 deletions(-) diff --git a/include/ipconfig.h b/include/ipconfig.h index a0673af..8980a78 100644 --- a/include/ipconfig.h +++ b/include/ipconfig.h @@ -58,6 +58,7 @@ void connman_ipaddress_copy(struct connman_ipaddress *ipaddress, enum connman_ipconfig_type { CONNMAN_IPCONFIG_TYPE_UNKNOWN = 0, + CONNMAN_IPCONFIG_TYPE_ALL = 0, CONNMAN_IPCONFIG_TYPE_IPV4= 1, CONNMAN_IPCONFIG_TYPE_IPV6= 2, }; diff --git a/src/connection.c b/src/connection.c index 10ef04a..a402588 100644 --- a/src/connection.c +++ b/src/connection.c @@ -31,22 +31,27 @@ #include connman.h -struct gateway_data { - int index; - struct connman_service *service; - char *ipv4_gateway; - char *ipv6_gateway; - unsigned int order; +struct gateway_config { gboolean active; + char *gateway; + /* VPN extra data */ gboolean vpn; char *vpn_ip; int vpn_phy_index; }; +struct gateway_data { + int index; + struct connman_service *service; + unsigned int order; + struct gateway_config *ipv4_gateway; + struct gateway_config *ipv6_gateway; +}; + static GHashTable *gateway_hash = NULL; -static struct gateway_data *find_gateway(int index, const char *gateway) +static struct gateway_config *find_gateway(int index, const char *gateway) { GHashTableIter iter; gpointer value, key; @@ -59,46 +64,113 @@ static struct gateway_data *find_gateway(int index, const char *gateway) while (g_hash_table_iter_next(iter, key, value) == TRUE) { struct gateway_data *data = value; - if (data-ipv4_gateway == NULL) - continue; + if (data-ipv4_gateway != NULL data-index == index + g_str_equal(data-ipv4_gateway-gateway, + gateway) == TRUE) + return data-ipv4_gateway; - if (data-index == index - g_str_equal(data-ipv4_gateway, gateway) - == TRUE) - return data; + if (data-ipv6_gateway != NULL data-index == index + g_str_equal(data-ipv6_gateway-gateway, + gateway) == TRUE) + return data-ipv6_gateway; } return NULL; } -static int del_routes(struct gateway_data *data) +static int del_routes(struct gateway_data *data, + enum connman_ipconfig_type type) { - if (data-vpn) { - if (data-vpn_phy_index = 0) - connman_inet_del_host_route(data-vpn_phy_index, - data-ipv4_gateway); - return connman_inet_clear_gateway_address(data-index, - data-vpn_ip); - } else if (g_strcmp0(data-ipv4_gateway, 0.0.0.0) == 0) { - return connman_inet_clear_gateway_interface(data-index); - } else { - connman_inet_del_ipv6_host_route(data-index, - data-ipv6_gateway); - connman_inet_clear_ipv6_gateway_address(data-index, - data-ipv6_gateway); - connman_inet_del_host_route(data-index, data-ipv4_gateway); - return connman_inet_clear_gateway_address(data-index, - data-ipv4_gateway); + int status4 = 0, status6 = 0; + int do_ipv4 = FALSE, do_ipv6 = FALSE; + + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) + do_ipv4 = TRUE; + else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) + do_ipv6 = TRUE; + else + do_ipv4 = do_ipv6 = TRUE; + + if (do_ipv4 == TRUE data-ipv4_gateway != NULL) { + if (data-ipv4_gateway-vpn == TRUE) { + if (data-ipv4_gateway-vpn_phy_index = 0) + connman_inet_del_host_route( + data-ipv4_gateway-vpn_phy_index, + data-ipv4_gateway-gateway); + + status4 = connman_inet_clear_gateway_address( + data-index, + data-ipv4_gateway-vpn_ip); + + } else if (g_strcmp0(data-ipv4_gateway-gateway, + 0.0.0.0) == 0) { + status4 = connman_inet_clear_gateway_interface( +
[PATCH ipv6 gw v2 10/13] network: Clear interface addresses after removing gateway address.
The reason for this patch is that service disconnect code path is different from service change code path. In disconnect, the __connman_ipconfig_address_remove() is called which clears the addresses from interface. When changing from one service to another, the function __connman_service_disconnect() is not called and thus the interface address is not removed. We cannot call __connman_ipconfig_address_remove() yet at this point because it would clear addresses from internal data structures so we use __connman_ipconfig_address_unset() instead. --- src/network.c |3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 4abcb09..0ae77ca 100644 --- a/src/network.c +++ b/src/network.c @@ -1101,6 +1101,9 @@ static gboolean set_connected(gpointer user_data) __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); + __connman_ipconfig_address_unset(ipconfig_ipv4); + __connman_ipconfig_address_unset(ipconfig_ipv6); + __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 11/13] ipconfig: Added function to enable IPv6.
--- include/ipconfig.h |1 + src/ipconfig.c |8 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/include/ipconfig.h b/include/ipconfig.h index 8980a78..34463eb 100644 --- a/include/ipconfig.h +++ b/include/ipconfig.h @@ -99,6 +99,7 @@ void connman_ipconfig_set_ops(struct connman_ipconfig *ipconfig, int connman_ipconfig_set_method(struct connman_ipconfig *ipconfig, enum connman_ipconfig_method method); void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig); +void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig); #ifdef __cplusplus } diff --git a/src/ipconfig.c b/src/ipconfig.c index 4d74ca8..454d5d5 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1516,6 +1516,14 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) set_ipv6_state(ipdevice-ifname, TRUE); } +void __connman_ipconfig_enable_ipv6(struct connman_ipconfig *ipconfig) +{ + if (ipconfig == NULL || ipconfig-type != CONNMAN_IPCONFIG_TYPE_IPV6) + return; + + enable_ipv6(ipconfig); +} + void __connman_ipconfig_disable_ipv6(struct connman_ipconfig *ipconfig) { if (ipconfig == NULL || ipconfig-type != CONNMAN_IPCONFIG_TYPE_IPV6) -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 09/13] ipconfig: Add function to remove address from interface.
The new function removes the address from interface but does not touch internal data structures. --- src/connman.h |1 + src/ipconfig.c | 30 -- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/connman.h b/src/connman.h index da8323d..948a285 100644 --- a/src/connman.h +++ b/src/connman.h @@ -249,6 +249,7 @@ enum connman_ipconfig_method __connman_ipconfig_get_method( int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig); int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig); +int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig); int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig); void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig); unsigned char __connman_ipconfig_netmask_prefix_len(const char *netmask); diff --git a/src/ipconfig.c b/src/ipconfig.c index c8466d9..4d74ca8 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1401,6 +1401,34 @@ int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig) case CONNMAN_IPCONFIG_METHOD_FIXED: case CONNMAN_IPCONFIG_METHOD_DHCP: case CONNMAN_IPCONFIG_METHOD_MANUAL: + err = __connman_ipconfig_address_unset(ipconfig); + connman_ipaddress_clear(ipconfig-address); + + return err; + } + + return 0; +} + +int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig) +{ + int err; + + DBG(); + + if (ipconfig == NULL) + return 0; + + DBG(method %d, ipconfig-method); + + switch (ipconfig-method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_AUTO: + break; + case CONNMAN_IPCONFIG_METHOD_FIXED: + case CONNMAN_IPCONFIG_METHOD_DHCP: + case CONNMAN_IPCONFIG_METHOD_MANUAL: if (ipconfig-type == CONNMAN_IPCONFIG_TYPE_IPV4) err = connman_inet_clear_address(ipconfig-index, ipconfig-address); @@ -1412,8 +1440,6 @@ int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig) else err = -EINVAL; - connman_ipaddress_clear(ipconfig-address); - return err; } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 12/13] network: Clear IPv6 autoconfigured routes when disconnected.
--- src/network.c | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/src/network.c b/src/network.c index 0ae77ca..ac7bd07 100644 --- a/src/network.c +++ b/src/network.c @@ -1104,6 +1104,17 @@ static gboolean set_connected(gpointer user_data) __connman_ipconfig_address_unset(ipconfig_ipv4); __connman_ipconfig_address_unset(ipconfig_ipv6); + /* +* Special handling for IPv6 autoconfigured address. +* The simplest way to remove autoconfigured routes is to +* disable IPv6 temporarily so that kernel will do the cleanup +* automagically. +*/ + if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) { + __connman_ipconfig_disable_ipv6(ipconfig_ipv6); + __connman_ipconfig_enable_ipv6(ipconfig_ipv6); + } + __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE, CONNMAN_IPCONFIG_TYPE_IPV4); -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH ipv6 gw v2 13/13] TODO: IPv6 gateway handling done.
--- TODO | 10 -- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/TODO b/TODO index e376522..36f8240 100644 --- a/TODO +++ b/TODO @@ -57,16 +57,6 @@ Core not all driver (especially WiFi ones) implement runtime PM hooks. -- IPv6 gateway handling - - Priority: Medium - Complexity: C4 - - We should be able to switch between IPv6 only services and thus - change the default IPv6 gateway on the fly. For that we need to - improve the connection.c code to properly handle IPv6 gateways. - - - IP ranges allocation and check Priority: High -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH dns cache 0/3] Implement DNS caching
Hi, this patchset implements a simple DNS A and record caching based on their TTL. The caching is implemented inside dnsproxy. Following limits are implemented in the cache: - max number of cached entries is currently 256 (in order to not use too much memory, each cache entry is about 100 bytes long) - max cache ttl is set to 30min so the cache entry can stay in the cache only maximum 30 minutes (in order not to flood the cache with long ttl entries) Regards, Jukka TODO: DNS caching dnsproxy: Implement A and DNS record caching. dnsproxy: Fix indentation. TODO |9 -- src/dnsproxy.c | 418 ++-- 2 files changed, 407 insertions(+), 20 deletions(-) ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH dns cache 1/3] TODO: DNS caching
--- TODO |9 - 1 files changed, 0 insertions(+), 9 deletions(-) diff --git a/TODO b/TODO index 36f8240..22078c8 100644 --- a/TODO +++ b/TODO @@ -36,15 +36,6 @@ Core credentials, ConnMan should be able to initiate a WiSPR authentication. -- DNS caching - - Priority: Low - Complexity: C4 - - A simple initial implementation would see ConnMan's dnsproxy - caching the DNS record based on their TTL. - - - Power management Priority: Medium -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH dns cache 3/3] dnsproxy: Fix indentation.
--- src/dnsproxy.c |6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dnsproxy.c b/src/dnsproxy.c index a9bab01..1bf5328 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -306,7 +306,7 @@ static gboolean request_timeout(gpointer user_data) hdr = (void *) (req-request + 2); hdr-id = req-srcid; send_response(req-client_sk, req-request, - req-request_len, NULL, 0, IPPROTO_TCP); + req-request_len, NULL, 0, IPPROTO_TCP); } else if (req-protocol == IPPROTO_UDP) { int sk; @@ -929,7 +929,7 @@ hangup: hdr = (void *) (req-request + 2); hdr-id = req-srcid; send_response(req-client_sk, req-request, - req-request_len, NULL, 0, IPPROTO_TCP); + req-request_len, NULL, 0, IPPROTO_TCP); request_list = g_slist_remove(request_list, req); } @@ -1655,7 +1655,7 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition, err = parse_request(buf, len, query, sizeof(query)); if (err 0 || (g_slist_length(server_list) == 0)) { send_response(sk, buf, len, (void *)client_addr, - client_addr_len, IPPROTO_UDP); + client_addr_len, IPPROTO_UDP); return TRUE; } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH dns cache 2/3] dnsproxy: Implement A and AAAA DNS record caching.
--- src/dnsproxy.c | 412 ++- 1 files changed, 404 insertions(+), 8 deletions(-) diff --git a/src/dnsproxy.c b/src/dnsproxy.c index d03b734..a9bab01 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -90,6 +90,7 @@ struct server_data { gboolean enabled; gboolean connected; struct partial_reply *incoming_reply; + GHashTable *cache; }; struct request_data { @@ -123,6 +124,33 @@ struct listener_data { guint tcp_listener_watch; }; +struct cache_entry { + GHashTable *cache; + unsigned char *key; + int type; + int timeout; + int answers; + unsigned int data_len; + unsigned char *data; /* contains dns header + body */ +}; + +/* + * We limit the cache size to some sane value so that cached data does + * not occupy too much memory. Each cached entry occupies on average + * about 100 bytes memory (depending on dns name length). + * Example: caching www.connman.net uses 93 bytes memory. + * The value is the max amount of cached dns responses (count). + */ +#define MAX_CACHE_SIZE 256 +static int cache_size; + +/* + * We limit how long the cached dns entry stays in the cache. + * By default the TTL (time-to-live) of the dns response is used + * when setting the cache entry life time. The value is in seconds. + */ +#define MAX_CACHE_TTL (60 * 30) + static GSList *server_list = NULL; static GSList *request_list = NULL; static GSList *request_pending_list = NULL; @@ -187,6 +215,34 @@ static struct server_data *find_server(const char *interface, return NULL; } +static void send_cached_response(int sk, unsigned char *buf, int len, + const struct sockaddr *to, socklen_t tolen, + int protocol, int id, int answers) +{ + struct domain_hdr *hdr; + int err, offset = protocol_offset(protocol); + + if (offset 0) + return; + + if (len 12) + return; + + hdr = (void *) (buf + offset); + + hdr-id = id; + hdr-qr = 1; + hdr-rcode = 0; + hdr-ancount = htons(answers); + hdr-nscount = 0; + hdr-arcount = 0; + + DBG(id 0x%04x answers %d, hdr-id, answers); + + err = sendto(sk, buf, len, 0, to, tolen); + if (err 0) + return; +} static void send_response(int sk, unsigned char *buf, int len, const struct sockaddr *to, socklen_t tolen, @@ -325,12 +381,301 @@ static int append_query(unsigned char *buf, unsigned int size, return ptr - buf; } +static struct cache_entry *cache_check(struct server_data *server, + gpointer request) +{ + uint16_t type; + unsigned int offset = 0; + unsigned char *dns_body = (unsigned char *)request + 12; + unsigned char *question = dns_body[offset]; + struct cache_entry *entry; + + offset = strlen((char *)question) + 1; + type = ntohs(*(uint16_t *)(dns_body[offset])); + + /* ATM we only cache either A (1) or (28) requests */ + if (type != 1 type != 28) + return NULL; + + entry = g_hash_table_lookup(server-cache, question); + if (entry == NULL || entry-type != type) + return NULL; + + return entry; +} + +static gboolean cache_entry_timeout(gpointer user_data) +{ + struct cache_entry *entry = user_data; + + DBG(cache %d key \%s\, cache_size - 1, entry-key); + + g_hash_table_remove(entry-cache, entry-key); + return FALSE; +} + +static int get_name(int counter, unsigned char *pkt, unsigned char *start, + unsigned char *max, unsigned char *name, int max_name, + int *name_len, unsigned char **end) +{ + unsigned char *p; + + /* Limit recursion to 10 (this means up to 10 labels in domain name) */ + if (counter 10) + return -EINVAL; + + p = start; + while (*p) { + if (*p 0xc0) { + uint16_t offset = (*p 0x3F) * 256 + *(p + 1); + + if (offset = max - pkt) + return -ENOBUFS; + + if (*end == NULL) + *end = p + 2; + + return get_name(counter+1, pkt, pkt + offset, max, + name, max_name, name_len, end); + } else { + unsigned label_len = *p; + + if (pkt+label_len max) + return -ENOBUFS; + + if (*name_len max_name) + return -ENOBUFS; + + /* We compress the result and use pointers */ + name[0] = 0xC0; + name[1] = 0x0C; + *name_len = 2; + + p += label_len + 1; + +
Re: [PATCH dns cache v2 3/3] dnsproxy: Implement A and AAAA DNS record caching.
Hi Marcel, On 07/07/2011 08:52 AM, Marcel Holtmann wrote: Hi Jukka, diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 9701343..246a6a2 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -123,6 +123,52 @@ struct listener_data { guint tcp_listener_watch; }; +struct cache_data { + int type; + int timeout; + int answers; is a signed integer really a good idea here. Might uint16_t or uint32_t not be better here? Ok, I will change to unsigned although it should not make much difference. + unsigned int data_len; + unsigned char *data; /* contains dns header + body */ Nitpick here, but upper case DNS please (and in all other comments as well). Sure, I changed all occurances of dns to upper case, plus fixed all the other nitpicks. +}; + +struct cache_entry { + unsigned char *key; + + /* The same cache entry can have both IPv4 and IPv6 addresses */ + struct cache_data *A; + struct cache_data *; In general I prefer not to have upper case variable names. So maybe just calling these ipv4 and ipv6 might be a bit more clear than just a generic name a and some cryptic . Ok. + + *qtype = type; If you are sure that qtype is always provided (since the function is internal), then it is fine. Otherwise check for qtype != NULL. qtype is always provided so I did not change this. + /* +* Note that the name var below and the question and response variables +* in cache_update() should have the same length so we use a define +* here. +*/ +#define MAX_NAME_LEN 255 + char name[MAX_NAME_LEN + 1]; Don't we have some sort of constant in resolv.h for that provided by Glibc? Yes, there was some constants in arpa/nameser.h, I start to use them. + if (new_entry == TRUE) { + data-timeout = g_timeout_add_seconds(ttl, + cache_entry_timeout, + entry); We could do it like this, but generally I do not like this way of dealing with the timeout. I rather prefer to have some garbage collection style handling of expired values. Reason here is that we unnecessarily wake up ConnMan to clean a value in a cache that has no relevance to us at that point of time. Next time a DNS request comes in for that specific record we can clean it. Or if the cache size is too big, we purge the oldest ones. That said, we do not have to fix this right now. I will apply a patch with this timeout in it, but your next step then needs to be to get this fixed. I changed the timeout handling anyway, it was not a big issue. The new version clears the cache only if it is full or if cache entry has expired when checking if entry is in cache. I might need another read-through the patch in details since it changes a lot of code. If you can break it down into smaller pieces that would help. Not sure if that is possible. The patch is not easy to break to smaller pieces so if possible please try to review it as is. I am quite confident that caching works ok, I have been using valgrind when testing it and there should be no invalid access or memory leaks in this patch. But all in all it looks pretty good. Regards Marcel Thanks, Jukka ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH dns cache v3 0/2] Implement DNS caching
Hi, this is the 3rd version of the patch and fixes following issues - Timeout handling is not using glib timeouts but just purges the cache if it is full and removes old entries. Also when adding entry to cache, old and expired entry is removed and new value is cached. - Using various name server constants (NS_) from resolv.h Regards, Jukka Jukka Rissanen (2): dnsproxy: Implement A and DNS record caching. TODO: DNS caching TODO |9 - src/dnsproxy.c | 708 +++- 2 files changed, 699 insertions(+), 18 deletions(-) ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH dns cache v3 1/2] dnsproxy: Implement A and AAAA DNS record caching.
--- src/dnsproxy.c | 708 +++- 1 files changed, 699 insertions(+), 9 deletions(-) diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 9701343..37e6b1e 100644 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -32,6 +32,7 @@ #include sys/types.h #include sys/socket.h #include netdb.h +#include resolv.h #include glib.h @@ -123,6 +124,51 @@ struct listener_data { guint tcp_listener_watch; }; +struct cache_data { + time_t inserted; + int timeout; + uint16_t type; + uint16_t answers; + unsigned int data_len; + unsigned char *data; /* contains DNS header + body */ +}; + +struct cache_entry { + unsigned char *key; + struct cache_data *ipv4; + struct cache_data *ipv6; +}; + +struct domain_question { + uint16_t type; + uint16_t class; +} __attribute__ ((packed)); + +struct domain_rr { + uint16_t type; + uint16_t class; + uint32_t ttl; + uint16_t rdlen; +} __attribute__ ((packed)); + +/* + * We limit how long the cached DNS entry stays in the cache. + * By default the TTL (time-to-live) of the DNS response is used + * when setting the cache entry life time. The value is in seconds. + */ +#define MAX_CACHE_TTL (60 * 30) + +/* + * We limit the cache size to some sane value so that cached data does + * not occupy too much memory. Each cached entry occupies on average + * about 100 bytes memory (depending on DNS name length). + * Example: caching www.connman.net uses 97 bytes memory. + * The value is the max amount of cached DNS responses (count). + */ +#define MAX_CACHE_SIZE 256 + +static int cache_size; +static GHashTable *cache; static GSList *server_list = NULL; static GSList *request_list = NULL; static GSList *request_pending_list = NULL; @@ -187,6 +233,34 @@ static struct server_data *find_server(const char *interface, return NULL; } +static void send_cached_response(int sk, unsigned char *buf, int len, + const struct sockaddr *to, socklen_t tolen, + int protocol, int id, uint16_t answers) +{ + struct domain_hdr *hdr; + int err, offset = protocol_offset(protocol); + + if (offset 0) + return; + + if (len 12) + return; + + hdr = (void *) (buf + offset); + + hdr-id = id; + hdr-qr = 1; + hdr-rcode = 0; + hdr-ancount = htons(answers); + hdr-nscount = 0; + hdr-arcount = 0; + + DBG(id 0x%04x answers %d, hdr-id, answers); + + err = sendto(sk, buf, len, 0, to, tolen); + if (err 0) + return; +} static void send_response(int sk, unsigned char *buf, int len, const struct sockaddr *to, socklen_t tolen, @@ -325,12 +399,570 @@ static int append_query(unsigned char *buf, unsigned int size, return ptr - buf; } +static struct cache_entry *cache_check(gpointer request, int *qtype) +{ + unsigned char *question = (unsigned char *)request + 12; + struct cache_entry *entry; + struct domain_question *q; + time_t current_time; + uint16_t type; + int offset; + + offset = strlen((char *)question) + 1; + q = (void *) (question + offset); + type = ntohs(q-type); + + /* we only cache either A (1) or (28) requests */ + if (type != 1 type != 28) + return NULL; + + entry = g_hash_table_lookup(cache, question); + if (entry == NULL) + return NULL; + + if (type == 1 entry-ipv4 == NULL) + return NULL; + + if (type == 28 entry-ipv6 == NULL) + return NULL; + + current_time = time(0); + + if (type == 1 (entry-ipv4-inserted + entry-ipv4-timeout +current_time)) { + DBG(cache timeout \%s\ type A, question); + + /* +* We do not remove cache entry if there is still valid IPv6 +* entry found in the cache. +*/ + if (entry-ipv6 == NULL || + (entry-ipv6-inserted + + entry-ipv6-timeout current_time)) + g_hash_table_remove(cache, question); + + return NULL; + } + + if (type == 28 (entry-ipv6-inserted + entry-ipv6-timeout +current_time)) { + DBG(cache timeout \%s\ type , question); + if (entry-ipv4 == NULL || + (entry-ipv4-inserted + + entry-ipv4-timeout current_time)) + g_hash_table_remove(cache, question); + + return NULL; + } + + *qtype = type; + return entry; +} + +static int get_name(int counter, + unsigned char
[PATCH dns cache v3 2/2] TODO: DNS caching
--- TODO |9 - 1 files changed, 0 insertions(+), 9 deletions(-) diff --git a/TODO b/TODO index 36f8240..22078c8 100644 --- a/TODO +++ b/TODO @@ -36,15 +36,6 @@ Core credentials, ConnMan should be able to initiate a WiSPR authentication. -- DNS caching - - Priority: Low - Complexity: C4 - - A simple initial implementation would see ConnMan's dnsproxy - caching the DNS record based on their TTL. - - - Power management Priority: Medium -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH pre-l2tp/pptp 01/11] provider: NULL pointer check.
--- src/provider.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/src/provider.c b/src/provider.c index 9ae62cd..f3b10a0 100644 --- a/src/provider.c +++ b/src/provider.c @@ -879,7 +879,10 @@ int connman_provider_append_route(struct connman_provider *provider, const char *connman_provider_get_driver_name(struct connman_provider *provider) { - return provider-driver-name; + if (provider-driver != NULL) + return provider-driver-name; + + return NULL; } static gint compare_priority(gconstpointer a, gconstpointer b) -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH pre-l2tp/pptp 06/11] service: Fix function name as it is static.
--- src/service.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service.c b/src/service.c index c11ae44..dbd0c83 100644 --- a/src/service.c +++ b/src/service.c @@ -3428,7 +3428,7 @@ static void report_error_cb(struct connman_service *service, } } -static int __connman_service_indicate_state(struct connman_service *service) +static int service_indicate_state(struct connman_service *service) { enum connman_service_state old_state, new_state; GSequenceIter *iter; @@ -3733,7 +3733,7 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) service-state_ipv6 = new_state; - return __connman_service_indicate_state(service); + return service_indicate_state(service); } int __connman_service_request_login(struct connman_service *service) -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH pre-l2tp/pptp 05/11] service: Set the user connect status correctly for VPN.
If the userconnect is not set, then informatation about authentication errors cannot be reported by agent API. --- src/service.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/src/service.c b/src/service.c index b2670aa..c11ae44 100644 --- a/src/service.c +++ b/src/service.c @@ -4987,6 +4987,7 @@ __connman_service_create_from_provider(struct connman_provider *provider) service-type = CONNMAN_SERVICE_TYPE_VPN; service-provider = connman_provider_ref(provider); service-autoconnect = FALSE; + service-userconnect = TRUE; service-state_ipv4 = service-state_ipv6 = CONNMAN_SERVICE_STATE_IDLE; -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH pre-l2tp/pptp 08/11] service: Change the ipconfig state only when needed.
We should not try to change the state if the corresponding ipconfig is set to be OFF. What this means that we change the state and combine ipv4 and ipv6 states only if both are active. This patch is needed by provider and the VPN authentication failure case. --- src/service.c | 20 +++- 1 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/service.c b/src/service.c index 133e5cf..27ad068 100644 --- a/src/service.c +++ b/src/service.c @@ -3727,11 +3727,21 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, break; } - /* We keep that state */ - if (type == CONNMAN_IPCONFIG_TYPE_IPV4) - service-state_ipv4 = new_state; - else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) - service-state_ipv6 = new_state; + /* We keep that state but only if the method is not OFF */ + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { + enum connman_ipconfig_method method; + method = __connman_ipconfig_get_method(service-ipconfig_ipv4); + if (method != CONNMAN_IPCONFIG_METHOD_OFF + method != CONNMAN_IPCONFIG_METHOD_UNKNOWN) + service-state_ipv4 = new_state; + + } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { + enum connman_ipconfig_method method; + method = __connman_ipconfig_get_method(service-ipconfig_ipv6); + if (method != CONNMAN_IPCONFIG_METHOD_OFF + method != CONNMAN_IPCONFIG_METHOD_UNKNOWN) + service-state_ipv6 = new_state; + } return service_indicate_state(service); } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH pre-l2tp/pptp 10/11] provider: Return existing service path if already connected.
--- src/provider.c |9 + 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/provider.c b/src/provider.c index f0ede5e..90f145d 100644 --- a/src/provider.c +++ b/src/provider.c @@ -571,11 +571,12 @@ int __connman_provider_create_and_connect(DBusMessage *msg) err = -EOPNOTSUPP; goto unref; } - } - err = __connman_service_connect(provider-vpn_service); - if (err 0 err != -EINPROGRESS) - goto failed; + err = __connman_service_connect(provider-vpn_service); + if (err 0 err != -EINPROGRESS) + goto failed; + } else + DBG(provider already connected); service_path = __connman_service_get_path(provider-vpn_service); g_dbus_send_reply(connection, msg, -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH pre-l2tp/pptp 11/11] connection: Service was not ref counted properly.
The reference counting problems were clearly seen with VPN service. --- src/connection.c |6 -- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/connection.c b/src/connection.c index 4f3b3f8..38269d6 100644 --- a/src/connection.c +++ b/src/connection.c @@ -227,6 +227,7 @@ static struct gateway_data *add_gateway(struct connman_service *service, } } + connman_service_ref(service); g_hash_table_replace(gateway_hash, service, data); return data; @@ -614,9 +615,10 @@ void __connman_connection_gateway_remove(struct connman_service *service, do_ipv4 == TRUE) || (data-ipv6_gateway != NULL data-ipv4_gateway == NULL do_ipv6 == TRUE) - ) + ) { + connman_service_unref(service); g_hash_table_remove(gateway_hash, service); - else + } else DBG(Not yet removing gw ipv4 %p/%d ipv6 %p/%d, data-ipv4_gateway, do_ipv4, data-ipv6_gateway, do_ipv6); -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH l2tp/pptp 00/21] L2TP/PPTP support
Hi, here are the L2TP/PPTP patches. Patches 01, 03, 04, 05, 06 and 07 were sent by Mohamed Abbas of Intel in February 2011 but they were never integrated to connman. I modified the original patches and they now contain fixes to suggestions that Daniel Wagner did back in February. There are also some fixes needed so that the code would work with current head. The rest of the patches add authentication failure support and fix various bugs. Both the l2tp and pptp have been tested with real network and they seem to work ok. 01 - ppp tunneling support added 02 - Added various null checks in order to avoid crashes in following patches 03 - Catch dbus request and send back data to ppp plugin 04 - pptp support 05 - ppp plugin 06 - l2tp support 07 - l2tp/pptp test script support 08 - l2tp in Makefile/configure file 09 - pptp in Makefile/configure file 10 - compile libppp-plugin properly 11 - Set the ip address of the l2tp VPN link. The established VPN connection will be closed after two minutes without this patch. 12 - ppp plugin will catch authentication error and report it to connman 13 - xl2tpd does not return any useful information in its exit code so check the auth error in dbus notify function 14 - pptp auth error check is needed in dbus notify function 15 - Same as patch #11 but for the pptp driver 16 - Remove password from options list so that its value is not used when starting the pppd (because it would then be shown in ps list) Password will be passed via libppp-plugin instead of cmd line. 17 - Added information what l2tp/pptp packages are needed 18 - Memory leak fix in vpn.c 19 - Memory leak fix in provider.c 20 - Make sure the task gets killed by sending SIGTERM. If that does not work try SIGINT and finally kill the process by SIGKILL. This is needed because xl2tpd seems to hang really easily even if it catches SIGTERM. Without this patch xl2tpd seems to hang when L2TP VPN is disconnected and subsequent L2TP sessions will not work. When xl2tpd is killed, the pppd daemon will also kill itself so there are no processes left around. 21 - Mark l2tp and pptp support as done. Regards, Jukka Jukka Rissanen (15): vpn: Add null checks. l2tp: Add l2tp makefile and configure file. pptp: Add pptp makefile and configure file. scripts: Compile libppp-plugin.so properly. l2tp: Set the provider IP address when connected. scripts: Report authentication error to connman. l2tp: Check authentication error properly. pptp: Return authentication errors properly. pptp: Set the provider IP address when connected. pptp: Do not put password in command line options. readme: Add l2tp and pptp information. vpn: Fix memory leak. provider: Fix memory leak. task: Make sure the process is eventually killed. todo: Mark l2tp and pptp as done. Mohamed Abbas (6): vpn: Add support to allow ppp tunnelling. task: Allow vpn plugins to send reply. pptp: Add pptp vpn support pptp: Add ppp plugin library. l2tp: Add l2tp vpn support. test: Add test script support for pptp/l2tp. Makefile.plugins| 51 + README | 15 ++ TODO| 14 -- configure.ac| 34 include/task.h |2 +- plugins/l2tp.c | 501 +++ plugins/pptp.c | 311 + plugins/vpn.c | 146 +++ plugins/vpn.h |4 + scripts/libppp-plugin.c | 318 ++ src/provider.c |1 + src/task.c | 74 ++-- test/connect-vpn| 18 ++ 13 files changed, 1424 insertions(+), 65 deletions(-) create mode 100644 plugins/l2tp.c create mode 100644 plugins/pptp.c create mode 100644 scripts/libppp-plugin.c ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH l2tp/pptp 02/21] vpn: Add null checks.
--- plugins/vpn.c | 18 -- 1 files changed, 16 insertions(+), 2 deletions(-) diff --git a/plugins/vpn.c b/plugins/vpn.c index 506a71c..a1759c9 100644 --- a/plugins/vpn.c +++ b/plugins/vpn.c @@ -77,6 +77,9 @@ static int stop_vpn(struct connman_provider *provider) return -1; name = connman_provider_get_driver_name(provider); + if (name == NULL) + return -EINVAL; + vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data != NULL vpn_driver_data-vpn_driver != NULL @@ -136,10 +139,12 @@ void vpn_died(struct connman_task *task, int exit_code, void *user_data) vpn_exit: if (state != VPN_STATE_READY state != VPN_STATE_DISCONNECT) { const char *name; - struct vpn_driver_data *vpn_data; + struct vpn_driver_data *vpn_data = NULL; name = connman_provider_get_driver_name(provider); - vpn_data = g_hash_table_lookup(driver_hash, name); + if (name != NULL) + vpn_data = g_hash_table_lookup(driver_hash, name); + if (vpn_data != NULL vpn_data-vpn_driver-error_code != NULL) ret = vpn_data-vpn_driver-error_code(exit_code); @@ -203,6 +208,9 @@ static void vpn_notify(struct connman_task *task, data = connman_provider_get_data(provider); name = connman_provider_get_driver_name(provider); + if (name == NULL) + return; + vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data == NULL) return; @@ -325,6 +333,9 @@ static int vpn_connect(struct connman_provider *provider) connman_provider_set_data(provider, data); name = connman_provider_get_driver_name(provider); + if (name == NULL) + return -EINVAL; + vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data != NULL vpn_driver_data-vpn_driver != NULL @@ -394,6 +405,9 @@ static int vpn_disconnect(struct connman_provider *provider) return 0; name = connman_provider_get_driver_name(provider); + if (name == NULL) + return 0; + vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data-vpn_driver-disconnect) vpn_driver_data-vpn_driver-disconnect(); -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman
[PATCH l2tp/pptp 03/21] task: Allow vpn plugins to send reply.
From: Mohamed Abbas mab...@linux.intel.com Change task notify to allow client to send dbus reply. This will allow vpn plugin to send requested user/password info. --- include/task.h |2 +- plugins/vpn.c |8 +--- src/task.c | 30 +- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/task.h b/include/task.h index bde2a29..d93df2d 100644 --- a/include/task.h +++ b/include/task.h @@ -39,7 +39,7 @@ struct connman_task; typedef void (* connman_task_exit_t) (struct connman_task *task, int exit_code, void *user_data); -typedef void (* connman_task_notify_t) (struct connman_task *task, +typedef DBusMessage * (* connman_task_notify_t) (struct connman_task *task, DBusMessage *message, void *user_data); struct connman_task *connman_task_create(const char *program); diff --git a/plugins/vpn.c b/plugins/vpn.c index a1759c9..ee85dd7 100644 --- a/plugins/vpn.c +++ b/plugins/vpn.c @@ -196,7 +196,7 @@ static void vpn_newlink(unsigned flags, unsigned change, void *user_data) data-flags = flags; } -static void vpn_notify(struct connman_task *task, +static DBusMessage *vpn_notify(struct connman_task *task, DBusMessage *msg, void *user_data) { struct connman_provider *provider = user_data; @@ -209,11 +209,11 @@ static void vpn_notify(struct connman_task *task, name = connman_provider_get_driver_name(provider); if (name == NULL) - return; + return NULL; vpn_driver_data = g_hash_table_lookup(driver_hash, name); if (vpn_driver_data == NULL) - return; + return NULL; state = vpn_driver_data-vpn_driver-notify(msg, provider); switch (state) { @@ -238,6 +238,8 @@ static void vpn_notify(struct connman_task *task, CONNMAN_PROVIDER_ERROR_AUTH_FAILED); break; } + + return NULL; } static int vpn_create_tun(struct connman_provider *provider) diff --git a/src/task.c b/src/task.c index b5b9ef7..51b4898 100644 --- a/src/task.c +++ b/src/task.c @@ -366,6 +366,7 @@ static DBusHandlerResult task_filter(DBusConnection *connection, struct connman_task *task; struct notify_data *notify; const char *path, *member; + DBusMessage *reply = NULL; if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -382,29 +383,32 @@ static DBusHandlerResult task_filter(DBusConnection *connection, if (task == NULL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - if (dbus_message_get_no_reply(message) == FALSE) { - DBusMessage *reply; + member = dbus_message_get_member(message); + if (member == NULL) + goto send_reply; + + notify = g_hash_table_lookup(task-notify, member); + if (notify == NULL) + goto send_reply; + + if (notify-func) + reply = notify-func(task, message, notify-data); + +send_reply: + if (dbus_message_get_no_reply(message) == FALSE + reply == NULL) { reply = dbus_message_new_method_return(message); if (reply == NULL) return DBUS_HANDLER_RESULT_NEED_MEMORY; + } + if (reply != NULL) { dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); } - member = dbus_message_get_member(message); - if (member == NULL) - return DBUS_HANDLER_RESULT_HANDLED; - - notify = g_hash_table_lookup(task-notify, member); - if (notify == NULL) - return DBUS_HANDLER_RESULT_HANDLED; - - if (notify-func) - notify-func(task, message, notify-data); - return DBUS_HANDLER_RESULT_HANDLED; } -- 1.7.1 ___ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman