Add setter/getter for handling MAC randomization policy
[platform/upstream/connman.git] / src / device.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 <errno.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/ioctl.h>
32 #include <net/ethernet.h>
33 #include <net/if.h>
34
35 #include "connman.h"
36
37 static GSList *device_list = NULL;
38 static gchar **device_filter = NULL;
39 static gchar **nodevice_filter = NULL;
40
41 #if defined TIZEN_EXT
42 static DBusConnection *connection;
43 #endif
44
45 enum connman_pending_type {
46         PENDING_NONE    = 0,
47         PENDING_ENABLE  = 1,
48         PENDING_DISABLE = 2,
49 };
50
51 struct connman_device {
52         int refcount;
53         enum connman_device_type type;
54         enum connman_pending_type powered_pending;      /* Indicates a pending
55                                                          * enable/disable
56                                                          * request
57                                                          */
58         bool powered;
59         bool scanning[MAX_CONNMAN_SERVICE_TYPES];
60         char *name;
61         char *node;
62         char *address;
63         char *interface;
64         char *ident;
65         char *path;
66         int index;
67         guint pending_timeout;
68
69         struct connman_device_driver *driver;
70         void *driver_data;
71
72         char *last_network;
73         struct connman_network *network;
74         GHashTable *networks;
75 #if defined TIZEN_EXT
76         time_t last_user_selection_time;
77         char *last_user_selection_ident;
78         char *last_connected_ident;
79         DBusMessage *pending_reply;
80         int max_scan_ssids;
81         bool is_5_0_ghz_supported;
82         unsigned int mac_policy;
83         unsigned int preassoc_mac_policy;
84         unsigned int random_mac_lifetime;
85 #endif
86 };
87
88 static void clear_pending_trigger(struct connman_device *device)
89 {
90 #if defined TIZEN_EXT
91         if (device->pending_reply) {
92                 dbus_message_unref(device->pending_reply);
93                 device->pending_reply = NULL;
94         }
95 #endif
96         if (device->pending_timeout > 0) {
97                 g_source_remove(device->pending_timeout);
98                 device->pending_timeout = 0;
99         }
100 }
101
102 static const char *type2description(enum connman_device_type type)
103 {
104         switch (type) {
105         case CONNMAN_DEVICE_TYPE_UNKNOWN:
106         case CONNMAN_DEVICE_TYPE_VENDOR:
107                 break;
108         case CONNMAN_DEVICE_TYPE_ETHERNET:
109                 return "Ethernet";
110         case CONNMAN_DEVICE_TYPE_WIFI:
111                 return "Wireless";
112         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
113                 return "Bluetooth";
114         case CONNMAN_DEVICE_TYPE_GPS:
115                 return "GPS";
116         case CONNMAN_DEVICE_TYPE_CELLULAR:
117                 return "Cellular";
118         case CONNMAN_DEVICE_TYPE_GADGET:
119                 return "Gadget";
120
121         }
122
123         return NULL;
124 }
125
126 static const char *type2string(enum connman_device_type type)
127 {
128         switch (type) {
129         case CONNMAN_DEVICE_TYPE_UNKNOWN:
130         case CONNMAN_DEVICE_TYPE_VENDOR:
131                 break;
132         case CONNMAN_DEVICE_TYPE_ETHERNET:
133                 return "ethernet";
134         case CONNMAN_DEVICE_TYPE_WIFI:
135                 return "wifi";
136         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
137                 return "bluetooth";
138         case CONNMAN_DEVICE_TYPE_GPS:
139                 return "gps";
140         case CONNMAN_DEVICE_TYPE_CELLULAR:
141                 return "cellular";
142         case CONNMAN_DEVICE_TYPE_GADGET:
143                 return "gadget";
144
145         }
146
147         return NULL;
148 }
149
150 enum connman_service_type __connman_device_get_service_type(
151                                 struct connman_device *device)
152 {
153         enum connman_device_type type = connman_device_get_type(device);
154
155         switch (type) {
156         case CONNMAN_DEVICE_TYPE_UNKNOWN:
157         case CONNMAN_DEVICE_TYPE_VENDOR:
158         case CONNMAN_DEVICE_TYPE_GPS:
159                 break;
160         case CONNMAN_DEVICE_TYPE_ETHERNET:
161                 return CONNMAN_SERVICE_TYPE_ETHERNET;
162         case CONNMAN_DEVICE_TYPE_WIFI:
163                 return CONNMAN_SERVICE_TYPE_WIFI;
164         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
165                 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
166         case CONNMAN_DEVICE_TYPE_CELLULAR:
167                 return CONNMAN_SERVICE_TYPE_CELLULAR;
168         case CONNMAN_DEVICE_TYPE_GADGET:
169                 return CONNMAN_SERVICE_TYPE_GADGET;
170
171         }
172
173         return CONNMAN_SERVICE_TYPE_UNKNOWN;
174 }
175
176 static bool device_has_service_type(struct connman_device *device,
177                                 enum connman_service_type service_type)
178 {
179         enum connman_service_type device_service_type =
180                 __connman_device_get_service_type(device);
181
182         /*
183          * For devices whose device_service_type is unknown we should
184          * allow to decide whether they support specific service_type
185          * by themself.
186          */
187         if (device_service_type == CONNMAN_SERVICE_TYPE_UNKNOWN)
188                 return true;
189
190 #if defined TIZEN_EXT_WIFI_MESH
191         if (device_service_type == CONNMAN_SERVICE_TYPE_MESH)
192                 return service_type != CONNMAN_SERVICE_TYPE_MESH;
193 #endif
194
195         if (device_service_type == CONNMAN_SERVICE_TYPE_WIFI) {
196                 return service_type == CONNMAN_SERVICE_TYPE_WIFI ||
197                         service_type == CONNMAN_SERVICE_TYPE_P2P;
198         }
199
200         return service_type == device_service_type;
201 }
202
203 static gboolean device_pending_reset(gpointer user_data)
204 {
205         struct connman_device *device = user_data;
206
207         DBG("device %p", device);
208
209 #if defined TIZEN_EXT
210         DBusMessage *reply;
211
212         /* Power request timed out, send ETIMEDOUT. */
213         if (device->pending_reply) {
214                 reply = __connman_error_failed(device->pending_reply, ETIMEDOUT);
215                 if (reply)
216                         g_dbus_send_message(connection, reply);
217
218                 dbus_message_unref(device->pending_reply);
219                 device->pending_reply = NULL;
220         }
221 #endif
222         /* Power request timedout, reset power pending state. */
223         device->pending_timeout = 0;
224         device->powered_pending = PENDING_NONE;
225
226         return FALSE;
227 }
228
229 int __connman_device_enable(struct connman_device *device)
230 {
231         int err;
232
233         DBG("device %p", device);
234
235         if (!device->driver || !device->driver->enable)
236                 return -EOPNOTSUPP;
237
238         /* There is an ongoing power disable request. */
239         if (device->powered_pending == PENDING_DISABLE)
240                 return -EBUSY;
241
242         if (device->powered_pending == PENDING_ENABLE)
243                 return -EINPROGRESS;
244
245         if (device->powered_pending == PENDING_NONE && device->powered)
246                 return -EALREADY;
247
248         if (device->index > 0) {
249                 err = connman_inet_ifup(device->index);
250                 if (err < 0 && err != -EALREADY)
251                         return err;
252         }
253
254         device->powered_pending = PENDING_ENABLE;
255
256         err = device->driver->enable(device);
257         /*
258          * device gets enabled right away.
259          * Invoke the callback
260          */
261         if (err == 0) {
262                 connman_device_set_powered(device, true);
263                 goto done;
264         }
265
266         if (err == -EALREADY) {
267                 /* If device is already powered, but connman is not updated */
268                 connman_device_set_powered(device, true);
269                 goto done;
270         }
271         /*
272          * if err == -EINPROGRESS, then the DBus call to the respective daemon
273          * was successful. We set a 4 sec timeout so if the daemon never
274          * returns a reply, we would reset the pending request.
275          */
276         if (err == -EINPROGRESS)
277                 device->pending_timeout = g_timeout_add_seconds(4,
278                                         device_pending_reset, device);
279 done:
280         return err;
281 }
282
283 int __connman_device_disable(struct connman_device *device)
284 {
285         int err;
286
287         DBG("device %p", device);
288
289         /* Ongoing power enable request */
290         if (device->powered_pending == PENDING_ENABLE)
291                 return -EBUSY;
292
293         if (device->powered_pending == PENDING_DISABLE)
294                 return -EINPROGRESS;
295
296         if (device->powered_pending == PENDING_NONE && !device->powered)
297                 return -EALREADY;
298
299         device->powered_pending = PENDING_DISABLE;
300
301         if (device->network) {
302                 struct connman_service *service =
303                         connman_service_lookup_from_network(device->network);
304
305                 if (service)
306                         __connman_service_disconnect(service);
307                 else
308                         connman_network_set_connected(device->network, false);
309         }
310
311         if (!device->driver || !device->driver->disable)
312                 return -EOPNOTSUPP;
313
314         err = device->driver->disable(device);
315         if (err == 0 || err == -EALREADY) {
316                 connman_device_set_powered(device, false);
317                 goto done;
318         }
319
320         if (err == -EINPROGRESS)
321                 device->pending_timeout = g_timeout_add_seconds(4,
322                                         device_pending_reset, device);
323 done:
324         return err;
325 }
326
327 static void probe_driver(struct connman_device_driver *driver)
328 {
329         GSList *list;
330
331         DBG("driver %p name %s", driver, driver->name);
332
333         for (list = device_list; list; list = list->next) {
334                 struct connman_device *device = list->data;
335
336                 if (device->driver)
337                         continue;
338
339                 if (driver->type != device->type)
340                         continue;
341
342                 if (driver->probe(device) < 0)
343                         continue;
344
345                 device->driver = driver;
346
347                 __connman_technology_add_device(device);
348         }
349 }
350
351 static void remove_device(struct connman_device *device)
352 {
353         DBG("device %p", device);
354
355         __connman_device_disable(device);
356
357         __connman_technology_remove_device(device);
358
359         if (device->driver->remove)
360                 device->driver->remove(device);
361
362         device->driver = NULL;
363 }
364
365 static void remove_driver(struct connman_device_driver *driver)
366 {
367         GSList *list;
368
369         DBG("driver %p name %s", driver, driver->name);
370
371         for (list = device_list; list; list = list->next) {
372                 struct connman_device *device = list->data;
373
374                 if (device->driver == driver)
375                         remove_device(device);
376         }
377 }
378
379 bool __connman_device_has_driver(struct connman_device *device)
380 {
381         if (!device || !device->driver)
382                 return false;
383
384         return true;
385 }
386
387 static GSList *driver_list = NULL;
388
389 static gint compare_priority(gconstpointer a, gconstpointer b)
390 {
391         const struct connman_device_driver *driver1 = a;
392         const struct connman_device_driver *driver2 = b;
393
394         return driver2->priority - driver1->priority;
395 }
396
397 /**
398  * connman_device_driver_register:
399  * @driver: device driver definition
400  *
401  * Register a new device driver
402  *
403  * Returns: %0 on success
404  */
405 int connman_device_driver_register(struct connman_device_driver *driver)
406 {
407         DBG("driver %p name %s", driver, driver->name);
408
409         driver_list = g_slist_insert_sorted(driver_list, driver,
410                                                         compare_priority);
411         probe_driver(driver);
412
413         return 0;
414 }
415
416 /**
417  * connman_device_driver_unregister:
418  * @driver: device driver definition
419  *
420  * Remove a previously registered device driver
421  */
422 void connman_device_driver_unregister(struct connman_device_driver *driver)
423 {
424         DBG("driver %p name %s", driver, driver->name);
425
426         driver_list = g_slist_remove(driver_list, driver);
427
428         remove_driver(driver);
429 }
430
431 static void free_network(gpointer data)
432 {
433         struct connman_network *network = data;
434
435         DBG("network %p", network);
436
437         __connman_network_set_device(network, NULL);
438
439         connman_network_unref(network);
440 }
441
442 static void device_destruct(struct connman_device *device)
443 {
444         DBG("device %p name %s", device, device->name);
445
446         clear_pending_trigger(device);
447
448         g_hash_table_destroy(device->networks);
449         device->networks = NULL;
450
451         g_free(device->ident);
452         g_free(device->node);
453         g_free(device->name);
454         g_free(device->address);
455         g_free(device->interface);
456         g_free(device->path);
457
458         g_free(device->last_network);
459
460 #if defined TIZEN_EXT
461         g_free(device->last_user_selection_ident);
462         g_free(device->last_connected_ident);
463 #endif
464
465         g_free(device);
466 }
467
468 #if defined TIZEN_EXT
469 static void device_send_changed(const char *ifname, enum connman_service_type type,
470                                                                 const char *key, bool state)
471 {
472         DBusMessage *signal;
473         DBusMessageIter iter, dict;
474         dbus_bool_t value = state;
475         const char *tech_path = connman_techonology_get_path(type);
476
477         if (!tech_path || !ifname)
478                 return;
479
480         DBG("%s %s %s", ifname, key, state ? "TRUE" : "FALSE");
481
482         signal = dbus_message_new_signal(tech_path,
483                         CONNMAN_TECHNOLOGY_INTERFACE, "DeviceChanged");
484         if (!signal)
485                 return;
486
487         dbus_message_iter_init_append(signal, &iter);
488
489         connman_dbus_dict_open(&iter, &dict);
490         connman_dbus_dict_append_basic(&dict, "Ifname",
491                                         DBUS_TYPE_STRING,
492                                         &ifname);
493         connman_dbus_dict_append_basic(&dict, key,
494                                         DBUS_TYPE_BOOLEAN,
495                                         &value);
496         connman_dbus_dict_close(&iter, &dict);
497
498         dbus_connection_send(connection, signal, NULL);
499         dbus_message_unref(signal);
500 }
501
502 static void device_send_reply(struct connman_device *device)
503 {
504         if (device->pending_reply) {
505                 g_dbus_send_reply(connection,
506                                 device->pending_reply, DBUS_TYPE_INVALID);
507                 dbus_message_unref(device->pending_reply);
508                 device->pending_reply = NULL;
509         }
510 }
511 #endif
512
513 /**
514  * connman_device_create:
515  * @node: device node name (for example an address)
516  * @type: device type
517  *
518  * Allocate a new device of given #type and assign the #node name to it.
519  *
520  * Returns: a newly-allocated #connman_device structure
521  */
522 struct connman_device *connman_device_create(const char *node,
523                                                 enum connman_device_type type)
524 {
525         struct connman_device *device;
526
527         DBG("node %s type %d", node, type);
528
529         device = g_try_new0(struct connman_device, 1);
530         if (!device)
531                 return NULL;
532
533         DBG("device %p", device);
534
535         device->refcount = 1;
536
537         device->type = type;
538         device->name = g_strdup(type2description(device->type));
539
540         device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
541                                                 g_free, free_network);
542
543         device_list = g_slist_prepend(device_list, device);
544
545         return device;
546 }
547
548 /**
549  * connman_device_ref:
550  * @device: device structure
551  *
552  * Increase reference counter of device
553  */
554 struct connman_device *connman_device_ref_debug(struct connman_device *device,
555                                 const char *file, int line, const char *caller)
556 {
557         DBG("%p ref %d by %s:%d:%s()", device, device->refcount + 1,
558                 file, line, caller);
559
560         __sync_fetch_and_add(&device->refcount, 1);
561
562         return device;
563 }
564
565 /**
566  * connman_device_unref:
567  * @device: device structure
568  *
569  * Decrease reference counter of device
570  */
571 void connman_device_unref_debug(struct connman_device *device,
572                                 const char *file, int line, const char *caller)
573 {
574         DBG("%p ref %d by %s:%d:%s()", device, device->refcount - 1,
575                 file, line, caller);
576
577         if (__sync_fetch_and_sub(&device->refcount, 1) != 1)
578                 return;
579
580         if (device->driver) {
581                 device->driver->remove(device);
582                 device->driver = NULL;
583         }
584
585         device_list = g_slist_remove(device_list, device);
586
587         device_destruct(device);
588 }
589
590 const char *__connman_device_get_type(struct connman_device *device)
591 {
592         return type2string(device->type);
593 }
594
595 /**
596  * connman_device_get_type:
597  * @device: device structure
598  *
599  * Get type of device
600  */
601 enum connman_device_type connman_device_get_type(struct connman_device *device)
602 {
603         return device->type;
604 }
605
606 /**
607  * connman_device_set_index:
608  * @device: device structure
609  * @index: index number
610  *
611  * Set index number of device
612  */
613 void connman_device_set_index(struct connman_device *device, int index)
614 {
615         device->index = index;
616 }
617
618 /**
619  * connman_device_get_index:
620  * @device: device structure
621  *
622  * Get index number of device
623  */
624 int connman_device_get_index(struct connman_device *device)
625 {
626         return device->index;
627 }
628
629 /**
630  * connman_device_set_interface:
631  * @device: device structure
632  * @interface: interface name
633  *
634  * Set interface name of device
635  */
636 void connman_device_set_interface(struct connman_device *device,
637                                                 const char *interface)
638 {
639         g_free(device->interface);
640         device->interface = g_strdup(interface);
641
642         if (!device->name) {
643                 const char *str = type2description(device->type);
644                 if (str && device->interface)
645                         device->name = g_strdup_printf("%s (%s)", str,
646                                                         device->interface);
647         }
648 }
649
650 /**
651  * connman_device_set_ident:
652  * @device: device structure
653  * @ident: unique identifier
654  *
655  * Set unique identifier of device
656  */
657 void connman_device_set_ident(struct connman_device *device,
658                                                         const char *ident)
659 {
660 #ifdef TIZEN_EXT
661         if (device->ident)
662                 return;
663         else
664 #endif
665         g_free(device->ident);
666         device->ident = g_strdup(ident);
667 }
668
669 const char *connman_device_get_ident(struct connman_device *device)
670 {
671         return device->ident;
672 }
673
674 /**
675  * connman_device_set_powered:
676  * @device: device structure
677  * @powered: powered state
678  *
679  * Change power state of device
680  */
681 int connman_device_set_powered(struct connman_device *device,
682                                                 bool powered)
683 {
684         struct connman_device_scan_params params;
685         enum connman_service_type type;
686         int i;
687
688         DBG("device %p powered %d", device, powered);
689
690         if (device->powered == powered)
691                 return -EALREADY;
692
693 #if defined TIZEN_EXT
694         device_send_reply(device);
695 #endif
696
697         clear_pending_trigger(device);
698
699         device->powered_pending = PENDING_NONE;
700
701         device->powered = powered;
702
703         type = __connman_device_get_service_type(device);
704
705 #if defined TIZEN_EXT
706         device_send_changed(device->interface, type, "Powered", powered);
707         technology_save_device(device);
708 #endif
709
710         if (!device->powered) {
711                 __connman_technology_disabled(type);
712                 return 0;
713         }
714
715         __connman_technology_enabled(type);
716
717         for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++)
718                 device->scanning[i] = false;
719
720         if (device->driver && device->driver->scan) {
721                 memset(&params, 0, sizeof(params));
722                 params.type = CONNMAN_SERVICE_TYPE_UNKNOWN;
723
724                 device->driver->scan(device, &params);
725         }
726
727         return 0;
728 }
729
730 bool connman_device_get_powered(struct connman_device *device)
731 {
732         return device->powered;
733 }
734
735 static int device_scan(enum connman_service_type type,
736                                 struct connman_device *device,
737                                 bool force_full_scan)
738 {
739         struct connman_device_scan_params params;
740
741         if (!device->driver || !device->driver->scan)
742                 return -EOPNOTSUPP;
743
744         if (!device->powered)
745                 return -ENOLINK;
746
747         memset(&params, 0, sizeof(params));
748         params.type = type;
749         params.force_full_scan = force_full_scan;
750
751         return device->driver->scan(device, &params);
752 }
753
754 int __connman_device_disconnect(struct connman_device *device)
755 {
756         GHashTableIter iter;
757         gpointer key, value;
758
759         DBG("device %p", device);
760
761         g_hash_table_iter_init(&iter, device->networks);
762
763         while (g_hash_table_iter_next(&iter, &key, &value)) {
764                 struct connman_network *network = value;
765
766                 if (connman_network_get_connecting(network)) {
767                         /*
768                          * Skip network in the process of connecting.
769                          * This is a workaround for WiFi networks serviced
770                          * by the supplicant plugin that hold a reference
771                          * to the network.  If we disconnect the network
772                          * here then the referenced object will not be
773                          * registered and usage (like launching DHCP client)
774                          * will fail.  There is nothing to be gained by
775                          * removing the network here anyway.
776                          */
777                         connman_warn("Skipping disconnect of %s, network is connecting.",
778                                 connman_network_get_identifier(network));
779                         continue;
780                 }
781
782                 __connman_network_disconnect(network);
783         }
784
785         return 0;
786 }
787
788 int connman_device_reconnect_service(struct connman_device *device)
789 {
790         DBG("device %p", device);
791
792         __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
793
794         return 0;
795 }
796
797 #if defined TIZEN_EXT
798 bool connman_device_set_last_user_selection_time(struct connman_device *device,
799                                                 time_t time)
800 {
801         if (device->last_user_selection_time != time) {
802                 device->last_user_selection_time = time;
803                 return true;
804         }
805
806         return false;
807 }
808
809 time_t connman_device_get_last_user_selection_time(struct connman_device *device)
810 {
811         return device->last_user_selection_time;
812 }
813
814 bool connman_device_set_last_user_selection_ident(struct connman_device *device,
815                                                 const char *ident)
816 {
817         if (g_strcmp0(device->last_user_selection_ident, ident) != 0) {
818                 g_free(device->last_user_selection_ident);
819                 device->last_user_selection_ident = g_strdup(ident);
820
821                 return true;
822         }
823
824         return false;
825 }
826
827 const char *connman_device_get_last_user_selection_ident(struct connman_device *device)
828 {
829         return device->last_user_selection_ident;
830 }
831
832 bool connman_device_set_last_connected_ident(struct connman_device *device,
833                                                 const char *ident)
834 {
835         if (g_strcmp0(device->last_connected_ident, ident) != 0) {
836                 g_free(device->last_connected_ident);
837                 device->last_connected_ident = g_strdup(ident);
838
839                 return true;
840         }
841
842         return false;
843 }
844
845 const char *connman_device_get_last_connected_ident(struct connman_device *device)
846 {
847         return device->last_connected_ident;
848 }
849
850 void connman_device_save_last_user_selection(struct connman_device *device)
851 {
852         GKeyFile *keyfile;
853         gchar *get_str;
854         gchar *selection_str;
855
856         keyfile = __connman_storage_load_ins();
857
858         selection_str = g_strdup_printf("%s:%ld",
859                         device->last_user_selection_ident, device->last_user_selection_time);
860
861         if (!keyfile) {
862                 keyfile = g_key_file_new();
863
864                 g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
865                 DBG("%s", selection_str);
866                 __connman_storage_save_ins(keyfile);
867
868         } else {
869                 get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
870                 if (!get_str || g_strcmp0(get_str, selection_str) != 0) {
871                         g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
872                         DBG("%s -> %s", get_str, selection_str);
873                         __connman_storage_save_ins(keyfile);
874                 }
875
876                 g_free(get_str);
877         }
878
879         g_free(selection_str);
880         g_key_file_free(keyfile);
881 }
882
883 void connman_device_load_last_user_selection(struct connman_device *device)
884 {
885         GKeyFile *keyfile;
886         gchar *get_str;
887         char **selection_str;
888
889         keyfile = __connman_storage_load_ins();
890         if (!keyfile)
891                 return;
892
893         get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
894         if (get_str) {
895                 selection_str = g_strsplit(get_str, ":", 0);
896                 if (selection_str) {
897                         time_t ref_time;
898                         struct tm* timeinfo;
899                         time_t last_user_selection_time;
900
901                         /* Only events that occur within 8 hours are counted. */
902                         ref_time = time(NULL);
903                         timeinfo = localtime(&ref_time);
904                         timeinfo->tm_hour -= 8;
905                         ref_time = mktime(timeinfo);
906
907                         last_user_selection_time = strtol(selection_str[1], NULL, 10);
908
909                         if (last_user_selection_time > ref_time) {
910                                 if (g_strcmp0(selection_str[0], device->last_user_selection_ident) != 0) {
911                                         g_free(device->last_user_selection_ident);
912                                         device->last_user_selection_ident = g_strdup(selection_str[0]);
913                                 }
914
915                                 device->last_user_selection_time = last_user_selection_time;
916
917                                 DBG("%s %ld", device->last_user_selection_ident, device->last_user_selection_time);
918                         }
919
920                         g_strfreev(selection_str);
921                 }
922
923                 g_free(get_str);
924         }
925
926         g_key_file_free(keyfile);
927 }
928
929 void connman_device_save_last_connected(struct connman_device *device)
930 {
931         GKeyFile *keyfile;
932         gchar *get_str;
933
934         if (!device->last_connected_ident)
935                 return;
936
937         keyfile = __connman_storage_load_ins();
938
939         if (!keyfile) {
940                 keyfile = g_key_file_new();
941
942                 g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
943                 DBG("%s", device->last_connected_ident);
944                 __connman_storage_save_ins(keyfile);
945
946         } else {
947                 get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
948                 if (!get_str || g_strcmp0(get_str, device->last_connected_ident) != 0) {
949                         g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
950                         DBG("%s -> %s", get_str, device->last_connected_ident);
951                         __connman_storage_save_ins(keyfile);
952                 }
953
954                 g_free(get_str);
955         }
956
957         g_key_file_free(keyfile);
958 }
959
960 void connman_device_load_last_connected(struct connman_device *device)
961 {
962         GKeyFile *keyfile;
963         gchar *get_str;
964
965         keyfile = __connman_storage_load_ins();
966         if (!keyfile)
967                 return;
968
969         get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
970         if (get_str) {
971                 if (g_strcmp0(get_str, device->last_connected_ident) != 0) {
972                         g_free(device->last_connected_ident);
973                         device->last_connected_ident = g_strdup(get_str);
974                 }
975
976                 DBG("%s", device->last_connected_ident);
977
978                 g_free(get_str);
979         }
980
981         g_key_file_free(keyfile);
982 }
983 #endif
984
985 static void mark_network_available(gpointer key, gpointer value,
986                                                         gpointer user_data)
987 {
988         struct connman_network *network = value;
989
990         connman_network_set_available(network, true);
991 }
992
993 static void mark_network_unavailable(gpointer key, gpointer value,
994                                                         gpointer user_data)
995 {
996         struct connman_network *network = value;
997
998         if (connman_network_get_connected(network) ||
999                         connman_network_get_connecting(network))
1000                 return;
1001
1002         connman_network_set_available(network, false);
1003 }
1004
1005 static gboolean remove_unavailable_network(gpointer key, gpointer value,
1006                                                         gpointer user_data)
1007 {
1008         struct connman_network *network = value;
1009
1010         if (connman_network_get_connected(network) ||
1011                         connman_network_get_connecting(network))
1012                 return FALSE;
1013
1014         if (connman_network_get_available(network))
1015                 return FALSE;
1016
1017         return TRUE;
1018 }
1019
1020 void __connman_device_cleanup_networks(struct connman_device *device)
1021 {
1022         g_hash_table_foreach_remove(device->networks,
1023                                         remove_unavailable_network, NULL);
1024 }
1025
1026 bool connman_device_get_scanning(struct connman_device *device,
1027                                 enum connman_service_type type)
1028 {
1029         int i;
1030
1031         if (type != CONNMAN_SERVICE_TYPE_UNKNOWN)
1032                 return device->scanning[type];
1033
1034         for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++)
1035                 if (device->scanning[i])
1036                         return true;
1037
1038         return false;
1039 }
1040
1041 void connman_device_reset_scanning(struct connman_device *device)
1042 {
1043         g_hash_table_foreach(device->networks,
1044                                 mark_network_available, NULL);
1045 }
1046
1047 /**
1048  * connman_device_set_scanning:
1049  * @device: device structure
1050  * @scanning: scanning state
1051  *
1052  * Change scanning state of device
1053  */
1054 int connman_device_set_scanning(struct connman_device *device,
1055                                 enum connman_service_type type, bool scanning)
1056 {
1057         DBG("device %p scanning %d", device, scanning);
1058
1059         if (!device->driver || !device->driver->scan)
1060                 return -EINVAL;
1061
1062         if (type == CONNMAN_SERVICE_TYPE_UNKNOWN)
1063                 return -EINVAL;
1064
1065         if (device->scanning[type] == scanning)
1066                 return -EALREADY;
1067
1068         device->scanning[type] = scanning;
1069
1070         if (scanning) {
1071                 __connman_technology_scan_started(device);
1072
1073                 g_hash_table_foreach(device->networks,
1074                                         mark_network_unavailable, NULL);
1075
1076                 return 0;
1077         }
1078
1079         __connman_device_cleanup_networks(device);
1080
1081         __connman_technology_scan_stopped(device, type);
1082
1083         __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
1084
1085 #if defined TIZEN_EXT_WIFI_MESH
1086         if (type == CONNMAN_SERVICE_TYPE_MESH)
1087                 __connman_mesh_auto_connect();
1088 #endif
1089
1090         return 0;
1091 }
1092
1093 /**
1094  * connman_device_set_string:
1095  * @device: device structure
1096  * @key: unique identifier
1097  * @value: string value
1098  *
1099  * Set string value for specific key
1100  */
1101 int connman_device_set_string(struct connman_device *device,
1102                                         const char *key, const char *value)
1103 {
1104         DBG("device %p key %s value %s", device, key, value);
1105
1106         if (g_str_equal(key, "Address")) {
1107 #ifdef TIZEN_EXT
1108                 if (device->address)
1109                         return 0;
1110                 else
1111 #endif
1112                 g_free(device->address);
1113                 device->address = g_strdup(value);
1114         } else if (g_str_equal(key, "Name")) {
1115                 g_free(device->name);
1116                 device->name = g_strdup(value);
1117         } else if (g_str_equal(key, "Node")) {
1118                 g_free(device->node);
1119                 device->node = g_strdup(value);
1120         } else if (g_str_equal(key, "Path")) {
1121                 g_free(device->path);
1122                 device->path = g_strdup(value);
1123         } else {
1124                 return -EINVAL;
1125         }
1126
1127         return 0;
1128 }
1129
1130 /**
1131  * connman_device_get_string:
1132  * @device: device structure
1133  * @key: unique identifier
1134  *
1135  * Get string value for specific key
1136  */
1137 const char *connman_device_get_string(struct connman_device *device,
1138                                                         const char *key)
1139 {
1140 #if defined TIZEN_EXT
1141         if (!simplified_log)
1142 #endif
1143         DBG("device %p key %s", device, key);
1144
1145         if (g_str_equal(key, "Address"))
1146                 return device->address;
1147         else if (g_str_equal(key, "Name"))
1148                 return device->name;
1149         else if (g_str_equal(key, "Node"))
1150                 return device->node;
1151         else if (g_str_equal(key, "Interface"))
1152                 return device->interface;
1153         else if (g_str_equal(key, "Path"))
1154                 return device->path;
1155
1156         return NULL;
1157 }
1158
1159 /**
1160  * connman_device_add_network:
1161  * @device: device structure
1162  * @network: network structure
1163  *
1164  * Add new network to the device
1165  */
1166 int connman_device_add_network(struct connman_device *device,
1167                                         struct connman_network *network)
1168 {
1169         const char *identifier = connman_network_get_identifier(network);
1170 #if defined TIZEN_EXT
1171         if (!simplified_log)
1172 #endif
1173         DBG("device %p network %p", device, network);
1174
1175         if (!identifier)
1176                 return -EINVAL;
1177
1178         connman_network_ref(network);
1179
1180         __connman_network_set_device(network, device);
1181
1182         g_hash_table_replace(device->networks, g_strdup(identifier),
1183                                                                 network);
1184
1185         return 0;
1186 }
1187
1188 /**
1189  * connman_device_get_network:
1190  * @device: device structure
1191  * @identifier: network identifier
1192  *
1193  * Get network for given identifier
1194  */
1195 struct connman_network *connman_device_get_network(struct connman_device *device,
1196                                                         const char *identifier)
1197 {
1198 #if defined TIZEN_EXT
1199         if (!simplified_log)
1200 #endif
1201         DBG("device %p identifier %s", device, identifier);
1202
1203         return g_hash_table_lookup(device->networks, identifier);
1204 }
1205
1206 #if defined TIZEN_EXT
1207 struct connman_network *connman_device_get_default_network(
1208                                                         struct connman_device *device)
1209 {
1210         return device->network;
1211 }
1212
1213 void connman_device_set_pending_reply(struct connman_device *device,
1214                                                         DBusMessage *msg)
1215 {
1216         device->pending_reply = dbus_message_ref(msg);
1217 }
1218
1219 void connman_device_send_connected_signal(struct connman_device *device,
1220                                                         bool connected)
1221 {
1222         enum connman_service_type type;
1223
1224         if (!device)
1225                 return;
1226
1227         type = __connman_device_get_service_type(device);
1228         device_send_changed(device->interface, type, "Connected", connected);
1229 }
1230
1231 void connman_device_set_max_scan_ssids(struct connman_device *device,
1232                                                         int max_scan_ssids)
1233 {
1234         device->max_scan_ssids = max_scan_ssids;
1235 }
1236
1237 int connman_device_get_max_scan_ssids(struct connman_device *device)
1238 {
1239         return device->max_scan_ssids;
1240 }
1241
1242 void connman_device_set_wifi_5ghz_supported(struct connman_device *device,
1243                                                         bool is_5_0_ghz_supported)
1244 {
1245         device->is_5_0_ghz_supported = is_5_0_ghz_supported;
1246 }
1247
1248 bool connman_device_get_wifi_5ghz_supported(struct connman_device *device)
1249 {
1250         return device->is_5_0_ghz_supported;
1251 }
1252 #endif
1253
1254 /**
1255  * connman_device_remove_network:
1256  * @device: device structure
1257  * @identifier: network identifier
1258  *
1259  * Remove network for given identifier
1260  */
1261 int connman_device_remove_network(struct connman_device *device,
1262                                                 struct connman_network *network)
1263 {
1264         const char *identifier;
1265
1266         DBG("device %p network %p", device, network);
1267
1268         if (!network)
1269                 return 0;
1270
1271         identifier = connman_network_get_identifier(network);
1272         g_hash_table_remove(device->networks, identifier);
1273
1274         return 0;
1275 }
1276
1277 void __connman_device_set_network(struct connman_device *device,
1278                                         struct connman_network *network)
1279 {
1280         const char *name;
1281
1282         if (!device)
1283                 return;
1284
1285         if (device->network == network)
1286                 return;
1287
1288         if (network) {
1289                 name = connman_network_get_string(network, "Name");
1290                 g_free(device->last_network);
1291                 device->last_network = g_strdup(name);
1292
1293                 device->network = network;
1294         } else {
1295                 g_free(device->last_network);
1296                 device->last_network = NULL;
1297
1298                 device->network = NULL;
1299         }
1300 }
1301
1302 static bool match_driver(struct connman_device *device,
1303                                         struct connman_device_driver *driver)
1304 {
1305         if (device->type == driver->type ||
1306                         driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
1307                 return true;
1308
1309         return false;
1310 }
1311
1312 /**
1313  * connman_device_register:
1314  * @device: device structure
1315  *
1316  * Register device with the system
1317  */
1318 int connman_device_register(struct connman_device *device)
1319 {
1320         GSList *list;
1321
1322         DBG("device %p name %s", device, device->name);
1323
1324         if (device->driver)
1325                 return -EALREADY;
1326
1327         for (list = driver_list; list; list = list->next) {
1328                 struct connman_device_driver *driver = list->data;
1329
1330                 if (!match_driver(device, driver))
1331                         continue;
1332
1333                 DBG("driver %p name %s", driver, driver->name);
1334
1335                 if (driver->probe(device) == 0) {
1336                         device->driver = driver;
1337                         break;
1338                 }
1339         }
1340
1341         if (!device->driver)
1342                 return 0;
1343
1344         return __connman_technology_add_device(device);
1345 }
1346
1347 /**
1348  * connman_device_unregister:
1349  * @device: device structure
1350  *
1351  * Unregister device with the system
1352  */
1353 void connman_device_unregister(struct connman_device *device)
1354 {
1355         DBG("device %p name %s", device, device->name);
1356
1357         if (!device->driver)
1358                 return;
1359
1360         remove_device(device);
1361 }
1362
1363 /**
1364  * connman_device_get_data:
1365  * @device: device structure
1366  *
1367  * Get private device data pointer
1368  */
1369 void *connman_device_get_data(struct connman_device *device)
1370 {
1371         return device->driver_data;
1372 }
1373
1374 /**
1375  * connman_device_set_data:
1376  * @device: device structure
1377  * @data: data pointer
1378  *
1379  * Set private device data pointer
1380  */
1381 void connman_device_set_data(struct connman_device *device, void *data)
1382 {
1383         device->driver_data = data;
1384 }
1385
1386 struct connman_device *__connman_device_find_device(
1387                                 enum connman_service_type type)
1388 {
1389         GSList *list;
1390
1391         for (list = device_list; list; list = list->next) {
1392                 struct connman_device *device = list->data;
1393                 enum connman_service_type service_type =
1394                         __connman_device_get_service_type(device);
1395
1396                 if (service_type != type)
1397                         continue;
1398
1399                 return device;
1400         }
1401
1402         return NULL;
1403 }
1404
1405 struct connman_device *connman_device_find_by_index(int index)
1406 {
1407         GSList *list;
1408
1409         for (list = device_list; list; list = list->next) {
1410                 struct connman_device *device = list->data;
1411                 if (device->index == index)
1412                         return device;
1413         }
1414
1415         return NULL;
1416 }
1417
1418 /**
1419  * connman_device_set_regdom
1420  * @device: device structure
1421  * @alpha2: string representing regulatory domain
1422  *
1423  * Set regulatory domain on device basis
1424  */
1425 int connman_device_set_regdom(struct connman_device *device,
1426                                                 const char *alpha2)
1427 {
1428         if (!device->driver || !device->driver->set_regdom)
1429                 return -ENOTSUP;
1430
1431         if (!device->powered)
1432                 return -EINVAL;
1433
1434         return device->driver->set_regdom(device, alpha2);
1435 }
1436
1437 /**
1438  * connman_device_regdom_notify
1439  * @device: device structure
1440  * @alpha2: string representing regulatory domain
1441  *
1442  * Notify on setting regulatory domain on device basis
1443  */
1444 void connman_device_regdom_notify(struct connman_device *device,
1445                                         int result, const char *alpha2)
1446 {
1447         __connman_technology_notify_regdom_by_device(device, result, alpha2);
1448 }
1449
1450 #if defined TIZEN_EXT
1451 static int device_specific_scan(enum connman_service_type type,
1452                                 struct connman_device *device,
1453                                 int scan_type, GSList *specific_scan_list)
1454 {
1455         if (!device->driver || !device->driver->specific_scan)
1456                 return -EOPNOTSUPP;
1457
1458         if (!device->powered)
1459                 return -ENOLINK;
1460
1461         return device->driver->specific_scan(type, device, scan_type,
1462                         specific_scan_list, NULL);
1463 }
1464
1465 int __connman_device_request_specific_scan(enum connman_service_type type,
1466                                 const char *ifname, int scan_type, GSList *specific_scan_list)
1467 {
1468         bool success = false;
1469         int last_err = -ENOSYS;
1470         GSList *list;
1471         int err;
1472
1473         switch (type) {
1474         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1475         case CONNMAN_SERVICE_TYPE_SYSTEM:
1476         case CONNMAN_SERVICE_TYPE_ETHERNET:
1477         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1478         case CONNMAN_SERVICE_TYPE_CELLULAR:
1479         case CONNMAN_SERVICE_TYPE_GPS:
1480         case CONNMAN_SERVICE_TYPE_VPN:
1481         case CONNMAN_SERVICE_TYPE_GADGET:
1482                 return -EOPNOTSUPP;
1483         case CONNMAN_SERVICE_TYPE_WIFI:
1484         case CONNMAN_SERVICE_TYPE_P2P:
1485 #if defined TIZEN_EXT_WIFI_MESH
1486         case CONNMAN_SERVICE_TYPE_MESH:
1487 #endif
1488                 break;
1489         }
1490
1491         for (list = device_list; list; list = list->next) {
1492                 struct connman_device *device = list->data;
1493                 enum connman_service_type service_type =
1494                         __connman_device_get_service_type(device);
1495
1496                 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1497                         if (type == CONNMAN_SERVICE_TYPE_P2P) {
1498                                 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1499                                         continue;
1500                         } else if (service_type != type)
1501                                 continue;
1502                 }
1503
1504                 if (ifname && g_strcmp0(device->interface, ifname) != 0)
1505                         continue;
1506
1507                 err = device_specific_scan(type, device, scan_type, specific_scan_list);
1508                 if (err == 0 || err == -EINPROGRESS) {
1509                         success = true;
1510                 } else {
1511                         last_err = err;
1512                         DBG("device %p err %d", device, err);
1513                 }
1514         }
1515
1516         if (success)
1517                 return 0;
1518
1519         return last_err;
1520 }
1521
1522 int connman_device_request_device_scan(enum connman_service_type type,
1523                                 const char * ifname, bool force_full_scan)
1524 {
1525         bool success = false;
1526         int last_err = -ENOSYS;
1527         GSList *list;
1528         int err;
1529
1530         switch (type) {
1531         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1532         case CONNMAN_SERVICE_TYPE_SYSTEM:
1533         case CONNMAN_SERVICE_TYPE_ETHERNET:
1534         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1535         case CONNMAN_SERVICE_TYPE_CELLULAR:
1536         case CONNMAN_SERVICE_TYPE_GPS:
1537         case CONNMAN_SERVICE_TYPE_VPN:
1538         case CONNMAN_SERVICE_TYPE_GADGET:
1539                 return -EOPNOTSUPP;
1540         case CONNMAN_SERVICE_TYPE_WIFI:
1541         case CONNMAN_SERVICE_TYPE_P2P:
1542 #if defined TIZEN_EXT_WIFI_MESH
1543         case CONNMAN_SERVICE_TYPE_MESH:
1544 #endif
1545                 break;
1546         }
1547
1548         for (list = device_list; list; list = list->next) {
1549                 struct connman_device *device = list->data;
1550
1551                 if (!device_has_service_type(device, type))
1552                         continue;
1553
1554                 if (g_strcmp0(device->interface, ifname) != 0)
1555                         continue;
1556
1557                 err = device_scan(type, device, force_full_scan);
1558
1559                 if (err == 0 || err == -EINPROGRESS) {
1560                         success = true;
1561                 } else {
1562                         last_err = err;
1563                         DBG("device %p err %d", device, err);
1564                 }
1565                 break;
1566         }
1567
1568         if (success)
1569                 return 0;
1570
1571         return last_err;
1572 }
1573
1574 #if defined TIZEN_EXT_WIFI_MESH
1575 static int device_abort_scan(enum connman_service_type type,
1576                                 struct connman_device *device)
1577 {
1578         if (!device->driver || !device->driver->scan)
1579                 return -EOPNOTSUPP;
1580
1581         if (!device->powered)
1582                 return -ENOLINK;
1583
1584         return device->driver->abort_scan(type, device);
1585 }
1586
1587 int __connman_device_abort_scan(enum connman_service_type type)
1588 {
1589         GSList *list;
1590         int err = -EINVAL;
1591
1592         if (type != CONNMAN_SERVICE_TYPE_MESH)
1593                 return -EINVAL;
1594
1595         for (list = device_list; list; list = list->next) {
1596                 struct connman_device *device = list->data;
1597                 enum connman_service_type service_type =
1598                         __connman_device_get_service_type(device);
1599
1600                 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1601                         if (type == CONNMAN_SERVICE_TYPE_MESH)
1602                                 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1603                                         continue;
1604
1605                         if (!device->scanning) {
1606                                 err = -EEXIST;
1607                                 continue;
1608                         }
1609
1610                         err = device_abort_scan(type, device);
1611                 }
1612         }
1613         return err;
1614 }
1615
1616 static int device_mesh_specific_scan(enum connman_service_type type,
1617                                 struct connman_device *device, const char *name,
1618                                 unsigned int freq)
1619 {
1620         if (!device->driver || !device->driver->mesh_specific_scan)
1621                 return -EOPNOTSUPP;
1622
1623         if (!device->powered)
1624                 return -ENOLINK;
1625
1626         return device->driver->mesh_specific_scan(type, device, name, freq, NULL);
1627 }
1628
1629 int __connman_device_request_mesh_specific_scan(enum connman_service_type type,
1630                                                 const char *name,
1631                                                 unsigned int freq)
1632 {
1633         bool success = false;
1634         int last_err = -ENOSYS;
1635         GSList *list;
1636         int err;
1637
1638         if (type != CONNMAN_SERVICE_TYPE_MESH)
1639                 return -EINVAL;
1640
1641         for (list = device_list; list; list = list->next) {
1642                 struct connman_device *device = list->data;
1643                 enum connman_service_type service_type =
1644                         __connman_device_get_service_type(device);
1645
1646                 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1647                         if (type == CONNMAN_SERVICE_TYPE_MESH)
1648                                 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1649                                         continue;
1650                 }
1651
1652                 err = device_mesh_specific_scan(type, device, name, freq);
1653                 if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
1654                         success = true;
1655                 } else {
1656                         last_err = err;
1657                         DBG("device %p err %d", device, err);
1658                 }
1659         }
1660
1661         if (success)
1662                 return 0;
1663
1664         return last_err;
1665 }
1666 #endif /* TIZEN_EXT_WIFI_MESH */
1667 #endif
1668
1669 static int connman_device_request_scan(enum connman_service_type type,
1670                                         bool force_full_scan)
1671 {
1672         bool success = false;
1673         int last_err = -ENOSYS;
1674         GSList *list;
1675         int err;
1676
1677         switch (type) {
1678         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1679         case CONNMAN_SERVICE_TYPE_SYSTEM:
1680         case CONNMAN_SERVICE_TYPE_ETHERNET:
1681         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1682         case CONNMAN_SERVICE_TYPE_CELLULAR:
1683         case CONNMAN_SERVICE_TYPE_GPS:
1684         case CONNMAN_SERVICE_TYPE_VPN:
1685         case CONNMAN_SERVICE_TYPE_GADGET:
1686                 return -EOPNOTSUPP;
1687         case CONNMAN_SERVICE_TYPE_WIFI:
1688         case CONNMAN_SERVICE_TYPE_P2P:
1689 #if defined TIZEN_EXT_WIFI_MESH
1690         case CONNMAN_SERVICE_TYPE_MESH:
1691 #endif
1692                 break;
1693         }
1694
1695         for (list = device_list; list; list = list->next) {
1696                 struct connman_device *device = list->data;
1697
1698                 if (!device_has_service_type(device, type))
1699                         continue;
1700
1701                 err = device_scan(type, device, force_full_scan);
1702 #if defined TIZEN_EXT
1703                 /* When Scan is already in progress then return Error so that
1704                  * wifi-manager can block the scan-done signal to be sent to
1705                  * application and start requested scan after scan already in progress
1706                  * is completed then notify to application about the scan event */
1707                 if (err == 0 || err == -EINPROGRESS) {
1708 #else
1709                 if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
1710 #endif
1711                         success = true;
1712                 } else {
1713                         last_err = err;
1714                         DBG("device %p err %d", device, err);
1715                 }
1716         }
1717
1718         if (success)
1719                 return 0;
1720
1721         return last_err;
1722 }
1723
1724 int __connman_device_request_scan(enum connman_service_type type)
1725 {
1726         return connman_device_request_scan(type, false);
1727 }
1728
1729 int __connman_device_request_scan_full(enum connman_service_type type)
1730 {
1731         return connman_device_request_scan(type, true);
1732 }
1733
1734 int __connman_device_request_hidden_scan(struct connman_device *device,
1735                                 const char *ssid, unsigned int ssid_len,
1736                                 const char *identity, const char *passphrase,
1737                                 const char *security, void *user_data)
1738 {
1739         struct connman_device_scan_params params;
1740
1741         DBG("device %p", device);
1742
1743         if (!device || !device->driver ||
1744                         !device->driver->scan)
1745                 return -EINVAL;
1746
1747         params.type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1748         params.ssid = ssid;
1749         params.ssid_len = ssid_len;
1750         params.identity = identity;
1751         params.passphrase = passphrase;
1752         params.security = security;
1753         params.user_data = user_data;
1754
1755         return device->driver->scan(device, &params);
1756 }
1757
1758 void __connman_device_stop_scan(enum connman_service_type type)
1759 {
1760         GSList *list;
1761
1762         for (list = device_list; list; list = list->next) {
1763                 struct connman_device *device = list->data;
1764
1765                 if (!device_has_service_type(device, type))
1766                         continue;
1767
1768                 if (device->driver && device->driver->stop_scan)
1769                         device->driver->stop_scan(type, device);
1770         }
1771 }
1772
1773 #if defined TIZEN_EXT
1774 char *index2ident(int index, const char *prefix)
1775 #else
1776 static char *index2ident(int index, const char *prefix)
1777 #endif
1778 {
1779         struct ifreq ifr;
1780         struct ether_addr eth;
1781         char *str;
1782         int sk, err, len;
1783
1784         if (index < 0)
1785                 return NULL;
1786
1787         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1788         if (sk < 0)
1789                 return NULL;
1790
1791         memset(&ifr, 0, sizeof(ifr));
1792         ifr.ifr_ifindex = index;
1793
1794         err = ioctl(sk, SIOCGIFNAME, &ifr);
1795
1796         if (err == 0)
1797                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1798
1799         close(sk);
1800
1801         if (err < 0)
1802                 return NULL;
1803
1804         len = prefix ? strlen(prefix) + 18 : 18;
1805
1806         str = g_malloc(len);
1807         if (!str)
1808                 return NULL;
1809
1810         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1811         snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
1812                                                 prefix ? prefix : "",
1813                                                 eth.ether_addr_octet[0],
1814                                                 eth.ether_addr_octet[1],
1815                                                 eth.ether_addr_octet[2],
1816                                                 eth.ether_addr_octet[3],
1817                                                 eth.ether_addr_octet[4],
1818                                                 eth.ether_addr_octet[5]);
1819
1820         return str;
1821 }
1822
1823 #if defined TIZEN_EXT
1824 char *index2addr(int index)
1825 #else
1826 static char *index2addr(int index)
1827 #endif
1828 {
1829         struct ifreq ifr;
1830         struct ether_addr eth;
1831         char *str;
1832         int sk, err;
1833
1834         if (index < 0)
1835                 return NULL;
1836
1837         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1838         if (sk < 0)
1839                 return NULL;
1840
1841         memset(&ifr, 0, sizeof(ifr));
1842         ifr.ifr_ifindex = index;
1843
1844         err = ioctl(sk, SIOCGIFNAME, &ifr);
1845
1846         if (err == 0)
1847                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1848
1849         close(sk);
1850
1851         if (err < 0)
1852                 return NULL;
1853
1854         str = g_malloc(18);
1855         if (!str)
1856                 return NULL;
1857
1858         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1859         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
1860                                                 eth.ether_addr_octet[0],
1861                                                 eth.ether_addr_octet[1],
1862                                                 eth.ether_addr_octet[2],
1863                                                 eth.ether_addr_octet[3],
1864                                                 eth.ether_addr_octet[4],
1865                                                 eth.ether_addr_octet[5]);
1866
1867         return str;
1868 }
1869
1870 struct connman_device *connman_device_create_from_index(int index)
1871 {
1872         enum connman_device_type type;
1873         struct connman_device *device;
1874         char *devname, *ident = NULL;
1875         char *addr = NULL, *name = NULL;
1876
1877         if (index < 0)
1878                 return NULL;
1879
1880         devname = connman_inet_ifname(index);
1881         if (!devname)
1882                 return NULL;
1883
1884         if (__connman_device_isfiltered(devname)) {
1885                 connman_info("Ignoring interface %s (filtered)", devname);
1886                 g_free(devname);
1887                 return NULL;
1888         }
1889
1890         type = __connman_rtnl_get_device_type(index);
1891
1892         switch (type) {
1893         case CONNMAN_DEVICE_TYPE_UNKNOWN:
1894                 connman_info("Ignoring interface %s (type unknown)", devname);
1895                 g_free(devname);
1896                 return NULL;
1897         case CONNMAN_DEVICE_TYPE_ETHERNET:
1898         case CONNMAN_DEVICE_TYPE_GADGET:
1899         case CONNMAN_DEVICE_TYPE_WIFI:
1900                 name = index2ident(index, "");
1901                 addr = index2addr(index);
1902                 break;
1903         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1904         case CONNMAN_DEVICE_TYPE_CELLULAR:
1905         case CONNMAN_DEVICE_TYPE_GPS:
1906         case CONNMAN_DEVICE_TYPE_VENDOR:
1907                 name = g_strdup(devname);
1908                 break;
1909         }
1910
1911         device = connman_device_create(name, type);
1912         if (!device)
1913                 goto done;
1914
1915         switch (type) {
1916         case CONNMAN_DEVICE_TYPE_UNKNOWN:
1917         case CONNMAN_DEVICE_TYPE_VENDOR:
1918         case CONNMAN_DEVICE_TYPE_GPS:
1919                 break;
1920         case CONNMAN_DEVICE_TYPE_ETHERNET:
1921         case CONNMAN_DEVICE_TYPE_GADGET:
1922                 ident = index2ident(index, NULL);
1923                 break;
1924         case CONNMAN_DEVICE_TYPE_WIFI:
1925                 ident = index2ident(index, NULL);
1926                 break;
1927         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1928                 break;
1929         case CONNMAN_DEVICE_TYPE_CELLULAR:
1930                 ident = index2ident(index, NULL);
1931                 break;
1932         }
1933
1934         connman_device_set_index(device, index);
1935         connman_device_set_interface(device, devname);
1936 #if defined TIZEN_EXT
1937         connman_device_load_last_connected(device);
1938         connman_device_load_last_user_selection(device);
1939 #endif
1940
1941         if (ident) {
1942                 connman_device_set_ident(device, ident);
1943                 g_free(ident);
1944         }
1945
1946         connman_device_set_string(device, "Address", addr);
1947
1948 done:
1949         g_free(devname);
1950         g_free(name);
1951         g_free(addr);
1952
1953         return device;
1954 }
1955
1956 bool __connman_device_isfiltered(const char *devname)
1957 {
1958         char **pattern;
1959         char **blacklisted_interfaces;
1960         bool match;
1961
1962         if (!device_filter)
1963                 goto nodevice;
1964
1965         for (pattern = device_filter, match = false; *pattern; pattern++) {
1966                 if (g_pattern_match_simple(*pattern, devname)) {
1967                         match = true;
1968                         break;
1969                 }
1970         }
1971
1972         if (!match) {
1973                 DBG("ignoring device %s (match)", devname);
1974                 return true;
1975         }
1976
1977 nodevice:
1978         if (g_pattern_match_simple("dummy*", devname)) {
1979                 DBG("ignoring dummy networking devices");
1980                 return true;
1981         }
1982
1983         if (!nodevice_filter)
1984                 goto list;
1985
1986         for (pattern = nodevice_filter; *pattern; pattern++) {
1987                 if (g_pattern_match_simple(*pattern, devname)) {
1988                         DBG("ignoring device %s (no match)", devname);
1989                         return true;
1990                 }
1991         }
1992
1993 list:
1994         if (__connman_inet_isrootnfs_device(devname)) {
1995                 DBG("ignoring device %s (rootnfs)", devname);
1996                 return true;
1997         }
1998
1999         blacklisted_interfaces =
2000                 connman_setting_get_string_list("NetworkInterfaceBlacklist");
2001         if (!blacklisted_interfaces)
2002                 return false;
2003
2004         for (pattern = blacklisted_interfaces; *pattern; pattern++) {
2005                 if (g_str_has_prefix(devname, *pattern)) {
2006                         DBG("ignoring device %s (blacklist)", devname);
2007                         return true;
2008                 }
2009         }
2010
2011         return false;
2012 }
2013
2014 static void cleanup_devices(void)
2015 {
2016         /*
2017          * Check what interfaces are currently up and if connman is
2018          * suppose to handle the interface, then cleanup the mess
2019          * related to that interface. There might be weird routes etc
2020          * that are related to that interface and that might confuse
2021          * connmand. So in this case we just turn the interface down
2022          * so that kernel removes routes/addresses automatically and
2023          * then proceed the startup.
2024          *
2025          * Note that this cleanup must be done before rtnl/detect code
2026          * has activated interface watches.
2027          */
2028
2029         char **interfaces;
2030         int i;
2031
2032         interfaces = __connman_inet_get_running_interfaces();
2033
2034         if (!interfaces)
2035                 return;
2036
2037         for (i = 0; interfaces[i]; i++) {
2038                 bool filtered;
2039                 int index;
2040                 struct sockaddr_in sin_addr, sin_mask;
2041
2042                 filtered = __connman_device_isfiltered(interfaces[i]);
2043                 if (filtered)
2044                         continue;
2045
2046                 index = connman_inet_ifindex(interfaces[i]);
2047                 if (index < 0)
2048                         continue;
2049
2050                 if (!__connman_inet_get_address_netmask(index, &sin_addr,
2051                                                         &sin_mask)) {
2052                         char *address = g_strdup(inet_ntoa(sin_addr.sin_addr));
2053                         char *netmask = g_strdup(inet_ntoa(sin_mask.sin_addr));
2054
2055                         if (__connman_config_address_provisioned(address,
2056                                                                 netmask)) {
2057                                 DBG("Skip %s which is already provisioned "
2058                                         "with %s/%s", interfaces[i], address,
2059                                         netmask);
2060                                 g_free(address);
2061                                 g_free(netmask);
2062                                 continue;
2063                         }
2064
2065                         g_free(address);
2066                         g_free(netmask);
2067                 }
2068
2069                 DBG("cleaning up %s index %d", interfaces[i], index);
2070
2071 #if defined TIZEN_EXT
2072                 if (strcmp(interfaces[i], "wlan0") != 0)
2073 #endif
2074                 connman_inet_ifdown(index);
2075
2076                 /*
2077                  * ConnMan will turn the interface UP automatically so
2078                  * no need to do it here.
2079                  */
2080         }
2081
2082         g_strfreev(interfaces);
2083 }
2084
2085 int __connman_device_init(const char *device, const char *nodevice)
2086 {
2087         DBG("");
2088
2089 #if defined TIZEN_EXT
2090         connection = connman_dbus_get_connection();
2091 #endif
2092
2093         if (device)
2094                 device_filter = g_strsplit(device, ",", -1);
2095
2096         if (nodevice)
2097                 nodevice_filter = g_strsplit(nodevice, ",", -1);
2098
2099         cleanup_devices();
2100
2101         return 0;
2102 }
2103
2104 void __connman_device_cleanup(void)
2105 {
2106         DBG("");
2107
2108         g_strfreev(nodevice_filter);
2109         g_strfreev(device_filter);
2110
2111 #if defined TIZEN_EXT
2112         dbus_connection_unref(connection);
2113 #endif
2114 }
2115
2116 #ifdef TIZEN_EXT
2117 void connman_device_mac_policy_notify(struct connman_device *device,
2118                                         int result, unsigned int policy)
2119 {
2120         device->mac_policy = policy;
2121         __connman_technology_notify_mac_policy_by_device(device, result, policy);
2122 }
2123
2124 int connman_device_set_mac_policy(struct connman_device *device,
2125                                         unsigned int policy)
2126 {
2127         int err = 0;
2128
2129         if (!device || !device->driver || !device->driver->set_mac_policy)
2130                 return -EOPNOTSUPP;
2131
2132         device->mac_policy = policy;
2133         err = device->driver->set_mac_policy(device, policy);
2134         return err;
2135 }
2136
2137 unsigned int connman_device_get_mac_policy(struct connman_device *device)
2138 {
2139         return device->mac_policy;
2140 }
2141
2142 void connman_device_preassoc_mac_policy_notify(struct connman_device *device,
2143                                         int result, unsigned int policy)
2144 {
2145         device->preassoc_mac_policy = policy;
2146         __connman_technology_notify_preassoc_mac_policy_by_device(device, result, policy);
2147 }
2148
2149 int connman_device_set_preassoc_mac_policy(struct connman_device *device,
2150                                         unsigned int policy)
2151 {
2152         int err = 0;
2153
2154         if (!device || !device->driver || !device->driver->set_preassoc_mac_policy)
2155                 return -EOPNOTSUPP;
2156
2157         device->preassoc_mac_policy = policy;
2158         err = device->driver->set_preassoc_mac_policy(device, policy);
2159         return err;
2160 }
2161
2162 unsigned int connman_device_get_preassoc_mac_policy(struct connman_device *device)
2163 {
2164         return device->preassoc_mac_policy;
2165 }
2166
2167 void connman_device_random_mac_lifetime_notify(struct connman_device *device,
2168                                         int result, unsigned int lifetime)
2169 {
2170         device->random_mac_lifetime = lifetime;
2171         __connman_technology_notify_random_mac_lifetime_by_device(device, result, lifetime);
2172 }
2173
2174 int connman_device_set_random_mac_lifetime(struct connman_device *device,
2175                                         unsigned int lifetime)
2176 {
2177         int err = 0;
2178
2179         if (!device || !device->driver || !device->driver->set_random_mac_lifetime)
2180                 return -EOPNOTSUPP;
2181
2182         device->random_mac_lifetime = lifetime;
2183         err = device->driver->set_random_mac_lifetime(device, lifetime);
2184         return err;
2185 }
2186
2187 unsigned int connman_device_get_random_mac_lifetime(struct connman_device *device)
2188 {
2189         return device->random_mac_lifetime;
2190 }
2191
2192 #endif