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