+ return provider->index;
+}
+
+int connman_provider_set_ipaddress(struct connman_provider *provider,
+ struct connman_ipaddress *ipaddress)
+{
+ struct connman_ipconfig *ipconfig = NULL;
+
+ ipconfig = __connman_service_get_ipconfig(provider->vpn_service,
+ ipaddress->family);
+ if (ipconfig == NULL)
+ return -EINVAL;
+
+ provider->family = ipaddress->family;
+
+ __connman_ipconfig_set_local(ipconfig, ipaddress->local);
+ __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
+ __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
+ __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
+ __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
+
+ return 0;
+}
+
+int connman_provider_set_pac(struct connman_provider *provider, const char *pac)
+{
+ DBG("provider %p pac %s", provider, pac);
+
+ __connman_service_set_pac(provider->vpn_service, pac);
+
+ return 0;
+}
+
+
+int connman_provider_set_domain(struct connman_provider *provider,
+ const char *domain)
+{
+ DBG("provider %p domain %s", provider, domain);
+
+ g_free(provider->domain);
+ provider->domain = g_strdup(domain);
+
+ __connman_service_set_domainname(provider->vpn_service, domain);
+
+ return 0;
+}
+
+int connman_provider_set_nameservers(struct connman_provider *provider,
+ const char *nameservers)
+{
+ int i;
+ char **nameservers_array = NULL;
+
+ DBG("provider %p nameservers %s", provider, nameservers);
+
+ __connman_service_nameserver_clear(provider->vpn_service);
+
+ if (nameservers == NULL)
+ return 0;
+
+ nameservers_array = g_strsplit(nameservers, " ", 0);
+
+ for (i = 0; nameservers_array[i] != NULL; i++) {
+ __connman_service_nameserver_append(provider->vpn_service,
+ nameservers_array[i], FALSE);
+ }
+
+ g_strfreev(nameservers_array);
+
+ return 0;
+}
+
+enum provider_route_type {
+ PROVIDER_ROUTE_TYPE_NONE = 0,
+ PROVIDER_ROUTE_TYPE_MASK = 1,
+ PROVIDER_ROUTE_TYPE_ADDR = 2,
+ PROVIDER_ROUTE_TYPE_GW = 3,
+};
+
+static int route_env_parse(struct connman_provider *provider, const char *key,
+ int *family, unsigned long *idx,
+ enum provider_route_type *type)
+{
+ char *end;
+ const char *start;
+
+ DBG("name %s", provider->name);
+
+ if (!strcmp(provider->type, "openvpn")) {
+ if (g_str_has_prefix(key, "route_network_") == TRUE) {
+ start = key + strlen("route_network_");
+ *type = PROVIDER_ROUTE_TYPE_ADDR;
+ } else if (g_str_has_prefix(key, "route_netmask_") == TRUE) {
+ start = key + strlen("route_netmask_");
+ *type = PROVIDER_ROUTE_TYPE_MASK;
+ } else if (g_str_has_prefix(key, "route_gateway_") == TRUE) {
+ start = key + strlen("route_gateway_");
+ *type = PROVIDER_ROUTE_TYPE_GW;
+ } else
+ return -EINVAL;
+
+ *family = AF_INET;
+ *idx = g_ascii_strtoull(start, &end, 10);
+
+ } else if (!strcmp(provider->type, "openconnect")) {
+ if (g_str_has_prefix(key, "CISCO_SPLIT_INC_") == TRUE) {
+ *family = AF_INET;
+ start = key + strlen("CISCO_SPLIT_INC_");
+ } else if (g_str_has_prefix(key, "CISCO_IPV6_SPLIT_INC_") == TRUE) {
+ *family = AF_INET6;
+ start = key + strlen("CISCO_IPV6_SPLIT_INC_");
+ } else
+ return -EINVAL;
+
+ *idx = g_ascii_strtoull(start, &end, 10);
+
+ if (strncmp(end, "_ADDR", 5) == 0)
+ *type = PROVIDER_ROUTE_TYPE_ADDR;
+ else if (strncmp(end, "_MASK", 5) == 0)
+ *type = PROVIDER_ROUTE_TYPE_MASK;
+ else if (strncmp(end, "_MASKLEN", 8) == 0 &&
+ *family == AF_INET6) {
+ *type = PROVIDER_ROUTE_TYPE_MASK;
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int connman_provider_append_route(struct connman_provider *provider,
+ const char *key, const char *value)
+{
+ struct connman_route *route;
+ int ret, family = 0;
+ unsigned long idx = 0;
+ enum provider_route_type type = PROVIDER_ROUTE_TYPE_NONE;
+
+ DBG("key %s value %s", key, value);
+
+ ret = route_env_parse(provider, key, &family, &idx, &type);
+ if (ret < 0)
+ return ret;
+
+ DBG("idx %lu family %d type %d", idx, family, type);
+
+ route = g_hash_table_lookup(provider->routes, GINT_TO_POINTER(idx));
+ if (route == NULL) {
+ route = g_try_new0(struct connman_route, 1);
+ if (route == NULL) {
+ connman_error("out of memory");
+ return -ENOMEM;
+ }
+
+ route->family = family;
+
+ g_hash_table_replace(provider->routes, GINT_TO_POINTER(idx),
+ route);
+ }
+
+ switch (type) {
+ case PROVIDER_ROUTE_TYPE_NONE:
+ break;
+ case PROVIDER_ROUTE_TYPE_MASK:
+ route->netmask = g_strdup(value);
+ break;
+ case PROVIDER_ROUTE_TYPE_ADDR:
+ route->host = g_strdup(value);
+ break;
+ case PROVIDER_ROUTE_TYPE_GW:
+ route->gateway = g_strdup(value);
+ break;
+ }
+
+ return 0;
+}
+
+const char *connman_provider_get_driver_name(struct connman_provider *provider)
+{
+ if (provider->driver == NULL)
+ return NULL;
+
+ return provider->driver->name;
+}
+
+const char *connman_provider_get_save_group(struct connman_provider *provider)
+{
+ return provider->identifier;