Add support for setting proxy configuration method
[platform/upstream/connman.git] / src / ipconfig.c
index e3bff4c..0a7eb8b 100644 (file)
@@ -71,7 +71,11 @@ struct connman_ipdevice {
        uint32_t tx_dropped;
 
        GSList *address_list;
-       char *gateway;
+       char *ipv4_gateway;
+       char *ipv6_gateway;
+
+       char *proxy;
+       char *pac;
 
        struct connman_ipconfig *config;
 
@@ -82,7 +86,7 @@ struct connman_ipdevice {
 static GHashTable *ipdevice_hash = NULL;
 static GList *ipconfig_list = NULL;
 
-struct connman_ipaddress *connman_ipaddress_alloc(void)
+struct connman_ipaddress *connman_ipaddress_alloc(int family)
 {
        struct connman_ipaddress *ipaddress;
 
@@ -90,6 +94,7 @@ struct connman_ipaddress *connman_ipaddress_alloc(void)
        if (ipaddress == NULL)
                return NULL;
 
+       ipaddress->family = family;
        ipaddress->prefixlen = 0;
        ipaddress->local = NULL;
        ipaddress->peer = NULL;
@@ -210,6 +215,7 @@ void connman_ipaddress_copy(struct connman_ipaddress *ipaddress,
        if (ipaddress == NULL || source == NULL)
                return;
 
+       ipaddress->family = source->family;
        ipaddress->prefixlen = source->prefixlen;
 
        g_free(ipaddress->local);
@@ -297,7 +303,10 @@ static void free_ipdevice(gpointer data)
                connman_ipconfig_unref(ipdevice->config);
 
        free_address_list(ipdevice);
-       g_free(ipdevice->gateway);
+       g_free(ipdevice->ipv4_gateway);
+       g_free(ipdevice->ipv6_gateway);
+       g_free(ipdevice->proxy);
+       g_free(ipdevice->pac);
 
        g_free(ipdevice->address);
        g_free(ipdevice->ifname);
@@ -432,7 +441,7 @@ static void update_stats(struct connman_ipdevice *ipdevice,
        ipdevice->rx_dropped = stats->rx_dropped;
        ipdevice->tx_dropped = stats->tx_dropped;
 
-       __connman_counter_notify(ipdevice->config,
+       __connman_service_notify(ipdevice->config,
                                ipdevice->rx_packets, ipdevice->tx_packets,
                                ipdevice->rx_bytes, ipdevice->tx_bytes,
                                ipdevice->rx_errors, ipdevice->tx_errors,
@@ -596,7 +605,7 @@ void __connman_ipconfig_newaddr(int index, int family, const char *label,
        if (ipdevice == NULL)
                return;
 
-       ipaddress = connman_ipaddress_alloc();
+       ipaddress = connman_ipaddress_alloc(family);
        if (ipaddress == NULL)
                return;
 
@@ -685,7 +694,7 @@ void __connman_ipconfig_deladdr(int index, int family, const char *label,
        }
 }
 
-void __connman_ipconfig_newroute(int index, unsigned char scope,
+void __connman_ipconfig_newroute(int index, int family, unsigned char scope,
                                        const char *dst, const char *gateway)
 {
        struct connman_ipdevice *ipdevice;
@@ -699,8 +708,13 @@ void __connman_ipconfig_newroute(int index, unsigned char scope,
        if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
                GSList *list;
 
-               g_free(ipdevice->gateway);
-               ipdevice->gateway = g_strdup(gateway);
+               if (family == AF_INET6) {
+                       g_free(ipdevice->ipv6_gateway);
+                       ipdevice->ipv6_gateway = g_strdup(gateway);
+               } else {
+                       g_free(ipdevice->ipv4_gateway);
+                       ipdevice->ipv4_gateway = g_strdup(gateway);
+               }
 
                if (ipdevice->config != NULL &&
                                        ipdevice->config->system != NULL) {
@@ -721,7 +735,7 @@ void __connman_ipconfig_newroute(int index, unsigned char scope,
                                                scope, scope2str(scope));
 }
 
-void __connman_ipconfig_delroute(int index, unsigned char scope,
+void __connman_ipconfig_delroute(int index, int family, unsigned char scope,
                                        const char *dst, const char *gateway)
 {
        struct connman_ipdevice *ipdevice;
@@ -735,8 +749,13 @@ void __connman_ipconfig_delroute(int index, unsigned char scope,
        if (scope == 0 && g_strcmp0(dst, "0.0.0.0") == 0) {
                GSList *list;
 
-               g_free(ipdevice->gateway);
-               ipdevice->gateway = NULL;
+               if (family == AF_INET6) {
+                       g_free(ipdevice->ipv6_gateway);
+                       ipdevice->ipv6_gateway = NULL;
+               } else {
+                       g_free(ipdevice->ipv4_gateway);
+                       ipdevice->ipv4_gateway = NULL;
+               }
 
                if (ipdevice->config != NULL &&
                                        ipdevice->config->system != NULL) {
@@ -805,8 +824,8 @@ const char *__connman_ipconfig_get_gateway(int index)
        if (ipdevice == NULL)
                return NULL;
 
-       if (ipdevice->gateway != NULL)
-               return ipdevice->gateway;
+       if (ipdevice->ipv4_gateway != NULL)
+               return ipdevice->ipv4_gateway;
 
        if (ipdevice->config != NULL &&
                        ipdevice->config->address != NULL)
@@ -835,14 +854,15 @@ static struct connman_ipconfig *create_ipv6config(int index)
 
        ipv6config->index = index;
        ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
+       ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF;
 
-       ipv6config->address = connman_ipaddress_alloc();
+       ipv6config->address = connman_ipaddress_alloc(AF_INET6);
        if (ipv6config->address == NULL) {
                g_free(ipv6config);
                return NULL;
        }
 
-       ipv6config->system = connman_ipaddress_alloc();
+       ipv6config->system = connman_ipaddress_alloc(AF_INET6);
 
        ipv6config->ipv6 = NULL;
 
@@ -873,13 +893,13 @@ struct connman_ipconfig *connman_ipconfig_create(int index)
        ipconfig->index = index;
        ipconfig->type = CONNMAN_IPCONFIG_TYPE_IPV4;
 
-       ipconfig->address = connman_ipaddress_alloc();
+       ipconfig->address = connman_ipaddress_alloc(AF_INET);
        if (ipconfig->address == NULL) {
                g_free(ipconfig);
                return NULL;
        }
 
-       ipconfig->system = connman_ipaddress_alloc();
+       ipconfig->system = connman_ipaddress_alloc(AF_INET);
 
        ipconfig->ipv6 = create_ipv6config(index);
 
@@ -1172,6 +1192,44 @@ int __connman_ipconfig_clear_address(struct connman_ipconfig *ipconfig)
        return 0;
 }
 
+int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig,
+                                                        const char *url)
+{
+       struct connman_ipdevice *ipdevice;
+
+       DBG("ipconfig %p", ipconfig);
+
+       if (ipconfig == NULL || ipconfig->index < 0)
+               return -ENODEV;
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash,
+                                       GINT_TO_POINTER(ipconfig->index));
+       if (ipdevice == NULL)
+               return -ENXIO;
+
+       g_free(ipdevice->pac);
+       ipdevice->pac = g_strdup(url);
+
+       return 0;
+}
+
+const char *__connman_ipconfig_get_proxy_autoconfig(struct connman_ipconfig *ipconfig)
+{
+       struct connman_ipdevice *ipdevice;
+
+       DBG("ipconfig %p", ipconfig);
+
+       if (ipconfig == NULL || ipconfig->index < 0)
+               return NULL;
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash,
+                                       GINT_TO_POINTER(ipconfig->index));
+       if (ipdevice == NULL)
+               return NULL;
+
+       return ipdevice->pac;
+}
+
 int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
 {
        struct connman_ipdevice *ipdevice;
@@ -1548,12 +1606,109 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
 void __connman_ipconfig_append_proxy(struct connman_ipconfig *ipconfig,
                                                        DBusMessageIter *iter)
 {
+       struct connman_ipdevice *ipdevice;
        const char *method = "direct";
 
+       ipdevice = g_hash_table_lookup(ipdevice_hash,
+                                        GINT_TO_POINTER(ipconfig->index));
+       if (ipdevice == NULL)
+               goto done;
+
+       if (ipdevice->pac == NULL)
+               goto done;
+
+       method = "auto-config";
+
+       connman_dbus_dict_append_basic(iter, "URL",
+                                       DBUS_TYPE_STRING, &ipdevice->pac);
+
+done:
+       connman_dbus_dict_append_basic(iter, "Method",
+                                               DBUS_TYPE_STRING, &method);
+}
+
+void __connman_ipconfig_append_proxyconfig(struct connman_ipconfig *ipconfig,
+                                                       DBusMessageIter *iter)
+{
+       struct connman_ipdevice *ipdevice;
+       const char *method = "auto";
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash,
+                                       GINT_TO_POINTER(ipconfig->index));
+       if (ipdevice == NULL)
+               goto done;
+
+       if (ipdevice->proxy == NULL)
+               goto done;
+
+       method = ipdevice->proxy;
+
+done:
        connman_dbus_dict_append_basic(iter, "Method",
                                                DBUS_TYPE_STRING, &method);
 }
 
+int __connman_ipconfig_set_proxyconfig(struct connman_ipconfig *ipconfig,
+                                                       DBusMessageIter *array)
+{
+       struct connman_ipdevice *ipdevice;
+       DBusMessageIter dict;
+       const char *method;
+
+       DBG("ipconfig %p", ipconfig);
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash,
+                                       GINT_TO_POINTER(ipconfig->index));
+       if (ipdevice == NULL)
+               return -ENXIO;
+
+       if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
+               return -EINVAL;
+
+       dbus_message_iter_recurse(array, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry;
+               const char *key;
+               int type;
+
+               dbus_message_iter_recurse(&dict, &entry);
+
+               if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+                       return -EINVAL;
+
+               dbus_message_iter_get_basic(&entry, &key);
+               dbus_message_iter_next(&entry);
+
+               type = dbus_message_iter_get_arg_type(&entry);
+
+               if (g_str_equal(key, "Method") == TRUE) {
+                       if (type != DBUS_TYPE_STRING)
+                               return -EINVAL;
+
+                       dbus_message_iter_get_basic(&entry, &method);
+                       if (strlen(method) == 0)
+                               method = NULL;
+               }
+
+               dbus_message_iter_next(&dict);
+       }
+
+       DBG("method %s", method);
+
+       if (method == NULL)
+               return -EINVAL;
+
+       if (g_str_equal(method, "auto") == FALSE &&
+                               g_str_equal(method, "direct") == FALSE)
+               return -EINVAL;
+
+       g_free(ipdevice->proxy);
+       ipdevice->proxy = g_strdup(method);
+
+       return 0;
+}
+
 void __connman_ipconfig_append_ethernet(struct connman_ipconfig *ipconfig,
                                                        DBusMessageIter *iter)
 {
@@ -1591,9 +1746,12 @@ int __connman_ipconfig_load(struct connman_ipconfig *ipconfig,
 
        key = g_strdup_printf("%smethod", prefix);
        method = g_key_file_get_string(keyfile, identifier, key, NULL);
-       if (method == NULL)
-               ipconfig->method = CONNMAN_IPCONFIG_METHOD_DHCP;
-       else
+       if (method == NULL) {
+               if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV4)
+                       ipconfig->method = CONNMAN_IPCONFIG_METHOD_DHCP;
+               else
+                       ipconfig->method = CONNMAN_IPCONFIG_METHOD_OFF;
+       } else
                ipconfig->method = __connman_ipconfig_string2method(method);
        g_free(key);