Browse Source

Add RoboSwitch driver interface for wpa_supplicant

Find attached the patch that creates a new driver: roboswitch. This
driver adds support for wired authentication with a Broadcom
RoboSwitch chipset. For example it is now possible to do wired
authentication with a Linksys WRT54G router running OpenWRT.

LIMITATIONS
- At the moment the driver does not support the BCM5365 series (though
adding it requires just some register tweaks).
- The driver is also limited to Linux (this is a far more technical
restriction).
- In order to compile against a 2.4 series you need to edit
include/linux/mii.h and change all references to "u16" in "__u16". I
have submitted a patch upstream that will fix this in a future version
of the 2.4 kernel. [These modifications (and more) are now included in
the kernel source and can be found in versions 2.4.37-rc2 and up.]

USAGE
- Usage is similar to the wired driver. Choose the interfacename of
the vlan that contains your desired authentication port on the router.
This name must be formatted as <interface>.<vlan>, which is the
default on all systems I know.
Jouke Witteveen 16 years ago
parent
commit
e519314ee9

+ 8 - 1
src/drivers/driver.h

@@ -711,7 +711,7 @@ struct wpa_driver_ops {
 	 * @priv: private driver interface data
 	 * @priv: private driver interface data
 	 *
 	 *
 	 * Returns: Pointer to the interface name. This can differ from the
 	 * Returns: Pointer to the interface name. This can differ from the
-	 * interface name used in init() call.
+	 * interface name used in init() call. Init() is called first.
 	 *
 	 *
 	 * This optional function can be used to allow the driver interface to
 	 * This optional function can be used to allow the driver interface to
 	 * replace the interface name with something else, e.g., based on an
 	 * replace the interface name with something else, e.g., based on an
@@ -945,6 +945,13 @@ struct wpa_driver_ops {
 	int (*set_mode)(void *priv, int mode);
 	int (*set_mode)(void *priv, int mode);
 };
 };
 
 
+/* Function to check whether a driver is for wired connections */
+static inline int IS_WIRED(const struct wpa_driver_ops *drv)
+{
+	return os_strcmp(drv->name, "wired") == 0 ||
+		os_strcmp(drv->name, "roboswitch") == 0;
+}
+
 /**
 /**
  * enum wpa_event_type - Event type for wpa_supplicant_event() calls
  * enum wpa_event_type - Event type for wpa_supplicant_event() calls
  */
  */

+ 409 - 0
src/drivers/driver_roboswitch.c

@@ -0,0 +1,409 @@
+/*
+ * WPA Supplicant - roboswitch driver interface
+ * Copyright (c) 2008 Jouke Witteveen
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+#include <sys/ioctl.h>
+#include <linux/if.h>
+#include <linux/sockios.h>
+#include <linux/mii.h>
+
+#include "common.h"
+#include "driver.h"
+
+#define ROBO_PHY_ADDR		0x1E	/* RoboSwitch PHY address */
+
+/* MII access registers */
+#define ROBO_MII_PAGE		0x10	/* MII page register */
+#define ROBO_MII_ADDR		0x11	/* MII address register */
+#define ROBO_MII_DATA_OFFSET	0x18	/* Start of MII data registers */
+
+#define ROBO_MII_PAGE_ENABLE	0x01	/* MII page op code */
+#define ROBO_MII_ADDR_WRITE	0x01	/* MII address write op code */
+#define ROBO_MII_ADDR_READ	0x02	/* MII address read op code */
+#define ROBO_MII_DATA_MAX	   4	/* Consecutive MII data registers */
+#define ROBO_MII_RETRY_MAX	  10	/* Read attempts before giving up */
+
+/* Page numbers */
+#define ROBO_ARLCTRL_PAGE	0x04	/* ARL control page */
+#define ROBO_VLAN_PAGE		0x34	/* VLAN page */
+
+/* ARL control page registers */
+#define ROBO_ARLCTRL_CONF	0x00	/* ARL configuration register */
+#define ROBO_ARLCTRL_ADDR_1	0x10	/* Multiport address 1 */
+#define ROBO_ARLCTRL_VEC_1	0x16	/* Multiport vector 1 */
+#define ROBO_ARLCTRL_ADDR_2	0x20	/* Multiport address 2 */
+#define ROBO_ARLCTRL_VEC_2	0x26	/* Multiport vector 2 */
+
+/* VLAN page registers */
+#define ROBO_VLAN_ACCESS	0x06	/* VLAN table Access register */
+#define ROBO_VLAN_READ		0x0C	/* VLAN read register */
+
+
+static const u8 pae_group_addr[ETH_ALEN] =
+{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
+
+
+struct wpa_driver_roboswitch_data {
+	void *ctx;
+	char ifname[IFNAMSIZ + 1];
+	struct ifreq ifr;
+	int fd;
+	u16 ports;
+};
+
+
+/* Copied from the kernel-only part of mii.h. */
+static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
+{
+	return (struct mii_ioctl_data *) &rq->ifr_ifru;
+}
+
+
+static u16 wpa_driver_roboswitch_mdio_read(
+		struct wpa_driver_roboswitch_data *drv, u8 reg)
+{
+	struct mii_ioctl_data *mii = if_mii(&drv->ifr);
+
+	mii->phy_id = ROBO_PHY_ADDR;
+	mii->reg_num = reg;
+
+	if (ioctl(drv->fd, SIOCGMIIREG, &drv->ifr) < 0) {
+		perror("ioctl[SIOCGMIIREG]");
+		return 0x00;
+	}
+	return mii->val_out;
+}
+
+
+static void wpa_driver_roboswitch_mdio_write(
+		struct wpa_driver_roboswitch_data *drv, u8 reg, u16 val)
+{
+	struct mii_ioctl_data *mii = if_mii(&drv->ifr);
+
+	mii->phy_id = ROBO_PHY_ADDR;
+	mii->reg_num = reg;
+	mii->val_in = val;
+
+	if (ioctl(drv->fd, SIOCSMIIREG, &drv->ifr) < 0) {
+		perror("ioctl[SIOCSMIIREG");
+	}
+}
+
+
+static int wpa_driver_roboswitch_reg(struct wpa_driver_roboswitch_data *drv,
+				     u8 page, u8 reg, u8 op)
+{
+	int i;
+
+	/* set page number */
+	wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_PAGE,
+					 (page << 8) | ROBO_MII_PAGE_ENABLE);
+	/* set register address */
+	wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_ADDR, (reg << 8) | op);
+
+	/* check if operation completed */
+	for (i = 0; i < ROBO_MII_RETRY_MAX; ++i) {
+		if ((wpa_driver_roboswitch_mdio_read(drv, ROBO_MII_ADDR) & 3) ==
+		    0) {
+			return 0;
+		}
+	}
+	/* timeout */
+	return -1;
+}
+
+
+static int wpa_driver_roboswitch_read(struct wpa_driver_roboswitch_data *drv,
+				      u8 page, u8 reg, u16 *val, int len)
+{
+	int i;
+
+	if (len > ROBO_MII_DATA_MAX ||
+	    wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_READ) < 0) {
+		return -1;
+	}
+	for (i = 0; i < len; ++i) {
+		val[i] = wpa_driver_roboswitch_mdio_read(drv,
+						      ROBO_MII_DATA_OFFSET + i);
+	}
+	return 0;
+}
+
+
+static int wpa_driver_roboswitch_write(struct wpa_driver_roboswitch_data *drv,
+				       u8 page, u8 reg, u16 *val, int len)
+{
+	int i;
+
+	if (len > ROBO_MII_DATA_MAX) return -1;
+	for (i = 0; i < len; ++i) {
+		wpa_driver_roboswitch_mdio_write(drv, ROBO_MII_DATA_OFFSET + i,
+						 val[i]);
+	}
+	return wpa_driver_roboswitch_reg(drv, page, reg, ROBO_MII_ADDR_WRITE);
+}
+
+
+static int wpa_driver_roboswitch_get_ssid(void *priv, u8 *ssid)
+{
+	ssid[0] = 0;
+	return 0;
+}
+
+
+static int wpa_driver_roboswitch_get_bssid(void *priv, u8 *bssid)
+{
+	/* Report PAE group address as the "BSSID" for wired connection. */
+	os_memcpy(bssid, pae_group_addr, ETH_ALEN);
+	return 0;
+}
+
+
+static const char * wpa_driver_roboswitch_get_ifname(void *priv)
+{
+	struct wpa_driver_roboswitch_data *drv = priv;
+	return drv->ifname;
+}
+
+
+static int wpa_driver_roboswitch_join(struct wpa_driver_roboswitch_data *drv,
+				      const u8 *addr)
+{
+	int i;
+	u16 _read, zero = 0;
+	/* For reasons of simplicity we assume ETH_ALEN is even. */
+	u16 addr_word[ETH_ALEN/2];
+	/* RoboSwitch uses 16-bit Big Endian addresses.			*/
+	/* The ordering of the words is reversed in the MII registers.	*/
+	for (i = 0; i < ETH_ALEN; i += 2) {
+		addr_word[(ETH_ALEN - i) / 2 - 1] = WPA_GET_BE16(addr + i);
+	}
+
+	/* check if multiport addresses are not yet enabled */
+	if (wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
+				       ROBO_ARLCTRL_CONF, &_read, 1) < 0) {
+		return -1;
+	}
+	if (!(_read & (1 << 4))){
+		_read |= 1 << 4;
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_ADDR_1, addr_word, 3);
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_VEC_1, &drv->ports, 1);
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_VEC_2, &zero, 1);
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_CONF, &_read, 1);
+		return 0;
+	}
+	/* check if multiport address 1 is free */
+	wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_VEC_1,
+				   &_read, 1);
+	if (_read == 0) {
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_ADDR_1, addr_word, 3);
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_VEC_1, &drv->ports, 1);
+		return 0;
+	}
+	/* check if multiport address 2 is free */
+	wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_VEC_2,
+				   &_read, 1);
+	if (_read == 0) {
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_ADDR_2, addr_word, 3);
+		wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+					    ROBO_ARLCTRL_VEC_2, &drv->ports, 1);
+		return 0;
+	}
+	/* out of free multiport addresses */
+	return -1;
+}
+
+
+static int wpa_driver_roboswitch_leave(struct wpa_driver_roboswitch_data *drv,
+				       const u8 *addr)
+{
+	int i;
+	u8 mport[4] = { ROBO_ARLCTRL_VEC_1, ROBO_ARLCTRL_ADDR_1,
+			ROBO_ARLCTRL_VEC_2, ROBO_ARLCTRL_ADDR_2 };
+	u16 _read[3], zero = 0;
+	/* same as at join */
+	u16 addr_word[ETH_ALEN/2];
+	for (i = 0; i < ETH_ALEN; i += 2) {
+		addr_word[(ETH_ALEN - i) / 2 - 1] = WPA_GET_BE16(addr + i);
+	}
+
+	/* find our address/vector pair */
+	for (i = 0; i < 4; i += 2) {
+		wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, mport[i],
+					   _read, 1);
+		if (_read[0] == drv->ports) {
+			wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
+						   mport[i + 1], _read, 3);
+			if (os_memcmp(read, addr_word, 6) == 0)
+				break;
+		}
+	}
+	/* check if we found our address/vector pair and deactivate it */
+	if (i == 4) return -1;
+	wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE, mport[i], &zero, 1);
+
+	/* leave the multiport registers in a sane state */
+	wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE, ROBO_ARLCTRL_VEC_1,
+				   _read, 1);
+	if (_read[0] == 0) {
+		wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
+					   ROBO_ARLCTRL_VEC_2, _read, 1);
+		if (_read[0] == 0) {
+			wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
+						   ROBO_ARLCTRL_CONF, _read, 1);
+			_read[0] &= ~(1 << 4);
+			wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+						    ROBO_ARLCTRL_CONF, _read, 1);
+		} else {
+			wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
+						   ROBO_ARLCTRL_ADDR_2, _read,
+						   3);
+			wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+						    ROBO_ARLCTRL_ADDR_1, _read,
+						    3);
+			wpa_driver_roboswitch_read(drv, ROBO_ARLCTRL_PAGE,
+						   ROBO_ARLCTRL_VEC_2, _read, 1);
+			wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+						    ROBO_ARLCTRL_VEC_1, _read,
+						    1);
+			wpa_driver_roboswitch_write(drv, ROBO_ARLCTRL_PAGE,
+						    ROBO_ARLCTRL_VEC_2, &zero,
+						    1);
+		}
+	}
+	return 0;
+}
+
+
+static void * wpa_driver_roboswitch_init(void *ctx, const char *ifname)
+{
+	struct wpa_driver_roboswitch_data *drv;
+	int len = -1, sep = -1;
+	u16 vlan = 0, vlan_read[2];
+
+	drv = os_zalloc(sizeof(*drv));
+	if (drv == NULL) return NULL;
+	drv->ctx = ctx;
+
+	while (ifname[++len]) if (ifname[len] == '.') sep = len;
+	if (sep < 0 || sep >= len - 1) {
+		wpa_printf(MSG_INFO, "%s: No <interface>.<vlan> pair in "
+			   "interfacename %s", __func__, ifname);
+		os_free(drv);
+		return NULL;
+	}
+	if (sep > IFNAMSIZ) {
+		wpa_printf(MSG_INFO, "%s: Interfacename %s is too long",
+			   __func__, ifname);
+		os_free(drv);
+		return NULL;
+	}
+	os_memcpy(drv->ifname, ifname, sep);
+	drv->ifname[sep] = '\0';
+	while (++sep < len) {
+		if (ifname[sep] < '0' || ifname[sep] > '9') {
+			wpa_printf(MSG_INFO, "%s: Invalid vlan specification "
+				   "in interfacename %s", __func__, ifname);
+			os_free(drv);
+			return NULL;
+		}
+		vlan *= 10;
+		vlan += ifname[sep] - '0';
+		if (vlan > 255) {
+			wpa_printf(MSG_INFO, "%s: VLAN out of range in "
+				   "interfacename %s", __func__, ifname);
+			os_free(drv);
+			return NULL;
+		}
+	}
+
+	drv->fd = socket(PF_INET, SOCK_DGRAM, 0);
+	if (drv->fd < 0) {
+		wpa_printf(MSG_INFO, "%s: Unable to create socket", __func__);
+		os_free(drv);
+		return NULL;
+	}
+
+	os_memset(&drv->ifr, 0, sizeof(drv->ifr));
+	os_strlcpy(drv->ifr.ifr_name, drv->ifname, IFNAMSIZ);
+	if (ioctl(drv->fd, SIOCGMIIPHY, &drv->ifr) < 0) {
+		perror("ioctl[SIOCGMIIPHY]");
+		os_free(drv);
+		return NULL;
+	}
+	if (if_mii(&drv->ifr)->phy_id != ROBO_PHY_ADDR) {
+		wpa_printf(MSG_INFO, "%s: Invalid phy address (not a "
+			   "RoboSwitch?)", __func__);
+		os_free(drv);
+		return NULL;
+	}
+
+	vlan |= 1 << 13;
+	/* The BCM5365 uses a different register and is not accounted for. */
+	wpa_driver_roboswitch_write(drv, ROBO_VLAN_PAGE, ROBO_VLAN_ACCESS,
+				    &vlan, 1);
+	wpa_driver_roboswitch_read(drv, ROBO_VLAN_PAGE, ROBO_VLAN_READ,
+				   vlan_read, 2);
+	if (!(vlan_read[1] & (1 << 4))) {
+		wpa_printf(MSG_INFO, "%s: Could not get port information for "
+				     "VLAN %d", __func__, vlan & ~(1 << 13));
+		os_free(drv);
+		return NULL;
+	}
+	drv->ports = vlan_read[0] & 0x001F;
+	/* add the MII port */
+	drv->ports |= 1 << 8;
+	if (wpa_driver_roboswitch_join(drv, pae_group_addr) < 0) {
+		wpa_printf(MSG_INFO, "%s: Unable to join PAE group", __func__);
+		os_free(drv);
+		return NULL;
+	} else {
+		wpa_printf(MSG_DEBUG, "%s: Added PAE group address to "
+				      "RoboSwitch ARL", __func__);
+	}
+
+	return drv;
+}
+
+
+static void wpa_driver_roboswitch_deinit(void *priv)
+{
+	struct wpa_driver_roboswitch_data *drv = priv;
+
+	if (wpa_driver_roboswitch_leave(drv, pae_group_addr) < 0) {
+		wpa_printf(MSG_DEBUG, "%s: Unable to leave PAE group",
+			   __func__);
+	}
+
+	close(drv->fd);
+	os_free(drv);
+}
+
+
+const struct wpa_driver_ops wpa_driver_roboswitch_ops = {
+	.name = "roboswitch",
+	.desc = "wpa_supplicant roboswitch driver",
+	.get_ssid = wpa_driver_roboswitch_get_ssid,
+	.get_bssid = wpa_driver_roboswitch_get_bssid,
+	.init = wpa_driver_roboswitch_init,
+	.deinit = wpa_driver_roboswitch_deinit,
+	.get_ifname = wpa_driver_roboswitch_get_ifname,
+};

+ 7 - 0
src/drivers/drivers.c

@@ -70,6 +70,10 @@ extern struct wpa_driver_ops wpa_driver_ps3_ops; /* driver_ps3.c */
 #ifdef CONFIG_DRIVER_IPHONE
 #ifdef CONFIG_DRIVER_IPHONE
 extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
 extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */
 #endif /* CONFIG_DRIVER_IPHONE */
 #endif /* CONFIG_DRIVER_IPHONE */
+#ifdef CONFIG_DRIVER_ROBOSWITCH
+/* driver_roboswitch.c */
+extern struct wpa_driver_ops wpa_driver_roboswitch_ops;
+#endif /* CONFIG_DRIVER_ROBOSWITCH */
 
 
 
 
 struct wpa_driver_ops *wpa_supplicant_drivers[] =
 struct wpa_driver_ops *wpa_supplicant_drivers[] =
@@ -128,5 +132,8 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] =
 #ifdef CONFIG_DRIVER_IPHONE
 #ifdef CONFIG_DRIVER_IPHONE
 	&wpa_driver_iphone_ops,
 	&wpa_driver_iphone_ops,
 #endif /* CONFIG_DRIVER_IPHONE */
 #endif /* CONFIG_DRIVER_IPHONE */
+#ifdef CONFIG_DRIVER_ROBOSWITCH
+	&wpa_driver_roboswitch_ops,
+#endif /* CONFIG_DRIVER_ROBOSWITCH */
 	NULL
 	NULL
 };
 };

+ 2 - 0
wpa_supplicant/ChangeLog

@@ -21,6 +21,8 @@ ChangeLog for wpa_supplicant
 	* updated userspace MLME instructions to match with the current Linux
 	* updated userspace MLME instructions to match with the current Linux
 	  mac80211 implementation; please also note that this can only be used
 	  mac80211 implementation; please also note that this can only be used
 	  with driver_nl80211.c (the old code from driver_wext.c was removed)
 	  with driver_nl80211.c (the old code from driver_wext.c was removed)
+	* added support (Linux only) for RoboSwitch chipsets (often found in
+	  consumer grade routers); driver interface 'roboswitch'
 
 
 2008-11-01 - v0.6.5
 2008-11-01 - v0.6.5
 	* added support for SHA-256 as X.509 certificate digest when using the
 	* added support for SHA-256 as X.509 certificate digest when using the

+ 5 - 0
wpa_supplicant/Makefile

@@ -235,6 +235,11 @@ OBJS_d += ../src/drivers/MobileApple80211.o
 LIBS += -framework CoreFoundation
 LIBS += -framework CoreFoundation
 endif
 endif
 
 
+ifdef CONFIG_DRIVER_ROBOSWITCH
+CFLAGS += -DCONFIG_DRIVER_ROBOSWITCH
+OBJS_d += ../src/drivers/driver_roboswitch.o
+endif
+
 ifndef CONFIG_L2_PACKET
 ifndef CONFIG_L2_PACKET
 CONFIG_L2_PACKET=linux
 CONFIG_L2_PACKET=linux
 endif
 endif

+ 3 - 2
wpa_supplicant/README

@@ -525,6 +525,7 @@ drivers:
   broadcom = Broadcom wl.o driver
   broadcom = Broadcom wl.o driver
   ipw = Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 or newer)
   ipw = Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 or newer)
   wired = wpa_supplicant wired Ethernet driver
   wired = wpa_supplicant wired Ethernet driver
+  roboswitch = wpa_supplicant Broadcom switch driver
   bsd = BSD 802.11 support (Atheros, etc.)
   bsd = BSD 802.11 support (Atheros, etc.)
   ndis = Windows NDIS driver
   ndis = Windows NDIS driver
 
 
@@ -694,8 +695,8 @@ network={
 }
 }
 
 
 
 
-6) Authentication for wired Ethernet. This can be used with 'wired' interface
-   (-Dwired on command line).
+6) Authentication for wired Ethernet. This can be used with 'wired' or
+   'roboswitch' interface (-Dwired or -Droboswitch on command line).
 
 
 ctrl_interface=/var/run/wpa_supplicant
 ctrl_interface=/var/run/wpa_supplicant
 ctrl_interface_group=wheel
 ctrl_interface_group=wheel

+ 3 - 0
wpa_supplicant/defconfig

@@ -106,6 +106,9 @@ CONFIG_DRIVER_WEXT=y
 # Driver interface for wired Ethernet drivers
 # Driver interface for wired Ethernet drivers
 CONFIG_DRIVER_WIRED=y
 CONFIG_DRIVER_WIRED=y
 
 
+# Driver interface for the Broadcom RoboSwitch family
+#CONFIG_DRIVER_ROBOSWITCH=y
+
 # Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
 # Enable IEEE 802.1X Supplicant (automatically included if any EAP method is
 # included)
 # included)
 CONFIG_IEEE8021X_EAPOL=y
 CONFIG_IEEE8021X_EAPOL=y

+ 2 - 1
wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml

@@ -174,7 +174,8 @@ network={
 
 
       <listitem>
       <listitem>
 	<para>Authentication for wired Ethernet. This can be used with
 	<para>Authentication for wired Ethernet. This can be used with
-       <emphasis>wired</emphasis> interface (-Dwired on command line).</para>
+        <emphasis>wired</emphasis> or <emphasis>roboswitch</emphasis> interface
+        (-Dwired or -Droboswitch on command line).</para>
 
 
 <blockquote><programlisting>
 <blockquote><programlisting>
 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel
 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel

+ 7 - 0
wpa_supplicant/doc/docbook/wpa_supplicant.sgml

@@ -309,6 +309,13 @@
 	</listitem>
 	</listitem>
       </varlistentry>
       </varlistentry>
 
 
+      <varlistentry>
+	<term>roboswitch</term>
+	<listitem>
+	  <para>wpa_supplicant Broadcom switch driver</para>
+	</listitem>
+      </varlistentry>
+
       <varlistentry>
       <varlistentry>
 	<term>bsd</term>
 	<term>bsd</term>
 	<listitem>
 	<listitem>

+ 3 - 3
wpa_supplicant/scan.c

@@ -70,9 +70,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 	wpa_s->scan_req = 0;
 	wpa_s->scan_req = 0;
 
 
 	if (wpa_s->conf->ap_scan != 0 &&
 	if (wpa_s->conf->ap_scan != 0 &&
-	    wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0) {
-		wpa_printf(MSG_DEBUG, "Using wired driver - overriding "
-			   "ap_scan configuration");
+	    wpa_s->driver && IS_WIRED(wpa_s->driver)) {
+		wpa_printf(MSG_DEBUG, "Using wired authentication - "
+			   "overriding ap_scan configuration");
 		wpa_s->conf->ap_scan = 0;
 		wpa_s->conf->ap_scan = 0;
 	}
 	}
 
 

+ 3 - 4
wpa_supplicant/wpa_supplicant.c

@@ -212,7 +212,7 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
 				     int sec, int usec)
 				     int sec, int usec)
 {
 {
 	if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
 	if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
-	    wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0)
+	    wpa_s->driver && IS_WIRED(wpa_s->driver))
 		return;
 		return;
 
 
 	wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
 	wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
@@ -273,8 +273,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
 				EAPOL_REQUIRE_KEY_BROADCAST;
 				EAPOL_REQUIRE_KEY_BROADCAST;
 		}
 		}
 
 
-		if (wpa_s->conf && wpa_s->driver &&
-		    os_strcmp(wpa_s->driver->name, "wired") == 0) {
+		if (wpa_s->conf && wpa_s->driver && IS_WIRED(wpa_s->driver)) {
 			eapol_conf.required_keys = 0;
 			eapol_conf.required_keys = 0;
 		}
 		}
 	}
 	}
@@ -1388,7 +1387,7 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
 	}
 	}
 
 
 	wired = wpa_s->conf->ap_scan == 0 && wpa_s->driver &&
 	wired = wpa_s->conf->ap_scan == 0 && wpa_s->driver &&
-		os_strcmp(wpa_s->driver->name, "wired") == 0;
+		IS_WIRED(wpa_s->driver);
 
 
 	entry = wpa_s->conf->ssid;
 	entry = wpa_s->conf->ssid;
 	while (entry) {
 	while (entry) {