diff options
| author | Michael Biebl <biebl@debian.org> | 2012-03-24 01:37:02 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2012-03-24 01:37:02 +0100 |
| commit | de06e5715e780baade318f3490ac7a4c9ce84e32 (patch) | |
| tree | 23fbc3fafc12072476eff98bee60100eb54c29db /src/nm-device-olpc-mesh.c | |
| parent | b436a68a20ff3114ded32a7a3d70cdd4954039f9 (diff) | |
Imported Upstream version 0.9.4.0 upstream/0.9.4.0
Diffstat (limited to 'src/nm-device-olpc-mesh.c')
| -rw-r--r-- | src/nm-device-olpc-mesh.c | 308 |
1 files changed, 45 insertions, 263 deletions
diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c index ddd5198e..f6390c16 100644 --- a/src/nm-device-olpc-mesh.c +++ b/src/nm-device-olpc-mesh.c @@ -31,16 +31,18 @@ #include <netinet/in.h> #include <string.h> #include <net/ethernet.h> -#include <iwlib.h> +#include <netinet/ether.h> #include <sys/stat.h> #include <sys/wait.h> #include <signal.h> #include <unistd.h> +#include <linux/if.h> +#include <sys/ioctl.h> +#include <errno.h> #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" -#include "nm-device-interface.h" #include "nm-device-private.h" #include "nm-utils.h" #include "nm-logging.h" @@ -51,6 +53,8 @@ #include "nm-setting-olpc-mesh.h" #include "nm-system.h" #include "nm-manager.h" +#include "nm-enum-types.h" +#include "wifi-utils.h" /* This is a bug; but we can't really change API now... */ #include "NetworkManagerVPN.h" @@ -58,8 +62,6 @@ #include "nm-device-olpc-mesh-glue.h" -static void nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid); - G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) #define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate)) @@ -82,15 +84,7 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -typedef enum -{ - NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH = 0, - NM_OLPC_MESH_ERROR_CONNECTION_INVALID, - NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, -} NMOlpcMeshError; - #define NM_OLPC_MESH_ERROR (nm_olpc_mesh_error_quark ()) -#define NM_TYPE_OLPC_MESH_ERROR (nm_olpc_mesh_error_get_type ()) struct _NMDeviceOlpcMeshPrivate @@ -101,8 +95,7 @@ struct _NMDeviceOlpcMeshPrivate GByteArray * ssid; - gint8 num_freqs; - guint32 freqs[IW_MAX_FREQUENCIES]; + WifiData * wifi_data; gboolean up; @@ -120,29 +113,6 @@ nm_olpc_mesh_error_quark (void) return quark; } -/* This should really be standard. */ -#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } - -static GType -nm_olpc_mesh_error_get_type (void) -{ - static GType etype = 0; - - if (etype == 0) { - static const GEnumValue values[] = { - /* Connection was not a wireless connection. */ - ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_NOT_MESH, "ConnectionNotMesh"), - /* Connection was not a valid wireless connection. */ - ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_INVALID, "ConnectionInvalid"), - /* Connection does not apply to this device. */ - ENUM_ENTRY (NM_OLPC_MESH_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"), - { 0, 0, 0 } - }; - etype = g_enum_register_static ("NMOlpcMeshError", values); - } - return etype; -} - static guint32 real_get_generic_capabilities (NMDevice *dev) { @@ -161,44 +131,6 @@ nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) memset (&(priv->hw_addr), 0, sizeof (struct ether_addr)); } -static guint32 iw_freq_to_uint32 (struct iw_freq *freq) -{ - if (freq->e == 0) { - /* Some drivers report channel not frequency. Convert to a - * frequency; but this assumes that the device is in b/g mode. - */ - if ((freq->m >= 1) && (freq->m <= 13)) - return 2407 + (5 * freq->m); - else if (freq->m == 14) - return 2484; - } - - return (guint32) (((double) freq->m) * pow (10, freq->e) / 1000000); -} - - -/* Until a new wireless-tools comes out that has the defs and the structure, - * need to copy them here. - */ -/* Scan capability flags - in (struct iw_range *)->scan_capa */ -#define NM_IW_SCAN_CAPA_NONE 0x00 -#define NM_IW_SCAN_CAPA_ESSID 0x01 - -struct iw_range_with_scan_capa -{ - guint32 throughput; - guint32 min_nwid; - guint32 max_nwid; - guint16 old_num_channels; - guint8 old_num_frequency; - - guint8 scan_capa; -/* don't need the rest... */ -}; - - - - static GObject* constructor (GType type, guint n_construct_params, @@ -208,11 +140,6 @@ constructor (GType type, GObjectClass *klass; NMDeviceOlpcMesh *self; NMDeviceOlpcMeshPrivate *priv; - const char *iface; - int fd; - struct iw_range range; - struct iwreq wrq; - int i; klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); object = klass->constructor (type, n_construct_params, construct_params); @@ -226,46 +153,19 @@ constructor (GType type, nm_device_get_iface (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); - iface = nm_device_get_iface (NM_DEVICE (self)); - fd = socket (PF_INET, SOCK_DGRAM, 0); - if (fd < 0) - goto error; - - memset (&wrq, 0, sizeof (struct iwreq)); - memset (&range, 0, sizeof (struct iw_range)); - strncpy (wrq.ifr_name, iface, IFNAMSIZ); - wrq.u.data.pointer = (caddr_t) ⦥ - wrq.u.data.length = sizeof (struct iw_range); - - if (ioctl (fd, SIOCGIWRANGE, &wrq) < 0) { - nm_log_info (LOGD_HW | LOGD_WIFI, "(%s): driver WEXT range request failed", + priv->wifi_data = wifi_utils_init (nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_ifindex (NM_DEVICE (self)), + FALSE); + if (priv->wifi_data == NULL) { + nm_log_warn (LOGD_HW | LOGD_OLPC_MESH, "(%s): failed to initialize WiFi driver", nm_device_get_iface (NM_DEVICE (self))); - goto error; - } - - if ((wrq.u.data.length < 300) || (range.we_version_compiled < 21)) { - nm_log_info (LOGD_HW | LOGD_WIFI, - "(%s): driver WEXT version too old (got %d, expected >= 21)", - nm_device_get_iface (NM_DEVICE (self)), - range.we_version_compiled); - goto error; + g_object_unref (object); + return NULL; } - priv->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES); - for (i = 0; i < priv->num_freqs; i++) - priv->freqs[i] = iw_freq_to_uint32 (&range.freq[i]); - - close (fd); - /* shorter timeout for mesh connectivity */ nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); return object; - -error: - if (fd >= 0) - close (fd); - g_object_unref (object); - return NULL; } static gboolean @@ -331,7 +231,7 @@ real_check_connection_compatible (NMDevice *device, NMSettingConnection *s_con; NMSettingOlpcMesh *s_mesh; - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_OLPC_MESH_SETTING_NAME)) { @@ -341,7 +241,7 @@ real_check_connection_compatible (NMDevice *device, return FALSE; } - s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH)); + s_mesh = nm_connection_get_setting_olpc_mesh (connection); if (!s_mesh) { g_set_error (error, NM_OLPC_MESH_ERROR, NM_OLPC_MESH_ERROR_CONNECTION_INVALID, @@ -364,7 +264,7 @@ real_complete_connection (NMDevice *device, NMSettingOlpcMesh *s_mesh; GByteArray *tmp; - s_mesh = (NMSettingOlpcMesh *) nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH); + s_mesh = nm_connection_get_setting_olpc_mesh (connection); if (!s_mesh) { s_mesh = (NMSettingOlpcMesh *) nm_setting_olpc_mesh_new (); nm_connection_add_setting (connection, NM_SETTING (s_mesh)); @@ -414,131 +314,6 @@ nm_device_olpc_mesh_get_address (NMDeviceOlpcMesh *self, memcpy (addr, &(priv->hw_addr), sizeof (struct ether_addr)); } -static int -create_socket_with_request (NMDevice *self, struct iwreq *req) -{ - int sk; - const char * iface; - - g_return_val_if_fail (self != NULL, -1); - - sk = socket (AF_INET, SOCK_DGRAM, 0); - if (sk == -1) { - nm_log_err (LOGD_OLPC_MESH, "Couldn't create socket: %d.", errno); - return -1; - } - - memset (req, 0, sizeof (struct iwreq)); - iface = nm_device_get_iface (NM_DEVICE (self)); - strncpy (req->ifr_name, iface, IFNAMSIZ); - - return sk; -} - -static guint32 -nm_device_olpc_mesh_get_channel (NMDeviceOlpcMesh *self) -{ - NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - int sk; - struct iwreq req; - int ret = 0; - int i; - guint32 freq; - - sk = create_socket_with_request (NM_DEVICE (self), &req); - if (sk == -1) - return 0; - - if ((ioctl (sk, SIOCGIWFREQ, &req)) != 0) { - nm_log_warn (LOGD_OLPC_MESH, "(%s): failed to get channel (errno: %d)", - nm_device_get_iface (NM_DEVICE (self)), errno); - goto out; - } - - freq = iw_freq_to_uint32 (&req.u.freq); - - for (i = 0 ; i < priv->num_freqs; i++) { - if (freq == priv->freqs[i]) - break; - } - if (i < priv->num_freqs) - ret = i + 1; - -out: - if (sk >= 0) - close (sk); - return ret; -} - -static void -nm_device_olpc_mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) -{ - int sk; - struct iwreq req; - - if (nm_device_olpc_mesh_get_channel (self) == channel) - return; - - sk = create_socket_with_request (NM_DEVICE (self), &req); - if (sk < 0) - return; - - if (channel > 0) { - req.u.freq.flags = IW_FREQ_FIXED; - req.u.freq.e = 0; - req.u.freq.m = channel; - } - - if (ioctl (sk, SIOCSIWFREQ, &req) != 0) { - nm_log_warn (LOGD_OLPC_MESH, "(%s): failed to set to channel %d (errno: %d)", - nm_device_get_iface (NM_DEVICE (self)), channel, errno); - } else - g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL); - - close (sk); -} - -static void -nm_device_olpc_mesh_set_ssid (NMDeviceOlpcMesh *self, const GByteArray * ssid) -{ - int sk; - struct iwreq wrq; - const char * iface; - guint32 len = 0; - char buf[IW_ESSID_MAX_SIZE + 1]; - - g_return_if_fail (self != NULL); - - sk = socket (AF_INET, SOCK_DGRAM, 0); - if (sk == -1) { - nm_log_err (LOGD_OLPC_MESH, "Couldn't create socket: %d.", errno); - return; - } - - iface = nm_device_get_iface (NM_DEVICE (self)); - - memset (buf, 0, sizeof (buf)); - if (ssid) { - len = ssid->len; - memcpy (buf, ssid->data, MIN (sizeof (buf) - 1, len)); - } - wrq.u.essid.pointer = (caddr_t) buf; - wrq.u.essid.length = len; - wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */ - - strncpy (wrq.ifr_name, iface, IFNAMSIZ); - if (ioctl (sk, SIOCSIWESSID, &wrq) < 0) { - if (errno != ENODEV) { - nm_log_err (LOGD_OLPC_MESH, "(%s): error setting SSID to '%s': %s", - iface, - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(null)", - strerror (errno)); - } - } - - close (sk); -} - /****************************************************************************/ static void @@ -605,30 +380,38 @@ real_act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) return NM_ACT_STAGE_RETURN_SUCCESS; } +static void +_mesh_set_channel (NMDeviceOlpcMesh *self, guint32 channel) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); + + if (wifi_utils_get_mesh_channel (priv->wifi_data) != channel) { + if (wifi_utils_set_mesh_channel (priv->wifi_data, channel)) + g_object_notify (G_OBJECT (self), NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL); + } +} + static NMActStageReturn real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (dev); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); NMConnection *connection; NMSettingOlpcMesh *s_mesh; - NMActRequest *req; guint32 channel; const GByteArray *anycast_addr_array; guint8 *anycast_addr = NULL; - req = nm_device_get_act_request (dev); - g_assert (req); - - connection = nm_act_request_get_connection (req); + connection = nm_device_get_connection (dev); g_assert (connection); - s_mesh = NM_SETTING_OLPC_MESH (nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH)); + s_mesh = nm_connection_get_setting_olpc_mesh (connection); g_assert (s_mesh); channel = nm_setting_olpc_mesh_get_channel (s_mesh); if (channel != 0) - nm_device_olpc_mesh_set_channel (self, channel); - nm_device_olpc_mesh_set_ssid (self, nm_setting_olpc_mesh_get_ssid (s_mesh)); + _mesh_set_channel (self, channel); + wifi_utils_set_mesh_ssid (priv->wifi_data, nm_setting_olpc_mesh_get_ssid (s_mesh)); anycast_addr_array = nm_setting_olpc_mesh_get_dhcp_anycast_address (s_mesh); if (anycast_addr_array) @@ -651,6 +434,9 @@ dispose (GObject *object) } priv->dispose_has_run = TRUE; + if (priv->wifi_data) + wifi_utils_deinit (priv->wifi_data); + device_cleanup (self); manager = nm_manager_get (); @@ -672,7 +458,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_HW_ADDRESS: nm_device_olpc_mesh_get_address (device, &hw_addr); - g_value_take_string (value, nm_ether_ntop (&hw_addr)); + g_value_take_string (value, nm_utils_hwaddr_ntoa (&hw_addr, ARPHRD_ETHER)); break; case PROP_COMPANION: if (priv->companion) @@ -681,7 +467,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boxed (value, "/"); break; case PROP_ACTIVE_CHANNEL: - g_value_set_uint (value, nm_device_olpc_mesh_get_channel (device)); + g_value_set_uint (value, wifi_utils_get_mesh_channel (priv->wifi_data)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -810,9 +596,7 @@ static gboolean companion_scan_allowed_cb (NMDeviceWifi *companion, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceState state; - - g_object_get (G_OBJECT (self), NM_DEVICE_INTERFACE_STATE, &state, NULL); + NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); /* Don't allow the companion to scan while configuring the mesh interface */ return (state < NM_DEVICE_STATE_PREPARE) || (state > NM_DEVICE_STATE_IP_CONFIG); @@ -822,9 +606,7 @@ static gboolean companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data); - NMDeviceState state; - - g_object_get (G_OBJECT (self), NM_DEVICE_INTERFACE_STATE, &state, NULL); + NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); /* Don't allow the companion to autoconnect while a mesh connection is * active */ @@ -961,11 +743,11 @@ nm_device_olpc_mesh_new (const char *udi, g_return_val_if_fail (driver != NULL, NULL); obj = g_object_new (NM_TYPE_DEVICE_OLPC_MESH, - NM_DEVICE_INTERFACE_UDI, udi, - NM_DEVICE_INTERFACE_IFACE, iface, - NM_DEVICE_INTERFACE_DRIVER, driver, - NM_DEVICE_INTERFACE_TYPE_DESC, "802.11 OLPC Mesh", - NM_DEVICE_INTERFACE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, + NM_DEVICE_UDI, udi, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, driver, + NM_DEVICE_TYPE_DESC, "802.11 OLPC Mesh", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, NULL); if (obj == NULL) return NULL; |