wifi-utils: don't cache interface name
For nl80211, we don't care about the interface name and only use it when formatting error messages. For wext, an up-to-date interface name should be obtained every time to minimize the chance of race conditions when the interface is renamed.
This commit is contained in:
@@ -5503,34 +5503,17 @@ wifi_get_wifi_data (NMPlatform *platform, int ifindex)
|
|||||||
wifi_data = g_hash_table_lookup (priv->wifi_data, GINT_TO_POINTER (ifindex));
|
wifi_data = g_hash_table_lookup (priv->wifi_data, GINT_TO_POINTER (ifindex));
|
||||||
pllink = nm_platform_link_get (platform, ifindex);
|
pllink = nm_platform_link_get (platform, ifindex);
|
||||||
|
|
||||||
/* @wifi_data contains an interface name which is used for WEXT queries. If
|
|
||||||
* the interface name changes we should at least replace the name in the
|
|
||||||
* existing structure; but probably a complete reinitialization is better
|
|
||||||
* because during the initial creation there can be race conditions while
|
|
||||||
* the interface is renamed by udev.
|
|
||||||
*/
|
|
||||||
if (wifi_data && pllink) {
|
|
||||||
if (!nm_streq (wifi_utils_get_iface (wifi_data), pllink->name)) {
|
|
||||||
_LOGD ("wifi: interface %s renamed to %s, dropping old data for ifindex %d",
|
|
||||||
wifi_utils_get_iface (wifi_data),
|
|
||||||
pllink->name,
|
|
||||||
ifindex);
|
|
||||||
g_hash_table_remove (priv->wifi_data, GINT_TO_POINTER (ifindex));
|
|
||||||
wifi_data = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wifi_data) {
|
if (!wifi_data) {
|
||||||
if (pllink) {
|
if (pllink) {
|
||||||
if (pllink->type == NM_LINK_TYPE_WIFI)
|
if (pllink->type == NM_LINK_TYPE_WIFI)
|
||||||
wifi_data = wifi_utils_init (pllink->name, ifindex, TRUE);
|
wifi_data = wifi_utils_init (ifindex, TRUE);
|
||||||
else if (pllink->type == NM_LINK_TYPE_OLPC_MESH) {
|
else if (pllink->type == NM_LINK_TYPE_OLPC_MESH) {
|
||||||
/* The kernel driver now uses nl80211, but we force use of WEXT because
|
/* The kernel driver now uses nl80211, but we force use of WEXT because
|
||||||
* the cfg80211 interactions are not quite ready to support access to
|
* the cfg80211 interactions are not quite ready to support access to
|
||||||
* mesh control through nl80211 just yet.
|
* mesh control through nl80211 just yet.
|
||||||
*/
|
*/
|
||||||
#if HAVE_WEXT
|
#if HAVE_WEXT
|
||||||
wifi_data = wifi_wext_init (pllink->name, ifindex, FALSE);
|
wifi_data = wifi_wext_init (ifindex, FALSE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "wifi-utils-private.h"
|
#include "wifi-utils-private.h"
|
||||||
#include "wifi-utils-nl80211.h"
|
#include "wifi-utils-nl80211.h"
|
||||||
#include "platform/nm-platform.h"
|
#include "platform/nm-platform.h"
|
||||||
|
#include "platform/nm-platform-utils.h"
|
||||||
#include "nm-utils.h"
|
#include "nm-utils.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -1032,13 +1033,20 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WifiData *
|
WifiData *
|
||||||
wifi_nl80211_init (const char *iface, int ifindex)
|
wifi_nl80211_init (int ifindex)
|
||||||
{
|
{
|
||||||
WifiDataNl80211 *nl80211;
|
WifiDataNl80211 *nl80211;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
struct nl80211_device_info device_info = {};
|
struct nl80211_device_info device_info = {};
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
nl80211 = wifi_data_new (iface, ifindex, sizeof (*nl80211));
|
if (!nmp_utils_if_indextoname (ifindex, ifname)) {
|
||||||
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
|
"wifi-nl80211: can't determine interface name for ifindex %d", ifindex);
|
||||||
|
nm_sprintf_buf (ifname, "if %d", ifindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
nl80211 = wifi_data_new (ifindex, sizeof (*nl80211));
|
||||||
nl80211->parent.get_mode = wifi_nl80211_get_mode;
|
nl80211->parent.get_mode = wifi_nl80211_get_mode;
|
||||||
nl80211->parent.set_mode = wifi_nl80211_set_mode;
|
nl80211->parent.set_mode = wifi_nl80211_set_mode;
|
||||||
nl80211->parent.set_powersave = wifi_nl80211_set_powersave;
|
nl80211->parent.set_powersave = wifi_nl80211_set_powersave;
|
||||||
@@ -1075,42 +1083,42 @@ wifi_nl80211_init (const char *iface, int ifindex)
|
|||||||
&device_info) < 0) {
|
&device_info) < 0) {
|
||||||
nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): NL80211_CMD_GET_WIPHY request failed",
|
"(%s): NL80211_CMD_GET_WIPHY request failed",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device_info.success) {
|
if (!device_info.success) {
|
||||||
nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): NL80211_CMD_GET_WIPHY request indicated failure",
|
"(%s): NL80211_CMD_GET_WIPHY request indicated failure",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device_info.supported) {
|
if (!device_info.supported) {
|
||||||
nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_dbg (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver does not fully support nl80211, falling back to WEXT",
|
"(%s): driver does not fully support nl80211, falling back to WEXT",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device_info.can_scan_ssid) {
|
if (!device_info.can_scan_ssid) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver does not support SSID scans",
|
"(%s): driver does not support SSID scans",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_info.num_freqs == 0 || device_info.freqs == NULL) {
|
if (device_info.num_freqs == 0 || device_info.freqs == NULL) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver reports no supported frequencies",
|
"(%s): driver reports no supported frequencies",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_info.caps == 0) {
|
if (device_info.caps == 0) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver doesn't report support of any encryption",
|
"(%s): driver doesn't report support of any encryption",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1124,7 +1132,7 @@ wifi_nl80211_init (const char *iface, int ifindex)
|
|||||||
|
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): using nl80211 for WiFi device control",
|
"(%s): using nl80211 for WiFi device control",
|
||||||
nl80211->parent.iface);
|
ifname);
|
||||||
|
|
||||||
return (WifiData *) nl80211;
|
return (WifiData *) nl80211;
|
||||||
|
|
||||||
|
@@ -23,6 +23,6 @@
|
|||||||
|
|
||||||
#include "wifi-utils.h"
|
#include "wifi-utils.h"
|
||||||
|
|
||||||
WifiData *wifi_nl80211_init (const char *iface, int ifindex);
|
WifiData *wifi_nl80211_init (int ifindex);
|
||||||
|
|
||||||
#endif /* __WIFI_UTILS_NL80211_H__ */
|
#endif /* __WIFI_UTILS_NL80211_H__ */
|
||||||
|
@@ -25,7 +25,6 @@
|
|||||||
#include "wifi-utils.h"
|
#include "wifi-utils.h"
|
||||||
|
|
||||||
struct WifiData {
|
struct WifiData {
|
||||||
char *iface;
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
NMDeviceWifiCapabilities caps;
|
NMDeviceWifiCapabilities caps;
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ struct WifiData {
|
|||||||
gboolean (*indicate_addressing_running) (WifiData *data, gboolean running);
|
gboolean (*indicate_addressing_running) (WifiData *data, gboolean running);
|
||||||
};
|
};
|
||||||
|
|
||||||
gpointer wifi_data_new (const char *iface, int ifindex, gsize len);
|
gpointer wifi_data_new (int ifindex, gsize len);
|
||||||
void wifi_data_free (WifiData *data);
|
void wifi_data_free (WifiData *data);
|
||||||
|
|
||||||
#endif /* __WIFI_UTILS_PRIVATE_H__ */
|
#endif /* __WIFI_UTILS_PRIVATE_H__ */
|
||||||
|
@@ -94,20 +94,36 @@ wifi_wext_deinit (WifiData *parent)
|
|||||||
close (wext->fd);
|
close (wext->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_ifname (int ifindex, char *buffer, const char *op)
|
||||||
|
{
|
||||||
|
int errsv;
|
||||||
|
|
||||||
|
if (!nmp_utils_if_indextoname (ifindex, buffer)) {
|
||||||
|
errsv = errno;
|
||||||
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
|
"wifi-wext: error getting interface name for ifindex %d, operation '%s': %s (%d)",
|
||||||
|
ifindex, op, g_strerror (errsv), errsv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static NM80211Mode
|
static NM80211Mode
|
||||||
wifi_wext_get_mode (WifiData *data)
|
wifi_wext_get_mode_ifname (WifiData *data, const char *ifname)
|
||||||
{
|
{
|
||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
|
|
||||||
if (ioctl (wext->fd, SIOCGIWMODE, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCGIWMODE, &wrq) < 0) {
|
||||||
if (errno != ENODEV) {
|
if (errno != ENODEV) {
|
||||||
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): error %d getting card mode",
|
"(%s): error %d getting card mode",
|
||||||
wext->parent.iface, errno);
|
ifname, errno);
|
||||||
}
|
}
|
||||||
return NM_802_11_MODE_UNKNOWN;
|
return NM_802_11_MODE_UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -126,13 +142,28 @@ wifi_wext_get_mode (WifiData *data)
|
|||||||
return NM_802_11_MODE_UNKNOWN;
|
return NM_802_11_MODE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NM80211Mode
|
||||||
|
wifi_wext_get_mode (WifiData *data)
|
||||||
|
{
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "get-mode"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return wifi_wext_get_mode_ifname (data, ifname);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
wifi_wext_set_mode (WifiData *data, const NM80211Mode mode)
|
wifi_wext_set_mode (WifiData *data, const NM80211Mode mode)
|
||||||
{
|
{
|
||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
if (wifi_wext_get_mode (data) == mode)
|
if (!get_ifname (data->ifindex, ifname, "set-mode"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (wifi_wext_get_mode_ifname (data, ifname) == mode)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
@@ -151,11 +182,12 @@ wifi_wext_set_mode (WifiData *data, const NM80211Mode mode)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
if (ioctl (wext->fd, SIOCSIWMODE, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCSIWMODE, &wrq) < 0) {
|
||||||
if (errno != ENODEV) {
|
if (errno != ENODEV) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI, "(%s): error setting mode %d",
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
wext->parent.iface, mode);
|
"(%s): error setting mode %d",
|
||||||
|
ifname, mode);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -168,6 +200,10 @@ wifi_wext_set_powersave (WifiData *data, guint32 powersave)
|
|||||||
{
|
{
|
||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "set-powersave"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
if (powersave == 1) {
|
if (powersave == 1) {
|
||||||
@@ -175,11 +211,12 @@ wifi_wext_set_powersave (WifiData *data, guint32 powersave)
|
|||||||
} else
|
} else
|
||||||
wrq.u.power.disabled = 1;
|
wrq.u.power.disabled = 1;
|
||||||
|
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
if (ioctl (wext->fd, SIOCSIWPOWER, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCSIWPOWER, &wrq) < 0) {
|
||||||
if (errno != ENODEV) {
|
if (errno != ENODEV) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI, "(%s): error setting powersave %" G_GUINT32_FORMAT,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
wext->parent.iface, powersave);
|
"(%s): error setting powersave %" G_GUINT32_FORMAT,
|
||||||
|
ifname, powersave);
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -192,13 +229,17 @@ wifi_wext_get_freq (WifiData *data)
|
|||||||
{
|
{
|
||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "get-freq"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
if (ioctl (wext->fd, SIOCGIWFREQ, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCGIWFREQ, &wrq) < 0) {
|
||||||
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): error getting frequency: %s",
|
"(%s): error getting frequency: %s",
|
||||||
wext->parent.iface, strerror (errno));
|
ifname, strerror (errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,13 +267,17 @@ wifi_wext_get_bssid (WifiData *data, guint8 *out_bssid)
|
|||||||
{
|
{
|
||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "get-bssid"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (wrq));
|
memset (&wrq, 0, sizeof (wrq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
if (ioctl (wext->fd, SIOCGIWAP, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCGIWAP, &wrq) < 0) {
|
||||||
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): error getting associated BSSID: %s",
|
"(%s): error getting associated BSSID: %s",
|
||||||
wext->parent.iface, strerror (errno));
|
ifname, strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
memcpy (out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN);
|
memcpy (out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN);
|
||||||
@@ -245,9 +290,13 @@ wifi_wext_get_rate (WifiData *data)
|
|||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
int err;
|
int err;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "get-rate"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (wrq));
|
memset (&wrq, 0, sizeof (wrq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
err = ioctl (wext->fd, SIOCGIWRATE, &wrq);
|
err = ioctl (wext->fd, SIOCGIWRATE, &wrq);
|
||||||
return ((err == 0) ? wrq.u.bitrate.value / 1000 : 0);
|
return ((err == 0) ? wrq.u.bitrate.value / 1000 : 0);
|
||||||
}
|
}
|
||||||
@@ -352,17 +401,21 @@ wifi_wext_get_qual (WifiData *data)
|
|||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
struct iw_statistics stats;
|
struct iw_statistics stats;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "get-qual"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (&stats, 0, sizeof (stats));
|
memset (&stats, 0, sizeof (stats));
|
||||||
wrq.u.data.pointer = &stats;
|
wrq.u.data.pointer = &stats;
|
||||||
wrq.u.data.length = sizeof (stats);
|
wrq.u.data.length = sizeof (stats);
|
||||||
wrq.u.data.flags = 1; /* Clear updated flag */
|
wrq.u.data.flags = 1; /* Clear updated flag */
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
|
|
||||||
if (ioctl (wext->fd, SIOCGIWSTATS, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCGIWSTATS, &wrq) < 0) {
|
||||||
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): error getting signal strength: %s",
|
"(%s): error getting signal strength: %s",
|
||||||
wext->parent.iface, strerror (errno));
|
ifname, strerror (errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,9 +445,13 @@ wifi_wext_set_mesh_channel (WifiData *data, guint32 channel)
|
|||||||
{
|
{
|
||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "set-mesh-channel"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
|
|
||||||
if (channel > 0) {
|
if (channel > 0) {
|
||||||
wrq.u.freq.flags = IW_FREQ_FIXED;
|
wrq.u.freq.flags = IW_FREQ_FIXED;
|
||||||
@@ -405,7 +462,7 @@ wifi_wext_set_mesh_channel (WifiData *data, guint32 channel)
|
|||||||
if (ioctl (wext->fd, SIOCSIWFREQ, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCSIWFREQ, &wrq) < 0) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC,
|
||||||
"(%s): error setting channel to %d: %s",
|
"(%s): error setting channel to %d: %s",
|
||||||
wext->parent.iface, channel, strerror (errno));
|
ifname, channel, strerror (errno));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +475,10 @@ wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
|
|||||||
WifiDataWext *wext = (WifiDataWext *) data;
|
WifiDataWext *wext = (WifiDataWext *) data;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
char buf[IW_ESSID_MAX_SIZE + 1];
|
char buf[IW_ESSID_MAX_SIZE + 1];
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (!get_ifname (data->ifindex, ifname, "set-mesh-ssid"))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
memset (buf, 0, sizeof (buf));
|
memset (buf, 0, sizeof (buf));
|
||||||
memcpy (buf, ssid, MIN (sizeof (buf) - 1, len));
|
memcpy (buf, ssid, MIN (sizeof (buf) - 1, len));
|
||||||
@@ -426,14 +487,14 @@ wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
|
|||||||
wrq.u.essid.length = len;
|
wrq.u.essid.length = len;
|
||||||
wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */
|
wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */
|
||||||
|
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
if (ioctl (wext->fd, SIOCSIWESSID, &wrq) == 0)
|
if (ioctl (wext->fd, SIOCSIWESSID, &wrq) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (errno != ENODEV) {
|
if (errno != ENODEV) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI | LOGD_OLPC,
|
||||||
"(%s): error setting SSID to '%s': %s",
|
"(%s): error setting SSID to '%s': %s",
|
||||||
wext->parent.iface,
|
ifname,
|
||||||
ssid ? nm_utils_escape_ssid (ssid, len) : "(null)",
|
ssid ? nm_utils_escape_ssid (ssid, len) : "(null)",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
}
|
}
|
||||||
@@ -444,12 +505,12 @@ wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
wext_can_scan (WifiDataWext *wext)
|
wext_can_scan_ifname (WifiDataWext *wext, const char *ifname)
|
||||||
{
|
{
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
if (ioctl (wext->fd, SIOCSIWSCAN, &wrq) < 0) {
|
if (ioctl (wext->fd, SIOCSIWSCAN, &wrq) < 0) {
|
||||||
if (errno == EOPNOTSUPP)
|
if (errno == EOPNOTSUPP)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -458,16 +519,17 @@ wext_can_scan (WifiDataWext *wext)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
wext_get_range (WifiDataWext *wext,
|
wext_get_range_ifname (WifiDataWext *wext,
|
||||||
struct iw_range *range,
|
const char *ifname,
|
||||||
guint32 *response_len)
|
struct iw_range *range,
|
||||||
|
guint32 *response_len)
|
||||||
{
|
{
|
||||||
int i = 26;
|
int i = 26;
|
||||||
gboolean success = FALSE;
|
gboolean success = FALSE;
|
||||||
struct iwreq wrq;
|
struct iwreq wrq;
|
||||||
|
|
||||||
memset (&wrq, 0, sizeof (struct iwreq));
|
memset (&wrq, 0, sizeof (struct iwreq));
|
||||||
nm_utils_ifname_cpy (wrq.ifr_name, wext->parent.iface);
|
nm_utils_ifname_cpy (wrq.ifr_name, ifname);
|
||||||
wrq.u.data.pointer = (caddr_t) range;
|
wrq.u.data.pointer = (caddr_t) range;
|
||||||
wrq.u.data.length = sizeof (struct iw_range);
|
wrq.u.data.length = sizeof (struct iw_range);
|
||||||
|
|
||||||
@@ -484,7 +546,7 @@ wext_get_range (WifiDataWext *wext,
|
|||||||
} else if (errno != EAGAIN) {
|
} else if (errno != EAGAIN) {
|
||||||
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_err (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): couldn't get driver range information (%d).",
|
"(%s): couldn't get driver range information (%d).",
|
||||||
wext->parent.iface, errno);
|
ifname, errno);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,7 +556,7 @@ wext_get_range (WifiDataWext *wext,
|
|||||||
if (i <= 0) {
|
if (i <= 0) {
|
||||||
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver took too long to respond to IWRANGE query.",
|
"(%s): driver took too long to respond to IWRANGE query.",
|
||||||
wext->parent.iface);
|
ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@@ -506,7 +568,7 @@ wext_get_range (WifiDataWext *wext,
|
|||||||
NM_WIFI_DEVICE_CAP_RSN)
|
NM_WIFI_DEVICE_CAP_RSN)
|
||||||
|
|
||||||
static guint32
|
static guint32
|
||||||
wext_get_caps (WifiDataWext *wext, struct iw_range *range)
|
wext_get_caps (WifiDataWext *wext, const char *ifname, struct iw_range *range)
|
||||||
{
|
{
|
||||||
guint32 caps = NM_WIFI_DEVICE_CAP_NONE;
|
guint32 caps = NM_WIFI_DEVICE_CAP_NONE;
|
||||||
|
|
||||||
@@ -531,16 +593,18 @@ wext_get_caps (WifiDataWext *wext, struct iw_range *range)
|
|||||||
/* Check for cipher support but not WPA support */
|
/* Check for cipher support but not WPA support */
|
||||||
if ( (caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
|
if ( (caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
|
||||||
&& !(caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))) {
|
&& !(caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))) {
|
||||||
nm_log_warn (LOGD_WIFI, "%s: device supports WPA ciphers but not WPA protocol; "
|
nm_log_warn (LOGD_WIFI,
|
||||||
"WPA unavailable.", wext->parent.iface);
|
"%s: device supports WPA ciphers but not WPA protocol; WPA unavailable.",
|
||||||
|
ifname);
|
||||||
caps &= ~WPA_CAPS;
|
caps &= ~WPA_CAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for WPA support but not cipher support */
|
/* Check for WPA support but not cipher support */
|
||||||
if ( (caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))
|
if ( (caps & (NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN))
|
||||||
&& !(caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))) {
|
&& !(caps & (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP))) {
|
||||||
nm_log_warn (LOGD_WIFI, "%s: device supports WPA protocol but not WPA ciphers; "
|
nm_log_warn (LOGD_WIFI,
|
||||||
"WPA unavailable.", wext->parent.iface);
|
"%s: device supports WPA protocol but not WPA ciphers; WPA unavailable.",
|
||||||
|
ifname);
|
||||||
caps &= ~WPA_CAPS;
|
caps &= ~WPA_CAPS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +618,7 @@ wext_get_caps (WifiDataWext *wext, struct iw_range *range)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WifiData *
|
WifiData *
|
||||||
wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
|
wifi_wext_init (int ifindex, gboolean check_scan)
|
||||||
{
|
{
|
||||||
WifiDataWext *wext;
|
WifiDataWext *wext;
|
||||||
struct iw_range range;
|
struct iw_range range;
|
||||||
@@ -562,8 +626,15 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
|
|||||||
struct iw_range_with_scan_capa *scan_capa_range;
|
struct iw_range_with_scan_capa *scan_capa_range;
|
||||||
int i;
|
int i;
|
||||||
gboolean freq_valid = FALSE, has_5ghz = FALSE, has_2ghz = FALSE;
|
gboolean freq_valid = FALSE, has_5ghz = FALSE, has_2ghz = FALSE;
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
|
||||||
wext = wifi_data_new (iface, ifindex, sizeof (*wext));
|
if (!nmp_utils_if_indextoname (ifindex, ifname)) {
|
||||||
|
nm_log_warn (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
|
"wifi-wext: can't determine interface name for ifindex %d", ifindex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wext = wifi_data_new (ifindex, sizeof (*wext));
|
||||||
wext->parent.get_mode = wifi_wext_get_mode;
|
wext->parent.get_mode = wifi_wext_get_mode;
|
||||||
wext->parent.set_mode = wifi_wext_set_mode;
|
wext->parent.set_mode = wifi_wext_set_mode;
|
||||||
wext->parent.set_powersave = wifi_wext_set_powersave;
|
wext->parent.set_powersave = wifi_wext_set_powersave;
|
||||||
@@ -582,16 +653,16 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
memset (&range, 0, sizeof (struct iw_range));
|
memset (&range, 0, sizeof (struct iw_range));
|
||||||
if (wext_get_range (wext, &range, &response_len) == FALSE) {
|
if (wext_get_range_ifname (wext, ifname, &range, &response_len) == FALSE) {
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI, "(%s): driver WEXT range request failed",
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI, "(%s): driver WEXT range request failed",
|
||||||
wext->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((response_len < 300) || (range.we_version_compiled < 21)) {
|
if ((response_len < 300) || (range.we_version_compiled < 21)) {
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver WEXT version too old (got %d, expected >= 21)",
|
"(%s): driver WEXT version too old (got %d, expected >= 21)",
|
||||||
wext->parent.iface,
|
ifname,
|
||||||
range.we_version_compiled);
|
range.we_version_compiled);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -612,10 +683,10 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for scanning capability; cards that can't scan are not supported */
|
/* Check for scanning capability; cards that can't scan are not supported */
|
||||||
if (check_scan && (wext_can_scan (wext) == FALSE)) {
|
if (check_scan && (wext_can_scan_ifname (wext, ifname) == FALSE)) {
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): drivers that cannot scan are unsupported",
|
"(%s): drivers that cannot scan are unsupported",
|
||||||
wext->parent.iface);
|
ifname);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,16 +698,16 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
|
|||||||
if (scan_capa_range->scan_capa & NM_IW_SCAN_CAPA_ESSID) {
|
if (scan_capa_range->scan_capa & NM_IW_SCAN_CAPA_ESSID) {
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver supports SSID scans (scan_capa 0x%02X).",
|
"(%s): driver supports SSID scans (scan_capa 0x%02X).",
|
||||||
wext->parent.iface,
|
ifname,
|
||||||
scan_capa_range->scan_capa);
|
scan_capa_range->scan_capa);
|
||||||
} else {
|
} else {
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): driver does not support SSID scans (scan_capa 0x%02X).",
|
"(%s): driver does not support SSID scans (scan_capa 0x%02X).",
|
||||||
wext->parent.iface,
|
ifname,
|
||||||
scan_capa_range->scan_capa);
|
scan_capa_range->scan_capa);
|
||||||
}
|
}
|
||||||
|
|
||||||
wext->parent.caps = wext_get_caps (wext, &range);
|
wext->parent.caps = wext_get_caps (wext, ifname, &range);
|
||||||
if (freq_valid)
|
if (freq_valid)
|
||||||
wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID;
|
wext->parent.caps |= NM_WIFI_DEVICE_CAP_FREQ_VALID;
|
||||||
if (has_2ghz)
|
if (has_2ghz)
|
||||||
@@ -646,7 +717,7 @@ wifi_wext_init (const char *iface, int ifindex, gboolean check_scan)
|
|||||||
|
|
||||||
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
nm_log_info (LOGD_PLATFORM | LOGD_WIFI,
|
||||||
"(%s): using WEXT for WiFi device control",
|
"(%s): using WEXT for WiFi device control",
|
||||||
wext->parent.iface);
|
ifname);
|
||||||
|
|
||||||
return (WifiData *) wext;
|
return (WifiData *) wext;
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "wifi-utils.h"
|
#include "wifi-utils.h"
|
||||||
|
|
||||||
WifiData *wifi_wext_init (const char *iface, int ifindex, gboolean check_scan);
|
WifiData *wifi_wext_init (int ifindex, gboolean check_scan);
|
||||||
|
|
||||||
gboolean wifi_wext_is_wifi (const char *iface);
|
gboolean wifi_wext_is_wifi (const char *iface);
|
||||||
|
|
||||||
|
@@ -38,12 +38,11 @@
|
|||||||
#include "platform/nm-platform-utils.h"
|
#include "platform/nm-platform-utils.h"
|
||||||
|
|
||||||
gpointer
|
gpointer
|
||||||
wifi_data_new (const char *iface, int ifindex, gsize len)
|
wifi_data_new (int ifindex, gsize len)
|
||||||
{
|
{
|
||||||
WifiData *data;
|
WifiData *data;
|
||||||
|
|
||||||
data = g_malloc0 (len);
|
data = g_malloc0 (len);
|
||||||
data->iface = g_strdup (iface);
|
|
||||||
data->ifindex = ifindex;
|
data->ifindex = ifindex;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -51,7 +50,6 @@ wifi_data_new (const char *iface, int ifindex, gsize len)
|
|||||||
void
|
void
|
||||||
wifi_data_free (WifiData *data)
|
wifi_data_free (WifiData *data)
|
||||||
{
|
{
|
||||||
g_free (data->iface);
|
|
||||||
memset (data, 0, sizeof (*data));
|
memset (data, 0, sizeof (*data));
|
||||||
g_free (data);
|
g_free (data);
|
||||||
}
|
}
|
||||||
@@ -59,17 +57,16 @@ wifi_data_free (WifiData *data)
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
WifiData *
|
WifiData *
|
||||||
wifi_utils_init (const char *iface, int ifindex, gboolean check_scan)
|
wifi_utils_init (int ifindex, gboolean check_scan)
|
||||||
{
|
{
|
||||||
WifiData *ret;
|
WifiData *ret;
|
||||||
|
|
||||||
g_return_val_if_fail (iface != NULL, NULL);
|
|
||||||
g_return_val_if_fail (ifindex > 0, NULL);
|
g_return_val_if_fail (ifindex > 0, NULL);
|
||||||
|
|
||||||
ret = wifi_nl80211_init (iface, ifindex);
|
ret = wifi_nl80211_init (ifindex);
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
#if HAVE_WEXT
|
#if HAVE_WEXT
|
||||||
ret = wifi_wext_init (iface, ifindex, check_scan);
|
ret = wifi_wext_init (ifindex, check_scan);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@@ -83,14 +80,6 @@ wifi_utils_get_ifindex (WifiData *data)
|
|||||||
return data->ifindex;
|
return data->ifindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
|
||||||
wifi_utils_get_iface (WifiData *data)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (data != NULL, NULL);
|
|
||||||
|
|
||||||
return data->iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
NMDeviceWifiCapabilities
|
NMDeviceWifiCapabilities
|
||||||
wifi_utils_get_caps (WifiData *data)
|
wifi_utils_get_caps (WifiData *data)
|
||||||
{
|
{
|
||||||
|
@@ -30,12 +30,10 @@ typedef struct WifiData WifiData;
|
|||||||
|
|
||||||
gboolean wifi_utils_is_wifi (int dirfd, const char *ifname);
|
gboolean wifi_utils_is_wifi (int dirfd, const char *ifname);
|
||||||
|
|
||||||
WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan);
|
WifiData *wifi_utils_init (int ifindex, gboolean check_scan);
|
||||||
|
|
||||||
int wifi_utils_get_ifindex (WifiData *data);
|
int wifi_utils_get_ifindex (WifiData *data);
|
||||||
|
|
||||||
const char *wifi_utils_get_iface (WifiData *data);
|
|
||||||
|
|
||||||
void wifi_utils_deinit (WifiData *data);
|
void wifi_utils_deinit (WifiData *data);
|
||||||
|
|
||||||
NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data);
|
NMDeviceWifiCapabilities wifi_utils_get_caps (WifiData *data);
|
||||||
|
Reference in New Issue
Block a user