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