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