Remove obsolete DHCP element handling
[connman] / plugins / wifi.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  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 <string.h>
27 #include <dbus/dbus.h>
28
29 #include <connman/plugin.h>
30 #include <connman/driver.h>
31 #include <connman/log.h>
32
33 #include "supplicant.h"
34
35 static int network_probe(struct connman_element *element)
36 {
37         DBG("element %p name %s", element, element->name);
38
39         return 0;
40 }
41
42 static void network_remove(struct connman_element *element)
43 {
44         DBG("element %p name %s", element, element->name);
45 }
46
47 static int network_enable(struct connman_element *element)
48 {
49         DBG("element %p name %s", element, element->name);
50
51         element->enabled = FALSE;
52         connman_element_update(element);
53
54         if (element->parent) {
55                 g_free(element->parent->network.identifier);
56                 element->parent->network.identifier =
57                                         g_strdup(element->network.identifier);
58         }
59
60         if (__supplicant_connect(element, element->network.identifier) < 0)
61                 connman_error("Failed to initiate connect");
62
63         return 0;
64 }
65
66 static int network_disable(struct connman_element *element)
67 {
68         DBG("element %p name %s", element, element->name);
69
70         connman_element_unregister_children(element);
71
72         __supplicant_disconnect(element);
73
74         element->enabled = FALSE;
75         connman_element_update(element);
76
77         return 0;
78 }
79
80 static struct connman_driver network_driver = {
81         .name           = "wifi-network",
82         .type           = CONNMAN_ELEMENT_TYPE_NETWORK,
83         .subtype        = CONNMAN_ELEMENT_SUBTYPE_WIFI,
84         .probe          = network_probe,
85         .remove         = network_remove,
86         .enable         = network_enable,
87         .disable        = network_disable,
88 };
89
90 struct wifi_data {
91         GStaticMutex mutex;
92         GSList *list;
93 };
94
95 static struct connman_element *find_element(struct wifi_data *data,
96                                                 const char *identifier)
97 {
98         GSList *list;
99
100         for (list = data->list; list; list = list->next) {
101                 struct connman_element *element = list->data;
102
103                 if (element->network.identifier == NULL)
104                         continue;
105
106                 if (g_str_equal(element->network.identifier,
107                                                         identifier) == TRUE)
108                         return element;
109         }
110
111         return NULL;
112 }
113
114 static void state_change(struct connman_element *parent,
115                                                 enum supplicant_state state)
116 {
117         struct wifi_data *data = connman_element_get_data(parent);
118         struct connman_element *element;
119
120         DBG("state %d", state);
121
122         if (parent->network.identifier == NULL)
123                 return;
124
125         element = find_element(data, parent->network.identifier);
126         if (element == NULL)
127                 return;
128
129         if (state == STATE_COMPLETED) {
130                 struct connman_element *dhcp;
131
132                 dhcp = connman_element_create(NULL);
133
134                 dhcp->type = CONNMAN_ELEMENT_TYPE_DHCP;
135                 dhcp->index = element->index;
136
137                 element->enabled = TRUE;
138                 connman_element_update(element);
139
140                 connman_element_register(dhcp, element);
141         }
142 }
143
144 static void scan_result(struct connman_element *parent,
145                                         struct supplicant_network *network)
146 {
147         struct wifi_data *data = connman_element_get_data(parent);
148         struct connman_element *element;
149         gchar *temp;
150         int i;
151
152         DBG("network %p identifier %s", network, network->identifier);
153
154         if (data == NULL)
155                 return;
156
157         if (network->identifier == NULL)
158                 return;
159
160         if (network->identifier[0] == '\0')
161                 return;
162
163         temp = g_strdup(network->identifier);
164
165         for (i = 0; i < strlen(temp); i++) {
166                 if (temp[i] == ' ' || temp[i] == '.' || temp[i] == '-')
167                         temp[i] = '_';
168                 if (temp[i] == '(' || temp[i] == ')')
169                         temp[i] = '_';
170                 if (g_ascii_isprint(temp[i]) == FALSE)
171                         temp[i] = '_';
172                 temp[i] = g_ascii_tolower(temp[i]);
173         }
174
175         g_static_mutex_lock(&data->mutex);
176
177         element = find_element(data, network->identifier);
178         if (element == NULL) {
179                 element = connman_element_create(temp);
180
181                 element->type = CONNMAN_ELEMENT_TYPE_NETWORK;
182                 element->index = parent->index;
183
184                 element->network.identifier = g_strdup(network->identifier);
185
186                 data->list = g_slist_append(data->list, element);
187
188                 connman_element_add_static_property(element, "SSID",
189                                 DBUS_TYPE_STRING, &network->identifier);
190
191                 connman_element_register(element, parent);
192         }
193
194         g_static_mutex_unlock(&data->mutex);
195
196         g_free(temp);
197 }
198
199 static struct supplicant_callback wifi_callback = {
200         .state_change   = state_change,
201         .scan_result    = scan_result,
202 };
203
204 static int wifi_probe(struct connman_element *element)
205 {
206         struct wifi_data *data;
207         int err;
208
209         DBG("element %p name %s", element, element->name);
210
211         data = g_try_new0(struct wifi_data, 1);
212         if (data == NULL)
213                 return -ENOMEM;
214
215         g_static_mutex_init(&data->mutex);
216
217         connman_element_set_data(element, data);
218
219         err = __supplicant_start(element, &wifi_callback);
220         if (err < 0)
221                 return err;
222
223         __supplicant_scan(element);
224
225         return 0;
226 }
227
228 static void wifi_remove(struct connman_element *element)
229 {
230         struct wifi_data *data = connman_element_get_data(element);
231         GSList *list;
232
233         DBG("element %p name %s", element, element->name);
234
235         __supplicant_stop(element);
236
237         connman_element_set_data(element, NULL);
238
239         if (data == NULL)
240                 return;
241
242         g_static_mutex_lock(&data->mutex);
243
244         for (list = data->list; list; list = list->next) {
245                 struct connman_element *network = list->data;
246
247                 connman_element_unregister(network);
248                 connman_element_unref(network);
249         }
250
251         g_slist_free(data->list);
252
253         g_static_mutex_unlock(&data->mutex);
254
255         g_free(data);
256 }
257
258 static int wifi_update(struct connman_element *element)
259 {
260         DBG("element %p name %s", element, element->name);
261
262         __supplicant_scan(element);
263
264         return 0;
265 }
266
267 static struct connman_driver wifi_driver = {
268         .name           = "wifi-device",
269         .type           = CONNMAN_ELEMENT_TYPE_DEVICE,
270         .subtype        = CONNMAN_ELEMENT_SUBTYPE_WIFI,
271         .probe          = wifi_probe,
272         .remove         = wifi_remove,
273         .update         = wifi_update,
274 };
275
276 static int wifi_init(void)
277 {
278         int err;
279
280         err = __supplicant_init();
281         if (err < 0)
282                 return err;
283
284         err = connman_driver_register(&network_driver);
285         if (err < 0) {
286                 __supplicant_exit();
287                 return err;
288         }
289
290         err = connman_driver_register(&wifi_driver);
291         if (err < 0) {
292                 connman_driver_unregister(&network_driver);
293                 __supplicant_exit();
294                 return err;
295         }
296
297         return 0;
298 }
299
300 static void wifi_exit(void)
301 {
302         connman_driver_unregister(&network_driver);
303         connman_driver_unregister(&wifi_driver);
304
305         __supplicant_exit();
306 }
307
308 CONNMAN_PLUGIN_DEFINE("wifi", "WiFi interface plugin", VERSION,
309                                                         wifi_init, wifi_exit)