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