wifi: Remove old background scanning technique call
[framework/connectivity/connman.git] / plugins / wifi.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 <unistd.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <linux/if_arp.h>
34 #include <linux/wireless.h>
35 #include <net/ethernet.h>
36
37 #ifndef IFF_LOWER_UP
38 #define IFF_LOWER_UP    0x10000
39 #endif
40
41 #include <dbus/dbus.h>
42 #include <glib.h>
43
44 #define CONNMAN_API_SUBJECT_TO_CHANGE
45 #include <connman/plugin.h>
46 #include <connman/inet.h>
47 #include <connman/device.h>
48 #include <connman/rtnl.h>
49 #include <connman/technology.h>
50 #include <connman/log.h>
51 #include <connman/option.h>
52 #include <connman/storage.h>
53 #include <include/setting.h>
54
55 #include <gsupplicant/gsupplicant.h>
56
57 #define CLEANUP_TIMEOUT   8     /* in seconds */
58 #define INACTIVE_TIMEOUT  12    /* in seconds */
59 #define MAXIMUM_RETRIES   4
60
61 #define BGSCAN_DEFAULT "simple:30:-45:300"
62 #define AUTOSCAN_DEFAULT "exponential:2:3600"
63
64 struct connman_technology *wifi_technology = NULL;
65
66 struct hidden_params {
67         char ssid[32];
68         unsigned int ssid_len;
69         char *identity;
70         char *passphrase;
71 };
72
73 /**
74  * Used for autoscan "emulation".
75  * Should be removed when wpa_s autoscan support will be by default.
76  */
77 struct autoscan_params {
78         int base;
79         int limit;
80         int interval;
81         unsigned int timeout;
82 };
83
84 struct wifi_data {
85         char *identifier;
86         struct connman_device *device;
87         struct connman_network *network;
88         struct connman_network *pending_network;
89         GSList *networks;
90         GSupplicantInterface *interface;
91         GSupplicantState state;
92         connman_bool_t connected;
93         connman_bool_t disconnecting;
94         connman_bool_t tethering;
95         connman_bool_t bridged;
96         const char *bridge;
97         int index;
98         unsigned flags;
99         unsigned int watch;
100         int retries;
101         struct hidden_params *hidden;
102         /**
103          * autoscan "emulation".
104          */
105         struct autoscan_params *autoscan;
106 };
107
108 static GList *iface_list = NULL;
109
110 static void handle_tethering(struct wifi_data *wifi)
111 {
112         if (wifi->tethering == FALSE)
113                 return;
114
115         if (wifi->bridge == NULL)
116                 return;
117
118         if (wifi->bridged == TRUE)
119                 return;
120
121         DBG("index %d bridge %s", wifi->index, wifi->bridge);
122
123         if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
124                 return;
125
126         wifi->bridged = TRUE;
127 }
128
129 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
130 {
131         struct connman_device *device = user_data;
132         struct wifi_data *wifi = connman_device_get_data(device);
133
134         DBG("index %d flags %d change %d", wifi->index, flags, change);
135
136         if (!change)
137                 return;
138
139         if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
140                 if (flags & IFF_UP)
141                         DBG("interface up");
142                 else
143                         DBG("interface down");
144         }
145
146         if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
147                 if (flags & IFF_LOWER_UP) {
148                         DBG("carrier on");
149
150                         handle_tethering(wifi);
151                 } else
152                         DBG("carrier off");
153         }
154
155         wifi->flags = flags;
156 }
157
158 static int wifi_probe(struct connman_device *device)
159 {
160         struct wifi_data *wifi;
161
162         DBG("device %p", device);
163
164         wifi = g_try_new0(struct wifi_data, 1);
165         if (wifi == NULL)
166                 return -ENOMEM;
167
168         wifi->connected = FALSE;
169         wifi->disconnecting = FALSE;
170         wifi->tethering = FALSE;
171         wifi->bridged = FALSE;
172         wifi->bridge = NULL;
173         wifi->state = G_SUPPLICANT_STATE_INACTIVE;
174
175         connman_device_set_data(device, wifi);
176         wifi->device = connman_device_ref(device);
177
178         wifi->index = connman_device_get_index(device);
179         wifi->flags = 0;
180
181         wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
182                                                         wifi_newlink, device);
183
184         iface_list = g_list_append(iface_list, wifi);
185
186         return 0;
187 }
188
189 static void remove_networks(struct connman_device *device,
190                                 struct wifi_data *wifi)
191 {
192         GSList *list;
193
194         for (list = wifi->networks; list != NULL; list = list->next) {
195                 struct connman_network *network = list->data;
196
197                 connman_device_remove_network(device, network);
198                 connman_network_unref(network);
199         }
200
201         g_slist_free(wifi->networks);
202         wifi->networks = NULL;
203 }
204
205 static void stop_autoscan(struct connman_device *device)
206 {
207         struct wifi_data *wifi = connman_device_get_data(device);
208         struct autoscan_params *autoscan;
209
210         DBG("");
211
212         if (wifi == NULL || wifi->autoscan == NULL)
213                 return;
214
215         autoscan = wifi->autoscan;
216
217         if (autoscan->timeout > 0)
218                 g_source_remove(autoscan->timeout);
219
220         autoscan->timeout = 0;
221         autoscan->interval = 0;
222
223         connman_device_unref(device);
224 }
225
226 static void wifi_remove(struct connman_device *device)
227 {
228         struct wifi_data *wifi = connman_device_get_data(device);
229
230         DBG("device %p wifi %p", device, wifi);
231
232         if (wifi == NULL)
233                 return;
234
235         stop_autoscan(device);
236
237         iface_list = g_list_remove(iface_list, wifi);
238
239         remove_networks(device, wifi);
240
241         connman_device_set_powered(device, FALSE);
242         connman_device_set_data(device, NULL);
243         connman_device_unref(wifi->device);
244         connman_rtnl_remove_watch(wifi->watch);
245
246         g_supplicant_interface_set_data(wifi->interface, NULL);
247
248         g_free(wifi->autoscan);
249         g_free(wifi->identifier);
250         g_free(wifi);
251 }
252
253 static int throw_wifi_scan(struct connman_device *device,
254                         GSupplicantInterfaceCallback callback)
255 {
256         struct wifi_data *wifi = connman_device_get_data(device);
257         int ret;
258
259         DBG("device %p %p", device, wifi->interface);
260
261         if (wifi->tethering == TRUE)
262                 return 0;
263
264         connman_device_ref(device);
265
266         ret = g_supplicant_interface_scan(wifi->interface, NULL,
267                                                 callback, device);
268         if (ret == 0)
269                 connman_device_set_scanning(device, TRUE);
270         else
271                 connman_device_unref(device);
272
273         return ret;
274 }
275
276 static void autoscan_scan_callback(int result,
277                         GSupplicantInterface *interface, void *user_data)
278 {
279         struct connman_device *device = user_data;
280
281         DBG("");
282
283         connman_device_set_scanning(device, FALSE);
284 }
285
286 static gboolean autoscan_timeout(gpointer data)
287 {
288         struct connman_device *device = data;
289         struct wifi_data *wifi = connman_device_get_data(device);
290         struct autoscan_params *autoscan;
291         int interval;
292
293         autoscan = wifi->autoscan;
294
295         if (autoscan->interval <= 0) {
296                 interval = autoscan->base;
297                 goto set_interval;
298         } else
299                 interval = autoscan->interval * autoscan->base;
300
301         if (autoscan->interval >= autoscan->limit)
302                 interval = autoscan->limit;
303
304         throw_wifi_scan(wifi->device, autoscan_scan_callback);
305
306 set_interval:
307         DBG("interval %d", interval);
308
309         autoscan->interval = interval;
310
311         autoscan->timeout = g_timeout_add_seconds(interval,
312                                                 autoscan_timeout, device);
313
314         return FALSE;
315 }
316
317 static void start_autoscan(struct connman_device *device)
318 {
319         struct wifi_data *wifi = connman_device_get_data(device);
320         struct autoscan_params *autoscan;
321
322         DBG("");
323
324         if (wifi == NULL)
325                 return;
326
327         autoscan = wifi->autoscan;
328         if (autoscan == NULL)
329                 return;
330
331         if (autoscan->timeout > 0 || autoscan->interval > 0)
332                 return;
333
334         connman_device_ref(device);
335
336         autoscan_timeout(device);
337 }
338
339 static struct autoscan_params *parse_autoscan_params(const char *params)
340 {
341         struct autoscan_params *autoscan;
342         char **list_params;
343         int limit;
344         int base;
345
346         DBG("Emulating autoscan");
347
348         list_params = g_strsplit(params, ":", 0);
349         if (list_params == 0)
350                 return NULL;
351
352         if (g_strv_length(list_params) < 3) {
353                 g_strfreev(list_params);
354                 return NULL;
355         }
356
357         base = atoi(list_params[1]);
358         limit = atoi(list_params[2]);
359
360         g_strfreev(list_params);
361
362         autoscan = g_try_malloc0(sizeof(struct autoscan_params));
363         if (autoscan == NULL) {
364                 DBG("Could not allocate memory for autoscan");
365                 return NULL;
366         }
367
368         DBG("base %d - limit %d", base, limit);
369         autoscan->base = base;
370         autoscan->limit = limit;
371
372         return autoscan;
373 }
374
375 static void setup_autoscan(struct wifi_data *wifi)
376 {
377         if (wifi->autoscan == NULL)
378                 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
379
380         start_autoscan(wifi->device);
381 }
382
383 static void interface_create_callback(int result,
384                                         GSupplicantInterface *interface,
385                                                         void *user_data)
386 {
387         struct wifi_data *wifi = user_data;
388
389         DBG("result %d ifname %s, wifi %p", result,
390                                 g_supplicant_interface_get_ifname(interface),
391                                 wifi);
392
393         if (result < 0 || wifi == NULL)
394                 return;
395
396         wifi->interface = interface;
397         g_supplicant_interface_set_data(interface, wifi);
398
399         if (g_supplicant_interface_get_ready(interface) == FALSE)
400                 return;
401
402         DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
403
404         if (wifi->device == NULL) {
405                 connman_error("WiFi device not set");
406                 return;
407         }
408
409         connman_device_set_powered(wifi->device, TRUE);
410
411         if (connman_setting_get_bool("BackgroundScanning") == FALSE)
412                 return;
413
414         /* Setting up automatic scanning */
415         setup_autoscan(wifi);
416 }
417
418 static int wifi_enable(struct connman_device *device)
419 {
420         struct wifi_data *wifi = connman_device_get_data(device);
421         const char *interface = connman_device_get_string(device, "Interface");
422         const char *driver = connman_option_get_string("wifi");
423         int ret;
424
425         DBG("device %p %p", device, wifi);
426
427         ret = g_supplicant_interface_create(interface, driver, NULL,
428                                                 interface_create_callback,
429                                                         wifi);
430         if (ret < 0)
431                 return ret;
432
433         return -EINPROGRESS;
434 }
435
436 static int wifi_disable(struct connman_device *device)
437 {
438         struct wifi_data *wifi = connman_device_get_data(device);
439         int ret;
440
441         DBG("device %p", device);
442
443         wifi->connected = FALSE;
444         wifi->disconnecting = FALSE;
445
446         if (wifi->pending_network != NULL)
447                 wifi->pending_network = NULL;
448
449         remove_networks(device, wifi);
450
451         ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
452         if (ret < 0)
453                 return ret;
454
455         return -EINPROGRESS;
456 }
457
458 static void hidden_free(struct hidden_params *hidden)
459 {
460         if (hidden == NULL)
461                 return;
462
463         g_free(hidden->identity);
464         g_free(hidden->passphrase);
465         g_free(hidden);
466 }
467
468 static void scan_callback(int result, GSupplicantInterface *interface,
469                                                 void *user_data)
470 {
471         struct connman_device *device = user_data;
472         struct wifi_data *wifi = connman_device_get_data(device);
473
474         DBG("result %d", result);
475
476         if (wifi != NULL && wifi->hidden != NULL) {
477                 hidden_free(wifi->hidden);
478                 wifi->hidden = NULL;
479         }
480
481         if (result < 0)
482                 connman_device_reset_scanning(device);
483
484         connman_device_set_scanning(device, FALSE);
485         connman_device_unref(device);
486
487         start_autoscan(device);
488 }
489
490 static int add_scan_param(gchar *hex_ssid, int freq,
491                         GSupplicantScanParams *scan_data,
492                         int driver_max_scan_ssids)
493 {
494         unsigned int i;
495
496         if (driver_max_scan_ssids > scan_data->num_ssids && hex_ssid != NULL) {
497                 gchar *ssid;
498                 unsigned int j = 0, hex;
499                 size_t hex_ssid_len = strlen(hex_ssid);
500
501                 ssid = g_try_malloc0(hex_ssid_len / 2);
502                 if (ssid == NULL)
503                         return -ENOMEM;
504
505                 for (i = 0; i < hex_ssid_len; i += 2) {
506                         sscanf(hex_ssid + i, "%02x", &hex);
507                         ssid[j++] = hex;
508                 }
509
510                 memcpy(scan_data->ssids[scan_data->num_ssids].ssid, ssid, j);
511                 scan_data->ssids[scan_data->num_ssids].ssid_len = j;
512                 scan_data->num_ssids++;
513
514                 g_free(ssid);
515         }
516
517         /* Don't add duplicate entries */
518         for (i = 0; i < G_SUPPLICANT_MAX_FAST_SCAN; i++) {
519                 if (scan_data->freqs[i] == 0) {
520                         scan_data->freqs[i] = freq;
521                         break;
522                 } else if (scan_data->freqs[i] == freq)
523                         break;
524         }
525
526         return 0;
527 }
528
529 struct last_connected {
530         GTimeVal modified;
531         gchar *ssid;
532         int freq;
533 };
534
535 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
536 {
537         GTimeVal *aval = (GTimeVal *)a;
538         GTimeVal *bval = (GTimeVal *)b;
539
540         /* Note that the sort order is descending */
541         if (aval->tv_sec < bval->tv_sec)
542                 return 1;
543
544         if (aval->tv_sec > bval->tv_sec)
545                 return -1;
546
547         return 0;
548 }
549
550 static void free_entry(gpointer data)
551 {
552         struct last_connected *entry = data;
553
554         g_free(entry->ssid);
555         g_free(entry);
556 }
557
558 static int get_latest_connections(int max_ssids,
559                                 GSupplicantScanParams *scan_data)
560 {
561         GSequenceIter *iter;
562         GSequence *latest_list;
563         struct last_connected *entry;
564         GKeyFile *keyfile;
565         GTimeVal modified;
566         gchar **services;
567         gchar *str;
568         char *ssid;
569         int i, freq;
570         int num_ssids = 0;
571
572         latest_list = g_sequence_new(free_entry);
573         if (latest_list == NULL)
574                 return -ENOMEM;
575
576         services = connman_storage_get_services();
577         for (i = 0; services && services[i]; i++) {
578                 if (strncmp(services[i], "wifi_", 5) != 0)
579                         continue;
580
581                 keyfile = connman_storage_load_service(services[i]);
582
583                 str = g_key_file_get_string(keyfile,
584                                         services[i], "Favorite", NULL);
585                 if (str == NULL || g_strcmp0(str, "true")) {
586                         if (str)
587                                 g_free(str);
588                         g_key_file_free(keyfile);
589                         continue;
590                 }
591                 g_free(str);
592
593                 str = g_key_file_get_string(keyfile,
594                                         services[i], "AutoConnect", NULL);
595                 if (str == NULL || g_strcmp0(str, "true")) {
596                         if (str)
597                                 g_free(str);
598                         g_key_file_free(keyfile);
599                         continue;
600                 }
601                 g_free(str);
602
603                 str = g_key_file_get_string(keyfile,
604                                         services[i], "Modified", NULL);
605                 if (str != NULL) {
606                         g_time_val_from_iso8601(str, &modified);
607                         g_free(str);
608                 }
609
610                 ssid = g_key_file_get_string(keyfile,
611                                         services[i], "SSID", NULL);
612
613                 freq = g_key_file_get_integer(keyfile, services[i],
614                                         "Frequency", NULL);
615                 if (freq) {
616                         entry = g_try_new(struct last_connected, 1);
617                         if (entry == NULL) {
618                                 g_sequence_free(latest_list);
619                                 g_key_file_free(keyfile);
620                                 g_free(ssid);
621                                 return -ENOMEM;
622                         }
623
624                         entry->ssid = ssid;
625                         entry->modified = modified;
626                         entry->freq = freq;
627
628                         g_sequence_insert_sorted(latest_list, entry,
629                                                 sort_entry, NULL);
630                         num_ssids++;
631                 } else
632                         g_free(ssid);
633
634                 g_key_file_free(keyfile);
635         }
636
637         g_strfreev(services);
638
639         num_ssids = num_ssids > G_SUPPLICANT_MAX_FAST_SCAN ?
640                 G_SUPPLICANT_MAX_FAST_SCAN : num_ssids;
641
642         iter = g_sequence_get_begin_iter(latest_list);
643
644         for (i = 0; i < num_ssids; i++) {
645                 entry = g_sequence_get(iter);
646
647                 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
648                                                 entry->modified.tv_sec);
649
650                 add_scan_param(entry->ssid, entry->freq, scan_data, max_ssids);
651
652                 iter = g_sequence_iter_next(iter);
653         }
654
655         g_sequence_free(latest_list);
656         return num_ssids;
657 }
658
659 static int wifi_scan(struct connman_device *device)
660 {
661         stop_autoscan(device);
662
663         return throw_wifi_scan(device, scan_callback);
664 }
665
666 static int wifi_scan_fast(struct connman_device *device)
667 {
668         struct wifi_data *wifi = connman_device_get_data(device);
669         GSupplicantScanParams *scan_params = NULL;
670         int ret;
671         int driver_max_ssids = 0;
672
673         DBG("device %p %p", device, wifi->interface);
674
675         if (wifi->tethering == TRUE)
676                 return 0;
677
678         driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
679                                                         wifi->interface);
680         DBG("max ssids %d", driver_max_ssids);
681         if (driver_max_ssids == 0)
682                 return wifi_scan(device);
683
684         scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
685         if (scan_params == NULL)
686                 return -ENOMEM;
687
688         ret = get_latest_connections(driver_max_ssids, scan_params);
689         if (ret <= 0) {
690                 g_free(scan_params);
691                 return wifi_scan(device);
692         }
693
694         stop_autoscan(device);
695
696         connman_device_ref(device);
697         ret = g_supplicant_interface_scan(wifi->interface, scan_params,
698                                                 scan_callback, device);
699         if (ret == 0)
700                 connman_device_set_scanning(device, TRUE);
701         else {
702                 g_free(scan_params);
703                 connman_device_unref(device);
704         }
705
706         return ret;
707 }
708
709 static int wifi_scan_hidden(struct connman_device *device,
710                 const char *ssid, unsigned int ssid_len,
711                 const char *identity, const char* passphrase)
712 {
713         struct wifi_data *wifi = connman_device_get_data(device);
714         GSupplicantScanParams *scan_params = NULL;
715         struct hidden_params *hidden;
716         int ret;
717
718         DBG("hidden SSID %s", ssid);
719
720         if (wifi->tethering == TRUE || wifi->hidden != NULL)
721                 return -EBUSY;
722
723         if (ssid == NULL || ssid_len == 0 || ssid_len > 32)
724                 return -EINVAL;
725
726         scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
727         if (scan_params == NULL)
728                 return -ENOMEM;
729         memcpy(scan_params->ssids[0].ssid, ssid, ssid_len);
730         scan_params->ssids[0].ssid_len = ssid_len;
731         scan_params->num_ssids = 1;
732
733         hidden = g_try_new0(struct hidden_params, 1);
734         if (hidden == NULL) {
735                 g_free(scan_params);
736                 return -ENOMEM;
737         }
738         memcpy(hidden->ssid, ssid, ssid_len);
739         hidden->ssid_len = ssid_len;
740         hidden->identity = g_strdup(identity);
741         hidden->passphrase = g_strdup(passphrase);
742         wifi->hidden = hidden;
743
744         stop_autoscan(device);
745
746         connman_device_ref(device);
747         ret = g_supplicant_interface_scan(wifi->interface, scan_params,
748                         scan_callback, device);
749         if (ret == 0)
750                 connman_device_set_scanning(device, TRUE);
751         else {
752                 connman_device_unref(device);
753                 g_free(scan_params);
754                 hidden_free(wifi->hidden);
755                 wifi->hidden = NULL;
756         }
757
758         return ret;
759 }
760
761 static struct connman_device_driver wifi_ng_driver = {
762         .name           = "wifi",
763         .type           = CONNMAN_DEVICE_TYPE_WIFI,
764         .priority       = CONNMAN_DEVICE_PRIORITY_LOW,
765         .probe          = wifi_probe,
766         .remove         = wifi_remove,
767         .enable         = wifi_enable,
768         .disable        = wifi_disable,
769         .scan           = wifi_scan,
770         .scan_fast      = wifi_scan_fast,
771         .scan_hidden    = wifi_scan_hidden,
772 };
773
774 static void system_ready(void)
775 {
776         DBG("");
777
778         if (connman_device_driver_register(&wifi_ng_driver) < 0)
779                 connman_error("Failed to register WiFi driver");
780 }
781
782 static void system_killed(void)
783 {
784         DBG("");
785
786         connman_device_driver_unregister(&wifi_ng_driver);
787 }
788
789 static int network_probe(struct connman_network *network)
790 {
791         DBG("network %p", network);
792
793         return 0;
794 }
795
796 static void network_remove(struct connman_network *network)
797 {
798         struct connman_device *device = connman_network_get_device(network);
799         struct wifi_data *wifi;
800
801         DBG("network %p", network);
802
803         wifi = connman_device_get_data(device);
804         if (wifi == NULL)
805                 return;
806
807         if (wifi->network != network)
808                 return;
809
810         wifi->network = NULL;
811 }
812
813 static void connect_callback(int result, GSupplicantInterface *interface,
814                                                         void *user_data)
815 {
816         struct connman_network *network = user_data;
817
818         DBG("network %p result %d", network, result);
819
820         if (result == -ENOKEY) {
821                 connman_network_set_error(network,
822                                         CONNMAN_NETWORK_ERROR_INVALID_KEY);
823         } else if (result < 0) {
824                 connman_network_set_error(network,
825                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
826         }
827 }
828
829 static GSupplicantSecurity network_security(const char *security)
830 {
831         if (g_str_equal(security, "none") == TRUE)
832                 return G_SUPPLICANT_SECURITY_NONE;
833         else if (g_str_equal(security, "wep") == TRUE)
834                 return G_SUPPLICANT_SECURITY_WEP;
835         else if (g_str_equal(security, "psk") == TRUE)
836                 return G_SUPPLICANT_SECURITY_PSK;
837         else if (g_str_equal(security, "wpa") == TRUE)
838                 return G_SUPPLICANT_SECURITY_PSK;
839         else if (g_str_equal(security, "rsn") == TRUE)
840                 return G_SUPPLICANT_SECURITY_PSK;
841         else if (g_str_equal(security, "ieee8021x") == TRUE)
842                 return G_SUPPLICANT_SECURITY_IEEE8021X;
843
844         return G_SUPPLICANT_SECURITY_UNKNOWN;
845 }
846
847 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
848 {
849         const char *security, *passphrase, *agent_passphrase;
850
851         memset(ssid, 0, sizeof(*ssid));
852         ssid->mode = G_SUPPLICANT_MODE_INFRA;
853         ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
854                                                 &ssid->ssid_len);
855         ssid->scan_ssid = 1;
856         security = connman_network_get_string(network, "WiFi.Security");
857         ssid->security = network_security(security);
858         passphrase = connman_network_get_string(network,
859                                                 "WiFi.Passphrase");
860         if (passphrase == NULL || strlen(passphrase) == 0) {
861
862                 /* Use agent provided passphrase as a fallback */
863                 agent_passphrase = connman_network_get_string(network,
864                                                 "WiFi.AgentPassphrase");
865
866                 if (agent_passphrase == NULL || strlen(agent_passphrase) == 0)
867                         ssid->passphrase = NULL;
868                 else
869                         ssid->passphrase = agent_passphrase;
870         } else
871                 ssid->passphrase = passphrase;
872
873         ssid->eap = connman_network_get_string(network, "WiFi.EAP");
874
875         /*
876          * If our private key password is unset,
877          * we use the supplied passphrase. That is needed
878          * for PEAP where 2 passphrases (identity and client
879          * cert may have to be provided.
880          */
881         if (connman_network_get_string(network,
882                                         "WiFi.PrivateKeyPassphrase") == NULL)
883                 connman_network_set_string(network,
884                                                 "WiFi.PrivateKeyPassphrase",
885                                                 ssid->passphrase);
886         /* We must have an identity for both PEAP and TLS */
887         ssid->identity = connman_network_get_string(network, "WiFi.Identity");
888
889         /* Use agent provided identity as a fallback */
890         if (ssid->identity == NULL || strlen(ssid->identity) == 0)
891                 ssid->identity = connman_network_get_string(network,
892                                                         "WiFi.AgentIdentity");
893
894         ssid->ca_cert_path = connman_network_get_string(network,
895                                                         "WiFi.CACertFile");
896         ssid->client_cert_path = connman_network_get_string(network,
897                                                         "WiFi.ClientCertFile");
898         ssid->private_key_path = connman_network_get_string(network,
899                                                         "WiFi.PrivateKeyFile");
900         ssid->private_key_passphrase = connman_network_get_string(network,
901                                                 "WiFi.PrivateKeyPassphrase");
902         ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
903
904         ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
905         ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
906
907         if (connman_setting_get_bool("BackgroundScanning") == TRUE)
908                 ssid->bgscan = BGSCAN_DEFAULT;
909 }
910
911 static int network_connect(struct connman_network *network)
912 {
913         struct connman_device *device = connman_network_get_device(network);
914         struct wifi_data *wifi;
915         GSupplicantInterface *interface;
916         GSupplicantSSID *ssid;
917
918         DBG("network %p", network);
919
920         if (device == NULL)
921                 return -ENODEV;
922
923         wifi = connman_device_get_data(device);
924         if (wifi == NULL)
925                 return -ENODEV;
926
927         ssid = g_try_malloc0(sizeof(GSupplicantSSID));
928         if (ssid == NULL)
929                 return -ENOMEM;
930
931         interface = wifi->interface;
932
933         ssid_init(ssid, network);
934
935         if (wifi->disconnecting == TRUE)
936                 wifi->pending_network = network;
937         else {
938                 wifi->network = network;
939                 wifi->retries = 0;
940
941                 return g_supplicant_interface_connect(interface, ssid,
942                                                 connect_callback, network);
943         }
944
945         return -EINPROGRESS;
946 }
947
948 static void disconnect_callback(int result, GSupplicantInterface *interface,
949                                                                 void *user_data)
950 {
951         struct wifi_data *wifi = user_data;
952
953         if (wifi->network != NULL) {
954                 /*
955                  * if result < 0 supplican return an error because
956                  * the network is not current.
957                  * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
958                  * failed, call connman_network_set_connected to report
959                  * disconnect is completed.
960                  */
961                 if (result < 0)
962                         connman_network_set_connected(wifi->network, FALSE);
963         }
964
965         wifi->network = NULL;
966
967         wifi->disconnecting = FALSE;
968
969         if (wifi->pending_network != NULL) {
970                 network_connect(wifi->pending_network);
971                 wifi->pending_network = NULL;
972         }
973
974         start_autoscan(wifi->device);
975 }
976
977 static int network_disconnect(struct connman_network *network)
978 {
979         struct connman_device *device = connman_network_get_device(network);
980         struct wifi_data *wifi;
981         int err;
982
983         DBG("network %p", network);
984
985         wifi = connman_device_get_data(device);
986         if (wifi == NULL || wifi->interface == NULL)
987                 return -ENODEV;
988
989         connman_network_set_associating(network, FALSE);
990
991         if (wifi->disconnecting == TRUE)
992                 return -EALREADY;
993
994         wifi->disconnecting = TRUE;
995
996         err = g_supplicant_interface_disconnect(wifi->interface,
997                                                 disconnect_callback, wifi);
998         if (err < 0)
999                 wifi->disconnecting = FALSE;
1000
1001         return err;
1002 }
1003
1004 static struct connman_network_driver network_driver = {
1005         .name           = "wifi",
1006         .type           = CONNMAN_NETWORK_TYPE_WIFI,
1007         .priority       = CONNMAN_NETWORK_PRIORITY_LOW,
1008         .probe          = network_probe,
1009         .remove         = network_remove,
1010         .connect        = network_connect,
1011         .disconnect     = network_disconnect,
1012 };
1013
1014 static void interface_added(GSupplicantInterface *interface)
1015 {
1016         const char *ifname = g_supplicant_interface_get_ifname(interface);
1017         const char *driver = g_supplicant_interface_get_driver(interface);
1018         struct wifi_data *wifi;
1019
1020         wifi = g_supplicant_interface_get_data(interface);
1021
1022         /*
1023          * We can get here with a NULL wifi pointer when
1024          * the interface added signal is sent before the
1025          * interface creation callback is called.
1026          */
1027         if (wifi == NULL)
1028                 return;
1029
1030         DBG("ifname %s driver %s wifi %p tethering %d",
1031                         ifname, driver, wifi, wifi->tethering);
1032
1033         if (wifi->device == NULL) {
1034                 connman_error("WiFi device not set");
1035                 return;
1036         }
1037
1038         connman_device_set_powered(wifi->device, TRUE);
1039
1040         if (wifi->tethering == TRUE)
1041                 return;
1042 }
1043
1044 static connman_bool_t is_idle(struct wifi_data *wifi)
1045 {
1046         DBG("state %d", wifi->state);
1047
1048         switch (wifi->state) {
1049         case G_SUPPLICANT_STATE_UNKNOWN:
1050         case G_SUPPLICANT_STATE_DISCONNECTED:
1051         case G_SUPPLICANT_STATE_INACTIVE:
1052         case G_SUPPLICANT_STATE_SCANNING:
1053                 return TRUE;
1054
1055         case G_SUPPLICANT_STATE_AUTHENTICATING:
1056         case G_SUPPLICANT_STATE_ASSOCIATING:
1057         case G_SUPPLICANT_STATE_ASSOCIATED:
1058         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1059         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1060         case G_SUPPLICANT_STATE_COMPLETED:
1061                 return FALSE;
1062         }
1063
1064         return FALSE;
1065 }
1066
1067 static connman_bool_t is_idle_wps(GSupplicantInterface *interface,
1068                                                 struct wifi_data *wifi)
1069 {
1070         /* First, let's check if WPS processing did not went wrong */
1071         if (g_supplicant_interface_get_wps_state(interface) ==
1072                 G_SUPPLICANT_WPS_STATE_FAIL)
1073                 return FALSE;
1074
1075         /* Unlike normal connection, being associated while processing wps
1076          * actually means that we are idling. */
1077         switch (wifi->state) {
1078         case G_SUPPLICANT_STATE_UNKNOWN:
1079         case G_SUPPLICANT_STATE_DISCONNECTED:
1080         case G_SUPPLICANT_STATE_INACTIVE:
1081         case G_SUPPLICANT_STATE_SCANNING:
1082         case G_SUPPLICANT_STATE_ASSOCIATED:
1083                 return TRUE;
1084         case G_SUPPLICANT_STATE_AUTHENTICATING:
1085         case G_SUPPLICANT_STATE_ASSOCIATING:
1086         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1087         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1088         case G_SUPPLICANT_STATE_COMPLETED:
1089                 return FALSE;
1090         }
1091
1092         return FALSE;
1093 }
1094
1095 static connman_bool_t handle_wps_completion(GSupplicantInterface *interface,
1096                                         struct connman_network *network,
1097                                         struct connman_device *device,
1098                                         struct wifi_data *wifi)
1099 {
1100         connman_bool_t wps;
1101
1102         wps = connman_network_get_bool(network, "WiFi.UseWPS");
1103         if (wps == TRUE) {
1104                 const unsigned char *ssid, *wps_ssid;
1105                 unsigned int ssid_len, wps_ssid_len;
1106                 const char *wps_key;
1107
1108                 /* Checking if we got associated with requested
1109                  * network */
1110                 ssid = connman_network_get_blob(network, "WiFi.SSID",
1111                                                 &ssid_len);
1112
1113                 wps_ssid = g_supplicant_interface_get_wps_ssid(
1114                         interface, &wps_ssid_len);
1115
1116                 if (wps_ssid == NULL || wps_ssid_len != ssid_len ||
1117                                 memcmp(ssid, wps_ssid, ssid_len) != 0) {
1118                         connman_network_set_associating(network, FALSE);
1119                         g_supplicant_interface_disconnect(wifi->interface,
1120                                                 disconnect_callback, wifi);
1121                         return FALSE;
1122                 }
1123
1124                 wps_key = g_supplicant_interface_get_wps_key(interface);
1125                 connman_network_set_string(network, "WiFi.Passphrase",
1126                                         wps_key);
1127
1128                 connman_network_set_string(network, "WiFi.PinWPS", NULL);
1129         }
1130
1131         return TRUE;
1132 }
1133
1134 static connman_bool_t handle_4way_handshake_failure(GSupplicantInterface *interface,
1135                                         struct connman_network *network,
1136                                         struct wifi_data *wifi)
1137 {
1138         if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
1139                 return FALSE;
1140
1141         wifi->retries++;
1142
1143         if (wifi->retries < MAXIMUM_RETRIES)
1144                 return TRUE;
1145
1146         connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
1147
1148         return FALSE;
1149 }
1150
1151 static void interface_state(GSupplicantInterface *interface)
1152 {
1153         struct connman_network *network;
1154         struct connman_device *device;
1155         struct wifi_data *wifi;
1156         GSupplicantState state = g_supplicant_interface_get_state(interface);
1157         connman_bool_t wps;
1158
1159         wifi = g_supplicant_interface_get_data(interface);
1160
1161         DBG("wifi %p interface state %d", wifi, state);
1162
1163         if (wifi == NULL)
1164                 return;
1165
1166         network = wifi->network;
1167         device = wifi->device;
1168
1169         if (device == NULL || network == NULL)
1170                 return;
1171
1172         switch (state) {
1173         case G_SUPPLICANT_STATE_SCANNING:
1174                 break;
1175
1176         case G_SUPPLICANT_STATE_AUTHENTICATING:
1177         case G_SUPPLICANT_STATE_ASSOCIATING:
1178                 connman_network_set_associating(network, TRUE);
1179                 break;
1180
1181         case G_SUPPLICANT_STATE_COMPLETED:
1182                 if (handle_wps_completion(interface, network, device, wifi) ==
1183                                                                         FALSE)
1184                         break;
1185
1186                 connman_network_set_connected(network, TRUE);
1187                 break;
1188
1189         case G_SUPPLICANT_STATE_DISCONNECTED:
1190                 /*
1191                  * If we're in one of the idle modes, we have
1192                  * not started association yet and thus setting
1193                  * those ones to FALSE could cancel an association
1194                  * in progress.
1195                  */
1196                 wps = connman_network_get_bool(network, "WiFi.UseWPS");
1197                 if (wps == TRUE)
1198                         if (is_idle_wps(interface, wifi) == TRUE)
1199                                 break;
1200
1201                 if (is_idle(wifi))
1202                         break;
1203
1204                 /* If previous state was 4way-handshake, then
1205                  * it's either: psk was incorrect and thus we retry
1206                  * or if we reach the maximum retries we declare the
1207                  * psk as wrong */
1208                 if (handle_4way_handshake_failure(interface,
1209                                                 network, wifi) == TRUE)
1210                         break;
1211
1212                 /* We disable the selected network, if not then
1213                  * wpa_supplicant will loop retrying */
1214                 if (g_supplicant_interface_enable_selected_network(interface,
1215                                                 FALSE) != 0)
1216                         DBG("Could not disables selected network");
1217
1218                 connman_network_set_associating(network, FALSE);
1219                 connman_network_set_connected(network, FALSE);
1220                 break;
1221
1222         case G_SUPPLICANT_STATE_INACTIVE:
1223                 connman_network_set_associating(network, FALSE);
1224                 break;
1225
1226         case G_SUPPLICANT_STATE_UNKNOWN:
1227         case G_SUPPLICANT_STATE_ASSOCIATED:
1228         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1229         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1230                 break;
1231         }
1232
1233         wifi->state = state;
1234
1235         DBG("DONE");
1236 }
1237
1238 static void interface_removed(GSupplicantInterface *interface)
1239 {
1240         const char *ifname = g_supplicant_interface_get_ifname(interface);
1241         struct wifi_data *wifi;
1242
1243         DBG("ifname %s", ifname);
1244
1245         wifi = g_supplicant_interface_get_data(interface);
1246
1247         if (wifi != NULL && wifi->tethering == TRUE)
1248                 return;
1249
1250         if (wifi == NULL || wifi->device == NULL) {
1251                 connman_error("Wrong wifi pointer");
1252                 return;
1253         }
1254
1255         wifi->interface = NULL;
1256         connman_device_set_powered(wifi->device, FALSE);
1257 }
1258
1259 static void scan_started(GSupplicantInterface *interface)
1260 {
1261         DBG("");
1262 }
1263
1264 static void scan_finished(GSupplicantInterface *interface)
1265 {
1266         DBG("");
1267 }
1268
1269 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
1270 {
1271         unsigned char strength;
1272
1273         strength = 120 + g_supplicant_network_get_signal(supplicant_network);
1274         if (strength > 100)
1275                 strength = 100;
1276
1277         return strength;
1278 }
1279
1280 static void network_added(GSupplicantNetwork *supplicant_network)
1281 {
1282         struct connman_network *network;
1283         GSupplicantInterface *interface;
1284         struct wifi_data *wifi;
1285         const char *name, *identifier, *security, *group, *mode;
1286         const unsigned char *ssid;
1287         unsigned int ssid_len;
1288         connman_bool_t wps;
1289         connman_bool_t wps_pbc;
1290         connman_bool_t wps_ready;
1291         connman_bool_t wps_advertizing;
1292
1293         DBG("");
1294
1295         interface = g_supplicant_network_get_interface(supplicant_network);
1296         wifi = g_supplicant_interface_get_data(interface);
1297         name = g_supplicant_network_get_name(supplicant_network);
1298         identifier = g_supplicant_network_get_identifier(supplicant_network);
1299         security = g_supplicant_network_get_security(supplicant_network);
1300         group = g_supplicant_network_get_identifier(supplicant_network);
1301         wps = g_supplicant_network_get_wps(supplicant_network);
1302         wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
1303         wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
1304         wps_advertizing = g_supplicant_network_is_wps_advertizing(
1305                                                         supplicant_network);
1306         mode = g_supplicant_network_get_mode(supplicant_network);
1307
1308         if (wifi == NULL)
1309                 return;
1310
1311         ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
1312
1313         network = connman_device_get_network(wifi->device, identifier);
1314
1315         if (network == NULL) {
1316                 network = connman_network_create(identifier,
1317                                                 CONNMAN_NETWORK_TYPE_WIFI);
1318                 if (network == NULL)
1319                         return;
1320
1321                 connman_network_set_index(network, wifi->index);
1322
1323                 if (connman_device_add_network(wifi->device, network) < 0) {
1324                         connman_network_unref(network);
1325                         return;
1326                 }
1327
1328                 wifi->networks = g_slist_append(wifi->networks, network);
1329         }
1330
1331         if (name != NULL && name[0] != '\0')
1332                 connman_network_set_name(network, name);
1333
1334         connman_network_set_blob(network, "WiFi.SSID",
1335                                                 ssid, ssid_len);
1336         connman_network_set_string(network, "WiFi.Security", security);
1337         connman_network_set_strength(network,
1338                                 calculate_strength(supplicant_network));
1339         connman_network_set_bool(network, "WiFi.WPS", wps);
1340
1341         if (wps == TRUE) {
1342                 /* Is AP advertizing for WPS association?
1343                  * If so, we decide to use WPS by default */
1344                 if (wps_ready == TRUE && wps_pbc == TRUE &&
1345                                                 wps_advertizing == TRUE)
1346                         connman_network_set_bool(network, "WiFi.UseWPS", TRUE);
1347         }
1348
1349         connman_network_set_frequency(network,
1350                         g_supplicant_network_get_frequency(supplicant_network));
1351
1352         connman_network_set_available(network, TRUE);
1353         connman_network_set_string(network, "WiFi.Mode", mode);
1354
1355         if (ssid != NULL)
1356                 connman_network_set_group(network, group);
1357
1358         if (wifi->hidden != NULL) {
1359                 if (wifi->hidden->ssid_len == ssid_len &&
1360                                 memcmp(wifi->hidden->ssid, ssid,
1361                                                 ssid_len) == 0) {
1362                         connman_network_connect_hidden(network,
1363                                         wifi->hidden->identity,
1364                                         wifi->hidden->passphrase);
1365                         hidden_free(wifi->hidden);
1366                         wifi->hidden = NULL;
1367                 }
1368         }
1369 }
1370
1371 static void network_removed(GSupplicantNetwork *network)
1372 {
1373         GSupplicantInterface *interface;
1374         struct wifi_data *wifi;
1375         const char *name, *identifier;
1376         struct connman_network *connman_network;
1377
1378         interface = g_supplicant_network_get_interface(network);
1379         wifi = g_supplicant_interface_get_data(interface);
1380         identifier = g_supplicant_network_get_identifier(network);
1381         name = g_supplicant_network_get_name(network);
1382
1383         DBG("name %s", name);
1384
1385         if (wifi == NULL)
1386                 return;
1387
1388         connman_network = connman_device_get_network(wifi->device, identifier);
1389         if (connman_network == NULL)
1390                 return;
1391
1392         wifi->networks = g_slist_remove(wifi->networks, connman_network);
1393
1394         connman_device_remove_network(wifi->device, connman_network);
1395         connman_network_unref(connman_network);
1396 }
1397
1398 static void network_changed(GSupplicantNetwork *network, const char *property)
1399 {
1400         GSupplicantInterface *interface;
1401         struct wifi_data *wifi;
1402         const char *name, *identifier;
1403         struct connman_network *connman_network;
1404
1405         interface = g_supplicant_network_get_interface(network);
1406         wifi = g_supplicant_interface_get_data(interface);
1407         identifier = g_supplicant_network_get_identifier(network);
1408         name = g_supplicant_network_get_name(network);
1409
1410         DBG("name %s", name);
1411
1412         if (wifi == NULL)
1413                 return;
1414
1415         connman_network = connman_device_get_network(wifi->device, identifier);
1416         if (connman_network == NULL)
1417                 return;
1418
1419         if (g_str_equal(property, "Signal") == TRUE) {
1420                connman_network_set_strength(connman_network,
1421                                         calculate_strength(network));
1422                connman_network_update(connman_network);
1423         }
1424 }
1425
1426 static void debug(const char *str)
1427 {
1428         if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
1429                 connman_debug("%s", str);
1430 }
1431
1432 static const GSupplicantCallbacks callbacks = {
1433         .system_ready           = system_ready,
1434         .system_killed          = system_killed,
1435         .interface_added        = interface_added,
1436         .interface_state        = interface_state,
1437         .interface_removed      = interface_removed,
1438         .scan_started           = scan_started,
1439         .scan_finished          = scan_finished,
1440         .network_added          = network_added,
1441         .network_removed        = network_removed,
1442         .network_changed        = network_changed,
1443         .debug                  = debug,
1444 };
1445
1446
1447 static int tech_probe(struct connman_technology *technology)
1448 {
1449         wifi_technology = technology;
1450
1451         return 0;
1452 }
1453
1454 static void tech_remove(struct connman_technology *technology)
1455 {
1456         wifi_technology = NULL;
1457 }
1458
1459 struct wifi_tethering_info {
1460         struct wifi_data *wifi;
1461         struct connman_technology *technology;
1462         char *ifname;
1463         GSupplicantSSID *ssid;
1464 };
1465
1466 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
1467 {
1468         GSupplicantSSID *ap;
1469
1470         ap = g_try_malloc0(sizeof(GSupplicantSSID));
1471         if (ap == NULL)
1472                 return NULL;
1473
1474         ap->mode = G_SUPPLICANT_MODE_MASTER;
1475         ap->ssid = ssid;
1476         ap->ssid_len = strlen(ssid);
1477         ap->scan_ssid = 0;
1478         ap->freq = 2412;
1479
1480         if (passphrase == NULL || strlen(passphrase) == 0) {
1481                 ap->security = G_SUPPLICANT_SECURITY_NONE;
1482                 ap->passphrase = NULL;
1483         } else {
1484                ap->security = G_SUPPLICANT_SECURITY_PSK;
1485                ap->protocol = G_SUPPLICANT_PROTO_RSN;
1486                ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
1487                ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
1488                ap->passphrase = passphrase;
1489         }
1490
1491         return ap;
1492 }
1493
1494 static void ap_start_callback(int result, GSupplicantInterface *interface,
1495                                                         void *user_data)
1496 {
1497         struct wifi_tethering_info *info = user_data;
1498
1499         DBG("result %d index %d bridge %s",
1500                 result, info->wifi->index, info->wifi->bridge);
1501
1502         if (result < 0) {
1503                 connman_inet_remove_from_bridge(info->wifi->index,
1504                                                         info->wifi->bridge);
1505                 connman_technology_tethering_notify(info->technology, FALSE);
1506         }
1507
1508         g_free(info->ifname);
1509         g_free(info);
1510 }
1511
1512 static void ap_create_callback(int result,
1513                                 GSupplicantInterface *interface,
1514                                         void *user_data)
1515 {
1516         struct wifi_tethering_info *info = user_data;
1517
1518         DBG("result %d ifname %s", result,
1519                                 g_supplicant_interface_get_ifname(interface));
1520
1521         if (result < 0) {
1522                 connman_inet_remove_from_bridge(info->wifi->index,
1523                                                         info->wifi->bridge);
1524                 connman_technology_tethering_notify(info->technology, FALSE);
1525
1526                 g_free(info->ifname);
1527                 g_free(info);
1528                 return;
1529         }
1530
1531         info->wifi->interface = interface;
1532         g_supplicant_interface_set_data(interface, info->wifi);
1533
1534         if (g_supplicant_interface_set_apscan(interface, 2) < 0)
1535                 connman_error("Failed to set interface ap_scan property");
1536
1537         g_supplicant_interface_connect(interface, info->ssid,
1538                                                 ap_start_callback, info);
1539 }
1540
1541 static void sta_remove_callback(int result,
1542                                 GSupplicantInterface *interface,
1543                                         void *user_data)
1544 {
1545         struct wifi_tethering_info *info = user_data;
1546         const char *driver = connman_option_get_string("wifi");
1547
1548         DBG("ifname %s result %d ", info->ifname, result);
1549
1550         if (result < 0) {
1551                 info->wifi->tethering = TRUE;
1552
1553                 g_free(info->ifname);
1554                 g_free(info);
1555                 return;
1556         }
1557
1558         info->wifi->interface = NULL;
1559
1560         connman_technology_tethering_notify(info->technology, TRUE);
1561
1562         g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
1563                                                 ap_create_callback,
1564                                                         info);
1565 }
1566
1567 static int tech_set_tethering(struct connman_technology *technology,
1568                                 const char *identifier, const char *passphrase,
1569                                 const char *bridge, connman_bool_t enabled)
1570 {
1571         GList *list;
1572         GSupplicantInterface *interface;
1573         struct wifi_data *wifi;
1574         struct wifi_tethering_info *info;
1575         const char *ifname;
1576         unsigned int mode;
1577         int err;
1578
1579         DBG("");
1580
1581         if (enabled == FALSE) {
1582                 for (list = iface_list; list; list = list->next) {
1583                         wifi = list->data;
1584
1585                         if (wifi->tethering == TRUE) {
1586                                 wifi->tethering = FALSE;
1587
1588                                 connman_inet_remove_from_bridge(wifi->index,
1589                                                                         bridge);
1590                                 wifi->bridged = FALSE;
1591                         }
1592                 }
1593
1594                 connman_technology_tethering_notify(technology, FALSE);
1595
1596                 return 0;
1597         }
1598
1599         for (list = iface_list; list; list = list->next) {
1600                 wifi = list->data;
1601
1602                 interface = wifi->interface;
1603
1604                 if (interface == NULL)
1605                         continue;
1606
1607                 ifname = g_supplicant_interface_get_ifname(wifi->interface);
1608
1609                 mode = g_supplicant_interface_get_mode(interface);
1610                 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
1611                         DBG("%s does not support AP mode", ifname);
1612                         continue;
1613                 }
1614
1615                 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
1616                 if (info == NULL)
1617                         return -ENOMEM;
1618
1619                 info->wifi = wifi;
1620                 info->technology = technology;
1621                 info->wifi->bridge = bridge;
1622                 info->ssid = ssid_ap_init(identifier, passphrase);
1623                 if (info->ssid == NULL) {
1624                         g_free(info);
1625                         continue;
1626                 }
1627                 info->ifname = g_strdup(ifname);
1628                 if (info->ifname == NULL) {
1629                         g_free(info);
1630                         continue;
1631                 }
1632
1633                 info->wifi->tethering = TRUE;
1634
1635                 err = g_supplicant_interface_remove(interface,
1636                                                 sta_remove_callback,
1637                                                         info);
1638                 if (err == 0)
1639                         return err;
1640         }
1641
1642         return -EOPNOTSUPP;
1643 }
1644
1645 static void regdom_callback(void *user_data)
1646 {
1647         char *alpha2 = user_data;
1648
1649         DBG("");
1650
1651         if (wifi_technology == NULL)
1652                 return;
1653
1654         connman_technology_regdom_notify(wifi_technology, alpha2);
1655 }
1656
1657 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
1658 {
1659         return g_supplicant_set_country(alpha2, regdom_callback, alpha2);
1660 }
1661
1662 static struct connman_technology_driver tech_driver = {
1663         .name           = "wifi",
1664         .type           = CONNMAN_SERVICE_TYPE_WIFI,
1665         .probe          = tech_probe,
1666         .remove         = tech_remove,
1667         .set_tethering  = tech_set_tethering,
1668         .set_regdom     = tech_set_regdom,
1669 };
1670
1671 static int wifi_init(void)
1672 {
1673         int err;
1674
1675         err = connman_network_driver_register(&network_driver);
1676         if (err < 0)
1677                 return err;
1678
1679         err = g_supplicant_register(&callbacks);
1680         if (err < 0) {
1681                 connman_network_driver_unregister(&network_driver);
1682                 return err;
1683         }
1684
1685         err = connman_technology_driver_register(&tech_driver);
1686         if (err < 0) {
1687                 g_supplicant_unregister(&callbacks);
1688                 connman_network_driver_unregister(&network_driver);
1689                 return err;
1690         }
1691
1692         return 0;
1693 }
1694
1695 static void wifi_exit(void)
1696 {
1697         DBG();
1698
1699         connman_technology_driver_unregister(&tech_driver);
1700
1701         g_supplicant_unregister(&callbacks);
1702
1703         connman_network_driver_unregister(&network_driver);
1704 }
1705
1706 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
1707                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)