/* * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "ieee80211_i.h" #include "led.h" #include "rate.h" #include "wpa.h" #include "aes_ccm.h" 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); struct ieee80211_local *local = sdata->local; struct ieee80211_channel *chan; if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); else if (sdata->vif.type == NL80211_IFTYPE_STATION) return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ if (freq->e == 0) { if (freq->m < 0) return -EINVAL; else chan = ieee80211_get_channel(local->hw.wiphy, ieee80211_channel_to_frequency(freq->m)); } else { int i, div = 1000000; for (i = 0; i < freq->e; i++) div /= 10; if (div <= 0) return -EINVAL; chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div); } if (!chan) return -EINVAL; if (chan->flags & IEEE80211_CHAN_DISABLED) return -EINVAL; /* * no change except maybe auto -> fixed, ignore the HT * setting so you can fix a channel you're on already */ if (local->oper_channel == chan) return 0; local->oper_channel = chan; local->oper_channel_type = NL80211_CHAN_NO_HT; ieee80211_hw_config(local, 0); return 0; } static int ieee80211_ioctl_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) { struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); else if (sdata->vif.type == NL80211_IFTYPE_STATION) return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); freq->m = local->oper_channel->center_freq; freq->e = 6; return 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 = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); else if (sdata->vif.type == NL80211_IFTYPE_STATION) return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); return -EOPNOTSUPP; } static int ieee80211_ioctl_giwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid) { struct ieee80211_sub_if_data *sdata; sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); else if (sdata->vif.type == NL80211_IFTYPE_STATION) return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); return -EOPNOTSUPP; } 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 = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); if (sdata->vif.type == NL80211_IFTYPE_STATION) return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); if (sdata->vif.type == NL80211_IFTYPE_WDS) return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra); return -EOPNOTSUPP; } 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 = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == NL80211_IFTYPE_ADHOC) return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); if (sdata->vif.type == NL80211_IFTYPE_STATION) return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); if (sdata->vif.type == NL80211_IFTYPE_WDS) return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra); return -EOPNOTSUPP; } /* Structures to export the Wireless Handlers */ static const iw_handler ieee80211_handler[] = { (iw_handler) NULL, /* SIOCSIWCOMMIT */ (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */ (iw_handler) NULL, /* SIOCSIWNWID */ (iw_handler) NULL, /* SIOCGIWNWID */ (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */ (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */ (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */ (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */ (iw_handler) NULL, /* SIOCSIWSENS */ (iw_handler) NULL, /* SIOCGIWSENS */ (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */ (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ (iw_handler) NULL, /* SIOCSIWSPY */ (iw_handler) NULL, /* SIOCGIWSPY */ (iw_handler) NULL, /* SIOCSIWTHRSPY */ (iw_handler) NULL, /* SIOCGIWTHRSPY */ (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */ (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */ (iw_handler) NULL, /* SIOCSIWNICKN */ (iw_handler) NULL, /* SIOCGIWNICKN */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) cfg80211_wext_siwrate, /* SIOCSIWRATE */ (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */ (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */ (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ (iw_handler) NULL, /* SIOCGIWGENIE */ (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ (iw_handler) NULL, /* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ (iw_handler) NULL, /* -- hole -- */ }; const struct iw_handler_def ieee80211_iw_handler_def = { .num_standard = ARRAY_SIZE(ieee80211_handler), .standard = (iw_handler *) ieee80211_handler, .get_wireless_stats = cfg80211_wireless_stats, };