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