#include <errno.h>
#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <net/ethernet.h>
+#include <net/if.h>
#include "connman.h"
char *ident;
char *path;
char *devname;
- int phyindex;
int index;
guint pending_timeout;
return "Ethernet";
case CONNMAN_DEVICE_TYPE_WIFI:
return "Wireless";
- case CONNMAN_DEVICE_TYPE_WIMAX:
- return "WiMAX";
case CONNMAN_DEVICE_TYPE_BLUETOOTH:
return "Bluetooth";
case CONNMAN_DEVICE_TYPE_GPS:
return "ethernet";
case CONNMAN_DEVICE_TYPE_WIFI:
return "wifi";
- case CONNMAN_DEVICE_TYPE_WIMAX:
- return "wimax";
case CONNMAN_DEVICE_TYPE_BLUETOOTH:
return "bluetooth";
case CONNMAN_DEVICE_TYPE_GPS:
return CONNMAN_SERVICE_TYPE_ETHERNET;
case CONNMAN_DEVICE_TYPE_WIFI:
return CONNMAN_SERVICE_TYPE_WIFI;
- case CONNMAN_DEVICE_TYPE_WIMAX:
- return CONNMAN_SERVICE_TYPE_WIMAX;
case CONNMAN_DEVICE_TYPE_BLUETOOTH:
return CONNMAN_SERVICE_TYPE_BLUETOOTH;
case CONNMAN_DEVICE_TYPE_CELLULAR:
if (device->network) {
struct connman_service *service =
- __connman_service_lookup_from_network(device->network);
+ connman_service_lookup_from_network(device->network);
if (service != NULL)
__connman_service_disconnect(service);
device->type = type;
device->name = g_strdup(type2description(device->type));
- device->phyindex = -1;
-
device->networks = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, free_network);
- device_list = g_slist_append(device_list, device);
+ device_list = g_slist_prepend(device_list, device);
return device;
}
return device->index;
}
-int __connman_device_get_phyindex(struct connman_device *device)
-{
- return device->phyindex;
-}
-
-void __connman_device_set_phyindex(struct connman_device *device,
- int phyindex)
-{
- device->phyindex = phyindex;
-}
-
/**
* connman_device_set_interface:
* @device: device structure
connman_device_set_disconnected(device, FALSE);
device->scanning = FALSE;
- if (device->driver && device->driver->scan_fast)
- device->driver->scan_fast(device);
- else if (device->driver && device->driver->scan)
- device->driver->scan(device);
+ if (device->driver && device->driver->scan)
+ device->driver->scan(device, NULL, 0, NULL, NULL, NULL);
return 0;
}
+connman_bool_t connman_device_get_powered(struct connman_device *device)
+{
+ return device->powered;
+}
+
static int device_scan(struct connman_device *device)
{
if (!device->driver || !device->driver->scan)
if (device->powered == FALSE)
return -ENOLINK;
- return device->driver->scan(device);
+ return device->driver->scan(device, NULL, 0, NULL, NULL, NULL);
}
int __connman_device_disconnect(struct connman_device *device)
return 0;
}
+int connman_device_disconnect_service(struct connman_device *device)
+{
+ DBG("device %p", device);
+
+ device->reconnect = FALSE;
+
+ if (device->network) {
+ struct connman_service *service =
+ connman_service_lookup_from_network(device->network);
+
+ if (service != NULL)
+ __connman_service_disconnect(service);
+ else
+ connman_network_set_connected(device->network, FALSE);
+ }
+
+ return 0;
+}
+
+int connman_device_reconnect_service(struct connman_device *device)
+{
+ DBG("device %p", device);
+
+ device->reconnect = TRUE;
+
+ __connman_service_auto_connect();
+
+ return 0;
+}
+
static void mark_network_available(gpointer key, gpointer value,
gpointer user_data)
{
{
struct connman_network *network = value;
- if (connman_network_get_connected(network) == TRUE)
+ if (connman_network_get_connected(network) == TRUE ||
+ connman_network_get_connecting(network) == TRUE)
return;
connman_network_set_available(network, FALSE);
return NULL;
}
+struct connman_device *connman_device_find_by_index(int index)
+{
+ GSList *list;
+
+ for (list = device_list; list != NULL; list = list->next) {
+ struct connman_device *device = list->data;
+ if (device->index == index)
+ return device;
+ }
+
+ return NULL;
+}
+
+/**
+ * connman_device_set_regdom
+ * @device: device structure
+ * @alpha2: string representing regulatory domain
+ *
+ * Set regulatory domain on device basis
+ */
+int connman_device_set_regdom(struct connman_device *device,
+ const char *alpha2)
+{
+ if (device->driver == NULL || device->driver->set_regdom == NULL)
+ return -ENOTSUP;
+
+ if (device->powered == FALSE)
+ return -EINVAL;
+
+ return device->driver->set_regdom(device, alpha2);
+}
+
+/**
+ * connman_device_regdom_notify
+ * @device: device structure
+ * @alpha2: string representing regulatory domain
+ *
+ * Notify on setting regulatory domain on device basis
+ */
+void connman_device_regdom_notify(struct connman_device *device,
+ int result, const char *alpha2)
+{
+ __connman_technology_notify_regdom_by_device(device, result, alpha2);
+}
+
int __connman_device_request_scan(enum connman_service_type type)
{
connman_bool_t success = FALSE;
case CONNMAN_SERVICE_TYPE_GADGET:
return -EOPNOTSUPP;
case CONNMAN_SERVICE_TYPE_WIFI:
- case CONNMAN_SERVICE_TYPE_WIMAX:
break;
}
DBG("device %p", device);
if (device == NULL || device->driver == NULL ||
- device->driver->scan_hidden == NULL)
+ device->driver->scan == NULL)
return -EINVAL;
if (device->scanning == TRUE)
return -EALREADY;
- return device->driver->scan_hidden(device, ssid, ssid_len,
+ return device->driver->scan(device, ssid, ssid_len,
identity, passphrase, user_data);
}
+static char *index2ident(int index, const char *prefix)
+{
+ struct ifreq ifr;
+ struct ether_addr eth;
+ char *str;
+ int sk, err, len;
+
+ if (index < 0)
+ return NULL;
+
+ sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return NULL;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_ifindex = index;
+
+ err = ioctl(sk, SIOCGIFNAME, &ifr);
+
+ if (err == 0)
+ err = ioctl(sk, SIOCGIFHWADDR, &ifr);
+
+ close(sk);
+
+ if (err < 0)
+ return NULL;
+
+ len = prefix ? strlen(prefix) + 18 : 18;
+
+ str = g_malloc(len);
+ if (!str)
+ return NULL;
+
+ memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
+ snprintf(str, len, "%s%02x%02x%02x%02x%02x%02x",
+ prefix ? prefix : "",
+ eth.ether_addr_octet[0],
+ eth.ether_addr_octet[1],
+ eth.ether_addr_octet[2],
+ eth.ether_addr_octet[3],
+ eth.ether_addr_octet[4],
+ eth.ether_addr_octet[5]);
+
+ return str;
+}
+
+static char *index2addr(int index)
+{
+ struct ifreq ifr;
+ struct ether_addr eth;
+ char *str;
+ int sk, err;
+
+ if (index < 0)
+ return NULL;
+
+ sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (sk < 0)
+ return NULL;
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_ifindex = index;
+
+ err = ioctl(sk, SIOCGIFNAME, &ifr);
+
+ if (err == 0)
+ err = ioctl(sk, SIOCGIFHWADDR, &ifr);
+
+ close(sk);
+
+ if (err < 0)
+ return NULL;
+
+ str = g_malloc(18);
+ if (!str)
+ return NULL;
+
+ memcpy(ð, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
+ snprintf(str, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
+ eth.ether_addr_octet[0],
+ eth.ether_addr_octet[1],
+ eth.ether_addr_octet[2],
+ eth.ether_addr_octet[3],
+ eth.ether_addr_octet[4],
+ eth.ether_addr_octet[5]);
+
+ return str;
+}
+
+struct connman_device *connman_device_create_from_index(int index)
+{
+ enum connman_device_type type;
+ struct connman_device *device;
+ char *devname, *ident = NULL;
+ char *addr = NULL, *name = NULL;
+
+ if (index < 0)
+ return NULL;
+
+ devname = connman_inet_ifname(index);
+ if (devname == NULL)
+ return NULL;
+
+ if (__connman_device_isfiltered(devname) == TRUE) {
+ connman_info("Ignoring interface %s (filtered)", devname);
+ g_free(devname);
+ return NULL;
+ }
+
+ type = __connman_rtnl_get_device_type(index);
+
+ switch (type) {
+ case CONNMAN_DEVICE_TYPE_UNKNOWN:
+ connman_info("Ignoring interface %s (type unknown)", devname);
+ g_free(devname);
+ return NULL;
+ case CONNMAN_DEVICE_TYPE_ETHERNET:
+ case CONNMAN_DEVICE_TYPE_GADGET:
+ case CONNMAN_DEVICE_TYPE_WIFI:
+ name = index2ident(index, "");
+ addr = index2addr(index);
+ break;
+ case CONNMAN_DEVICE_TYPE_BLUETOOTH:
+ case CONNMAN_DEVICE_TYPE_CELLULAR:
+ case CONNMAN_DEVICE_TYPE_GPS:
+ case CONNMAN_DEVICE_TYPE_VENDOR:
+ name = g_strdup(devname);
+ break;
+ }
+
+ device = connman_device_create(name, type);
+ if (device == NULL)
+ goto done;
+
+ switch (type) {
+ case CONNMAN_DEVICE_TYPE_UNKNOWN:
+ case CONNMAN_DEVICE_TYPE_VENDOR:
+ case CONNMAN_DEVICE_TYPE_GPS:
+ break;
+ case CONNMAN_DEVICE_TYPE_ETHERNET:
+ case CONNMAN_DEVICE_TYPE_GADGET:
+ ident = index2ident(index, NULL);
+ break;
+ case CONNMAN_DEVICE_TYPE_WIFI:
+ ident = index2ident(index, NULL);
+ break;
+ case CONNMAN_DEVICE_TYPE_BLUETOOTH:
+ break;
+ case CONNMAN_DEVICE_TYPE_CELLULAR:
+ ident = index2ident(index, NULL);
+ break;
+ }
+
+ connman_device_set_index(device, index);
+ connman_device_set_interface(device, devname);
+
+ if (ident != NULL) {
+ connman_device_set_ident(device, ident);
+ g_free(ident);
+ }
+
+ connman_device_set_string(device, "Address", addr);
+
+done:
+ g_free(devname);
+ g_free(name);
+ g_free(addr);
+
+ return device;
+}
+
connman_bool_t __connman_device_isfiltered(const char *devname)
{
char **pattern;
char **blacklisted_interfaces;
+ gboolean match;
if (device_filter == NULL)
goto nodevice;
- for (pattern = device_filter; *pattern; pattern++) {
- if (g_pattern_match_simple(*pattern, devname) == FALSE) {
- DBG("ignoring device %s (match)", devname);
- return TRUE;
+ for (pattern = device_filter, match = FALSE; *pattern; pattern++) {
+ if (g_pattern_match_simple(*pattern, devname) == TRUE) {
+ match = TRUE;
+ break;
}
}
+ if (match == FALSE) {
+ DBG("ignoring device %s (match)", devname);
+ return TRUE;
+ }
+
nodevice:
if (g_pattern_match_simple("dummy*", devname) == TRUE) {
DBG("ignoring dummy networking devices");
list:
blacklisted_interfaces =
- connman_setting_get_string_list("BlacklistedInterfaces");
+ connman_setting_get_string_list("NetworkInterfaceBlacklist");
if (blacklisted_interfaces == NULL)
return FALSE;
return FALSE;
}
+static void cleanup_devices(void)
+{
+ /*
+ * Check what interfaces are currently up and if connman is
+ * suppose to handle the interface, then cleanup the mess
+ * related to that interface. There might be weird routes etc
+ * that are related to that interface and that might confuse
+ * connmand. So in this case we just turn the interface down
+ * so that kernel removes routes/addresses automatically and
+ * then proceed the startup.
+ *
+ * Note that this cleanup must be done before rtnl/detect code
+ * has activated interface watches.
+ */
+
+ char **interfaces;
+ int i;
+
+ interfaces = __connman_inet_get_running_interfaces();
+
+ if (interfaces == NULL)
+ return;
+
+ for (i = 0; interfaces[i] != NULL; i++) {
+ connman_bool_t filtered;
+ int index;
+
+ filtered = __connman_device_isfiltered(interfaces[i]);
+ if (filtered == TRUE)
+ continue;
+
+ index = connman_inet_ifindex(interfaces[i]);
+ if (index < 0)
+ continue;
+
+ DBG("cleaning up %s index %d", interfaces[i], index);
+
+ connman_inet_ifdown(index);
+
+ /*
+ * ConnMan will turn the interface UP automatically so
+ * no need to do it here.
+ */
+ }
+
+ g_strfreev(interfaces);
+}
+
int __connman_device_init(const char *device, const char *nodevice)
{
DBG("");
if (nodevice != NULL)
nodevice_filter = g_strsplit(nodevice, ",", -1);
+ cleanup_devices();
+
return 0;
}