service: wpad only run on ipv4
[framework/connectivity/connman.git] / src / location.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  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
28 #include "connman.h"
29
30 struct connman_location {
31         gint refcount;
32         struct connman_service *service;
33         enum connman_location_result result;
34
35         struct connman_location_driver *driver;
36         void *driver_data;
37 };
38
39 /**
40  * connman_location_ref:
41  * @location: Location structure
42  *
43  * Increase reference counter of location
44  */
45 struct connman_location *connman_location_ref(struct connman_location *location)
46 {
47         g_atomic_int_inc(&location->refcount);
48
49         return location;
50 }
51
52 /**
53  * connman_location_unref:
54  * @location: Location structure
55  *
56  * Decrease reference counter of location
57  */
58 void connman_location_unref(struct connman_location *location)
59 {
60         if (g_atomic_int_dec_and_test(&location->refcount) == FALSE)
61                 return;
62
63         if (location->driver) {
64                 location->driver->finish(location);
65                 location->driver = NULL;
66         }
67
68         g_free(location);
69 }
70
71 /**
72  * connman_location_get_type:
73  * @location: Location structure
74  *
75  * Get the service type of location
76  */
77 enum connman_service_type connman_location_get_type(struct connman_location *location)
78 {
79         if (location == NULL)
80                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
81
82         return connman_service_get_type(location->service);
83 }
84
85 /**
86  * connman_location_get_interface:
87  * @location: location structure
88  *
89  * Get network interface of location
90  */
91 char *connman_location_get_interface(struct connman_location *location)
92 {
93         if (location == NULL)
94                 return NULL;
95
96         return connman_service_get_interface(location->service);
97 }
98
99 struct connman_service *connman_location_get_service(
100                                         struct connman_location *location)
101 {
102         return location->service;
103 }
104 /**
105  * connman_location_get_data:
106  * @location: Location structure
107  *
108  * Get private location data pointer
109  */
110 void *connman_location_get_data(struct connman_location *location)
111 {
112         return location->driver_data;
113 }
114
115 /**
116  * connman_location_set_data:
117  * @location: Location structure
118  * @data: data pointer
119  *
120  * Set private location data pointer
121  */
122 void connman_location_set_data(struct connman_location *location, void *data)
123 {
124         location->driver_data = data;
125 }
126
127 static GSList *driver_list = NULL;
128
129 static gint compare_priority(gconstpointer a, gconstpointer b)
130 {
131         const struct connman_location_driver *driver1 = a;
132         const struct connman_location_driver *driver2 = b;
133
134         return driver2->priority - driver1->priority;
135 }
136
137 /**
138  * connman_location_driver_register:
139  * @driver: Location driver definition
140  *
141  * Register a new Location driver
142  *
143  * Returns: %0 on success
144  */
145 int connman_location_driver_register(struct connman_location_driver *driver)
146 {
147         DBG("driver %p name %s", driver, driver->name);
148
149         driver_list = g_slist_insert_sorted(driver_list, driver,
150                                                         compare_priority);
151
152         return 0;
153 }
154
155 /**
156  * connman_location_driver_unregister:
157  * @driver: Location driver definition
158  *
159  * Remove a previously registered Location driver
160  */
161 void connman_location_driver_unregister(struct connman_location_driver *driver)
162 {
163         DBG("driver %p name %s", driver, driver->name);
164
165         driver_list = g_slist_remove(driver_list, driver);
166 }
167
168 /**
169  * connman_location_report_result:
170  * @location: location structure
171  * @result: result information
172  *
173  * Report result of a location detection
174  */
175 void connman_location_report_result(struct connman_location *location,
176                                         enum connman_location_result result)
177 {
178         DBG("location %p result %d", location, result);
179
180         if (location == NULL)
181                 return;
182
183         if (location->result == result)
184                 return;
185
186         location->result = result;
187
188         switch (location->result) {
189         case CONNMAN_LOCATION_RESULT_UNKNOWN:
190                 return;
191         case CONNMAN_LOCATION_RESULT_PORTAL:
192                 __connman_service_request_login(location->service);
193                 break;
194         case CONNMAN_LOCATION_RESULT_ONLINE:
195                 __connman_service_ipconfig_indicate_state(location->service,
196                                                 CONNMAN_SERVICE_STATE_ONLINE,
197                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
198                 break;
199         }
200 }
201
202 struct connman_location *__connman_location_create(struct connman_service *service)
203 {
204         struct connman_location *location;
205
206         DBG("service %p", service);
207
208         if (service == NULL)
209                 return NULL;
210
211         location = g_try_new0(struct connman_location, 1);
212         if (location == NULL)
213                 return NULL;
214
215         DBG("location %p", location);
216
217         location->refcount = 1;
218
219         location->service = service;
220         location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
221
222         return location;
223 }
224
225 int __connman_location_detect(struct connman_service *service)
226 {
227         struct connman_location *location;
228         GSList *list;
229
230         DBG("service %p", service);
231
232         location = __connman_service_get_location(service);
233         if (location == NULL)
234                 return -EINVAL;
235
236         if (location->driver) {
237                 location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
238                 location->driver->finish(location);
239
240                 if (location->driver->detect(location) == 0)
241                         return 0;
242
243                 location->driver = NULL;
244         }
245
246         for (list = driver_list; list; list = list->next) {
247                 struct connman_location_driver *driver = list->data;
248
249                 DBG("driver %p name %s", driver, driver->name);
250
251                 if (driver->detect(location) == 0) {
252                         location->driver = driver;
253                         break;
254                 }
255         }
256
257         if (location->driver == NULL)
258                 connman_location_report_result(location,
259                                         CONNMAN_LOCATION_RESULT_ONLINE);
260
261         return 0;
262 }
263
264 int __connman_location_finish(struct connman_service *service)
265 {
266         struct connman_location *location;
267
268         DBG("service %p", service);
269
270         location = __connman_service_get_location(service);
271         if (location == NULL)
272                 return -EINVAL;
273
274         location->result = CONNMAN_LOCATION_RESULT_UNKNOWN;
275
276         if (location->driver) {
277                 location->driver->finish(location);
278                 location->driver = NULL;
279         }
280
281         return 0;
282 }
283
284 int __connman_location_init(void)
285 {
286         DBG("");
287
288         return 0;
289 }
290
291 void __connman_location_cleanup(void)
292 {
293         DBG("");
294 }