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