5 * Copyright (C) 2007-2014 Intel Corporation. All rights reserved.
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.
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.
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
31 #include <sys/ioctl.h>
32 #include <net/ethernet.h>
37 static GSList *device_list = NULL;
38 static gchar **device_filter = NULL;
39 static gchar **nodevice_filter = NULL;
41 enum connman_pending_type {
47 struct connman_device {
49 enum connman_device_type type;
50 enum connman_pending_type powered_pending; /* Indicates a pending
55 bool scanning[MAX_CONNMAN_SERVICE_TYPES];
63 guint pending_timeout;
65 struct connman_device_driver *driver;
69 struct connman_network *network;
73 static void clear_pending_trigger(struct connman_device *device)
75 if (device->pending_timeout > 0) {
76 g_source_remove(device->pending_timeout);
77 device->pending_timeout = 0;
81 static const char *type2description(enum connman_device_type type)
84 case CONNMAN_DEVICE_TYPE_UNKNOWN:
85 case CONNMAN_DEVICE_TYPE_VENDOR:
87 case CONNMAN_DEVICE_TYPE_ETHERNET:
89 case CONNMAN_DEVICE_TYPE_WIFI:
91 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
93 case CONNMAN_DEVICE_TYPE_GPS:
95 case CONNMAN_DEVICE_TYPE_CELLULAR:
97 case CONNMAN_DEVICE_TYPE_GADGET:
105 static const char *type2string(enum connman_device_type type)
108 case CONNMAN_DEVICE_TYPE_UNKNOWN:
109 case CONNMAN_DEVICE_TYPE_VENDOR:
111 case CONNMAN_DEVICE_TYPE_ETHERNET:
113 case CONNMAN_DEVICE_TYPE_WIFI:
115 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
117 case CONNMAN_DEVICE_TYPE_GPS:
119 case CONNMAN_DEVICE_TYPE_CELLULAR:
121 case CONNMAN_DEVICE_TYPE_GADGET:
129 enum connman_service_type __connman_device_get_service_type(
130 struct connman_device *device)
132 enum connman_device_type type = connman_device_get_type(device);
135 case CONNMAN_DEVICE_TYPE_UNKNOWN:
136 case CONNMAN_DEVICE_TYPE_VENDOR:
137 case CONNMAN_DEVICE_TYPE_GPS:
139 case CONNMAN_DEVICE_TYPE_ETHERNET:
140 return CONNMAN_SERVICE_TYPE_ETHERNET;
141 case CONNMAN_DEVICE_TYPE_WIFI:
142 return CONNMAN_SERVICE_TYPE_WIFI;
143 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
144 return CONNMAN_SERVICE_TYPE_BLUETOOTH;
145 case CONNMAN_DEVICE_TYPE_CELLULAR:
146 return CONNMAN_SERVICE_TYPE_CELLULAR;
147 case CONNMAN_DEVICE_TYPE_GADGET:
148 return CONNMAN_SERVICE_TYPE_GADGET;
152 return CONNMAN_SERVICE_TYPE_UNKNOWN;
155 static bool device_has_service_type(struct connman_device *device,
156 enum connman_service_type service_type)
158 enum connman_service_type device_service_type =
159 __connman_device_get_service_type(device);
162 * For devices whose device_service_type is unknown we should
163 * allow to decide whether they support specific service_type
166 if (device_service_type == CONNMAN_SERVICE_TYPE_UNKNOWN)
169 #if defined TIZEN_EXT_WIFI_MESH
170 if (device_service_type == CONNMAN_SERVICE_TYPE_MESH)
171 return service_type != CONNMAN_SERVICE_TYPE_MESH;
174 if (device_service_type == CONNMAN_SERVICE_TYPE_WIFI) {
175 return service_type == CONNMAN_SERVICE_TYPE_WIFI ||
176 service_type == CONNMAN_SERVICE_TYPE_P2P;
179 return service_type == device_service_type;
182 static gboolean device_pending_reset(gpointer user_data)
184 struct connman_device *device = user_data;
186 DBG("device %p", device);
188 /* Power request timedout, reset power pending state. */
189 device->pending_timeout = 0;
190 device->powered_pending = PENDING_NONE;
195 int __connman_device_enable(struct connman_device *device)
199 DBG("device %p", device);
201 if (!device->driver || !device->driver->enable)
204 /* There is an ongoing power disable request. */
205 if (device->powered_pending == PENDING_DISABLE)
208 if (device->powered_pending == PENDING_ENABLE)
211 if (device->powered_pending == PENDING_NONE && device->powered)
214 if (device->index > 0) {
215 err = connman_inet_ifup(device->index);
216 if (err < 0 && err != -EALREADY)
220 device->powered_pending = PENDING_ENABLE;
222 err = device->driver->enable(device);
224 * device gets enabled right away.
225 * Invoke the callback
228 connman_device_set_powered(device, true);
232 if (err == -EALREADY) {
233 /* If device is already powered, but connman is not updated */
234 connman_device_set_powered(device, true);
238 * if err == -EINPROGRESS, then the DBus call to the respective daemon
239 * was successful. We set a 4 sec timeout so if the daemon never
240 * returns a reply, we would reset the pending request.
242 if (err == -EINPROGRESS)
243 device->pending_timeout = g_timeout_add_seconds(4,
244 device_pending_reset, device);
249 int __connman_device_disable(struct connman_device *device)
253 DBG("device %p", device);
255 /* Ongoing power enable request */
256 if (device->powered_pending == PENDING_ENABLE)
259 if (device->powered_pending == PENDING_DISABLE)
262 if (device->powered_pending == PENDING_NONE && !device->powered)
265 device->powered_pending = PENDING_DISABLE;
267 if (device->network) {
268 struct connman_service *service =
269 connman_service_lookup_from_network(device->network);
272 __connman_service_disconnect(service);
274 connman_network_set_connected(device->network, false);
277 if (!device->driver || !device->driver->disable)
280 err = device->driver->disable(device);
281 if (err == 0 || err == -EALREADY) {
282 connman_device_set_powered(device, false);
286 if (err == -EINPROGRESS)
287 device->pending_timeout = g_timeout_add_seconds(4,
288 device_pending_reset, device);
293 static void probe_driver(struct connman_device_driver *driver)
297 DBG("driver %p name %s", driver, driver->name);
299 for (list = device_list; list; list = list->next) {
300 struct connman_device *device = list->data;
305 if (driver->type != device->type)
308 if (driver->probe(device) < 0)
311 device->driver = driver;
313 __connman_technology_add_device(device);
317 static void remove_device(struct connman_device *device)
319 DBG("device %p", device);
321 __connman_device_disable(device);
323 __connman_technology_remove_device(device);
325 if (device->driver->remove)
326 device->driver->remove(device);
328 device->driver = NULL;
331 static void remove_driver(struct connman_device_driver *driver)
335 DBG("driver %p name %s", driver, driver->name);
337 for (list = device_list; list; list = list->next) {
338 struct connman_device *device = list->data;
340 if (device->driver == driver)
341 remove_device(device);
345 bool __connman_device_has_driver(struct connman_device *device)
347 if (!device || !device->driver)
353 static GSList *driver_list = NULL;
355 static gint compare_priority(gconstpointer a, gconstpointer b)
357 const struct connman_device_driver *driver1 = a;
358 const struct connman_device_driver *driver2 = b;
360 return driver2->priority - driver1->priority;
364 * connman_device_driver_register:
365 * @driver: device driver definition
367 * Register a new device driver
369 * Returns: %0 on success
371 int connman_device_driver_register(struct connman_device_driver *driver)
373 DBG("driver %p name %s", driver, driver->name);
375 driver_list = g_slist_insert_sorted(driver_list, driver,
377 probe_driver(driver);
383 * connman_device_driver_unregister:
384 * @driver: device driver definition
386 * Remove a previously registered device driver
388 void connman_device_driver_unregister(struct connman_device_driver *driver)
390 DBG("driver %p name %s", driver, driver->name);
392 driver_list = g_slist_remove(driver_list, driver);
394 remove_driver(driver);
397 static void free_network(gpointer data)
399 struct connman_network *network = data;
401 DBG("network %p", network);
403 __connman_network_set_device(network, NULL);
405 connman_network_unref(network);
408 static void device_destruct(struct connman_device *device)
410 DBG("device %p name %s", device, device->name);
412 clear_pending_trigger(device);
414 g_hash_table_destroy(device->networks);
415 device->networks = NULL;
417 g_free(device->ident);
418 g_free(device->node);
419 g_free(device->name);
420 g_free(device->address);
421 g_free(device->interface);
422 g_free(device->path);
424 g_free(device->last_network);
430 * connman_device_create:
431 * @node: device node name (for example an address)
434 * Allocate a new device of given #type and assign the #node name to it.
436 * Returns: a newly-allocated #connman_device structure
438 struct connman_device *connman_device_create(const char *node,
439 enum connman_device_type type)
441 struct connman_device *device;
443 DBG("node %s type %d", node, type);
445 device = g_try_new0(struct connman_device, 1);
449 DBG("device %p", device);
451 device->refcount = 1;
454 device->name = g_strdup(type2description(device->type));
456 device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
457 g_free, free_network);
459 device_list = g_slist_prepend(device_list, device);
465 * connman_device_ref:
466 * @device: device structure
468 * Increase reference counter of device
470 struct connman_device *connman_device_ref_debug(struct connman_device *device,
471 const char *file, int line, const char *caller)
473 DBG("%p ref %d by %s:%d:%s()", device, device->refcount + 1,
476 __sync_fetch_and_add(&device->refcount, 1);
482 * connman_device_unref:
483 * @device: device structure
485 * Decrease reference counter of device
487 void connman_device_unref_debug(struct connman_device *device,
488 const char *file, int line, const char *caller)
490 DBG("%p ref %d by %s:%d:%s()", device, device->refcount - 1,
493 if (__sync_fetch_and_sub(&device->refcount, 1) != 1)
496 if (device->driver) {
497 device->driver->remove(device);
498 device->driver = NULL;
501 device_list = g_slist_remove(device_list, device);
503 device_destruct(device);
506 const char *__connman_device_get_type(struct connman_device *device)
508 return type2string(device->type);
512 * connman_device_get_type:
513 * @device: device structure
517 enum connman_device_type connman_device_get_type(struct connman_device *device)
523 * connman_device_set_index:
524 * @device: device structure
525 * @index: index number
527 * Set index number of device
529 void connman_device_set_index(struct connman_device *device, int index)
531 device->index = index;
535 * connman_device_get_index:
536 * @device: device structure
538 * Get index number of device
540 int connman_device_get_index(struct connman_device *device)
542 return device->index;
546 * connman_device_set_interface:
547 * @device: device structure
548 * @interface: interface name
550 * Set interface name of device
552 void connman_device_set_interface(struct connman_device *device,
553 const char *interface)
555 g_free(device->interface);
556 device->interface = g_strdup(interface);
559 const char *str = type2description(device->type);
560 if (str && device->interface)
561 device->name = g_strdup_printf("%s (%s)", str,
567 * connman_device_set_ident:
568 * @device: device structure
569 * @ident: unique identifier
571 * Set unique identifier of device
573 void connman_device_set_ident(struct connman_device *device,
576 g_free(device->ident);
577 device->ident = g_strdup(ident);
580 const char *connman_device_get_ident(struct connman_device *device)
582 return device->ident;
586 * connman_device_set_powered:
587 * @device: device structure
588 * @powered: powered state
590 * Change power state of device
592 int connman_device_set_powered(struct connman_device *device,
595 struct connman_device_scan_params params;
596 enum connman_service_type type;
599 DBG("device %p powered %d", device, powered);
601 if (device->powered == powered)
604 clear_pending_trigger(device);
606 device->powered_pending = PENDING_NONE;
608 device->powered = powered;
610 type = __connman_device_get_service_type(device);
612 if (!device->powered) {
613 __connman_technology_disabled(type);
617 __connman_technology_enabled(type);
619 for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++)
620 device->scanning[i] = false;
622 if (device->driver && device->driver->scan) {
623 memset(¶ms, 0, sizeof(params));
624 params.type = CONNMAN_SERVICE_TYPE_UNKNOWN;
626 device->driver->scan(device, ¶ms);
632 bool connman_device_get_powered(struct connman_device *device)
634 return device->powered;
637 static int device_scan(enum connman_service_type type,
638 struct connman_device *device,
639 bool force_full_scan)
641 struct connman_device_scan_params params;
643 if (!device->driver || !device->driver->scan)
646 if (!device->powered)
649 memset(¶ms, 0, sizeof(params));
651 params.force_full_scan = force_full_scan;
653 return device->driver->scan(device, ¶ms);
656 int __connman_device_disconnect(struct connman_device *device)
661 DBG("device %p", device);
663 g_hash_table_iter_init(&iter, device->networks);
665 while (g_hash_table_iter_next(&iter, &key, &value)) {
666 struct connman_network *network = value;
668 if (connman_network_get_connecting(network)) {
670 * Skip network in the process of connecting.
671 * This is a workaround for WiFi networks serviced
672 * by the supplicant plugin that hold a reference
673 * to the network. If we disconnect the network
674 * here then the referenced object will not be
675 * registered and usage (like launching DHCP client)
676 * will fail. There is nothing to be gained by
677 * removing the network here anyway.
679 connman_warn("Skipping disconnect of %s, network is connecting.",
680 connman_network_get_identifier(network));
684 __connman_network_disconnect(network);
690 int connman_device_reconnect_service(struct connman_device *device)
692 DBG("device %p", device);
694 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
699 static void mark_network_available(gpointer key, gpointer value,
702 struct connman_network *network = value;
704 connman_network_set_available(network, true);
707 static void mark_network_unavailable(gpointer key, gpointer value,
710 struct connman_network *network = value;
712 if (connman_network_get_connected(network) ||
713 connman_network_get_connecting(network))
716 connman_network_set_available(network, false);
719 static gboolean remove_unavailable_network(gpointer key, gpointer value,
722 struct connman_network *network = value;
724 if (connman_network_get_connected(network) ||
725 connman_network_get_connecting(network))
728 if (connman_network_get_available(network))
734 void __connman_device_cleanup_networks(struct connman_device *device)
736 g_hash_table_foreach_remove(device->networks,
737 remove_unavailable_network, NULL);
740 bool connman_device_get_scanning(struct connman_device *device,
741 enum connman_service_type type)
745 if (type != CONNMAN_SERVICE_TYPE_UNKNOWN)
746 return device->scanning[type];
748 for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++)
749 if (device->scanning[i])
755 void connman_device_reset_scanning(struct connman_device *device)
757 g_hash_table_foreach(device->networks,
758 mark_network_available, NULL);
762 * connman_device_set_scanning:
763 * @device: device structure
764 * @scanning: scanning state
766 * Change scanning state of device
768 int connman_device_set_scanning(struct connman_device *device,
769 enum connman_service_type type, bool scanning)
771 DBG("device %p scanning %d", device, scanning);
773 if (!device->driver || !device->driver->scan)
776 if (type == CONNMAN_SERVICE_TYPE_UNKNOWN)
779 if (device->scanning[type] == scanning)
782 device->scanning[type] = scanning;
785 __connman_technology_scan_started(device);
787 g_hash_table_foreach(device->networks,
788 mark_network_unavailable, NULL);
793 __connman_device_cleanup_networks(device);
795 __connman_technology_scan_stopped(device, type);
797 __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
799 #if defined TIZEN_EXT_WIFI_MESH
800 if (type == CONNMAN_SERVICE_TYPE_MESH)
801 __connman_mesh_auto_connect();
808 * connman_device_set_string:
809 * @device: device structure
810 * @key: unique identifier
811 * @value: string value
813 * Set string value for specific key
815 int connman_device_set_string(struct connman_device *device,
816 const char *key, const char *value)
818 DBG("device %p key %s value %s", device, key, value);
820 if (g_str_equal(key, "Address")) {
821 g_free(device->address);
822 device->address = g_strdup(value);
823 } else if (g_str_equal(key, "Name")) {
824 g_free(device->name);
825 device->name = g_strdup(value);
826 } else if (g_str_equal(key, "Node")) {
827 g_free(device->node);
828 device->node = g_strdup(value);
829 } else if (g_str_equal(key, "Path")) {
830 g_free(device->path);
831 device->path = g_strdup(value);
840 * connman_device_get_string:
841 * @device: device structure
842 * @key: unique identifier
844 * Get string value for specific key
846 const char *connman_device_get_string(struct connman_device *device,
849 DBG("device %p key %s", device, key);
851 if (g_str_equal(key, "Address"))
852 return device->address;
853 else if (g_str_equal(key, "Name"))
855 else if (g_str_equal(key, "Node"))
857 else if (g_str_equal(key, "Interface"))
858 return device->interface;
859 else if (g_str_equal(key, "Path"))
866 * connman_device_add_network:
867 * @device: device structure
868 * @network: network structure
870 * Add new network to the device
872 int connman_device_add_network(struct connman_device *device,
873 struct connman_network *network)
875 const char *identifier = connman_network_get_identifier(network);
877 DBG("device %p network %p", device, network);
882 connman_network_ref(network);
884 __connman_network_set_device(network, device);
886 g_hash_table_replace(device->networks, g_strdup(identifier),
893 * connman_device_get_network:
894 * @device: device structure
895 * @identifier: network identifier
897 * Get network for given identifier
899 struct connman_network *connman_device_get_network(struct connman_device *device,
900 const char *identifier)
902 DBG("device %p identifier %s", device, identifier);
904 return g_hash_table_lookup(device->networks, identifier);
908 * connman_device_remove_network:
909 * @device: device structure
910 * @identifier: network identifier
912 * Remove network for given identifier
914 int connman_device_remove_network(struct connman_device *device,
915 struct connman_network *network)
917 const char *identifier;
919 DBG("device %p network %p", device, network);
924 identifier = connman_network_get_identifier(network);
925 g_hash_table_remove(device->networks, identifier);
930 void __connman_device_set_network(struct connman_device *device,
931 struct connman_network *network)
938 if (device->network == network)
942 name = connman_network_get_string(network, "Name");
943 g_free(device->last_network);
944 device->last_network = g_strdup(name);
946 device->network = network;
948 g_free(device->last_network);
949 device->last_network = NULL;
951 device->network = NULL;
955 static bool match_driver(struct connman_device *device,
956 struct connman_device_driver *driver)
958 if (device->type == driver->type ||
959 driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN)
966 * connman_device_register:
967 * @device: device structure
969 * Register device with the system
971 int connman_device_register(struct connman_device *device)
975 DBG("device %p name %s", device, device->name);
980 for (list = driver_list; list; list = list->next) {
981 struct connman_device_driver *driver = list->data;
983 if (!match_driver(device, driver))
986 DBG("driver %p name %s", driver, driver->name);
988 if (driver->probe(device) == 0) {
989 device->driver = driver;
997 return __connman_technology_add_device(device);
1001 * connman_device_unregister:
1002 * @device: device structure
1004 * Unregister device with the system
1006 void connman_device_unregister(struct connman_device *device)
1008 DBG("device %p name %s", device, device->name);
1010 if (!device->driver)
1013 remove_device(device);
1017 * connman_device_get_data:
1018 * @device: device structure
1020 * Get private device data pointer
1022 void *connman_device_get_data(struct connman_device *device)
1024 return device->driver_data;
1028 * connman_device_set_data:
1029 * @device: device structure
1030 * @data: data pointer
1032 * Set private device data pointer
1034 void connman_device_set_data(struct connman_device *device, void *data)
1036 device->driver_data = data;
1039 struct connman_device *__connman_device_find_device(
1040 enum connman_service_type type)
1044 for (list = device_list; list; list = list->next) {
1045 struct connman_device *device = list->data;
1046 enum connman_service_type service_type =
1047 __connman_device_get_service_type(device);
1049 if (service_type != type)
1058 struct connman_device *connman_device_find_by_index(int index)
1062 for (list = device_list; list; list = list->next) {
1063 struct connman_device *device = list->data;
1064 if (device->index == index)
1072 * connman_device_set_regdom
1073 * @device: device structure
1074 * @alpha2: string representing regulatory domain
1076 * Set regulatory domain on device basis
1078 int connman_device_set_regdom(struct connman_device *device,
1081 if (!device->driver || !device->driver->set_regdom)
1084 if (!device->powered)
1087 return device->driver->set_regdom(device, alpha2);
1091 * connman_device_regdom_notify
1092 * @device: device structure
1093 * @alpha2: string representing regulatory domain
1095 * Notify on setting regulatory domain on device basis
1097 void connman_device_regdom_notify(struct connman_device *device,
1098 int result, const char *alpha2)
1100 __connman_technology_notify_regdom_by_device(device, result, alpha2);
1103 #if defined TIZEN_EXT
1104 static int device_specific_scan(enum connman_service_type type,
1105 struct connman_device *device,
1106 int scan_type, GSList *specific_scan_list)
1108 if (!device->driver || !device->driver->specific_scan)
1111 if (!device->powered)
1114 return device->driver->specific_scan(type, device, scan_type,
1115 specific_scan_list, NULL);
1118 int __connman_device_request_specific_scan(enum connman_service_type type,
1119 int scan_type, GSList *specific_scan_list)
1121 bool success = false;
1122 int last_err = -ENOSYS;
1127 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1128 case CONNMAN_SERVICE_TYPE_SYSTEM:
1129 case CONNMAN_SERVICE_TYPE_ETHERNET:
1130 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1131 case CONNMAN_SERVICE_TYPE_CELLULAR:
1132 case CONNMAN_SERVICE_TYPE_GPS:
1133 case CONNMAN_SERVICE_TYPE_VPN:
1134 case CONNMAN_SERVICE_TYPE_GADGET:
1136 case CONNMAN_SERVICE_TYPE_WIFI:
1137 case CONNMAN_SERVICE_TYPE_P2P:
1138 #if defined TIZEN_EXT_WIFI_MESH
1139 case CONNMAN_SERVICE_TYPE_MESH:
1144 for (list = device_list; list; list = list->next) {
1145 struct connman_device *device = list->data;
1146 enum connman_service_type service_type =
1147 __connman_device_get_service_type(device);
1149 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1150 if (type == CONNMAN_SERVICE_TYPE_P2P) {
1151 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1153 } else if (service_type != type)
1157 err = device_specific_scan(type, device, scan_type, specific_scan_list);
1158 if (err == 0 || err == -EINPROGRESS) {
1162 DBG("device %p err %d", device, err);
1172 #if defined TIZEN_EXT_WIFI_MESH
1173 static int device_abort_scan(enum connman_service_type type,
1174 struct connman_device *device)
1176 if (!device->driver || !device->driver->scan)
1179 if (!device->powered)
1182 return device->driver->abort_scan(type, device);
1185 int __connman_device_abort_scan(enum connman_service_type type)
1190 if (type != CONNMAN_SERVICE_TYPE_MESH)
1193 for (list = device_list; list; list = list->next) {
1194 struct connman_device *device = list->data;
1195 enum connman_service_type service_type =
1196 __connman_device_get_service_type(device);
1198 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1199 if (type == CONNMAN_SERVICE_TYPE_MESH)
1200 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1203 if (!device->scanning) {
1208 err = device_abort_scan(type, device);
1214 static int device_mesh_specific_scan(enum connman_service_type type,
1215 struct connman_device *device, const char *name,
1218 if (!device->driver || !device->driver->mesh_specific_scan)
1221 if (!device->powered)
1224 return device->driver->mesh_specific_scan(type, device, name, freq, NULL);
1227 int __connman_device_request_mesh_specific_scan(enum connman_service_type type,
1231 bool success = false;
1232 int last_err = -ENOSYS;
1236 if (type != CONNMAN_SERVICE_TYPE_MESH)
1239 for (list = device_list; list; list = list->next) {
1240 struct connman_device *device = list->data;
1241 enum connman_service_type service_type =
1242 __connman_device_get_service_type(device);
1244 if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
1245 if (type == CONNMAN_SERVICE_TYPE_MESH)
1246 if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
1250 err = device_mesh_specific_scan(type, device, name, freq);
1251 if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
1255 DBG("device %p err %d", device, err);
1264 #endif /* TIZEN_EXT_WIFI_MESH */
1267 static int connman_device_request_scan(enum connman_service_type type,
1268 bool force_full_scan)
1270 bool success = false;
1271 int last_err = -ENOSYS;
1276 case CONNMAN_SERVICE_TYPE_UNKNOWN:
1277 case CONNMAN_SERVICE_TYPE_SYSTEM:
1278 case CONNMAN_SERVICE_TYPE_ETHERNET:
1279 case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1280 case CONNMAN_SERVICE_TYPE_CELLULAR:
1281 case CONNMAN_SERVICE_TYPE_GPS:
1282 case CONNMAN_SERVICE_TYPE_VPN:
1283 case CONNMAN_SERVICE_TYPE_GADGET:
1285 case CONNMAN_SERVICE_TYPE_WIFI:
1286 case CONNMAN_SERVICE_TYPE_P2P:
1287 #if defined TIZEN_EXT_WIFI_MESH
1288 case CONNMAN_SERVICE_TYPE_MESH:
1293 for (list = device_list; list; list = list->next) {
1294 struct connman_device *device = list->data;
1296 if (!device_has_service_type(device, type))
1299 err = device_scan(type, device, force_full_scan);
1300 #if defined TIZEN_EXT
1301 /* When Scan is already in progress then return Error so that
1302 * wifi-manager can block the scan-done signal to be sent to
1303 * application and start requested scan after scan already in progress
1304 * is completed then notify to application about the scan event */
1305 if (err == 0 || err == -EINPROGRESS) {
1307 if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
1312 DBG("device %p err %d", device, err);
1322 int __connman_device_request_scan(enum connman_service_type type)
1324 return connman_device_request_scan(type, false);
1327 int __connman_device_request_scan_full(enum connman_service_type type)
1329 return connman_device_request_scan(type, true);
1332 int __connman_device_request_hidden_scan(struct connman_device *device,
1333 const char *ssid, unsigned int ssid_len,
1334 const char *identity, const char *passphrase,
1335 const char *security, void *user_data)
1337 struct connman_device_scan_params params;
1339 DBG("device %p", device);
1341 if (!device || !device->driver ||
1342 !device->driver->scan)
1345 params.type = CONNMAN_SERVICE_TYPE_UNKNOWN;
1347 params.ssid_len = ssid_len;
1348 params.identity = identity;
1349 params.passphrase = passphrase;
1350 params.security = security;
1351 params.user_data = user_data;
1353 return device->driver->scan(device, ¶ms);
1356 void __connman_device_stop_scan(enum connman_service_type type)
1360 for (list = device_list; list; list = list->next) {
1361 struct connman_device *device = list->data;
1363 if (!device_has_service_type(device, type))
1366 if (device->driver && device->driver->stop_scan)
1367 device->driver->stop_scan(type, device);
1371 #if defined TIZEN_EXT
1372 char *index2ident(int index, const char *prefix)
1374 static char *index2ident(int index, const char *prefix)
1378 struct ether_addr eth;
1385 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1389 memset(&ifr, 0, sizeof(ifr));
1390 ifr.ifr_ifindex = index;
1392 err = ioctl(sk, SIOCGIFNAME, &ifr);
1395 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1402 len = prefix ? strlen(prefix) + 18 : 18;
1404 str = g_malloc(len);
1408 memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1409 snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
1410 prefix ? prefix : "",
1411 eth.ether_addr_octet[0],
1412 eth.ether_addr_octet[1],
1413 eth.ether_addr_octet[2],
1414 eth.ether_addr_octet[3],
1415 eth.ether_addr_octet[4],
1416 eth.ether_addr_octet[5]);
1421 #if defined TIZEN_EXT
1422 char *index2addr(int index)
1424 static char *index2addr(int index)
1428 struct ether_addr eth;
1435 sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1439 memset(&ifr, 0, sizeof(ifr));
1440 ifr.ifr_ifindex = index;
1442 err = ioctl(sk, SIOCGIFNAME, &ifr);
1445 err = ioctl(sk, SIOCGIFHWADDR, &ifr);
1456 memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
1457 snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
1458 eth.ether_addr_octet[0],
1459 eth.ether_addr_octet[1],
1460 eth.ether_addr_octet[2],
1461 eth.ether_addr_octet[3],
1462 eth.ether_addr_octet[4],
1463 eth.ether_addr_octet[5]);
1468 struct connman_device *connman_device_create_from_index(int index)
1470 enum connman_device_type type;
1471 struct connman_device *device;
1472 char *devname, *ident = NULL;
1473 char *addr = NULL, *name = NULL;
1478 devname = connman_inet_ifname(index);
1482 if (__connman_device_isfiltered(devname)) {
1483 connman_info("Ignoring interface %s (filtered)", devname);
1488 type = __connman_rtnl_get_device_type(index);
1491 case CONNMAN_DEVICE_TYPE_UNKNOWN:
1492 connman_info("Ignoring interface %s (type unknown)", devname);
1495 case CONNMAN_DEVICE_TYPE_ETHERNET:
1496 case CONNMAN_DEVICE_TYPE_GADGET:
1497 case CONNMAN_DEVICE_TYPE_WIFI:
1498 name = index2ident(index, "");
1499 addr = index2addr(index);
1501 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1502 case CONNMAN_DEVICE_TYPE_CELLULAR:
1503 case CONNMAN_DEVICE_TYPE_GPS:
1504 case CONNMAN_DEVICE_TYPE_VENDOR:
1505 name = g_strdup(devname);
1509 device = connman_device_create(name, type);
1514 case CONNMAN_DEVICE_TYPE_UNKNOWN:
1515 case CONNMAN_DEVICE_TYPE_VENDOR:
1516 case CONNMAN_DEVICE_TYPE_GPS:
1518 case CONNMAN_DEVICE_TYPE_ETHERNET:
1519 case CONNMAN_DEVICE_TYPE_GADGET:
1520 ident = index2ident(index, NULL);
1522 case CONNMAN_DEVICE_TYPE_WIFI:
1523 ident = index2ident(index, NULL);
1525 case CONNMAN_DEVICE_TYPE_BLUETOOTH:
1527 case CONNMAN_DEVICE_TYPE_CELLULAR:
1528 ident = index2ident(index, NULL);
1532 connman_device_set_index(device, index);
1533 connman_device_set_interface(device, devname);
1536 connman_device_set_ident(device, ident);
1540 connman_device_set_string(device, "Address", addr);
1550 bool __connman_device_isfiltered(const char *devname)
1553 char **blacklisted_interfaces;
1559 for (pattern = device_filter, match = false; *pattern; pattern++) {
1560 if (g_pattern_match_simple(*pattern, devname)) {
1567 DBG("ignoring device %s (match)", devname);
1572 if (g_pattern_match_simple("dummy*", devname)) {
1573 DBG("ignoring dummy networking devices");
1577 if (!nodevice_filter)
1580 for (pattern = nodevice_filter; *pattern; pattern++) {
1581 if (g_pattern_match_simple(*pattern, devname)) {
1582 DBG("ignoring device %s (no match)", devname);
1588 if (__connman_inet_isrootnfs_device(devname)) {
1589 DBG("ignoring device %s (rootnfs)", devname);
1593 blacklisted_interfaces =
1594 connman_setting_get_string_list("NetworkInterfaceBlacklist");
1595 if (!blacklisted_interfaces)
1598 for (pattern = blacklisted_interfaces; *pattern; pattern++) {
1599 if (g_str_has_prefix(devname, *pattern)) {
1600 DBG("ignoring device %s (blacklist)", devname);
1608 static void cleanup_devices(void)
1611 * Check what interfaces are currently up and if connman is
1612 * suppose to handle the interface, then cleanup the mess
1613 * related to that interface. There might be weird routes etc
1614 * that are related to that interface and that might confuse
1615 * connmand. So in this case we just turn the interface down
1616 * so that kernel removes routes/addresses automatically and
1617 * then proceed the startup.
1619 * Note that this cleanup must be done before rtnl/detect code
1620 * has activated interface watches.
1626 interfaces = __connman_inet_get_running_interfaces();
1631 for (i = 0; interfaces[i]; i++) {
1634 struct sockaddr_in sin_addr, sin_mask;
1636 filtered = __connman_device_isfiltered(interfaces[i]);
1640 index = connman_inet_ifindex(interfaces[i]);
1644 if (!__connman_inet_get_address_netmask(index, &sin_addr,
1646 char *address = g_strdup(inet_ntoa(sin_addr.sin_addr));
1647 char *netmask = g_strdup(inet_ntoa(sin_mask.sin_addr));
1649 if (__connman_config_address_provisioned(address,
1651 DBG("Skip %s which is already provisioned "
1652 "with %s/%s", interfaces[i], address,
1663 DBG("cleaning up %s index %d", interfaces[i], index);
1665 #if defined TIZEN_EXT
1666 if (strcmp(interfaces[i], "wlan0") != 0)
1668 connman_inet_ifdown(index);
1671 * ConnMan will turn the interface UP automatically so
1672 * no need to do it here.
1676 g_strfreev(interfaces);
1679 int __connman_device_init(const char *device, const char *nodevice)
1684 device_filter = g_strsplit(device, ",", -1);
1687 nodevice_filter = g_strsplit(nodevice, ",", -1);
1694 void __connman_device_cleanup(void)
1698 g_strfreev(nodevice_filter);
1699 g_strfreev(device_filter);