technology: return already enabled when tethering is enabled
[framework/connectivity/connman.git] / src / wpad.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <gweb/gresolv.h>
31
32 #include "connman.h"
33
34 struct connman_wpad {
35         struct connman_service *service;
36         GResolv *resolv;
37         char *hostname;
38         char **addrlist;
39 };
40
41 static GHashTable *wpad_list = NULL;
42
43 static void resolv_debug(const char *str, void *data)
44 {
45         connman_info("%s: %s\n", (const char *) data, str);
46 }
47
48 static void free_wpad(gpointer data)
49 {
50         struct connman_wpad *wpad = data;
51
52         g_resolv_unref(wpad->resolv);
53
54         g_strfreev(wpad->addrlist);
55         g_free(wpad->hostname);
56         g_free(wpad);
57 }
58
59 static void download_pac(struct connman_wpad *wpad, const char *target)
60 {
61 }
62
63 static void wpad_result(GResolvResultStatus status,
64                                         char **results, gpointer user_data)
65 {
66         struct connman_wpad *wpad = user_data;
67         const char *ptr;
68         char *hostname;
69
70         DBG("status %d", status);
71
72         if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
73                 char *url;
74
75                 if (results == NULL || g_strv_length(results) == 0)
76                         goto failed;
77
78                 url = g_strdup_printf("http://%s/wpad.dat", wpad->hostname);
79
80                 __connman_service_set_proxy_autoconfig(wpad->service, url);
81
82                 wpad->addrlist = g_strdupv(results);
83                 if (wpad->addrlist != NULL)
84                         download_pac(wpad, "wpad.dat");
85
86                 g_free(url);
87
88                 __connman_wispr_start(wpad->service,
89                                         CONNMAN_IPCONFIG_TYPE_IPV4);
90
91                 return;
92         }
93
94         hostname = wpad->hostname;
95
96         if (strlen(hostname) < 6)
97                 goto failed;
98
99         ptr = strchr(hostname + 5, '.');
100         if (ptr == NULL || strlen(ptr) < 2)
101                 goto failed;
102
103         if (strchr(ptr + 1, '.') == NULL)
104                 goto failed;
105
106         wpad->hostname = g_strdup_printf("wpad.%s", ptr + 1);
107         g_free(hostname);
108
109         DBG("hostname %s", wpad->hostname);
110
111         g_resolv_lookup_hostname(wpad->resolv, wpad->hostname,
112                                                         wpad_result, wpad);
113
114         return;
115
116 failed:
117         connman_service_set_proxy_method(wpad->service,
118                                 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
119
120         __connman_wispr_start(wpad->service,
121                                         CONNMAN_IPCONFIG_TYPE_IPV4);
122 }
123
124 int __connman_wpad_start(struct connman_service *service)
125 {
126         struct connman_wpad *wpad;
127         const char *domainname;
128         char **nameservers;
129         int index;
130         int i;
131
132         DBG("service %p", service);
133
134         if (wpad_list == NULL)
135                 return -EINVAL;
136
137         index = __connman_service_get_index(service);
138         if (index < 0)
139                 return -EINVAL;
140
141         domainname = connman_service_get_domainname(service);
142         if (domainname == NULL)
143                 return -EINVAL;
144
145         nameservers = connman_service_get_nameservers(service);
146         if (nameservers == NULL)
147                 return -EINVAL;
148
149         wpad = g_try_new0(struct connman_wpad, 1);
150         if (wpad == NULL) {
151                 g_strfreev(nameservers);
152                 return -ENOMEM;
153         }
154
155         wpad->service = service;
156         wpad->resolv = g_resolv_new(index);
157         if (wpad->resolv == NULL) {
158                 g_strfreev(nameservers);
159                 g_free(wpad);
160                 return -ENOMEM;
161         }
162
163         if (getenv("CONNMAN_RESOLV_DEBUG"))
164                 g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV");
165
166         for (i = 0; nameservers[i] != NULL; i++)
167                 g_resolv_add_nameserver(wpad->resolv, nameservers[i], 53, 0);
168
169         g_strfreev(nameservers);
170
171         wpad->hostname = g_strdup_printf("wpad.%s", domainname);
172
173         DBG("hostname %s", wpad->hostname);
174
175         g_resolv_lookup_hostname(wpad->resolv, wpad->hostname,
176                                                         wpad_result, wpad);
177
178         connman_service_ref(service);
179         g_hash_table_replace(wpad_list, GINT_TO_POINTER(index), wpad);
180
181         return 0;
182 }
183
184 void __connman_wpad_stop(struct connman_service *service)
185 {
186         int index;
187
188         DBG("service %p", service);
189
190         if (wpad_list == NULL)
191                 return;
192
193         index = __connman_service_get_index(service);
194         if (index < 0)
195                 return;
196
197         if (g_hash_table_remove(wpad_list, GINT_TO_POINTER(index)) == TRUE)
198                 connman_service_unref(service);
199 }
200
201 int __connman_wpad_init(void)
202 {
203         DBG("");
204
205         wpad_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
206                                                         NULL, free_wpad);
207
208         return 0;
209 }
210
211 void __connman_wpad_cleanup(void)
212 {
213         DBG("");
214
215         g_hash_table_destroy(wpad_list);
216         wpad_list = NULL;
217 }