/* * * Connection Manager * * Copyright (C) 2007-2012 Intel 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 #endif #include #include #include #include #include "connman.h" struct connman_wpad { struct connman_service *service; GResolv *resolv; char *hostname; char **addrlist; }; static GHashTable *wpad_list = NULL; static void resolv_debug(const char *str, void *data) { connman_info("%s: %s\n", (const char *) data, str); } static void free_wpad(gpointer data) { struct connman_wpad *wpad = data; g_resolv_unref(wpad->resolv); g_strfreev(wpad->addrlist); g_free(wpad->hostname); g_free(wpad); } static void download_pac(struct connman_wpad *wpad, const char *target) { } static void wpad_result(GResolvResultStatus status, char **results, gpointer user_data) { struct connman_wpad *wpad = user_data; const char *ptr; char *hostname; DBG("status %d", status); if (status == G_RESOLV_RESULT_STATUS_SUCCESS) { char *url; if (results == NULL || g_strv_length(results) == 0) goto failed; url = g_strdup_printf("http://%s/wpad.dat", wpad->hostname); __connman_service_set_proxy_autoconfig(wpad->service, url); wpad->addrlist = g_strdupv(results); if (wpad->addrlist != NULL) download_pac(wpad, "wpad.dat"); g_free(url); __connman_wispr_start(wpad->service, CONNMAN_IPCONFIG_TYPE_IPV4); return; } hostname = wpad->hostname; if (strlen(hostname) < 6) goto failed; ptr = strchr(hostname + 5, '.'); if (ptr == NULL || strlen(ptr) < 2) goto failed; if (strchr(ptr + 1, '.') == NULL) goto failed; wpad->hostname = g_strdup_printf("wpad.%s", ptr + 1); g_free(hostname); DBG("hostname %s", wpad->hostname); g_resolv_lookup_hostname(wpad->resolv, wpad->hostname, wpad_result, wpad); return; failed: connman_service_set_proxy_method(wpad->service, CONNMAN_SERVICE_PROXY_METHOD_DIRECT); __connman_wispr_start(wpad->service, CONNMAN_IPCONFIG_TYPE_IPV4); } int __connman_wpad_start(struct connman_service *service) { struct connman_wpad *wpad; const char *domainname; char **nameservers; int index; int i; DBG("service %p", service); if (wpad_list == NULL) return -EINVAL; index = __connman_service_get_index(service); if (index < 0) return -EINVAL; domainname = connman_service_get_domainname(service); if (domainname == NULL) return -EINVAL; nameservers = connman_service_get_nameservers(service); if (nameservers == NULL) return -EINVAL; wpad = g_try_new0(struct connman_wpad, 1); if (wpad == NULL) { g_strfreev(nameservers); return -ENOMEM; } wpad->service = service; wpad->resolv = g_resolv_new(index); if (wpad->resolv == NULL) { g_strfreev(nameservers); g_free(wpad); return -ENOMEM; } if (getenv("CONNMAN_RESOLV_DEBUG")) g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV"); for (i = 0; nameservers[i] != NULL; i++) g_resolv_add_nameserver(wpad->resolv, nameservers[i], 53, 0); g_strfreev(nameservers); wpad->hostname = g_strdup_printf("wpad.%s", domainname); DBG("hostname %s", wpad->hostname); g_resolv_lookup_hostname(wpad->resolv, wpad->hostname, wpad_result, wpad); connman_service_ref(service); g_hash_table_replace(wpad_list, GINT_TO_POINTER(index), wpad); return 0; } void __connman_wpad_stop(struct connman_service *service) { int index; DBG("service %p", service); if (wpad_list == NULL) return; index = __connman_service_get_index(service); if (index < 0) return; if (g_hash_table_remove(wpad_list, GINT_TO_POINTER(index)) == TRUE) connman_service_unref(service); } int __connman_wpad_init(void) { DBG(""); wpad_list = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free_wpad); return 0; } void __connman_wpad_cleanup(void) { DBG(""); g_hash_table_destroy(wpad_list); wpad_list = NULL; }