Fix autoconnect issue at reboot in TW3
[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 #define WIFI_MAC "/opt/etc/.mac.info"
1775 #define MAC_ADDR_LEN 18
1776
1777 char *_get_wifi_addr(void)
1778 {
1779         FILE *fp = NULL;
1780         char* rv = 0;
1781         char wifi_mac[MAC_ADDR_LEN + 1];
1782         char *str;
1783
1784         fp = fopen(WIFI_MAC, "r");
1785         if (!fp){
1786                 connman_error("[%s] not present", WIFI_MAC);
1787                 return NULL;
1788         }
1789
1790         rv = fgets(wifi_mac, MAC_ADDR_LEN, fp);
1791         if (!rv) {
1792                 connman_error("Failed to get wifi mac address");
1793                 fclose(fp);
1794                 return NULL;
1795         }
1796
1797         str = g_try_malloc0(MAC_ADDR_LEN);
1798         if (!str) {
1799                 connman_error("memory allocation failed");
1800                 fclose(fp);
1801                 return NULL;
1802         }
1803
1804         snprintf(str, MAC_ADDR_LEN, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
1805                         g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]),
1806                         g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]),
1807                         g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]),
1808                         g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]),
1809                         g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]),
1810                         g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16]));
1811         fclose(fp);
1812         return str;
1813 }
1814
1815 char *_get_wifi_ident(void)
1816 {
1817         FILE *fp = NULL;
1818         char* rv = 0;
1819         char wifi_mac[MAC_ADDR_LEN + 1];
1820         char *str;
1821
1822         fp = fopen(WIFI_MAC, "r");
1823         if (!fp){
1824                 connman_error("[%s] not present", WIFI_MAC);
1825                 return NULL;
1826         }
1827
1828         rv = fgets(wifi_mac, MAC_ADDR_LEN, fp);
1829         if (!rv) {
1830                 connman_error("Failed to get wifi mac address");
1831                 fclose(fp);
1832                 return NULL;
1833         }
1834
1835         str = g_try_malloc0(MAC_ADDR_LEN);
1836         if (!str) {
1837                 connman_error("memory allocation failed");
1838                 fclose(fp);
1839                 return NULL;
1840         }
1841
1842         snprintf(str, MAC_ADDR_LEN, "%c%c%c%c%c%c%c%c%c%c%c%c",
1843                         g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]),
1844                         g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]),
1845                         g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]),
1846                         g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]),
1847                         g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]),
1848                         g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16]));
1849         fclose(fp);
1850         return str;
1851 }
1852 #endif
1853
1854 #if defined TIZEN_EXT
1855 char *index2ident(int index, const char *prefix)
1856 #else
1857 static char *index2ident(int index, const char *prefix)
1858 #endif
1859 {
1860         struct ifreq ifr;
1861         struct ether_addr eth;
1862         char *str;
1863         int sk, err, len;
1864
1865         if (index < 0)
1866                 return NULL;
1867
1868         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1869         if (sk < 0)
1870                 return NULL;
1871
1872         memset(&ifr, 0, sizeof(ifr));
1873         ifr.ifr_ifindex = index;
1874
1875         err = ioctl(sk, SIOCGIFNAME, &ifr);
1876
1877         if (err == 0)
1878                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1879
1880         close(sk);
1881
1882         if (err < 0)
1883                 return NULL;
1884
1885         len = prefix ? strlen(prefix) + 18 : 18;
1886
1887         str = g_malloc(len);
1888         if (!str)
1889                 return NULL;
1890
1891         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1892         snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
1893                                                 prefix ? prefix : "",
1894                                                 eth.ether_addr_octet[0],
1895                                                 eth.ether_addr_octet[1],
1896                                                 eth.ether_addr_octet[2],
1897                                                 eth.ether_addr_octet[3],
1898                                                 eth.ether_addr_octet[4],
1899                                                 eth.ether_addr_octet[5]);
1900
1901         return str;
1902 }
1903
1904 #if defined TIZEN_EXT
1905 char *index2addr(int index)
1906 #else
1907 static char *index2addr(int index)
1908 #endif
1909 {
1910         struct ifreq ifr;
1911         struct ether_addr eth;
1912         char *str;
1913         int sk, err;
1914
1915         if (index < 0)
1916                 return NULL;
1917
1918         sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1919         if (sk < 0)
1920                 return NULL;
1921
1922         memset(&ifr, 0, sizeof(ifr));
1923         ifr.ifr_ifindex = index;
1924
1925         err = ioctl(sk, SIOCGIFNAME, &ifr);
1926
1927         if (err == 0)
1928                 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1929
1930         close(sk);
1931
1932         if (err < 0)
1933                 return NULL;
1934
1935         str = g_malloc(18);
1936         if (!str)
1937                 return NULL;
1938
1939         memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1940         snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
1941                                                 eth.ether_addr_octet[0],
1942                                                 eth.ether_addr_octet[1],
1943                                                 eth.ether_addr_octet[2],
1944                                                 eth.ether_addr_octet[3],
1945                                                 eth.ether_addr_octet[4],
1946                                                 eth.ether_addr_octet[5]);
1947
1948         return str;
1949 }
1950
1951 struct connman_device *connman_device_create_from_index(int index)
1952 {
1953         enum connman_device_type type;
1954         struct connman_device *device;
1955         char *devname, *ident = NULL;
1956         char *addr = NULL, *name = NULL;
1957
1958         if (index < 0)
1959                 return NULL;
1960
1961         devname = connman_inet_ifname(index);
1962         if (!devname)
1963                 return NULL;
1964
1965         if (__connman_device_isfiltered(devname)) {
1966                 connman_info("Ignoring interface %s (filtered)", devname);
1967                 g_free(devname);
1968                 return NULL;
1969         }
1970
1971         type = __connman_rtnl_get_device_type(index);
1972
1973         switch (type) {
1974         case CONNMAN_DEVICE_TYPE_UNKNOWN:
1975                 connman_info("Ignoring interface %s (type unknown)", devname);
1976                 g_free(devname);
1977                 return NULL;
1978         case CONNMAN_DEVICE_TYPE_ETHERNET:
1979         case CONNMAN_DEVICE_TYPE_GADGET:
1980         case CONNMAN_DEVICE_TYPE_WIFI:
1981 #if defined TIZEN_EXT
1982                 if (type == CONNMAN_DEVICE_TYPE_WIFI)
1983                         name = _get_wifi_ident();
1984                 if (!name)
1985 #endif
1986                 name = index2ident(index, "");
1987 #if defined TIZEN_EXT
1988                 if (type == CONNMAN_DEVICE_TYPE_WIFI)
1989                         addr = _get_wifi_addr();
1990                 if (!addr)
1991 #endif
1992                 addr = index2addr(index);
1993                 break;
1994         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1995         case CONNMAN_DEVICE_TYPE_CELLULAR:
1996         case CONNMAN_DEVICE_TYPE_GPS:
1997         case CONNMAN_DEVICE_TYPE_VENDOR:
1998                 name = g_strdup(devname);
1999                 break;
2000         }
2001
2002         device = connman_device_create(name, type);
2003         if (!device)
2004                 goto done;
2005
2006         switch (type) {
2007         case CONNMAN_DEVICE_TYPE_UNKNOWN:
2008         case CONNMAN_DEVICE_TYPE_VENDOR:
2009         case CONNMAN_DEVICE_TYPE_GPS:
2010                 break;
2011         case CONNMAN_DEVICE_TYPE_ETHERNET:
2012         case CONNMAN_DEVICE_TYPE_GADGET:
2013                 ident = index2ident(index, NULL);
2014                 break;
2015         case CONNMAN_DEVICE_TYPE_WIFI:
2016 #if defined TIZEN_EXT
2017                 ident = _get_wifi_ident();
2018                 if (!ident)
2019 #endif
2020                 ident = index2ident(index, NULL);
2021                 break;
2022         case CONNMAN_DEVICE_TYPE_BLUETOOTH:
2023                 break;
2024         case CONNMAN_DEVICE_TYPE_CELLULAR:
2025                 ident = index2ident(index, NULL);
2026                 break;
2027         }
2028
2029         connman_device_set_index(device, index);
2030         connman_device_set_interface(device, devname);
2031 #if defined TIZEN_EXT
2032         connman_device_load_last_connected(device);
2033         connman_device_load_last_user_selection(device);
2034 #endif
2035
2036         if (ident) {
2037                 connman_device_set_ident(device, ident);
2038                 g_free(ident);
2039         }
2040
2041         connman_device_set_string(device, "Address", addr);
2042
2043 done:
2044         g_free(devname);
2045         g_free(name);
2046         g_free(addr);
2047
2048         return device;
2049 }
2050
2051 bool __connman_device_isfiltered(const char *devname)
2052 {
2053         char **pattern;
2054         char **blacklisted_interfaces;
2055         bool match;
2056
2057         if (!device_filter)
2058                 goto nodevice;
2059
2060         for (pattern = device_filter, match = false; *pattern; pattern++) {
2061                 if (g_pattern_match_simple(*pattern, devname)) {
2062                         match = true;
2063                         break;
2064                 }
2065         }
2066
2067         if (!match) {
2068                 DBG("ignoring device %s (match)", devname);
2069                 return true;
2070         }
2071
2072 nodevice:
2073         if (g_pattern_match_simple("dummy*", devname)) {
2074                 DBG("ignoring dummy networking devices");
2075                 return true;
2076         }
2077
2078         if (!nodevice_filter)
2079                 goto list;
2080
2081         for (pattern = nodevice_filter; *pattern; pattern++) {
2082                 if (g_pattern_match_simple(*pattern, devname)) {
2083                         DBG("ignoring device %s (no match)", devname);
2084                         return true;
2085                 }
2086         }
2087
2088 list:
2089         if (__connman_inet_isrootnfs_device(devname)) {
2090                 DBG("ignoring device %s (rootnfs)", devname);
2091                 return true;
2092         }
2093
2094         blacklisted_interfaces =
2095                 connman_setting_get_string_list("NetworkInterfaceBlacklist");
2096         if (!blacklisted_interfaces)
2097                 return false;
2098
2099         for (pattern = blacklisted_interfaces; *pattern; pattern++) {
2100                 if (g_str_has_prefix(devname, *pattern)) {
2101                         DBG("ignoring device %s (blacklist)", devname);
2102                         return true;
2103                 }
2104         }
2105
2106         return false;
2107 }
2108
2109 static void cleanup_devices(void)
2110 {
2111         /*
2112          * Check what interfaces are currently up and if connman is
2113          * suppose to handle the interface, then cleanup the mess
2114          * related to that interface. There might be weird routes etc
2115          * that are related to that interface and that might confuse
2116          * connmand. So in this case we just turn the interface down
2117          * so that kernel removes routes/addresses automatically and
2118          * then proceed the startup.
2119          *
2120          * Note that this cleanup must be done before rtnl/detect code
2121          * has activated interface watches.
2122          */
2123
2124         char **interfaces;
2125         int i;
2126
2127         interfaces = __connman_inet_get_running_interfaces();
2128
2129         if (!interfaces)
2130                 return;
2131
2132         for (i = 0; interfaces[i]; i++) {
2133                 bool filtered;
2134                 int index;
2135                 struct sockaddr_in sin_addr, sin_mask;
2136
2137                 filtered = __connman_device_isfiltered(interfaces[i]);
2138                 if (filtered)
2139                         continue;
2140
2141                 index = connman_inet_ifindex(interfaces[i]);
2142                 if (index < 0)
2143                         continue;
2144
2145                 if (!__connman_inet_get_address_netmask(index, &sin_addr,
2146                                                         &sin_mask)) {
2147                         char *address = g_strdup(inet_ntoa(sin_addr.sin_addr));
2148                         char *netmask = g_strdup(inet_ntoa(sin_mask.sin_addr));
2149
2150                         if (__connman_config_address_provisioned(address,
2151                                                                 netmask)) {
2152                                 DBG("Skip %s which is already provisioned "
2153                                         "with %s/%s", interfaces[i], address,
2154                                         netmask);
2155                                 g_free(address);
2156                                 g_free(netmask);
2157                                 continue;
2158                         }
2159
2160                         g_free(address);
2161                         g_free(netmask);
2162                 }
2163
2164                 DBG("cleaning up %s index %d", interfaces[i], index);
2165
2166 #if defined TIZEN_EXT
2167                 if (strcmp(interfaces[i], "wlan0") != 0)
2168 #endif
2169                 connman_inet_ifdown(index);
2170
2171                 /*
2172                  * ConnMan will turn the interface UP automatically so
2173                  * no need to do it here.
2174                  */
2175         }
2176
2177         g_strfreev(interfaces);
2178 }
2179
2180 int __connman_device_init(const char *device, const char *nodevice)
2181 {
2182         DBG("");
2183
2184 #if defined TIZEN_EXT
2185         connection = connman_dbus_get_connection();
2186 #endif
2187
2188         if (device)
2189                 device_filter = g_strsplit(device, ",", -1);
2190
2191         if (nodevice)
2192                 nodevice_filter = g_strsplit(nodevice, ",", -1);
2193
2194         cleanup_devices();
2195
2196         return 0;
2197 }
2198
2199 void __connman_device_cleanup(void)
2200 {
2201         DBG("");
2202
2203         g_strfreev(nodevice_filter);
2204         g_strfreev(device_filter);
2205
2206 #if defined TIZEN_EXT
2207         dbus_connection_unref(connection);
2208 #endif
2209 }
2210
2211 #ifdef TIZEN_EXT
2212 void connman_device_mac_policy_notify(struct connman_device *device,
2213                                         int result, unsigned int policy)
2214 {
2215         device->mac_policy = policy;
2216         __connman_technology_notify_mac_policy_by_device(device, result, policy);
2217 }
2218
2219 int connman_device_set_mac_policy(struct connman_device *device,
2220                                         unsigned int policy)
2221 {
2222         int err = 0;
2223
2224         if (!device || !device->driver || !device->driver->set_mac_policy)
2225                 return -EOPNOTSUPP;
2226
2227         device->mac_policy = policy;
2228         err = device->driver->set_mac_policy(device, policy);
2229         return err;
2230 }
2231
2232 unsigned int connman_device_get_mac_policy(struct connman_device *device)
2233 {
2234         return device->mac_policy;
2235 }
2236
2237 void connman_device_preassoc_mac_policy_notify(struct connman_device *device,
2238                                         int result, unsigned int policy)
2239 {
2240         device->preassoc_mac_policy = policy;
2241         __connman_technology_notify_preassoc_mac_policy_by_device(device, result, policy);
2242 }
2243
2244 int connman_device_set_preassoc_mac_policy(struct connman_device *device,
2245                                         unsigned int policy)
2246 {
2247         int err = 0;
2248
2249         if (!device || !device->driver || !device->driver->set_preassoc_mac_policy)
2250                 return -EOPNOTSUPP;
2251
2252         device->preassoc_mac_policy = policy;
2253         err = device->driver->set_preassoc_mac_policy(device, policy);
2254         return err;
2255 }
2256
2257 unsigned int connman_device_get_preassoc_mac_policy(struct connman_device *device)
2258 {
2259         return device->preassoc_mac_policy;
2260 }
2261
2262 void connman_device_random_mac_lifetime_notify(struct connman_device *device,
2263                                         int result, unsigned int lifetime)
2264 {
2265         device->random_mac_lifetime = lifetime;
2266         __connman_technology_notify_random_mac_lifetime_by_device(device, result, lifetime);
2267 }
2268
2269 int connman_device_set_random_mac_lifetime(struct connman_device *device,
2270                                         unsigned int lifetime)
2271 {
2272         int err = 0;
2273
2274         if (!device || !device->driver || !device->driver->set_random_mac_lifetime)
2275                 return -EOPNOTSUPP;
2276
2277         device->random_mac_lifetime = lifetime;
2278         err = device->driver->set_random_mac_lifetime(device, lifetime);
2279         return err;
2280 }
2281
2282 unsigned int connman_device_get_random_mac_lifetime(struct connman_device *device)
2283 {
2284         return device->random_mac_lifetime;
2285 }
2286
2287 #endif