Fix PASSED_TO_PROC_AFTER_FREE.EX
[platform/upstream/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         connman_service_unref(wpad->service);
53
54         g_resolv_unref(wpad->resolv);
55
56         g_strfreev(wpad->addrlist);
57         g_free(wpad->hostname);
58         g_free(wpad);
59 }
60
61 static void download_pac(struct connman_wpad *wpad, const char *target)
62 {
63 }
64
65 static void wpad_result(GResolvResultStatus status,
66                                         char **results, gpointer user_data)
67 {
68         struct connman_wpad *wpad = user_data;
69         const char *ptr;
70         char *hostname;
71
72         DBG("status %d", status);
73
74         if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
75                 char *url;
76
77                 if (!results || g_strv_length(results) == 0)
78                         goto failed;
79
80                 url = g_strdup_printf("http://%s/wpad.dat", wpad->hostname);
81
82                 __connman_service_set_proxy_autoconfig(wpad->service, url);
83
84                 wpad->addrlist = g_strdupv(results);
85                 if (wpad->addrlist)
86                         download_pac(wpad, "wpad.dat");
87
88                 g_free(url);
89
90                 __connman_service_wispr_start(wpad->service,
91                                         CONNMAN_IPCONFIG_TYPE_IPV4);
92
93                 return;
94         }
95
96         hostname = wpad->hostname;
97
98         if (strlen(hostname) < 6)
99                 goto failed;
100
101         ptr = strchr(hostname + 5, '.');
102         if (!ptr || strlen(ptr) < 2)
103                 goto failed;
104
105         if (!strchr(ptr + 1, '.'))
106                 goto failed;
107
108         wpad->hostname = g_strdup_printf("wpad.%s", ptr + 1);
109         g_free(hostname);
110
111         DBG("hostname %s", wpad->hostname);
112
113         g_resolv_lookup_hostname(wpad->resolv, wpad->hostname,
114                                                         wpad_result, wpad);
115
116         return;
117
118 failed:
119         connman_service_set_proxy_method(wpad->service,
120                                 CONNMAN_SERVICE_PROXY_METHOD_DIRECT);
121
122         __connman_service_wispr_start(wpad->service,
123                                         CONNMAN_IPCONFIG_TYPE_IPV4);
124 }
125
126 int __connman_wpad_start(struct connman_service *service)
127 {
128         struct connman_wpad *wpad;
129         const char *domainname;
130         char **nameservers;
131         int index;
132         int i;
133
134         DBG("service %p", service);
135
136         if (!wpad_list)
137                 return -EINVAL;
138
139         index = __connman_service_get_index(service);
140         if (index < 0)
141                 return -EINVAL;
142
143         domainname = connman_service_get_domainname(service);
144         if (!domainname)
145                 return -EINVAL;
146
147         nameservers = connman_service_get_nameservers(service);
148         if (!nameservers)
149                 return -EINVAL;
150
151         wpad = g_try_new0(struct connman_wpad, 1);
152         if (!wpad) {
153                 g_strfreev(nameservers);
154                 return -ENOMEM;
155         }
156
157         wpad->resolv = g_resolv_new(index);
158         if (!wpad->resolv) {
159                 g_strfreev(nameservers);
160                 g_free(wpad);
161                 return -ENOMEM;
162         }
163
164 #if !defined TIZEN_EXT
165         if (getenv("CONNMAN_RESOLV_DEBUG"))
166 #endif
167                 g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV");
168
169         for (i = 0; nameservers[i]; i++)
170                 g_resolv_add_nameserver(wpad->resolv, nameservers[i], 53, 0);
171
172         g_strfreev(nameservers);
173
174         wpad->hostname = g_strdup_printf("wpad.%s", domainname);
175
176         DBG("hostname %s", wpad->hostname);
177
178         wpad->service = connman_service_ref(service);
179
180         g_resolv_lookup_hostname(wpad->resolv, wpad->hostname,
181                                                         wpad_result, wpad);
182
183         g_hash_table_replace(wpad_list, GINT_TO_POINTER(index), wpad);
184
185         return 0;
186 }
187
188 void __connman_wpad_stop(struct connman_service *service)
189 {
190         int index;
191
192         DBG("service %p", service);
193
194         if (!wpad_list)
195                 return;
196
197         index = __connman_service_get_index(service);
198         if (index < 0)
199                 return;
200
201         g_hash_table_remove(wpad_list, GINT_TO_POINTER(index));
202 }
203
204 int __connman_wpad_init(void)
205 {
206         DBG("");
207
208         wpad_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
209                                                         NULL, free_wpad);
210
211         return 0;
212 }
213
214 void __connman_wpad_cleanup(void)
215 {
216         DBG("");
217
218         g_hash_table_destroy(wpad_list);
219         wpad_list = NULL;
220 }