Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab737a4f authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

cfg80211: implement IWAP for WDS



This implements siocsiwap/giwap for WDS mode.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent bc92afd9
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1018,6 +1018,9 @@ struct cfg80211_ops {
				enum tx_power_setting type, int dbm);
	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);

	int	(*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
				u8 *addr);

	void	(*rfkill_poll)(struct wiphy *wiphy);

#ifdef CONFIG_NL80211_TESTMODE
@@ -1619,6 +1622,13 @@ int cfg80211_wext_giwpower(struct net_device *dev,
			   struct iw_request_info *info,
			   struct iw_param *wrq, char *extra);

int cfg80211_wds_wext_siwap(struct net_device *dev,
			    struct iw_request_info *info,
			    struct sockaddr *addr, char *extra);
int cfg80211_wds_wext_giwap(struct net_device *dev,
			    struct iw_request_info *info,
			    struct sockaddr *addr, char *extra);

/*
 * callbacks for asynchronous cfg80211 methods, notification
 * functions and BSS handling helpers
+11 −0
Original line number Diff line number Diff line
@@ -1369,6 +1369,16 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
	return 0;
}

static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
				  u8 *addr)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN);

	return 0;
}

static void ieee80211_rfkill_poll(struct wiphy *wiphy)
{
	struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -1454,6 +1464,7 @@ struct cfg80211_ops mac80211_config_ops = {
	.set_wiphy_params = ieee80211_set_wiphy_params,
	.set_tx_power = ieee80211_set_tx_power,
	.get_tx_power = ieee80211_get_tx_power,
	.set_wds_peer = ieee80211_set_wds_peer,
	.rfkill_poll = ieee80211_rfkill_poll,
	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
	.set_power_mgmt = ieee80211_set_power_mgmt,
+4 −22
Original line number Diff line number Diff line
@@ -140,23 +140,8 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
		return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);

	if (sdata->vif.type == NL80211_IFTYPE_WDS) {
		/*
		 * If it is necessary to update the WDS peer address
		 * while the interface is running, then we need to do
		 * more work here, namely if it is running we need to
		 * add a new and remove the old STA entry, this is
		 * normally handled by _open() and _stop().
		 */
		if (netif_running(dev))
			return -EBUSY;

		memcpy(&sdata->u.wds.remote_addr, (u8 *) &ap_addr->sa_data,
		       ETH_ALEN);

		return 0;
	}

	if (sdata->vif.type == NL80211_IFTYPE_WDS)
		return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra);
	return -EOPNOTSUPP;
}

@@ -173,11 +158,8 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
	if (sdata->vif.type == NL80211_IFTYPE_STATION)
		return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);

	if (sdata->vif.type == NL80211_IFTYPE_WDS) {
		ap_addr->sa_family = ARPHRD_ETHER;
		memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
		return 0;
	}
	if (sdata->vif.type == NL80211_IFTYPE_WDS)
		return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra);

	return -EOPNOTSUPP;
}
+46 −0
Original line number Diff line number Diff line
@@ -1047,3 +1047,49 @@ int cfg80211_wext_giwpower(struct net_device *dev,
	return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower);

int cfg80211_wds_wext_siwap(struct net_device *dev,
			    struct iw_request_info *info,
			    struct sockaddr *addr, char *extra)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;
	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
	int err;

	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
		return -EINVAL;

	if (addr->sa_family != ARPHRD_ETHER)
		return -EINVAL;

	if (netif_running(dev))
		return -EBUSY;

	if (!rdev->ops->set_wds_peer)
		return -EOPNOTSUPP;

	err = rdev->ops->set_wds_peer(wdev->wiphy, dev, (u8 *) &addr->sa_data);
	if (err)
		return err;

	memcpy(&wdev->wext.bssid, (u8 *) &addr->sa_data, ETH_ALEN);

	return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wds_wext_siwap);

int cfg80211_wds_wext_giwap(struct net_device *dev,
			    struct iw_request_info *info,
			    struct sockaddr *addr, char *extra)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;

	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_WDS))
		return -EINVAL;

	addr->sa_family = ARPHRD_ETHER;
	memcpy(&addr->sa_data, wdev->wext.bssid, ETH_ALEN);

	return 0;
}
EXPORT_SYMBOL_GPL(cfg80211_wds_wext_giwap);