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