ef4dd9515e76d2918b1edabbefaec0b220f8b023
[platform/upstream/connman.git] / plugins / wifi.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2014  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/service.h>
51 #include <connman/peer.h>
52 #include <connman/log.h>
53 #include <connman/option.h>
54 #include <connman/storage.h>
55 #include <include/setting.h>
56 #include <connman/provision.h>
57
58 #include <gsupplicant/gsupplicant.h>
59
60 #define CLEANUP_TIMEOUT   8     /* in seconds */
61 #define INACTIVE_TIMEOUT  12    /* in seconds */
62 #define FAVORITE_MAXIMUM_RETRIES 2
63
64 #define BGSCAN_DEFAULT "simple:30:-45:300"
65 #define AUTOSCAN_DEFAULT "exponential:3:300"
66
67 #define P2P_FIND_TIMEOUT 30
68
69 static struct connman_technology *wifi_technology = NULL;
70 static struct connman_technology *p2p_technology = NULL;
71
72 struct hidden_params {
73         char ssid[32];
74         unsigned int ssid_len;
75         char *identity;
76         char *passphrase;
77         char *security;
78         GSupplicantScanParams *scan_params;
79         gpointer user_data;
80 };
81
82 /**
83  * Used for autoscan "emulation".
84  * Should be removed when wpa_s autoscan support will be by default.
85  */
86 struct autoscan_params {
87         int base;
88         int limit;
89         int interval;
90         unsigned int timeout;
91 };
92
93 struct wifi_data {
94         char *identifier;
95         struct connman_device *device;
96         struct connman_network *network;
97         struct connman_network *pending_network;
98         GSList *networks;
99         GSupplicantInterface *interface;
100         GSupplicantState state;
101         bool connected;
102         bool disconnecting;
103         bool tethering;
104         bool bridged;
105         bool interface_ready;
106         const char *bridge;
107         int index;
108         unsigned flags;
109         unsigned int watch;
110         int retries;
111         struct hidden_params *hidden;
112         bool postpone_hidden;
113         /**
114          * autoscan "emulation".
115          */
116         struct autoscan_params *autoscan;
117
118         GSupplicantScanParams *scan_params;
119         unsigned int p2p_find_timeout;
120 };
121
122 static GList *iface_list = NULL;
123
124 static void start_autoscan(struct connman_device *device);
125
126 static int p2p_tech_probe(struct connman_technology *technology)
127 {
128         p2p_technology = technology;
129
130         return 0;
131 }
132
133 static void p2p_tech_remove(struct connman_technology *technology)
134 {
135         p2p_technology = NULL;
136 }
137
138 static struct connman_technology_driver p2p_tech_driver = {
139         .name           = "p2p",
140         .type           = CONNMAN_SERVICE_TYPE_P2P,
141         .probe          = p2p_tech_probe,
142         .remove         = p2p_tech_remove,
143 };
144
145 static void handle_tethering(struct wifi_data *wifi)
146 {
147         if (!wifi->tethering)
148                 return;
149
150         if (!wifi->bridge)
151                 return;
152
153         if (wifi->bridged)
154                 return;
155
156         DBG("index %d bridge %s", wifi->index, wifi->bridge);
157
158         if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
159                 return;
160
161         wifi->bridged = true;
162 }
163
164 static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
165 {
166         struct connman_device *device = user_data;
167         struct wifi_data *wifi = connman_device_get_data(device);
168
169         if (!wifi)
170                 return;
171
172         DBG("index %d flags %d change %d", wifi->index, flags, change);
173
174         if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
175                 if (flags & IFF_UP)
176                         DBG("interface up");
177                 else
178                         DBG("interface down");
179         }
180
181         if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
182                 if (flags & IFF_LOWER_UP) {
183                         DBG("carrier on");
184
185                         handle_tethering(wifi);
186                 } else
187                         DBG("carrier off");
188         }
189
190         wifi->flags = flags;
191 }
192
193 static int wifi_probe(struct connman_device *device)
194 {
195         struct wifi_data *wifi;
196
197         DBG("device %p", device);
198
199         wifi = g_try_new0(struct wifi_data, 1);
200         if (!wifi)
201                 return -ENOMEM;
202
203         wifi->state = G_SUPPLICANT_STATE_INACTIVE;
204
205         connman_device_set_data(device, wifi);
206         wifi->device = connman_device_ref(device);
207
208         wifi->index = connman_device_get_index(device);
209         wifi->flags = 0;
210
211         wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
212                                                         wifi_newlink, device);
213
214         iface_list = g_list_append(iface_list, wifi);
215
216         return 0;
217 }
218
219 static void remove_networks(struct connman_device *device,
220                                 struct wifi_data *wifi)
221 {
222         GSList *list;
223
224         for (list = wifi->networks; list; list = list->next) {
225                 struct connman_network *network = list->data;
226
227                 connman_device_remove_network(device, network);
228                 connman_network_unref(network);
229         }
230
231         g_slist_free(wifi->networks);
232         wifi->networks = NULL;
233 }
234
235 static void reset_autoscan(struct connman_device *device)
236 {
237         struct wifi_data *wifi = connman_device_get_data(device);
238         struct autoscan_params *autoscan;
239
240         DBG("");
241
242         if (!wifi || !wifi->autoscan)
243                 return;
244
245         autoscan = wifi->autoscan;
246
247         if (autoscan->timeout == 0 && autoscan->interval == 0)
248                 return;
249
250         g_source_remove(autoscan->timeout);
251
252         autoscan->timeout = 0;
253         autoscan->interval = 0;
254
255         connman_device_unref(device);
256 }
257
258 static void stop_autoscan(struct connman_device *device)
259 {
260         const struct wifi_data *wifi = connman_device_get_data(device);
261
262         if (!wifi || !wifi->autoscan)
263                 return;
264
265         reset_autoscan(device);
266
267         connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
268 }
269
270 static void check_p2p_technology(void)
271 {
272         bool p2p_exists = false;
273         GList *list;
274
275         for (list = iface_list; list; list = list->next) {
276                 struct wifi_data *w = list->data;
277
278                 if (w->interface &&
279                                 g_supplicant_interface_has_p2p(w->interface))
280                         p2p_exists = true;
281         }
282
283         if (!p2p_exists)
284                 connman_technology_driver_unregister(&p2p_tech_driver);
285 }
286
287 static void wifi_remove(struct connman_device *device)
288 {
289         struct wifi_data *wifi = connman_device_get_data(device);
290
291         DBG("device %p wifi %p", device, wifi);
292
293         if (!wifi)
294                 return;
295
296         stop_autoscan(device);
297
298         iface_list = g_list_remove(iface_list, wifi);
299
300         check_p2p_technology();
301
302         if (wifi->p2p_find_timeout) {
303                 g_source_remove(wifi->p2p_find_timeout);
304                 connman_device_unref(wifi->device);
305         }
306
307         remove_networks(device, wifi);
308
309         connman_device_set_powered(device, false);
310         connman_device_set_data(device, NULL);
311         connman_device_unref(wifi->device);
312         connman_rtnl_remove_watch(wifi->watch);
313
314         g_supplicant_interface_set_data(wifi->interface, NULL);
315
316         if (wifi->scan_params)
317                 g_supplicant_free_scan_params(wifi->scan_params);
318
319         g_free(wifi->autoscan);
320         g_free(wifi->identifier);
321         g_free(wifi);
322 }
323
324 static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
325 {
326         GSList *iter;
327
328         for (iter = list; iter; iter = g_slist_next(iter)) {
329                 struct scan_ssid *scan_ssid = iter->data;
330
331                 if (ssid_len == scan_ssid->ssid_len &&
332                                 memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
333                         return true;
334         }
335
336         return false;
337 }
338
339 static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
340                         int freq, GSupplicantScanParams *scan_data,
341                         int driver_max_scan_ssids, char *ssid_name)
342 {
343         unsigned int i;
344         struct scan_ssid *scan_ssid;
345
346         if ((driver_max_scan_ssids == 0 ||
347                         driver_max_scan_ssids > scan_data->num_ssids) &&
348                         (hex_ssid || raw_ssid)) {
349                 gchar *ssid;
350                 unsigned int j = 0, hex;
351
352                 if (hex_ssid) {
353                         size_t hex_ssid_len = strlen(hex_ssid);
354
355                         ssid = g_try_malloc0(hex_ssid_len / 2);
356                         if (!ssid)
357                                 return -ENOMEM;
358
359                         for (i = 0; i < hex_ssid_len; i += 2) {
360                                 sscanf(hex_ssid + i, "%02x", &hex);
361                                 ssid[j++] = hex;
362                         }
363                 } else {
364                         ssid = raw_ssid;
365                         j = ssid_len;
366                 }
367
368                 /*
369                  * If we have already added hidden AP to the list,
370                  * then do not do it again. This might happen if you have
371                  * used or are using multiple wifi cards, so in that case
372                  * you might have multiple service files for same AP.
373                  */
374                 if (is_duplicate(scan_data->ssids, ssid, j)) {
375                         if (hex_ssid)
376                                 g_free(ssid);
377                         return 0;
378                 }
379
380                 scan_ssid = g_try_new(struct scan_ssid, 1);
381                 if (!scan_ssid) {
382                         if (hex_ssid)
383                                 g_free(ssid);
384                         return -ENOMEM;
385                 }
386
387                 memcpy(scan_ssid->ssid, ssid, j);
388                 scan_ssid->ssid_len = j;
389                 scan_data->ssids = g_slist_prepend(scan_data->ssids,
390                                                                 scan_ssid);
391
392                 scan_data->num_ssids++;
393
394                 DBG("SSID %s added to scanned list of %d entries", ssid_name,
395                                                         scan_data->num_ssids);
396
397                 if (hex_ssid)
398                         g_free(ssid);
399         } else
400                 return -EINVAL;
401
402         scan_data->ssids = g_slist_reverse(scan_data->ssids);
403
404         if (!scan_data->freqs) {
405                 scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
406                 if (!scan_data->freqs) {
407                         g_slist_free_full(scan_data->ssids, g_free);
408                         return -ENOMEM;
409                 }
410
411                 scan_data->num_freqs = 1;
412                 scan_data->freqs[0] = freq;
413         } else {
414                 bool duplicate = false;
415
416                 /* Don't add duplicate entries */
417                 for (i = 0; i < scan_data->num_freqs; i++) {
418                         if (scan_data->freqs[i] == freq) {
419                                 duplicate = true;
420                                 break;
421                         }
422                 }
423
424                 if (!duplicate) {
425                         scan_data->num_freqs++;
426                         scan_data->freqs = g_try_realloc(scan_data->freqs,
427                                 sizeof(uint16_t) * scan_data->num_freqs);
428                         if (!scan_data->freqs) {
429                                 g_slist_free_full(scan_data->ssids, g_free);
430                                 return -ENOMEM;
431                         }
432                         scan_data->freqs[scan_data->num_freqs - 1] = freq;
433                 }
434         }
435
436         return 1;
437 }
438
439 static int get_hidden_connections(GSupplicantScanParams *scan_data)
440 {
441         struct connman_config_entry **entries;
442         GKeyFile *keyfile;
443         gchar **services;
444         char *ssid, *name;
445         int i, freq, ret;
446         bool value;
447         int num_ssids = 0, add_param_failed = 0;
448
449         services = connman_storage_get_services();
450         for (i = 0; services && services[i]; i++) {
451                 if (strncmp(services[i], "wifi_", 5) != 0)
452                         continue;
453
454                 keyfile = connman_storage_load_service(services[i]);
455                 if (!keyfile)
456                         continue;
457
458                 value = g_key_file_get_boolean(keyfile,
459                                         services[i], "Hidden", NULL);
460                 if (!value) {
461                         g_key_file_free(keyfile);
462                         continue;
463                 }
464
465                 value = g_key_file_get_boolean(keyfile,
466                                         services[i], "Favorite", NULL);
467                 if (!value) {
468                         g_key_file_free(keyfile);
469                         continue;
470                 }
471
472                 ssid = g_key_file_get_string(keyfile,
473                                         services[i], "SSID", NULL);
474
475                 freq = g_key_file_get_integer(keyfile, services[i],
476                                         "Frequency", NULL);
477
478                 name = g_key_file_get_string(keyfile, services[i], "Name",
479                                                                 NULL);
480
481                 ret = add_scan_param(ssid, NULL, 0, freq, scan_data, 0, name);
482                 if (ret < 0)
483                         add_param_failed++;
484                 else if (ret > 0)
485                         num_ssids++;
486
487                 g_free(ssid);
488                 g_free(name);
489                 g_key_file_free(keyfile);
490         }
491
492         /*
493          * Check if there are any hidden AP that needs to be provisioned.
494          */
495         entries = connman_config_get_entries("wifi");
496         for (i = 0; entries && entries[i]; i++) {
497                 int len;
498
499                 if (!entries[i]->hidden)
500                         continue;
501
502                 if (!entries[i]->ssid) {
503                         ssid = entries[i]->name;
504                         len = strlen(ssid);
505                 } else {
506                         ssid = entries[i]->ssid;
507                         len = entries[i]->ssid_len;
508                 }
509
510                 if (!ssid)
511                         continue;
512
513                 ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
514                 if (ret < 0)
515                         add_param_failed++;
516                 else if (ret > 0)
517                         num_ssids++;
518         }
519
520         connman_config_free_entries(entries);
521
522         if (add_param_failed > 0)
523                 DBG("Unable to scan %d out of %d SSIDs",
524                                         add_param_failed, num_ssids);
525
526         g_strfreev(services);
527
528         return num_ssids;
529 }
530
531 static int get_hidden_connections_params(struct wifi_data *wifi,
532                                         GSupplicantScanParams *scan_params)
533 {
534         int driver_max_ssids, i;
535         GSupplicantScanParams *orig_params;
536
537         /*
538          * Scan hidden networks so that we can autoconnect to them.
539          * We will assume 1 as a default number of ssid to scan.
540          */
541         driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
542                                                         wifi->interface);
543         if (driver_max_ssids == 0)
544                 driver_max_ssids = 1;
545
546         DBG("max ssids %d", driver_max_ssids);
547
548         if (!wifi->scan_params) {
549                 wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
550                 if (!wifi->scan_params)
551                         return 0;
552
553                 if (get_hidden_connections(wifi->scan_params) == 0) {
554                         g_supplicant_free_scan_params(wifi->scan_params);
555                         wifi->scan_params = NULL;
556
557                         return 0;
558                 }
559         }
560
561         orig_params = wifi->scan_params;
562
563         /* Let's transfer driver_max_ssids params */
564         for (i = 0; i < driver_max_ssids; i++) {
565                 struct scan_ssid *ssid;
566
567                 if (!wifi->scan_params->ssids)
568                         break;
569
570                 ssid = orig_params->ssids->data;
571                 orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
572                 scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
573         }
574
575         if (i > 0) {
576                 scan_params->num_ssids = i;
577                 scan_params->ssids = g_slist_reverse(scan_params->ssids);
578
579                 scan_params->freqs = g_memdup(orig_params->freqs,
580                                 sizeof(uint16_t) * orig_params->num_freqs);
581                 if (!scan_params->freqs)
582                         goto err;
583
584                 scan_params->num_freqs = orig_params->num_freqs;
585
586         } else
587                 goto err;
588
589         orig_params->num_ssids -= scan_params->num_ssids;
590
591         return scan_params->num_ssids;
592
593 err:
594         g_slist_free_full(scan_params->ssids, g_free);
595         g_supplicant_free_scan_params(wifi->scan_params);
596         wifi->scan_params = NULL;
597
598         return 0;
599 }
600
601 static int throw_wifi_scan(struct connman_device *device,
602                         GSupplicantInterfaceCallback callback)
603 {
604         struct wifi_data *wifi = connman_device_get_data(device);
605         int ret;
606
607         if (!wifi)
608                 return -ENODEV;
609
610         DBG("device %p %p", device, wifi->interface);
611
612         if (wifi->tethering)
613                 return -EBUSY;
614
615         if (connman_device_get_scanning(device))
616                 return -EALREADY;
617
618         connman_device_ref(device);
619
620         ret = g_supplicant_interface_scan(wifi->interface, NULL,
621                                                 callback, device);
622         if (ret == 0) {
623                 connman_device_set_scanning(device,
624                                 CONNMAN_SERVICE_TYPE_WIFI, true);
625         } else
626                 connman_device_unref(device);
627
628         return ret;
629 }
630
631 static void hidden_free(struct hidden_params *hidden)
632 {
633         if (!hidden)
634                 return;
635
636         if (hidden->scan_params)
637                 g_supplicant_free_scan_params(hidden->scan_params);
638         g_free(hidden->identity);
639         g_free(hidden->passphrase);
640         g_free(hidden->security);
641         g_free(hidden);
642 }
643
644 static void scan_callback(int result, GSupplicantInterface *interface,
645                                                 void *user_data)
646 {
647         struct connman_device *device = user_data;
648         struct wifi_data *wifi = connman_device_get_data(device);
649         bool scanning;
650
651         DBG("result %d wifi %p", result, wifi);
652
653         if (wifi) {
654                 if (wifi->hidden && !wifi->postpone_hidden) {
655                         connman_network_clear_hidden(wifi->hidden->user_data);
656                         hidden_free(wifi->hidden);
657                         wifi->hidden = NULL;
658                 }
659
660                 if (wifi->scan_params) {
661                         g_supplicant_free_scan_params(wifi->scan_params);
662                         wifi->scan_params = NULL;
663                 }
664         }
665
666         if (result < 0)
667                 connman_device_reset_scanning(device);
668
669         /* User is connecting to a hidden AP, let's wait for finished event */
670         if (wifi && wifi->hidden && wifi->postpone_hidden) {
671                 GSupplicantScanParams *scan_params;
672                 int ret;
673
674                 wifi->postpone_hidden = false;
675                 scan_params = wifi->hidden->scan_params;
676                 wifi->hidden->scan_params = NULL;
677
678                 reset_autoscan(device);
679
680                 ret = g_supplicant_interface_scan(wifi->interface, scan_params,
681                                                         scan_callback, device);
682                 if (ret == 0)
683                         return;
684
685                 /* On error, let's recall scan_callback, which will cleanup */
686                 return scan_callback(ret, interface, user_data);
687         }
688
689         scanning = connman_device_get_scanning(device);
690
691         if (scanning) {
692                 connman_device_set_scanning(device,
693                                 CONNMAN_SERVICE_TYPE_WIFI, false);
694         }
695
696         if (result != -ENOLINK)
697                 start_autoscan(device);
698
699         /*
700          * If we are here then we were scanning; however, if we are
701          * also mid-flight disabling the interface, then wifi_disable
702          * has already cleared the device scanning state and
703          * unreferenced the device, obviating the need to do it here.
704          */
705
706         if (scanning)
707                 connman_device_unref(device);
708 }
709
710 static void scan_callback_hidden(int result,
711                         GSupplicantInterface *interface, void *user_data)
712 {
713         struct connman_device *device = user_data;
714         struct wifi_data *wifi = connman_device_get_data(device);
715         GSupplicantScanParams *scan_params;
716         int ret;
717
718         DBG("result %d wifi %p", result, wifi);
719
720         if (!wifi)
721                 goto out;
722
723         /* User is trying to connect to a hidden AP */
724         if (wifi->hidden && wifi->postpone_hidden)
725                 goto out;
726
727         scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
728         if (!scan_params)
729                 goto out;
730
731         if (get_hidden_connections_params(wifi, scan_params) > 0) {
732                 ret = g_supplicant_interface_scan(wifi->interface,
733                                                         scan_params,
734                                                         scan_callback_hidden,
735                                                         device);
736                 if (ret == 0)
737                         return;
738         }
739
740         g_supplicant_free_scan_params(scan_params);
741
742 out:
743         scan_callback(result, interface, user_data);
744 }
745
746 static gboolean autoscan_timeout(gpointer data)
747 {
748         struct connman_device *device = data;
749         struct wifi_data *wifi = connman_device_get_data(device);
750         struct autoscan_params *autoscan;
751         int interval;
752
753         if (!wifi)
754                 return FALSE;
755
756         autoscan = wifi->autoscan;
757
758         if (autoscan->interval <= 0) {
759                 interval = autoscan->base;
760                 goto set_interval;
761         } else
762                 interval = autoscan->interval * autoscan->base;
763
764         if (autoscan->interval >= autoscan->limit)
765                 interval = autoscan->limit;
766
767         throw_wifi_scan(wifi->device, scan_callback_hidden);
768
769 set_interval:
770         DBG("interval %d", interval);
771
772         autoscan->interval = interval;
773
774         autoscan->timeout = g_timeout_add_seconds(interval,
775                                                 autoscan_timeout, device);
776
777         return FALSE;
778 }
779
780 static void start_autoscan(struct connman_device *device)
781 {
782         struct wifi_data *wifi = connman_device_get_data(device);
783         struct autoscan_params *autoscan;
784
785         DBG("");
786
787         if (!wifi)
788                 return;
789
790         autoscan = wifi->autoscan;
791         if (!autoscan)
792                 return;
793
794         if (autoscan->timeout > 0 || autoscan->interval > 0)
795                 return;
796
797         connman_device_ref(device);
798
799         autoscan_timeout(device);
800 }
801
802 static struct autoscan_params *parse_autoscan_params(const char *params)
803 {
804         struct autoscan_params *autoscan;
805         char **list_params;
806         int limit;
807         int base;
808
809         DBG("Emulating autoscan");
810
811         list_params = g_strsplit(params, ":", 0);
812         if (list_params == 0)
813                 return NULL;
814
815         if (g_strv_length(list_params) < 3) {
816                 g_strfreev(list_params);
817                 return NULL;
818         }
819
820         base = atoi(list_params[1]);
821         limit = atoi(list_params[2]);
822
823         g_strfreev(list_params);
824
825         autoscan = g_try_malloc0(sizeof(struct autoscan_params));
826         if (!autoscan) {
827                 DBG("Could not allocate memory for autoscan");
828                 return NULL;
829         }
830
831         DBG("base %d - limit %d", base, limit);
832         autoscan->base = base;
833         autoscan->limit = limit;
834
835         return autoscan;
836 }
837
838 static void setup_autoscan(struct wifi_data *wifi)
839 {
840         if (!wifi->autoscan)
841                 wifi->autoscan = parse_autoscan_params(AUTOSCAN_DEFAULT);
842
843         start_autoscan(wifi->device);
844 }
845
846 static void interface_autoscan_callback(int result,
847                                         GSupplicantInterface *interface,
848                                                         void *user_data)
849 {
850         struct wifi_data *wifi = user_data;
851
852         if (result < 0) {
853                 DBG("Could not enable Autoscan, falling back...");
854                 setup_autoscan(wifi);
855         }
856 }
857
858 static void finalize_interface_creation(struct wifi_data *wifi)
859 {
860         GSupplicantInterface *interface = wifi->interface;
861
862         DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
863
864         if (!wifi->device) {
865                 connman_error("WiFi device not set");
866                 return;
867         }
868
869         connman_device_set_powered(wifi->device, true);
870
871         if (!connman_setting_get_bool("BackgroundScanning"))
872                 return;
873
874         /* Setting up automatic scanning */
875         if (g_supplicant_interface_autoscan(interface, AUTOSCAN_DEFAULT,
876                                 interface_autoscan_callback, wifi) < 0) {
877                 DBG("Could not enable Autoscan, falling back...");
878                 setup_autoscan(wifi);
879         }
880 }
881
882 static void interface_create_callback(int result,
883                                         GSupplicantInterface *interface,
884                                                         void *user_data)
885 {
886         struct wifi_data *wifi = user_data;
887
888         DBG("result %d ifname %s, wifi %p", result,
889                                 g_supplicant_interface_get_ifname(interface),
890                                 wifi);
891
892         if (result < 0 || !wifi)
893                 return;
894
895         wifi->interface = interface;
896         g_supplicant_interface_set_data(interface, wifi);
897
898         if (g_supplicant_interface_get_ready(interface)) {
899                 wifi->interface_ready = true;
900                 finalize_interface_creation(wifi);
901         }
902 }
903
904 static int wifi_enable(struct connman_device *device)
905 {
906         struct wifi_data *wifi = connman_device_get_data(device);
907         int index;
908         char *interface;
909         const char *driver = connman_option_get_string("wifi");
910         int ret;
911
912         DBG("device %p %p", device, wifi);
913
914         index = connman_device_get_index(device);
915         if (!wifi || index < 0)
916                 return -ENODEV;
917
918         interface = connman_inet_ifname(index);
919         ret = g_supplicant_interface_create(interface, driver, NULL,
920                                                 interface_create_callback,
921                                                         wifi);
922         g_free(interface);
923
924         if (ret < 0)
925                 return ret;
926
927         return -EINPROGRESS;
928 }
929
930 static int wifi_disable(struct connman_device *device)
931 {
932         struct wifi_data *wifi = connman_device_get_data(device);
933         int ret;
934
935         DBG("device %p wifi %p", device, wifi);
936
937         if (!wifi)
938                 return -ENODEV;
939
940         wifi->connected = false;
941         wifi->disconnecting = false;
942
943         if (wifi->pending_network)
944                 wifi->pending_network = NULL;
945
946         stop_autoscan(device);
947
948         if (wifi->p2p_find_timeout) {
949                 g_source_remove(wifi->p2p_find_timeout);
950                 wifi->p2p_find_timeout = 0;
951                 connman_device_unref(wifi->device);
952         }
953
954         /* In case of a user scan, device is still referenced */
955         if (connman_device_get_scanning(device)) {
956                 connman_device_set_scanning(device,
957                                 CONNMAN_SERVICE_TYPE_WIFI, false);
958                 connman_device_unref(wifi->device);
959         }
960
961         remove_networks(device, wifi);
962
963         ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
964         if (ret < 0)
965                 return ret;
966
967         return -EINPROGRESS;
968 }
969
970 struct last_connected {
971         GTimeVal modified;
972         gchar *ssid;
973         int freq;
974 };
975
976 static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
977 {
978         GTimeVal *aval = (GTimeVal *)a;
979         GTimeVal *bval = (GTimeVal *)b;
980
981         /* Note that the sort order is descending */
982         if (aval->tv_sec < bval->tv_sec)
983                 return 1;
984
985         if (aval->tv_sec > bval->tv_sec)
986                 return -1;
987
988         return 0;
989 }
990
991 static void free_entry(gpointer data)
992 {
993         struct last_connected *entry = data;
994
995         g_free(entry->ssid);
996         g_free(entry);
997 }
998
999 static int get_latest_connections(int max_ssids,
1000                                 GSupplicantScanParams *scan_data)
1001 {
1002         GSequenceIter *iter;
1003         GSequence *latest_list;
1004         struct last_connected *entry;
1005         GKeyFile *keyfile;
1006         GTimeVal modified;
1007         gchar **services;
1008         gchar *str;
1009         char *ssid;
1010         int i, freq;
1011         int num_ssids = 0;
1012
1013         latest_list = g_sequence_new(free_entry);
1014         if (!latest_list)
1015                 return -ENOMEM;
1016
1017         services = connman_storage_get_services();
1018         for (i = 0; services && services[i]; i++) {
1019                 if (strncmp(services[i], "wifi_", 5) != 0)
1020                         continue;
1021
1022                 keyfile = connman_storage_load_service(services[i]);
1023                 if (!keyfile)
1024                         continue;
1025
1026                 str = g_key_file_get_string(keyfile,
1027                                         services[i], "Favorite", NULL);
1028                 if (!str || g_strcmp0(str, "true")) {
1029                         g_free(str);
1030                         g_key_file_free(keyfile);
1031                         continue;
1032                 }
1033                 g_free(str);
1034
1035                 str = g_key_file_get_string(keyfile,
1036                                         services[i], "AutoConnect", NULL);
1037                 if (!str || g_strcmp0(str, "true")) {
1038                         g_free(str);
1039                         g_key_file_free(keyfile);
1040                         continue;
1041                 }
1042                 g_free(str);
1043
1044                 str = g_key_file_get_string(keyfile,
1045                                         services[i], "Modified", NULL);
1046                 if (!str) {
1047                         g_key_file_free(keyfile);
1048                         continue;
1049                 }
1050                 g_time_val_from_iso8601(str, &modified);
1051                 g_free(str);
1052
1053                 ssid = g_key_file_get_string(keyfile,
1054                                         services[i], "SSID", NULL);
1055
1056                 freq = g_key_file_get_integer(keyfile, services[i],
1057                                         "Frequency", NULL);
1058                 if (freq) {
1059                         entry = g_try_new(struct last_connected, 1);
1060                         if (!entry) {
1061                                 g_sequence_free(latest_list);
1062                                 g_key_file_free(keyfile);
1063                                 g_free(ssid);
1064                                 return -ENOMEM;
1065                         }
1066
1067                         entry->ssid = ssid;
1068                         entry->modified = modified;
1069                         entry->freq = freq;
1070
1071                         g_sequence_insert_sorted(latest_list, entry,
1072                                                 sort_entry, NULL);
1073                         num_ssids++;
1074                 } else
1075                         g_free(ssid);
1076
1077                 g_key_file_free(keyfile);
1078         }
1079
1080         g_strfreev(services);
1081
1082         num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
1083
1084         iter = g_sequence_get_begin_iter(latest_list);
1085
1086         for (i = 0; i < num_ssids; i++) {
1087                 entry = g_sequence_get(iter);
1088
1089                 DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
1090                                                 entry->modified.tv_sec);
1091
1092                 add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
1093                                                 max_ssids, entry->ssid);
1094
1095                 iter = g_sequence_iter_next(iter);
1096         }
1097
1098         g_sequence_free(latest_list);
1099         return num_ssids;
1100 }
1101
1102 static int wifi_scan_simple(struct connman_device *device)
1103 {
1104         reset_autoscan(device);
1105
1106         return throw_wifi_scan(device, scan_callback_hidden);
1107 }
1108
1109 static gboolean p2p_find_stop(gpointer data)
1110 {
1111         struct connman_device *device = data;
1112         struct wifi_data *wifi = connman_device_get_data(device);
1113
1114         DBG("");
1115
1116         wifi->p2p_find_timeout = 0;
1117
1118         connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
1119
1120         g_supplicant_interface_p2p_stop_find(wifi->interface);
1121
1122         connman_device_unref(device);
1123         reset_autoscan(device);
1124
1125         return FALSE;
1126 }
1127
1128 static void p2p_find_callback(int result, GSupplicantInterface *interface,
1129                                                         void *user_data)
1130 {
1131         struct connman_device *device = user_data;
1132         struct wifi_data *wifi = connman_device_get_data(device);
1133
1134         DBG("result %d wifi %p", result, wifi);
1135
1136         if (wifi->p2p_find_timeout) {
1137                 g_source_remove(wifi->p2p_find_timeout);
1138                 wifi->p2p_find_timeout = 0;
1139         }
1140
1141         if (result)
1142                 goto error;
1143
1144         wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
1145                                                         p2p_find_stop, device);
1146         if (!wifi->p2p_find_timeout)
1147                 goto error;
1148
1149         return;
1150 error:
1151         p2p_find_stop(device);
1152 }
1153
1154 static int p2p_find(struct connman_device *device)
1155 {
1156         struct wifi_data *wifi = connman_device_get_data(device);
1157         int ret;
1158
1159         DBG("");
1160
1161         if (!p2p_technology)
1162                 return -ENOTSUP;
1163
1164         reset_autoscan(device);
1165         connman_device_ref(device);
1166
1167         ret = g_supplicant_interface_p2p_find(wifi->interface,
1168                                                 p2p_find_callback, device);
1169         if (ret) {
1170                 connman_device_unref(device);
1171                 start_autoscan(device);
1172         } else {
1173                 connman_device_set_scanning(device,
1174                                 CONNMAN_SERVICE_TYPE_P2P, true);
1175         }
1176
1177         return ret;
1178 }
1179
1180 /*
1181  * Note that the hidden scan is only used when connecting to this specific
1182  * hidden AP first time. It is not used when system autoconnects to hidden AP.
1183  */
1184 static int wifi_scan(enum connman_service_type type,
1185                         struct connman_device *device,
1186                         const char *ssid, unsigned int ssid_len,
1187                         const char *identity, const char* passphrase,
1188                         const char *security, void *user_data)
1189 {
1190         struct wifi_data *wifi = connman_device_get_data(device);
1191         GSupplicantScanParams *scan_params = NULL;
1192         struct scan_ssid *scan_ssid;
1193         struct hidden_params *hidden;
1194         int ret;
1195         int driver_max_ssids = 0;
1196         bool do_hidden;
1197         bool scanning;
1198
1199         if (!wifi)
1200                 return -ENODEV;
1201
1202         if (type == CONNMAN_SERVICE_TYPE_P2P)
1203                 return p2p_find(device);
1204
1205         DBG("device %p wifi %p hidden ssid %s", device, wifi->interface, ssid);
1206
1207         if (wifi->tethering)
1208                 return 0;
1209
1210         scanning = connman_device_get_scanning(device);
1211
1212         if (!ssid || ssid_len == 0 || ssid_len > 32) {
1213                 if (scanning)
1214                         return -EALREADY;
1215
1216                 driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
1217                                                         wifi->interface);
1218                 DBG("max ssids %d", driver_max_ssids);
1219                 if (driver_max_ssids == 0)
1220                         return wifi_scan_simple(device);
1221
1222                 do_hidden = false;
1223         } else {
1224                 if (scanning && wifi->hidden && wifi->postpone_hidden)
1225                         return -EALREADY;
1226
1227                 do_hidden = true;
1228         }
1229
1230         scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
1231         if (!scan_params)
1232                 return -ENOMEM;
1233
1234         if (do_hidden) {
1235                 scan_ssid = g_try_new(struct scan_ssid, 1);
1236                 if (!scan_ssid) {
1237                         g_free(scan_params);
1238                         return -ENOMEM;
1239                 }
1240
1241                 memcpy(scan_ssid->ssid, ssid, ssid_len);
1242                 scan_ssid->ssid_len = ssid_len;
1243                 scan_params->ssids = g_slist_prepend(scan_params->ssids,
1244                                                                 scan_ssid);
1245                 scan_params->num_ssids = 1;
1246
1247                 hidden = g_try_new0(struct hidden_params, 1);
1248                 if (!hidden) {
1249                         g_supplicant_free_scan_params(scan_params);
1250                         return -ENOMEM;
1251                 }
1252
1253                 if (wifi->hidden) {
1254                         hidden_free(wifi->hidden);
1255                         wifi->hidden = NULL;
1256                 }
1257
1258                 memcpy(hidden->ssid, ssid, ssid_len);
1259                 hidden->ssid_len = ssid_len;
1260                 hidden->identity = g_strdup(identity);
1261                 hidden->passphrase = g_strdup(passphrase);
1262                 hidden->security = g_strdup(security);
1263                 hidden->user_data = user_data;
1264                 wifi->hidden = hidden;
1265
1266                 if (scanning) {
1267                         /* Let's keep this active scan for later,
1268                          * when current scan will be over. */
1269                         wifi->postpone_hidden = TRUE;
1270                         hidden->scan_params = scan_params;
1271
1272                         return 0;
1273                 }
1274         } else {
1275                 ret = get_latest_connections(driver_max_ssids, scan_params);
1276                 if (ret <= 0) {
1277                         g_supplicant_free_scan_params(scan_params);
1278                         return wifi_scan_simple(device);
1279                 }
1280         }
1281
1282         connman_device_ref(device);
1283
1284         reset_autoscan(device);
1285
1286         ret = g_supplicant_interface_scan(wifi->interface, scan_params,
1287                                                 scan_callback, device);
1288         if (ret == 0) {
1289                 connman_device_set_scanning(device,
1290                                 CONNMAN_SERVICE_TYPE_WIFI, true);
1291         } else {
1292                 g_supplicant_free_scan_params(scan_params);
1293                 connman_device_unref(device);
1294
1295                 if (do_hidden) {
1296                         hidden_free(wifi->hidden);
1297                         wifi->hidden = NULL;
1298                 }
1299         }
1300
1301         return ret;
1302 }
1303
1304 static void wifi_regdom_callback(int result,
1305                                         const char *alpha2,
1306                                                 void *user_data)
1307 {
1308         struct connman_device *device = user_data;
1309
1310         connman_device_regdom_notify(device, result, alpha2);
1311
1312         connman_device_unref(device);
1313 }
1314
1315 static int wifi_set_regdom(struct connman_device *device, const char *alpha2)
1316 {
1317         struct wifi_data *wifi = connman_device_get_data(device);
1318         int ret;
1319
1320         if (!wifi)
1321                 return -EINVAL;
1322
1323         connman_device_ref(device);
1324
1325         ret = g_supplicant_interface_set_country(wifi->interface,
1326                                                 wifi_regdom_callback,
1327                                                         alpha2, device);
1328         if (ret != 0)
1329                 connman_device_unref(device);
1330
1331         return ret;
1332 }
1333
1334 static struct connman_device_driver wifi_ng_driver = {
1335         .name           = "wifi",
1336         .type           = CONNMAN_DEVICE_TYPE_WIFI,
1337         .priority       = CONNMAN_DEVICE_PRIORITY_LOW,
1338         .probe          = wifi_probe,
1339         .remove         = wifi_remove,
1340         .enable         = wifi_enable,
1341         .disable        = wifi_disable,
1342         .scan           = wifi_scan,
1343         .set_regdom     = wifi_set_regdom,
1344 };
1345
1346 static void system_ready(void)
1347 {
1348         DBG("");
1349
1350         if (connman_device_driver_register(&wifi_ng_driver) < 0)
1351                 connman_error("Failed to register WiFi driver");
1352 }
1353
1354 static void system_killed(void)
1355 {
1356         DBG("");
1357
1358         connman_device_driver_unregister(&wifi_ng_driver);
1359 }
1360
1361 static int network_probe(struct connman_network *network)
1362 {
1363         DBG("network %p", network);
1364
1365         return 0;
1366 }
1367
1368 static void network_remove(struct connman_network *network)
1369 {
1370         struct connman_device *device = connman_network_get_device(network);
1371         struct wifi_data *wifi;
1372
1373         DBG("network %p", network);
1374
1375         wifi = connman_device_get_data(device);
1376         if (!wifi)
1377                 return;
1378
1379         if (wifi->network != network)
1380                 return;
1381
1382         wifi->network = NULL;
1383 }
1384
1385 static void connect_callback(int result, GSupplicantInterface *interface,
1386                                                         void *user_data)
1387 {
1388         struct connman_network *network = user_data;
1389
1390         DBG("network %p result %d", network, result);
1391
1392         if (result == -ENOKEY) {
1393                 connman_network_set_error(network,
1394                                         CONNMAN_NETWORK_ERROR_INVALID_KEY);
1395         } else if (result < 0) {
1396                 connman_network_set_error(network,
1397                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1398         }
1399
1400         connman_network_unref(network);
1401 }
1402
1403 static GSupplicantSecurity network_security(const char *security)
1404 {
1405         if (g_str_equal(security, "none"))
1406                 return G_SUPPLICANT_SECURITY_NONE;
1407         else if (g_str_equal(security, "wep"))
1408                 return G_SUPPLICANT_SECURITY_WEP;
1409         else if (g_str_equal(security, "psk"))
1410                 return G_SUPPLICANT_SECURITY_PSK;
1411         else if (g_str_equal(security, "wpa"))
1412                 return G_SUPPLICANT_SECURITY_PSK;
1413         else if (g_str_equal(security, "rsn"))
1414                 return G_SUPPLICANT_SECURITY_PSK;
1415         else if (g_str_equal(security, "ieee8021x"))
1416                 return G_SUPPLICANT_SECURITY_IEEE8021X;
1417
1418         return G_SUPPLICANT_SECURITY_UNKNOWN;
1419 }
1420
1421 static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
1422 {
1423         const char *security;
1424
1425         memset(ssid, 0, sizeof(*ssid));
1426         ssid->mode = G_SUPPLICANT_MODE_INFRA;
1427         ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
1428                                                 &ssid->ssid_len);
1429         ssid->scan_ssid = 1;
1430         security = connman_network_get_string(network, "WiFi.Security");
1431         ssid->security = network_security(security);
1432         ssid->passphrase = connman_network_get_string(network,
1433                                                 "WiFi.Passphrase");
1434
1435         ssid->eap = connman_network_get_string(network, "WiFi.EAP");
1436
1437         /*
1438          * If our private key password is unset,
1439          * we use the supplied passphrase. That is needed
1440          * for PEAP where 2 passphrases (identity and client
1441          * cert may have to be provided.
1442          */
1443         if (!connman_network_get_string(network, "WiFi.PrivateKeyPassphrase"))
1444                 connman_network_set_string(network,
1445                                                 "WiFi.PrivateKeyPassphrase",
1446                                                 ssid->passphrase);
1447         /* We must have an identity for both PEAP and TLS */
1448         ssid->identity = connman_network_get_string(network, "WiFi.Identity");
1449
1450         /* Use agent provided identity as a fallback */
1451         if (!ssid->identity || strlen(ssid->identity) == 0)
1452                 ssid->identity = connman_network_get_string(network,
1453                                                         "WiFi.AgentIdentity");
1454
1455         ssid->ca_cert_path = connman_network_get_string(network,
1456                                                         "WiFi.CACertFile");
1457         ssid->client_cert_path = connman_network_get_string(network,
1458                                                         "WiFi.ClientCertFile");
1459         ssid->private_key_path = connman_network_get_string(network,
1460                                                         "WiFi.PrivateKeyFile");
1461         ssid->private_key_passphrase = connman_network_get_string(network,
1462                                                 "WiFi.PrivateKeyPassphrase");
1463         ssid->phase2_auth = connman_network_get_string(network, "WiFi.Phase2");
1464
1465         ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
1466         ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
1467
1468         if (connman_setting_get_bool("BackgroundScanning"))
1469                 ssid->bgscan = BGSCAN_DEFAULT;
1470 }
1471
1472 static int network_connect(struct connman_network *network)
1473 {
1474         struct connman_device *device = connman_network_get_device(network);
1475         struct wifi_data *wifi;
1476         GSupplicantInterface *interface;
1477         GSupplicantSSID *ssid;
1478
1479         DBG("network %p", network);
1480
1481         if (!device)
1482                 return -ENODEV;
1483
1484         wifi = connman_device_get_data(device);
1485         if (!wifi)
1486                 return -ENODEV;
1487
1488         ssid = g_try_malloc0(sizeof(GSupplicantSSID));
1489         if (!ssid)
1490                 return -ENOMEM;
1491
1492         interface = wifi->interface;
1493
1494         ssid_init(ssid, network);
1495
1496         if (wifi->disconnecting) {
1497                 wifi->pending_network = network;
1498                 g_free(ssid);
1499         } else {
1500                 wifi->network = connman_network_ref(network);
1501                 wifi->retries = 0;
1502
1503                 return g_supplicant_interface_connect(interface, ssid,
1504                                                 connect_callback, network);
1505         }
1506
1507         return -EINPROGRESS;
1508 }
1509
1510 static void disconnect_callback(int result, GSupplicantInterface *interface,
1511                                                                 void *user_data)
1512 {
1513         struct wifi_data *wifi = user_data;
1514
1515         DBG("result %d supplicant interface %p wifi %p",
1516                         result, interface, wifi);
1517
1518         if (result == -ECONNABORTED) {
1519                 DBG("wifi interface no longer available");
1520                 return;
1521         }
1522
1523         if (wifi->network) {
1524                 /*
1525                  * if result < 0 supplican return an error because
1526                  * the network is not current.
1527                  * we wont receive G_SUPPLICANT_STATE_DISCONNECTED since it
1528                  * failed, call connman_network_set_connected to report
1529                  * disconnect is completed.
1530                  */
1531                 if (result < 0)
1532                         connman_network_set_connected(wifi->network, false);
1533         }
1534
1535         wifi->network = NULL;
1536
1537         wifi->disconnecting = false;
1538
1539         if (wifi->pending_network) {
1540                 network_connect(wifi->pending_network);
1541                 wifi->pending_network = NULL;
1542         }
1543
1544         start_autoscan(wifi->device);
1545 }
1546
1547 static int network_disconnect(struct connman_network *network)
1548 {
1549         struct connman_device *device = connman_network_get_device(network);
1550         struct wifi_data *wifi;
1551         int err;
1552
1553         DBG("network %p", network);
1554
1555         wifi = connman_device_get_data(device);
1556         if (!wifi || !wifi->interface)
1557                 return -ENODEV;
1558
1559         connman_network_set_associating(network, false);
1560
1561         if (wifi->disconnecting)
1562                 return -EALREADY;
1563
1564         wifi->disconnecting = true;
1565
1566         err = g_supplicant_interface_disconnect(wifi->interface,
1567                                                 disconnect_callback, wifi);
1568         if (err < 0)
1569                 wifi->disconnecting = false;
1570
1571         return err;
1572 }
1573
1574 static struct connman_network_driver network_driver = {
1575         .name           = "wifi",
1576         .type           = CONNMAN_NETWORK_TYPE_WIFI,
1577         .priority       = CONNMAN_NETWORK_PRIORITY_LOW,
1578         .probe          = network_probe,
1579         .remove         = network_remove,
1580         .connect        = network_connect,
1581         .disconnect     = network_disconnect,
1582 };
1583
1584 static void interface_added(GSupplicantInterface *interface)
1585 {
1586         const char *ifname = g_supplicant_interface_get_ifname(interface);
1587         const char *driver = g_supplicant_interface_get_driver(interface);
1588         struct wifi_data *wifi;
1589
1590         wifi = g_supplicant_interface_get_data(interface);
1591
1592         /*
1593          * We can get here with a NULL wifi pointer when
1594          * the interface added signal is sent before the
1595          * interface creation callback is called.
1596          */
1597         if (!wifi)
1598                 return;
1599
1600         DBG("ifname %s driver %s wifi %p tethering %d",
1601                         ifname, driver, wifi, wifi->tethering);
1602
1603         if (!wifi->device) {
1604                 connman_error("WiFi device not set");
1605                 return;
1606         }
1607
1608         connman_device_set_powered(wifi->device, true);
1609
1610         if (wifi->tethering)
1611                 return;
1612 }
1613
1614 static bool is_idle(struct wifi_data *wifi)
1615 {
1616         DBG("state %d", wifi->state);
1617
1618         switch (wifi->state) {
1619         case G_SUPPLICANT_STATE_UNKNOWN:
1620         case G_SUPPLICANT_STATE_DISABLED:
1621         case G_SUPPLICANT_STATE_DISCONNECTED:
1622         case G_SUPPLICANT_STATE_INACTIVE:
1623         case G_SUPPLICANT_STATE_SCANNING:
1624                 return true;
1625
1626         case G_SUPPLICANT_STATE_AUTHENTICATING:
1627         case G_SUPPLICANT_STATE_ASSOCIATING:
1628         case G_SUPPLICANT_STATE_ASSOCIATED:
1629         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1630         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1631         case G_SUPPLICANT_STATE_COMPLETED:
1632                 return false;
1633         }
1634
1635         return false;
1636 }
1637
1638 static bool is_idle_wps(GSupplicantInterface *interface,
1639                                                 struct wifi_data *wifi)
1640 {
1641         /* First, let's check if WPS processing did not went wrong */
1642         if (g_supplicant_interface_get_wps_state(interface) ==
1643                 G_SUPPLICANT_WPS_STATE_FAIL)
1644                 return false;
1645
1646         /* Unlike normal connection, being associated while processing wps
1647          * actually means that we are idling. */
1648         switch (wifi->state) {
1649         case G_SUPPLICANT_STATE_UNKNOWN:
1650         case G_SUPPLICANT_STATE_DISABLED:
1651         case G_SUPPLICANT_STATE_DISCONNECTED:
1652         case G_SUPPLICANT_STATE_INACTIVE:
1653         case G_SUPPLICANT_STATE_SCANNING:
1654         case G_SUPPLICANT_STATE_ASSOCIATED:
1655                 return true;
1656         case G_SUPPLICANT_STATE_AUTHENTICATING:
1657         case G_SUPPLICANT_STATE_ASSOCIATING:
1658         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1659         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1660         case G_SUPPLICANT_STATE_COMPLETED:
1661                 return false;
1662         }
1663
1664         return false;
1665 }
1666
1667 static bool handle_wps_completion(GSupplicantInterface *interface,
1668                                         struct connman_network *network,
1669                                         struct connman_device *device,
1670                                         struct wifi_data *wifi)
1671 {
1672         bool wps;
1673
1674         wps = connman_network_get_bool(network, "WiFi.UseWPS");
1675         if (wps) {
1676                 const unsigned char *ssid, *wps_ssid;
1677                 unsigned int ssid_len, wps_ssid_len;
1678                 const char *wps_key;
1679
1680                 /* Checking if we got associated with requested
1681                  * network */
1682                 ssid = connman_network_get_blob(network, "WiFi.SSID",
1683                                                 &ssid_len);
1684
1685                 wps_ssid = g_supplicant_interface_get_wps_ssid(
1686                         interface, &wps_ssid_len);
1687
1688                 if (!wps_ssid || wps_ssid_len != ssid_len ||
1689                                 memcmp(ssid, wps_ssid, ssid_len) != 0) {
1690                         connman_network_set_associating(network, false);
1691                         g_supplicant_interface_disconnect(wifi->interface,
1692                                                 disconnect_callback, wifi);
1693                         return false;
1694                 }
1695
1696                 wps_key = g_supplicant_interface_get_wps_key(interface);
1697                 connman_network_set_string(network, "WiFi.Passphrase",
1698                                         wps_key);
1699
1700                 connman_network_set_string(network, "WiFi.PinWPS", NULL);
1701         }
1702
1703         return true;
1704 }
1705
1706 static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
1707                                         struct connman_network *network,
1708                                         struct wifi_data *wifi)
1709 {
1710         struct connman_service *service;
1711
1712         if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
1713                 return false;
1714
1715         service = connman_service_lookup_from_network(network);
1716         if (!service)
1717                 return false;
1718
1719         wifi->retries++;
1720
1721         if (connman_service_get_favorite(service)) {
1722                 if (wifi->retries < FAVORITE_MAXIMUM_RETRIES)
1723                         return true;
1724         }
1725
1726         wifi->retries = 0;
1727         connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
1728
1729         return false;
1730 }
1731
1732 static void interface_state(GSupplicantInterface *interface)
1733 {
1734         struct connman_network *network;
1735         struct connman_device *device;
1736         struct wifi_data *wifi;
1737         GSupplicantState state = g_supplicant_interface_get_state(interface);
1738         bool wps;
1739
1740         wifi = g_supplicant_interface_get_data(interface);
1741
1742         DBG("wifi %p interface state %d", wifi, state);
1743
1744         if (!wifi)
1745                 return;
1746
1747         device = wifi->device;
1748         if (!device)
1749                 return;
1750
1751         if (g_supplicant_interface_get_ready(interface) &&
1752                                         !wifi->interface_ready) {
1753                 wifi->interface_ready = true;
1754                 finalize_interface_creation(wifi);
1755         }
1756
1757         network = wifi->network;
1758         if (!network)
1759                 return;
1760
1761         switch (state) {
1762         case G_SUPPLICANT_STATE_SCANNING:
1763                 break;
1764
1765         case G_SUPPLICANT_STATE_AUTHENTICATING:
1766         case G_SUPPLICANT_STATE_ASSOCIATING:
1767                 stop_autoscan(device);
1768
1769                 if (!wifi->connected)
1770                         connman_network_set_associating(network, true);
1771
1772                 break;
1773
1774         case G_SUPPLICANT_STATE_COMPLETED:
1775                 /* though it should be already stopped: */
1776                 stop_autoscan(device);
1777
1778                 if (!handle_wps_completion(interface, network, device, wifi))
1779                         break;
1780
1781                 connman_network_set_connected(network, true);
1782                 break;
1783
1784         case G_SUPPLICANT_STATE_DISCONNECTED:
1785                 /*
1786                  * If we're in one of the idle modes, we have
1787                  * not started association yet and thus setting
1788                  * those ones to FALSE could cancel an association
1789                  * in progress.
1790                  */
1791                 wps = connman_network_get_bool(network, "WiFi.UseWPS");
1792                 if (wps)
1793                         if (is_idle_wps(interface, wifi))
1794                                 break;
1795
1796                 if (is_idle(wifi))
1797                         break;
1798
1799                 /* If previous state was 4way-handshake, then
1800                  * it's either: psk was incorrect and thus we retry
1801                  * or if we reach the maximum retries we declare the
1802                  * psk as wrong */
1803                 if (handle_4way_handshake_failure(interface,
1804                                                 network, wifi))
1805                         break;
1806
1807                 /* We disable the selected network, if not then
1808                  * wpa_supplicant will loop retrying */
1809                 if (g_supplicant_interface_enable_selected_network(interface,
1810                                                 FALSE) != 0)
1811                         DBG("Could not disables selected network");
1812
1813                 connman_network_set_connected(network, false);
1814                 connman_network_set_associating(network, false);
1815                 wifi->disconnecting = false;
1816
1817                 start_autoscan(device);
1818
1819                 break;
1820
1821         case G_SUPPLICANT_STATE_INACTIVE:
1822                 connman_network_set_associating(network, false);
1823                 start_autoscan(device);
1824
1825                 break;
1826
1827         case G_SUPPLICANT_STATE_UNKNOWN:
1828         case G_SUPPLICANT_STATE_DISABLED:
1829         case G_SUPPLICANT_STATE_ASSOCIATED:
1830         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1831         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1832                 break;
1833         }
1834
1835         wifi->state = state;
1836
1837         /* Saving wpa_s state policy:
1838          * If connected and if the state changes are roaming related:
1839          * --> We stay connected
1840          * If completed
1841          * --> We are connected
1842          * All other case:
1843          * --> We are not connected
1844          * */
1845         switch (state) {
1846         case G_SUPPLICANT_STATE_AUTHENTICATING:
1847         case G_SUPPLICANT_STATE_ASSOCIATING:
1848         case G_SUPPLICANT_STATE_ASSOCIATED:
1849         case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
1850         case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
1851                 if (wifi->connected)
1852                         connman_warn("Probably roaming right now!"
1853                                                 " Staying connected...");
1854                 else
1855                         wifi->connected = false;
1856                 break;
1857         case G_SUPPLICANT_STATE_COMPLETED:
1858                 wifi->connected = true;
1859                 break;
1860         default:
1861                 wifi->connected = false;
1862                 break;
1863         }
1864
1865         DBG("DONE");
1866 }
1867
1868 static void interface_removed(GSupplicantInterface *interface)
1869 {
1870         const char *ifname = g_supplicant_interface_get_ifname(interface);
1871         struct wifi_data *wifi;
1872
1873         DBG("ifname %s", ifname);
1874
1875         wifi = g_supplicant_interface_get_data(interface);
1876
1877         if (wifi && wifi->tethering)
1878                 return;
1879
1880         if (!wifi || !wifi->device) {
1881                 DBG("wifi interface already removed");
1882                 return;
1883         }
1884
1885         wifi->interface = NULL;
1886         connman_device_set_powered(wifi->device, false);
1887
1888         check_p2p_technology();
1889 }
1890
1891 static void p2p_support(GSupplicantInterface *interface)
1892 {
1893         DBG("");
1894
1895         if (!g_supplicant_interface_has_p2p(interface))
1896                 return;
1897
1898         if (connman_technology_driver_register(&p2p_tech_driver) == 0)
1899                 DBG("Could not register P2P technology driver");
1900 }
1901
1902 static void scan_started(GSupplicantInterface *interface)
1903 {
1904         DBG("");
1905 }
1906
1907 static void scan_finished(GSupplicantInterface *interface)
1908 {
1909         DBG("");
1910 }
1911
1912 static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
1913 {
1914         unsigned char strength;
1915
1916         strength = 120 + g_supplicant_network_get_signal(supplicant_network);
1917         if (strength > 100)
1918                 strength = 100;
1919
1920         return strength;
1921 }
1922
1923 static void network_added(GSupplicantNetwork *supplicant_network)
1924 {
1925         struct connman_network *network;
1926         GSupplicantInterface *interface;
1927         struct wifi_data *wifi;
1928         const char *name, *identifier, *security, *group, *mode;
1929         const unsigned char *ssid;
1930         unsigned int ssid_len;
1931         bool wps;
1932         bool wps_pbc;
1933         bool wps_ready;
1934         bool wps_advertizing;
1935
1936         mode = g_supplicant_network_get_mode(supplicant_network);
1937         identifier = g_supplicant_network_get_identifier(supplicant_network);
1938
1939         DBG("%s", identifier);
1940
1941         if (!g_strcmp0(mode, "adhoc"))
1942                 return;
1943
1944         interface = g_supplicant_network_get_interface(supplicant_network);
1945         wifi = g_supplicant_interface_get_data(interface);
1946         name = g_supplicant_network_get_name(supplicant_network);
1947         security = g_supplicant_network_get_security(supplicant_network);
1948         group = g_supplicant_network_get_identifier(supplicant_network);
1949         wps = g_supplicant_network_get_wps(supplicant_network);
1950         wps_pbc = g_supplicant_network_is_wps_pbc(supplicant_network);
1951         wps_ready = g_supplicant_network_is_wps_active(supplicant_network);
1952         wps_advertizing = g_supplicant_network_is_wps_advertizing(
1953                                                         supplicant_network);
1954
1955         if (!wifi)
1956                 return;
1957
1958         ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
1959
1960         network = connman_device_get_network(wifi->device, identifier);
1961
1962         if (!network) {
1963                 network = connman_network_create(identifier,
1964                                                 CONNMAN_NETWORK_TYPE_WIFI);
1965                 if (!network)
1966                         return;
1967
1968                 connman_network_set_index(network, wifi->index);
1969
1970                 if (connman_device_add_network(wifi->device, network) < 0) {
1971                         connman_network_unref(network);
1972                         return;
1973                 }
1974
1975                 wifi->networks = g_slist_prepend(wifi->networks, network);
1976         }
1977
1978         if (name && name[0] != '\0')
1979                 connman_network_set_name(network, name);
1980
1981         connman_network_set_blob(network, "WiFi.SSID",
1982                                                 ssid, ssid_len);
1983         connman_network_set_string(network, "WiFi.Security", security);
1984         connman_network_set_strength(network,
1985                                 calculate_strength(supplicant_network));
1986         connman_network_set_bool(network, "WiFi.WPS", wps);
1987
1988         if (wps) {
1989                 /* Is AP advertizing for WPS association?
1990                  * If so, we decide to use WPS by default */
1991                 if (wps_ready && wps_pbc &&
1992                                                 wps_advertizing)
1993                         connman_network_set_bool(network, "WiFi.UseWPS", true);
1994         }
1995
1996         connman_network_set_frequency(network,
1997                         g_supplicant_network_get_frequency(supplicant_network));
1998
1999         connman_network_set_available(network, true);
2000         connman_network_set_string(network, "WiFi.Mode", mode);
2001
2002         if (ssid)
2003                 connman_network_set_group(network, group);
2004
2005         if (wifi->hidden && ssid) {
2006                 if (!g_strcmp0(wifi->hidden->security, security) &&
2007                                 wifi->hidden->ssid_len == ssid_len &&
2008                                 !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
2009                         connman_network_connect_hidden(network,
2010                                         wifi->hidden->identity,
2011                                         wifi->hidden->passphrase,
2012                                         wifi->hidden->user_data);
2013                         wifi->hidden->user_data = NULL;
2014                         hidden_free(wifi->hidden);
2015                         wifi->hidden = NULL;
2016                 }
2017         }
2018 }
2019
2020 static void network_removed(GSupplicantNetwork *network)
2021 {
2022         GSupplicantInterface *interface;
2023         struct wifi_data *wifi;
2024         const char *name, *identifier;
2025         struct connman_network *connman_network;
2026
2027         interface = g_supplicant_network_get_interface(network);
2028         wifi = g_supplicant_interface_get_data(interface);
2029         identifier = g_supplicant_network_get_identifier(network);
2030         name = g_supplicant_network_get_name(network);
2031
2032         DBG("name %s", name);
2033
2034         if (!wifi)
2035                 return;
2036
2037         connman_network = connman_device_get_network(wifi->device, identifier);
2038         if (!connman_network)
2039                 return;
2040
2041         wifi->networks = g_slist_remove(wifi->networks, connman_network);
2042
2043         connman_device_remove_network(wifi->device, connman_network);
2044         connman_network_unref(connman_network);
2045 }
2046
2047 static void network_changed(GSupplicantNetwork *network, const char *property)
2048 {
2049         GSupplicantInterface *interface;
2050         struct wifi_data *wifi;
2051         const char *name, *identifier;
2052         struct connman_network *connman_network;
2053
2054         interface = g_supplicant_network_get_interface(network);
2055         wifi = g_supplicant_interface_get_data(interface);
2056         identifier = g_supplicant_network_get_identifier(network);
2057         name = g_supplicant_network_get_name(network);
2058
2059         DBG("name %s", name);
2060
2061         if (!wifi)
2062                 return;
2063
2064         connman_network = connman_device_get_network(wifi->device, identifier);
2065         if (!connman_network)
2066                 return;
2067
2068         if (g_str_equal(property, "Signal")) {
2069                connman_network_set_strength(connman_network,
2070                                         calculate_strength(network));
2071                connman_network_update(connman_network);
2072         }
2073 }
2074
2075 static void peer_found(GSupplicantPeer *peer)
2076 {
2077         struct connman_peer *connman_peer;
2078         const char *identifier, *name;
2079
2080         identifier = g_supplicant_peer_get_identifier(peer);
2081         name = g_supplicant_peer_get_name(peer);
2082
2083         DBG("ident: %s", identifier);
2084
2085         connman_peer = connman_peer_get(identifier);
2086         if (connman_peer)
2087                 return;
2088
2089         connman_peer = connman_peer_create(identifier);
2090         connman_peer_set_name(connman_peer, name);
2091
2092         connman_peer_register(connman_peer);
2093 }
2094
2095 static void peer_lost(GSupplicantPeer *peer)
2096 {
2097         struct connman_peer *connman_peer;
2098         const char *identifier;
2099
2100         identifier = g_supplicant_peer_get_identifier(peer);
2101
2102         DBG("ident: %s", identifier);
2103
2104         connman_peer = connman_peer_get(identifier);
2105         if (connman_peer)
2106                 connman_peer_unregister(connman_peer);
2107 }
2108
2109 static void debug(const char *str)
2110 {
2111         if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
2112                 connman_debug("%s", str);
2113 }
2114
2115 static const GSupplicantCallbacks callbacks = {
2116         .system_ready           = system_ready,
2117         .system_killed          = system_killed,
2118         .interface_added        = interface_added,
2119         .interface_state        = interface_state,
2120         .interface_removed      = interface_removed,
2121         .p2p_support            = p2p_support,
2122         .scan_started           = scan_started,
2123         .scan_finished          = scan_finished,
2124         .network_added          = network_added,
2125         .network_removed        = network_removed,
2126         .network_changed        = network_changed,
2127         .peer_found             = peer_found,
2128         .peer_lost              = peer_lost,
2129         .debug                  = debug,
2130 };
2131
2132
2133 static int tech_probe(struct connman_technology *technology)
2134 {
2135         wifi_technology = technology;
2136
2137         return 0;
2138 }
2139
2140 static void tech_remove(struct connman_technology *technology)
2141 {
2142         wifi_technology = NULL;
2143 }
2144
2145 struct wifi_tethering_info {
2146         struct wifi_data *wifi;
2147         struct connman_technology *technology;
2148         char *ifname;
2149         GSupplicantSSID *ssid;
2150 };
2151
2152 static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
2153 {
2154         GSupplicantSSID *ap;
2155
2156         ap = g_try_malloc0(sizeof(GSupplicantSSID));
2157         if (!ap)
2158                 return NULL;
2159
2160         ap->mode = G_SUPPLICANT_MODE_MASTER;
2161         ap->ssid = ssid;
2162         ap->ssid_len = strlen(ssid);
2163         ap->scan_ssid = 0;
2164         ap->freq = 2412;
2165
2166         if (!passphrase || strlen(passphrase) == 0) {
2167                 ap->security = G_SUPPLICANT_SECURITY_NONE;
2168                 ap->passphrase = NULL;
2169         } else {
2170                ap->security = G_SUPPLICANT_SECURITY_PSK;
2171                ap->protocol = G_SUPPLICANT_PROTO_RSN;
2172                ap->pairwise_cipher = G_SUPPLICANT_PAIRWISE_CCMP;
2173                ap->group_cipher = G_SUPPLICANT_GROUP_CCMP;
2174                ap->passphrase = passphrase;
2175         }
2176
2177         return ap;
2178 }
2179
2180 static void ap_start_callback(int result, GSupplicantInterface *interface,
2181                                                         void *user_data)
2182 {
2183         struct wifi_tethering_info *info = user_data;
2184
2185         DBG("result %d index %d bridge %s",
2186                 result, info->wifi->index, info->wifi->bridge);
2187
2188         if (result < 0) {
2189                 connman_inet_remove_from_bridge(info->wifi->index,
2190                                                         info->wifi->bridge);
2191                 connman_technology_tethering_notify(info->technology, false);
2192         }
2193
2194         g_free(info->ifname);
2195         g_free(info);
2196 }
2197
2198 static void ap_create_callback(int result,
2199                                 GSupplicantInterface *interface,
2200                                         void *user_data)
2201 {
2202         struct wifi_tethering_info *info = user_data;
2203
2204         DBG("result %d ifname %s", result,
2205                                 g_supplicant_interface_get_ifname(interface));
2206
2207         if (result < 0) {
2208                 connman_inet_remove_from_bridge(info->wifi->index,
2209                                                         info->wifi->bridge);
2210                 connman_technology_tethering_notify(info->technology, false);
2211
2212                 g_free(info->ifname);
2213                 g_free(info->ssid);
2214                 g_free(info);
2215                 return;
2216         }
2217
2218         info->wifi->interface = interface;
2219         g_supplicant_interface_set_data(interface, info->wifi);
2220
2221         if (g_supplicant_interface_set_apscan(interface, 2) < 0)
2222                 connman_error("Failed to set interface ap_scan property");
2223
2224         g_supplicant_interface_connect(interface, info->ssid,
2225                                                 ap_start_callback, info);
2226 }
2227
2228 static void sta_remove_callback(int result,
2229                                 GSupplicantInterface *interface,
2230                                         void *user_data)
2231 {
2232         struct wifi_tethering_info *info = user_data;
2233         const char *driver = connman_option_get_string("wifi");
2234
2235         DBG("ifname %s result %d ", info->ifname, result);
2236
2237         if (result < 0) {
2238                 info->wifi->tethering = true;
2239
2240                 g_free(info->ifname);
2241                 g_free(info->ssid);
2242                 g_free(info);
2243                 return;
2244         }
2245
2246         info->wifi->interface = NULL;
2247
2248         connman_technology_tethering_notify(info->technology, true);
2249
2250         g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
2251                                                 ap_create_callback,
2252                                                         info);
2253 }
2254
2255 static int tech_set_tethering(struct connman_technology *technology,
2256                                 const char *identifier, const char *passphrase,
2257                                 const char *bridge, bool enabled)
2258 {
2259         GList *list;
2260         GSupplicantInterface *interface;
2261         struct wifi_data *wifi;
2262         struct wifi_tethering_info *info;
2263         const char *ifname;
2264         unsigned int mode;
2265         int err;
2266
2267         DBG("");
2268
2269         if (!enabled) {
2270                 for (list = iface_list; list; list = list->next) {
2271                         wifi = list->data;
2272
2273                         if (wifi->tethering) {
2274                                 wifi->tethering = false;
2275
2276                                 connman_inet_remove_from_bridge(wifi->index,
2277                                                                         bridge);
2278                                 wifi->bridged = false;
2279                         }
2280                 }
2281
2282                 connman_technology_tethering_notify(technology, false);
2283
2284                 return 0;
2285         }
2286
2287         for (list = iface_list; list; list = list->next) {
2288                 wifi = list->data;
2289
2290                 interface = wifi->interface;
2291
2292                 if (!interface)
2293                         continue;
2294
2295                 ifname = g_supplicant_interface_get_ifname(wifi->interface);
2296
2297                 mode = g_supplicant_interface_get_mode(interface);
2298                 if ((mode & G_SUPPLICANT_CAPABILITY_MODE_AP) == 0) {
2299                         DBG("%s does not support AP mode", ifname);
2300                         continue;
2301                 }
2302
2303                 info = g_try_malloc0(sizeof(struct wifi_tethering_info));
2304                 if (!info)
2305                         return -ENOMEM;
2306
2307                 info->wifi = wifi;
2308                 info->technology = technology;
2309                 info->wifi->bridge = bridge;
2310                 info->ssid = ssid_ap_init(identifier, passphrase);
2311                 if (!info->ssid) {
2312                         g_free(info);
2313                         continue;
2314                 }
2315                 info->ifname = g_strdup(ifname);
2316                 if (!info->ifname) {
2317                         g_free(info->ssid);
2318                         g_free(info);
2319                         continue;
2320                 }
2321
2322                 info->wifi->tethering = true;
2323
2324                 err = g_supplicant_interface_remove(interface,
2325                                                 sta_remove_callback,
2326                                                         info);
2327                 if (err == 0)
2328                         return err;
2329         }
2330
2331         return -EOPNOTSUPP;
2332 }
2333
2334 static void regdom_callback(int result, const char *alpha2, void *user_data)
2335 {
2336         DBG("");
2337
2338         if (!wifi_technology)
2339                 return;
2340
2341         if (result != 0)
2342                 alpha2 = NULL;
2343
2344         connman_technology_regdom_notify(wifi_technology, alpha2);
2345 }
2346
2347 static int tech_set_regdom(struct connman_technology *technology, const char *alpha2)
2348 {
2349         return g_supplicant_set_country(alpha2, regdom_callback, NULL);
2350 }
2351
2352 static struct connman_technology_driver tech_driver = {
2353         .name           = "wifi",
2354         .type           = CONNMAN_SERVICE_TYPE_WIFI,
2355         .probe          = tech_probe,
2356         .remove         = tech_remove,
2357         .set_tethering  = tech_set_tethering,
2358         .set_regdom     = tech_set_regdom,
2359 };
2360
2361 static int wifi_init(void)
2362 {
2363         int err;
2364
2365         err = connman_network_driver_register(&network_driver);
2366         if (err < 0)
2367                 return err;
2368
2369         err = g_supplicant_register(&callbacks);
2370         if (err < 0) {
2371                 connman_network_driver_unregister(&network_driver);
2372                 return err;
2373         }
2374
2375         err = connman_technology_driver_register(&tech_driver);
2376         if (err < 0) {
2377                 g_supplicant_unregister(&callbacks);
2378                 connman_network_driver_unregister(&network_driver);
2379                 return err;
2380         }
2381
2382         return 0;
2383 }
2384
2385 static void wifi_exit(void)
2386 {
2387         DBG();
2388
2389         connman_technology_driver_unregister(&tech_driver);
2390
2391         g_supplicant_unregister(&callbacks);
2392
2393         connman_network_driver_unregister(&network_driver);
2394 }
2395
2396 CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
2397                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, wifi_init, wifi_exit)