示例#1
0
static int ieee80211_ioctl_giwessid(struct net_device *dev,
                                    struct iw_request_info *info,
                                    struct iw_point *data, char *ssid)
{
    size_t len;

    struct ieee80211_sub_if_data *sdata;
    sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
            sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
        int res = ieee80211_sta_get_ssid(dev, ssid, &len);
        if (res == 0) {
            data->length = len;
            data->flags = 1;
        } else
            data->flags = 0;
        return res;
    }

    if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
        len = sdata->u.ap.ssid_len;
        if (len > IW_ESSID_MAX_SIZE)
            len = IW_ESSID_MAX_SIZE;
        memcpy(ssid, sdata->u.ap.ssid, len);
        data->length = len;
        data->flags = 1;
        return 0;
    }
    return -EOPNOTSUPP;
}
示例#2
0
static int ieee80211_ioctl_siwscan(struct net_device *dev,
				   struct iw_request_info *info,
				   union iwreq_data *wrqu, char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct iw_scan_req *req = NULL;
	u8 *ssid = NULL;
	size_t ssid_len = 0;

	if (!netif_running(dev))
		return -ENETDOWN;

	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
	    sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
		return -EOPNOTSUPP;

	/* if SSID was specified explicitly then use that */
	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
		req = (struct iw_scan_req *)extra;
		ssid = req->essid;
		ssid_len = req->essid_len;
	}

	return ieee80211_request_scan(sdata, ssid, ssid_len);
}
示例#3
0
static int ieee80211_ioctl_siwmode(struct net_device *dev,
                                   struct iw_request_info *info,
                                   __u32 *mode, char *extra)
{
    struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    int type;

    if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
        return -EOPNOTSUPP;

    switch (*mode) {
    case IW_MODE_INFRA:
        type = IEEE80211_IF_TYPE_STA;
        break;
    case IW_MODE_ADHOC:
        type = IEEE80211_IF_TYPE_IBSS;
        break;
    case IW_MODE_MONITOR:
        type = IEEE80211_IF_TYPE_MNTR;
        break;
    default:
        return -EINVAL;
    }

    if (type == sdata->vif.type)
        return 0;
    if (netif_running(dev))
        return -EBUSY;

    ieee80211_if_reinit(dev);
    ieee80211_if_set_type(dev, type);

    return 0;
}
static int netdev_notify(struct notifier_block *nb,
			 unsigned long state,
			 void *ndev)
{
	struct net_device *dev = ndev;
	struct dentry *dir;
	struct ieee80211_sub_if_data *sdata;
	char buf[10+IFNAMSIZ];

	if (state != NETDEV_CHANGENAME)
		return 0;

	if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
		return 0;

	if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
		return 0;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	dir = sdata->debugfsdir;

	if (!dir)
		return 0;

	sprintf(buf, "netdev:%s", dev->name);
	if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
		printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs "
		       "dir to %s\n", buf);

	return 0;
}
示例#5
0
static int ieee80211_ioctl_siwessid(struct net_device *dev,
				    struct iw_request_info *info,
				    struct iw_point *data, char *ssid)
{
	struct ieee80211_sub_if_data *sdata;
	size_t len = data->length;

	/* iwconfig uses nul termination in SSID.. */
	if (len > 0 && ssid[len - 1] == '\0')
		len--;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
		int ret;
		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
			if (len > IEEE80211_MAX_SSID_LEN)
				return -EINVAL;
			memcpy(sdata->u.sta.ssid, ssid, len);
			sdata->u.sta.ssid_len = len;
			return 0;
		}
		if (data->flags)
			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
		else
			sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL;
		ret = ieee80211_sta_set_ssid(sdata, ssid, len);
		if (ret)
			return ret;
		ieee80211_sta_req_auth(sdata, &sdata->u.sta);
		return 0;
	}

	return -EOPNOTSUPP;
}
示例#6
0
static int ieee80211_ioctl_giwap(struct net_device *dev,
				 struct iw_request_info *info,
				 struct sockaddr *ap_addr, char *extra)
{
	struct ieee80211_sub_if_data *sdata;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
		if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED ||
		    sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) {
			ap_addr->sa_family = ARPHRD_ETHER;
			memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
			return 0;
		} else {
			memset(&ap_addr->sa_data, 0, ETH_ALEN);
			return 0;
		}
	} else 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;
	}

	return -EOPNOTSUPP;
}
示例#7
0
static int ieee80211_ioctl_giwrate(struct net_device *dev,
				  struct iw_request_info *info,
				  struct iw_param *rate, char *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct sta_info *sta;
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_supported_band *sband;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	if (sdata->vif.type != NL80211_IFTYPE_STATION)
		return -EOPNOTSUPP;

	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

	rcu_read_lock();

	sta = sta_info_get(local, sdata->u.sta.bssid);

	if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
		rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate;
	else
		rate->value = 0;

	rcu_read_unlock();

	if (!sta)
		return -ENODEV;

	rate->value *= 100000;

	return 0;
}
示例#8
0
文件: mesh_hwmp.c 项目: DINKIN/tuo
void mesh_path_timer(unsigned long data)
{
	struct ieee80211_sub_if_data *sdata;
	struct mesh_path *mpath;

	rcu_read_lock();
	mpath = (struct mesh_path *) data;
	mpath = rcu_dereference(mpath);
	if (!mpath)
		goto endmpathtimer;
	spin_lock_bh(&mpath->state_lock);
	sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev);
	if (mpath->flags & MESH_PATH_RESOLVED ||
			(!(mpath->flags & MESH_PATH_RESOLVING)))
		mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
	else if (mpath->discovery_retries < max_preq_retries(sdata)) {
		++mpath->discovery_retries;
		mpath->discovery_timeout *= 2;
		mesh_queue_preq(mpath, 0);
	} else {
		mpath->flags = 0;
		mpath->exp_time = jiffies;
		mesh_path_flush_pending(mpath);
	}

	spin_unlock_bh(&mpath->state_lock);
endmpathtimer:
	rcu_read_unlock();
}
示例#9
0
static int ieee80211_ioctl_giwmode(struct net_device *dev,
                                   struct iw_request_info *info,
                                   __u32 *mode, char *extra)
{
    struct ieee80211_sub_if_data *sdata;

    sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    switch (sdata->vif.type) {
    case IEEE80211_IF_TYPE_AP:
        *mode = IW_MODE_MASTER;
        break;
    case IEEE80211_IF_TYPE_STA:
        *mode = IW_MODE_INFRA;
        break;
    case IEEE80211_IF_TYPE_IBSS:
        *mode = IW_MODE_ADHOC;
        break;
    case IEEE80211_IF_TYPE_MNTR:
        *mode = IW_MODE_MONITOR;
        break;
    case IEEE80211_IF_TYPE_WDS:
        *mode = IW_MODE_REPEAT;
        break;
    case IEEE80211_IF_TYPE_VLAN:
        *mode = IW_MODE_SECOND;		/* FIXME */
        break;
    default:
        *mode = IW_MODE_AUTO;
        break;
    }
    return 0;
}
示例#10
0
static int ieee80211_ioctl_giwrate(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_param *rate, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    struct sta_info *sta;
    struct ieee80211_sub_if_data *sdata;
    struct ieee80211_supported_band *sband;

    sdata = IEEE80211_DEV_TO_SUB_IF(dev);

    if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
        sta = sta_info_get(local, sdata->u.sta.bssid);
    else
        return -EOPNOTSUPP;
    if (!sta)
        return -ENODEV;

    sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

    if (sta->txrate_idx < sband->n_bitrates)
        rate->value = sband->bitrates[sta->txrate_idx].bitrate;
    else
        rate->value = 0;
    rate->value *= 100000;

    return 0;
}
示例#11
0
/* Get wireless statistics.  Called by /proc/net/wireless and by SIOCGIWSTATS */
static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct iw_statistics *wstats = &local->wstats;
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct sta_info *sta = NULL;

	rcu_read_lock();

	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC)
		sta = sta_info_get(local, sdata->u.sta.bssid);
	if (!sta) {
		wstats->discard.fragment = 0;
		wstats->discard.misc = 0;
		wstats->qual.qual = 0;
		wstats->qual.level = 0;
		wstats->qual.noise = 0;
		wstats->qual.updated = IW_QUAL_ALL_INVALID;
	} else {
		wstats->qual.level = sta->last_signal;
		wstats->qual.qual = sta->last_qual;
		wstats->qual.noise = sta->last_noise;
		wstats->qual.updated = local->wstats_flags;
	}

	rcu_read_unlock();

	return wstats;
}
示例#12
0
static int ieee80211_ioctl_siwfreq(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_freq *freq, char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	if (sdata->vif.type == NL80211_IFTYPE_STATION)
		sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL;

	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
	if (freq->e == 0) {
		if (freq->m < 0) {
			if (sdata->vif.type == NL80211_IFTYPE_STATION)
				sdata->u.sta.flags |=
					IEEE80211_STA_AUTO_CHANNEL_SEL;
			return 0;
		} else
			return ieee80211_set_freq(sdata,
				ieee80211_channel_to_frequency(freq->m));
	} else {
		int i, div = 1000000;
		for (i = 0; i < freq->e; i++)
			div /= 10;
		if (div > 0)
			return ieee80211_set_freq(sdata, freq->m / div);
		else
			return -EINVAL;
	}
}
示例#13
0
static void rate_control_rate_dec(struct ieee80211_local *local,
				  struct sta_info *sta)
{
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_hw_mode *mode;
	int i = sta->txrate;

	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
		/* forced unicast rate - do not change STA rate */
		return;
	}

	mode = local->oper_hw_mode;
	if (i > mode->num_rates)
		i = mode->num_rates;

	while (i > 0) {
		i--;
		if (sta->supp_rates & BIT(i) &&
		    mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
			sta->txrate = i;
			break;
		}
	}
}
示例#14
0
/* Adjust the rate while ensuring that we won't switch to a lower rate if it
 * exhibited a worse failed frames behaviour and we'll choose the highest rate
 * whose failed frames behaviour is not worse than the one of the original rate
 * target. While at it, check that the new rate is valid. */
static void rate_control_pid_adjust_rate(struct ieee80211_local *local,
					 struct sta_info *sta, int adj,
					 struct rc_pid_rateinfo *rinfo)
{
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_hw_mode *mode;
	int cur_sorted, new_sorted, probe, tmp, n_bitrates;
	int cur = sta->txrate;

	sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);

	mode = local->oper_hw_mode;
	n_bitrates = mode->num_rates;

	/* Map passed arguments to sorted values. */
	cur_sorted = rinfo[cur].rev_index;
	new_sorted = cur_sorted + adj;

	/* Check limits. */
	if (new_sorted < 0)
		new_sorted = rinfo[0].rev_index;
	else if (new_sorted >= n_bitrates)
		new_sorted = rinfo[n_bitrates - 1].rev_index;

	tmp = new_sorted;

	if (adj < 0) {
		/* Ensure that the rate decrease isn't disadvantageous. */
		for (probe = cur_sorted; probe >= new_sorted; probe--)
			if (rinfo[probe].diff <= rinfo[cur_sorted].diff &&
			    rate_supported(sta, mode, rinfo[probe].index))
				tmp = probe;
	} else {
		/* Look for rate increase with zero (or below) cost. */
		for (probe = new_sorted + 1; probe < n_bitrates; probe++)
			if (rinfo[probe].diff <= rinfo[new_sorted].diff &&
			    rate_supported(sta, mode, rinfo[probe].index))
				tmp = probe;
	}

	/* Fit the rate found to the nearest supported rate. */
	do {
		if (rate_supported(sta, mode, rinfo[tmp].index)) {
			sta->txrate = rinfo[tmp].index;
			break;
		}
		if (adj < 0)
			tmp--;
		else
			tmp++;
	} while (tmp < n_bitrates && tmp >= 0);

#ifdef CONFIG_MAC80211_DEBUGFS
	rate_control_pid_event_rate_change(
		&((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events,
		cur, mode->rates[cur].rate);
#endif
}
示例#15
0
static int ieee80211_ioctl_siwpower(struct net_device *dev,
				    struct iw_request_info *info,
				    struct iw_param *wrq,
				    char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_conf *conf = &local->hw.conf;
	int ret = 0, timeout = 0;
	bool ps;

	if (sdata->vif.type != NL80211_IFTYPE_STATION)
		return -EINVAL;

	if (wrq->disabled) {
		ps = false;
		timeout = 0;
		goto set;
	}

	switch (wrq->flags & IW_POWER_MODE) {
	case IW_POWER_ON:       /* If not specified */
	case IW_POWER_MODE:     /* If set all mask */
	case IW_POWER_ALL_R:    /* If explicitely state all */
		ps = true;
		break;
	default:                /* Otherwise we ignore */
		break;
	}

	if (wrq->flags & IW_POWER_TIMEOUT)
		timeout = wrq->value / 1000;

set:
	if (ps == local->powersave && timeout == local->dynamic_ps_timeout)
		return ret;

	local->powersave = ps;
	local->dynamic_ps_timeout = timeout;

	if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) {
		if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) &&
		    local->dynamic_ps_timeout > 0)
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(local->dynamic_ps_timeout));
		else {
			if (local->powersave)
				conf->flags |= IEEE80211_CONF_PS;
			else
				conf->flags &= ~IEEE80211_CONF_PS;
		}
		ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}

	return ret;
}
示例#16
0
文件: mesh_hwmp.c 项目: DINKIN/tuo
/**
 * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame
 *
 * @next_hop: output argument for next hop address
 * @skb: frame to be sent
 * @dev: network device the frame will be sent through
 *
 * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is
 * found, the function will start a path discovery and queue the frame so it is
 * sent when the path is resolved. This means the caller must not free the skb
 * in this case.
 */
int mesh_nexthop_lookup(u8 *next_hop, struct sk_buff *skb,
		struct net_device *dev)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct sk_buff *skb_to_free = NULL;
	struct mesh_path *mpath;
	int err = 0;

	rcu_read_lock();
	mpath = mesh_path_lookup(skb->data, dev);

	if (!mpath) {
		mesh_path_add(skb->data, dev);
		mpath = mesh_path_lookup(skb->data, dev);
		if (!mpath) {
			dev_kfree_skb(skb);
			sdata->u.sta.mshstats.dropped_frames_no_route++;
			err = -ENOSPC;
			goto endlookup;
		}
	}

	if (mpath->flags & MESH_PATH_ACTIVE) {
		if (time_after(jiffies, mpath->exp_time -
			msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time))
				&& skb->pkt_type != PACKET_OTHERHOST
				&& !(mpath->flags & MESH_PATH_RESOLVING)
				&& !(mpath->flags & MESH_PATH_FIXED)) {
			mesh_queue_preq(mpath,
					PREQ_Q_F_START | PREQ_Q_F_REFRESH);
		}
		memcpy(next_hop, mpath->next_hop->addr,
				ETH_ALEN);
	} else {
		if (!(mpath->flags & MESH_PATH_RESOLVING)) {
			/* Start discovery only if it is not running yet */
			mesh_queue_preq(mpath, PREQ_Q_F_START);
		}

		if (skb_queue_len(&mpath->frame_queue) >=
				MESH_FRAME_QUEUE_LEN) {
			skb_to_free = mpath->frame_queue.next;
			skb_unlink(skb_to_free, &mpath->frame_queue);
		}

		skb_queue_tail(&mpath->frame_queue, skb);
		if (skb_to_free)
			mesh_path_discard_frame(skb_to_free, dev);
		err = -ENOENT;
	}

endlookup:
	rcu_read_unlock();
	return err;
}
示例#17
0
static int ieee80211_ioctl_giwencode(struct net_device *dev,
				     struct iw_request_info *info,
				     struct iw_point *erq, char *key)
{
	struct ieee80211_sub_if_data *sdata;
	int idx, i;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	idx = erq->flags & IW_ENCODE_INDEX;
	if (idx < 1 || idx > 4) {
		idx = -1;
		if (!sdata->default_key)
			idx = 0;
		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
			if (sdata->default_key == sdata->keys[i]) {
				idx = i;
				break;
			}
		}
		if (idx < 0)
			return -EINVAL;
	} else
		idx--;

	erq->flags = idx + 1;

	if (!sdata->keys[idx]) {
		erq->length = 0;
		erq->flags |= IW_ENCODE_DISABLED;
		return 0;
	}

	memcpy(key, sdata->keys[idx]->conf.key,
	       min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
	erq->length = sdata->keys[idx]->conf.keylen;
	erq->flags |= IW_ENCODE_ENABLED;

	if (sdata->vif.type == NL80211_IFTYPE_STATION) {
		struct ieee80211_if_sta *ifsta = &sdata->u.sta;
		switch (ifsta->auth_alg) {
		case WLAN_AUTH_OPEN:
		case WLAN_AUTH_LEAP:
			erq->flags |= IW_ENCODE_OPEN;
			break;
		case WLAN_AUTH_SHARED_KEY:
			erq->flags |= IW_ENCODE_RESTRICTED;
			break;
		}
	}

	return 0;
}
示例#18
0
static struct ieee80211_rate *
rate_control_simple_get_rate(void *priv, struct net_device *dev,
			     struct sk_buff *skb,
			     struct rate_control_extra *extra)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_hw_mode *mode = extra->mode;
	struct sta_info *sta;
	int rateidx, nonerp_idx;
	u16 fc;

	memset(extra, 0, sizeof(*extra));

	fc = le16_to_cpu(hdr->frame_control);
	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
	    (hdr->addr1[0] & 0x01)) {
		/* Send management frames and broadcast/multicast data using
		 * lowest rate. */
		/* TODO: this could probably be improved.. */
		return rate_control_lowest_rate(local, mode);
	}

	sta = sta_info_get(local, hdr->addr1);

	if (!sta)
		return rate_control_lowest_rate(local, mode);

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
		sta->txrate = sdata->bss->force_unicast_rateidx;

	rateidx = sta->txrate;

	if (rateidx >= mode->num_rates)
		rateidx = mode->num_rates - 1;

	sta->last_txrate = rateidx;
	nonerp_idx = rateidx;
	while (nonerp_idx > 0 &&
	       ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
		!(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
		!(sta->supp_rates & BIT(nonerp_idx))))
		nonerp_idx--;
	extra->nonerp = &mode->rates[nonerp_idx];

	sta_info_put(sta);

	return &mode->rates[rateidx];
}
示例#19
0
static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
					struct iw_request_info *info,
					struct iw_point *erq, char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
	int uninitialized_var(alg), idx, i, remove = 0;

	switch (ext->alg) {
	case IW_ENCODE_ALG_NONE:
		remove = 1;
		break;
	case IW_ENCODE_ALG_WEP:
		alg = ALG_WEP;
		break;
	case IW_ENCODE_ALG_TKIP:
		alg = ALG_TKIP;
		break;
	case IW_ENCODE_ALG_CCMP:
		alg = ALG_CCMP;
		break;
	default:
		return -EOPNOTSUPP;
	}

	if (erq->flags & IW_ENCODE_DISABLED)
		remove = 1;

	idx = erq->flags & IW_ENCODE_INDEX;
	if (idx < 1 || idx > 4) {
		idx = -1;
		if (!sdata->default_key)
			idx = 0;
		else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
			if (sdata->default_key == sdata->keys[i]) {
				idx = i;
				break;
			}
		}
		if (idx < 0)
			return -EINVAL;
	} else
		idx--;

	return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg,
					remove,
					ext->ext_flags &
					IW_ENCODE_EXT_SET_TX_KEY,
					ext->key, ext->key_len);
}
示例#20
0
static ssize_t ieee80211_if_show(struct class_device *cd, char *buf,
			ssize_t (*format)(const struct ieee80211_sub_if_data *,
					  char *))
{
	struct net_device *dev = to_net_dev(cd);
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	ssize_t ret = -EINVAL;

	read_lock(&dev_base_lock);
	if (dev->reg_state == NETREG_REGISTERED) {
		ret = (*format)(sdata, buf);
	}
	read_unlock(&dev_base_lock);
	return ret;
}
示例#21
0
static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
				      struct ieee80211_supported_band *sband,
				      struct sk_buff *skb,
				      struct rate_selection *sel)
{
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_sub_if_data *sdata;
	struct sta_info *sta;
	int rateidx;
	u16 fc;

	rcu_read_lock();

	sta = sta_info_get(local, hdr->addr1);

	/* Send management frames and broadcast/multicast data using lowest
	 * rate. */
	fc = le16_to_cpu(hdr->frame_control);
	if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
	    is_multicast_ether_addr(hdr->addr1) || !sta) {
		sel->rate = rate_lowest(local, sband, sta);
		rcu_read_unlock();
		return;
	}

	/* If a forced rate is in effect, select it. */
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
		sta->txrate_idx = sdata->bss->force_unicast_rateidx;

	rateidx = sta->txrate_idx;

	if (rateidx >= sband->n_bitrates)
		rateidx = sband->n_bitrates - 1;

	sta->last_txrate_idx = rateidx;

	rcu_read_unlock();

	sel->rate = &sband->bitrates[rateidx];

#ifdef CONFIG_MAC80211_DEBUGFS
	rate_control_pid_event_tx_rate(
		&((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events,
		rateidx, sband->bitrates[rateidx].bitrate);
#endif
}
示例#22
0
static int ieee80211_ioctl_siwap(struct net_device *dev,
				 struct iw_request_info *info,
				 struct sockaddr *ap_addr, char *extra)
{
	struct ieee80211_sub_if_data *sdata;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
		int ret;
		if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) {
			memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data,
			       ETH_ALEN);
			return 0;
		}
		if (is_zero_ether_addr((u8 *) &ap_addr->sa_data))
			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL |
				IEEE80211_STA_AUTO_CHANNEL_SEL;
		else if (is_broadcast_ether_addr((u8 *) &ap_addr->sa_data))
			sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL;
		else
			sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
		ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
		if (ret)
			return ret;
		ieee80211_sta_req_auth(sdata, &sdata->u.sta);
		return 0;
	} else 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;
	}

	return -EOPNOTSUPP;
}
示例#23
0
static int ieee80211_ioctl_siwauth(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_param *data, char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	int ret = 0;

	switch (data->flags & IW_AUTH_INDEX) {
	case IW_AUTH_WPA_VERSION:
	case IW_AUTH_CIPHER_PAIRWISE:
	case IW_AUTH_CIPHER_GROUP:
	case IW_AUTH_WPA_ENABLED:
	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
	case IW_AUTH_KEY_MGMT:
		break;
	case IW_AUTH_DROP_UNENCRYPTED:
		sdata->drop_unencrypted = !!data->value;
		break;
	case IW_AUTH_PRIVACY_INVOKED:
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
			ret = -EINVAL;
		else {
			sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
			/*
			 * Privacy invoked by wpa_supplicant, store the
			 * value and allow associating to a protected
			 * network without having a key up front.
			 */
			if (data->value)
				sdata->u.sta.flags |=
					IEEE80211_STA_PRIVACY_INVOKED;
		}
		break;
	case IW_AUTH_80211_AUTH_ALG:
		if (sdata->vif.type == NL80211_IFTYPE_STATION ||
		    sdata->vif.type == NL80211_IFTYPE_ADHOC)
			sdata->u.sta.auth_algs = data->value;
		else
			ret = -EOPNOTSUPP;
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
	}
	return ret;
}
示例#24
0
文件: mesh_hwmp.c 项目: DINKIN/tuo
/**
 * mesh_queue_preq - queue a PREQ to a given destination
 *
 * @mpath: mesh path to discover
 * @flags: special attributes of the PREQ to be sent
 *
 * Locking: the function must be called from within a rcu read lock block.
 *
 */
static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
{
	struct ieee80211_sub_if_data *sdata =
		IEEE80211_DEV_TO_SUB_IF(mpath->dev);
	struct ieee80211_if_sta *ifsta = &sdata->u.sta;
	struct mesh_preq_queue *preq_node;

	preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
	if (!preq_node) {
		printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n");
		return;
	}

	spin_lock(&ifsta->mesh_preq_queue_lock);
	if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
		spin_unlock(&ifsta->mesh_preq_queue_lock);
		kfree(preq_node);
		if (printk_ratelimit())
			printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n");
		return;
	}

	memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
	preq_node->flags = flags;

	list_add_tail(&preq_node->list, &ifsta->preq_queue.list);
	++ifsta->preq_queue_len;
	spin_unlock(&ifsta->mesh_preq_queue_lock);

	if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata)))
		queue_work(sdata->local->hw.workqueue, &ifsta->work);

	else if (time_before(jiffies, ifsta->last_preq)) {
		/* avoid long wait if did not send preqs for a long time
		 * and jiffies wrapped around
		 */
		ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
		queue_work(sdata->local->hw.workqueue, &ifsta->work);
	} else
		mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq +
						min_preq_int_jiff(sdata));
}
示例#25
0
static int ieee80211_ioctl_giwessid(struct net_device *dev,
				    struct iw_request_info *info,
				    struct iw_point *data, char *ssid)
{
	size_t len;

	struct ieee80211_sub_if_data *sdata;
	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC) {
		int res = ieee80211_sta_get_ssid(sdata, ssid, &len);
		if (res == 0) {
			data->length = len;
			data->flags = 1;
		} else
			data->flags = 0;
		return res;
	}

	return -EOPNOTSUPP;
}
示例#26
0
static int ieee80211_ioctl_giwauth(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_param *data, char *extra)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	int ret = 0;

	switch (data->flags & IW_AUTH_INDEX) {
	case IW_AUTH_80211_AUTH_ALG:
		if (sdata->vif.type == NL80211_IFTYPE_STATION ||
		    sdata->vif.type == NL80211_IFTYPE_ADHOC)
			data->value = sdata->u.sta.auth_algs;
		else
			ret = -EOPNOTSUPP;
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
	}
	return ret;
}
示例#27
0
static int ieee80211_ioctl_giwscan(struct net_device *dev,
				   struct iw_request_info *info,
				   struct iw_point *data, char *extra)
{
	int res;
	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
	struct ieee80211_sub_if_data *sdata;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	if (local->sw_scanning || local->hw_scanning)
		return -EAGAIN;

	res = ieee80211_scan_results(local, info, extra, data->length);
	if (res >= 0) {
		data->length = res;
		return 0;
	}
	data->length = 0;
	return res;
}
示例#28
0
static int ieee80211_ioctl_giwencode(struct net_device *dev,
                                     struct iw_request_info *info,
                                     struct iw_point *erq, char *key)
{
    struct ieee80211_sub_if_data *sdata;
    int idx, i;

    sdata = IEEE80211_DEV_TO_SUB_IF(dev);

    idx = erq->flags & IW_ENCODE_INDEX;
    if (idx < 1 || idx > 4) {
        idx = -1;
        if (!sdata->default_key)
            idx = 0;
        else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
                if (sdata->default_key == sdata->keys[i]) {
                    idx = i;
                    break;
                }
            }
        if (idx < 0)
            return -EINVAL;
    } else
        idx--;

    erq->flags = idx + 1;

    if (!sdata->keys[idx]) {
        erq->length = 0;
        erq->flags |= IW_ENCODE_DISABLED;
        return 0;
    }

    memcpy(key, sdata->keys[idx]->conf.key,
           min_t(int, erq->length, sdata->keys[idx]->conf.keylen));
    erq->length = sdata->keys[idx]->conf.keylen;
    erq->flags |= IW_ENCODE_ENABLED;

    return 0;
}
示例#29
0
static int ieee80211_ioctl_siwencode(struct net_device *dev,
				     struct iw_request_info *info,
				     struct iw_point *erq, char *keybuf)
{
	struct ieee80211_sub_if_data *sdata;
	int idx, i, alg = ALG_WEP;
	u8 bcaddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
	int remove = 0;

	sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	idx = erq->flags & IW_ENCODE_INDEX;
	if (idx == 0) {
		if (sdata->default_key)
			for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
				if (sdata->default_key == sdata->keys[i]) {
					idx = i;
					break;
				}
			}
	} else if (idx < 1 || idx > 4)
		return -EINVAL;
	else
		idx--;

	if (erq->flags & IW_ENCODE_DISABLED)
		remove = 1;
	else if (erq->length == 0) {
		/* No key data - just set the default TX key index */
		ieee80211_set_default_key(sdata, idx);
		return 0;
	}

	return ieee80211_set_encryption(
		sdata, bcaddr,
		idx, alg, remove,
		!sdata->default_key,
		keybuf, erq->length);
}
示例#30
0
static int ieee80211_ioctl_siwrate(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_param *rate, char *extra)
{
    struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    int i, err = -EINVAL;
    u32 target_rate = rate->value / 100000;
    struct ieee80211_sub_if_data *sdata;
    struct ieee80211_supported_band *sband;

    sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    if (!sdata->bss)
        return -ENODEV;

    sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

    /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
     * target_rate = X, rate->fixed = 1 means only rate X
     * target_rate = X, rate->fixed = 0 means all rates <= X */
    sdata->bss->max_ratectrl_rateidx = -1;
    sdata->bss->force_unicast_rateidx = -1;
    if (rate->value < 0)
        return 0;

    for (i=0; i< sband->n_bitrates; i++) {
        struct ieee80211_rate *brate = &sband->bitrates[i];
        int this_rate = brate->bitrate;

        if (target_rate == this_rate) {
            sdata->bss->max_ratectrl_rateidx = i;
            if (rate->fixed)
                sdata->bss->force_unicast_rateidx = i;
            err = 0;
            break;
        }
    }
    return err;
}