I've been working with restoring userspace MLME functionality for client
mode. The patch below adds a new cfg80211 command for setting couple of
vif parameters. Does this approach look fine? The current wpa_supplicant
git tree has code for using the new command to enabled userspace MLME.
It is also using a monitor interface in the same way as hostapd is now
handling management frames. The goal of this new command is to be able
to add new vif/sdata-specific attributes in the future, if needed,
without having to define new nl80211 commands. I just added two
attributes now as an example of what can be done with the command (and
to get driver_nl80211.c in wpa_supplicant one step closer to using
cfg80211 instead of WEXT).
Index: wireless-testing/include/net/cfg80211.h
===================================================================
--- wireless-testing.orig/include/net/cfg80211.h
+++ wireless-testing/include/net/cfg80211.h
@@ -288,6 +288,21 @@ struct bss_parameters {
int use_short_slot_time;
};
+/**
+ * struct vif_parameters - Virtual interface parameters
+ *
+ * Used to change virtual interface parameters.
+ *
+ * @drop_unencrypted: Whether to drop unencrypted frames
+ * (0 = no, 1 = yes, -1 = do not change)
+ * @userspace_mlme: Whether to use userspace MLME
+ * (0 = no, 1 = yes, -1 = do not change)
+ */
+struct vif_parameters {
+ int drop_unencrypted;
+ int userspace_mlme;
+};
+
/* from net/wireless.h */
struct wiphy;
@@ -341,6 +356,8 @@ struct wiphy;
* @set_mesh_cfg: set mesh parameters (by now, just mesh id)
*
* @change_bss: Modify parameters for a given BSS.
+ *
+ * @change_vif: Modify parameters for a given virtual interface.
*/
struct cfg80211_ops {
int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
@@ -399,6 +416,9 @@ struct cfg80211_ops {
int (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
struct bss_parameters *params);
+
+ int (*change_vif)(struct wiphy *wiphy, struct net_device *dev,
+ struct vif_parameters *params);
};
#endif /* __NET_CFG80211_H */
Index: wireless-testing/net/mac80211/cfg.c
===================================================================
--- wireless-testing.orig/net/mac80211/cfg.c
+++ wireless-testing/net/mac80211/cfg.c
@@ -1079,6 +1079,28 @@ static int ieee80211_change_bss(struct w
return 0;
}
+static int ieee80211_change_vif(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct vif_parameters *params)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_sub_if_data *sdata;
+
+ if (dev == local->mdev)
+ return -EOPNOTSUPP;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+ if (params->drop_unencrypted >= 0)
+ sdata->drop_unencrypted = params->drop_unencrypted;
+ if (params->userspace_mlme == 0)
+ sdata->flags &= ~IEEE80211_SDATA_USERSPACE_MLME;
+ else if (params->userspace_mlme >= 0)
+ sdata->flags |= IEEE80211_SDATA_USERSPACE_MLME;
+
+ return 0;
+}
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -1104,4 +1126,5 @@ struct cfg80211_ops mac80211_config_ops
.dump_mpath = ieee80211_dump_mpath,
#endif
.change_bss = ieee80211_change_bss,
+ .change_vif = ieee80211_change_vif,
};
Index: wireless-testing/include/linux/nl80211.h
===================================================================
--- wireless-testing.orig/include/linux/nl80211.h
+++ wireless-testing/include/linux/nl80211.h
@@ -91,6 +91,8 @@
* by %NL80211_ATTR_IFINDEX.
* @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
* %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_VIF: Set virtual interface attributes for vif identified by
+ * %NL80211_ATTR_IFINDEX.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -131,6 +133,8 @@ enum nl80211_commands {
NL80211_CMD_SET_BSS,
+ NL80211_CMD_SET_VIF,
+
/* add commands here */
/* used to define NL80211_CMD_MAX below */
@@ -143,6 +147,7 @@ enum nl80211_commands {
* here
*/
#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS
+#define NL80211_CMD_SET_VIF NL80211_CMD_SET_VIF
/**
* enum nl80211_attrs - nl80211 netlink attributes
@@ -207,6 +212,11 @@ enum nl80211_commands {
* @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled
* (u8, 0 or 1)
*
+ * @NL80211_ATTR_VIF_DROP_UNENCRYPTED: whether unencrypted frames will be
+ * dropped (u8, 0 or 1)
+ * @NL80211_ATTR_VIF_USERSPACE_MLME: whether userspace MLME is used
+ * (u8, 0 or 1)
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -254,6 +264,9 @@ enum nl80211_attrs {
NL80211_ATTR_BSS_SHORT_PREAMBLE,
NL80211_ATTR_BSS_SHORT_SLOT_TIME,
+ NL80211_ATTR_VIF_DROP_UNENCRYPTED,
+ NL80211_ATTR_VIF_USERSPACE_MLME,
+
NL80211_ATTR_KEY_DEFAULT_MGMT,
/* add attributes here, update the policy in nl80211.c */
Index: wireless-testing/net/wireless/nl80211.c
===================================================================
--- wireless-testing.orig/net/wireless/nl80211.c
+++ wireless-testing/net/wireless/nl80211.c
@@ -92,6 +92,9 @@ static struct nla_policy nl80211_policy[
[NL80211_ATTR_BSS_SHORT_PREAMBLE] = { .type = NLA_U8 },
[NL80211_ATTR_BSS_SHORT_SLOT_TIME] = { .type = NLA_U8 },
+ [NL80211_ATTR_VIF_DROP_UNENCRYPTED] = { .type = NLA_U8 },
+ [NL80211_ATTR_VIF_USERSPACE_MLME] = { .type = NLA_U8 },
+
[NL80211_ATTR_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
};
@@ -1588,6 +1591,44 @@ static int nl80211_set_bss(struct sk_buf
return err;
}
+static int nl80211_set_vif(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *drv;
+ int err;
+ struct net_device *dev;
+ struct vif_parameters params;
+
+ memset(¶ms, 0, sizeof(params));
+ /* default to not changing parameters */
+ params.drop_unencrypted = -1;
+ params.userspace_mlme = -1;
+
+ if (info->attrs[NL80211_ATTR_VIF_DROP_UNENCRYPTED])
+ params.userspace_mlme =
+ nla_get_u8(info->attrs[NL80211_ATTR_VIF_DROP_UNENCRYPTED]);
+ if (info->attrs[NL80211_ATTR_VIF_USERSPACE_MLME])
+ params.userspace_mlme =
+ nla_get_u8(info->attrs[NL80211_ATTR_VIF_USERSPACE_MLME]);
+
+ err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+ if (err)
+ return err;
+
+ if (!drv->ops->change_vif) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ rtnl_lock();
+ err = drv->ops->change_vif(&drv->wiphy, dev, ¶ms);
+ rtnl_unlock();
+
+ out:
+ cfg80211_put_dev(drv);
+ dev_put(dev);
+ return err;
+}
+
static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
@@ -1725,6 +1766,12 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NL80211_CMD_SET_VIF,
+ .doit = nl80211_set_vif,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};
/* multicast groups */
--
Jouni Malinen PGP id EFC895FA
On Fri, 2008-08-15 at 22:33 +0300, Jouni Malinen wrote:
> +/**
> + * struct vif_parameters - Virtual interface parameters
> + *
> + * Used to change virtual interface parameters.
> + *
> + * @drop_unencrypted: Whether to drop unencrypted frames
> + * (0 = no, 1 = yes, -1 = do not change)
> + * @userspace_mlme: Whether to use userspace MLME
> + * (0 = no, 1 = yes, -1 = do not change)
> + */
> +struct vif_parameters {
> + int drop_unencrypted;
> + int userspace_mlme;
> +};
> * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
> *
> * @change_bss: Modify parameters for a given BSS.
> + *
> + * @change_vif: Modify parameters for a given virtual interface.
That reminds me, we should probably include the "bridge packets" thing
in the BSS parameters (or here?)
johannes
On Fri, Aug 15, 2008 at 09:43:44PM +0200, Johannes Berg wrote:
> On Fri, 2008-08-15 at 22:33 +0300, Jouni Malinen wrote:
> > * @change_bss: Modify parameters for a given BSS.
> > + *
> > + * @change_vif: Modify parameters for a given virtual interface.
>
> That reminds me, we should probably include the "bridge packets" thing
> in the BSS parameters (or here?)
Yes.. Since it is AP only feature, I would add it to change_bss. This
variable is currently per-radio, but it might be reasonable to move it
to sdata. Though, it may be needed for IEEE80211_IF_TYPE_VLAN, too, and
change_bss is now IEEE80211_IF_TYPE_AP-only.. change_vif allows any type
to go through, so maybe that would be easier after all (and then either
just ignore the value for other iface types or make the configuration
attempt fail if this particular attribute is changed for non-AP/VLAN
iftype).
--
Jouni Malinen PGP id EFC895FA
On Fri, Aug 15, 2008 at 12:33 PM, Jouni Malinen <[email protected]> wrote:
> @@ -1588,6 +1591,44 @@ static int nl80211_set_bss(struct sk_buf
> return err;
> }
>
> +static int nl80211_set_vif(struct sk_buff *skb, struct genl_info *info)
> +{
> + struct cfg80211_registered_device *drv;
> + int err;
> + struct net_device *dev;
> + struct vif_parameters params;
> +
> + memset(¶ms, 0, sizeof(params));
> + /* default to not changing parameters */
> + params.drop_unencrypted = -1;
> + params.userspace_mlme = -1;
> +
> + if (info->attrs[NL80211_ATTR_VIF_DROP_UNENCRYPTED])
> + params.userspace_mlme =
This should be params.drop_unencrypted instead right.
> + nla_get_u8(info->attrs[NL80211_ATTR_VIF_DROP_UNENCRYPTED]);
> + if (info->attrs[NL80211_ATTR_VIF_USERSPACE_MLME])
> + params.userspace_mlme =
> + nla_get_u8(info->attrs[NL80211_ATTR_VIF_USERSPACE_MLME]);