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