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