diff options
Diffstat (limited to 'package/d80211/src/ieee80211_sysfs_sta.c')
-rw-r--r-- | package/d80211/src/ieee80211_sysfs_sta.c | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/package/d80211/src/ieee80211_sysfs_sta.c b/package/d80211/src/ieee80211_sysfs_sta.c new file mode 100644 index 0000000..738daf5 --- /dev/null +++ b/package/d80211/src/ieee80211_sysfs_sta.c @@ -0,0 +1,437 @@ +/* + * Copyright 2003-2005, Devicescape Software, Inc. + * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> + * + * 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 <linux/kobject.h> +#include <linux/sysfs.h> +#include "ieee80211_i.h" +#include "ieee80211_key.h" +#include "sta_info.h" + +static ssize_t sta_sysfs_show(struct kobject *, struct attribute *, char *); +static ssize_t key_sysfs_show(struct kobject *, struct attribute *, char *); + +static struct sysfs_ops sta_ktype_ops = { + .show = sta_sysfs_show, +}; + +static struct sysfs_ops key_ktype_ops = { + .show = key_sysfs_show, +}; + +/* sta attributtes */ + +#define STA_SHOW(name, field, format_string) \ +static ssize_t show_sta_##name(const struct sta_info *sta, char *buf) \ +{ \ + return sprintf(buf, format_string, sta->field); \ +} +#define STA_SHOW_D(name, field) STA_SHOW(name, field, "%d\n") +#define STA_SHOW_U(name, field) STA_SHOW(name, field, "%u\n") +#define STA_SHOW_LU(name, field) STA_SHOW(name, field, "%lu\n") +#define STA_SHOW_S(name, field) STA_SHOW(name, field, "%s\n") + +#define STA_SHOW_RATE(name, field) \ +static ssize_t show_sta_##name(const struct sta_info *sta, char *buf) \ +{ \ + struct ieee80211_local *local = sta->dev->ieee80211_ptr; \ + return sprintf(buf, "%d\n", \ + (sta->field >= 0 && \ + sta->field < local->num_curr_rates) ? \ + local->curr_rates[sta->field].rate : -1); \ +} + +#define __STA_ATTR(name) \ +static struct sta_attribute sta_attr_##name = \ + __ATTR(name, S_IRUGO, show_sta_##name, NULL) + +#define STA_ATTR(name, field, format) \ + STA_SHOW_##format(name, field) \ + __STA_ATTR(name) + +STA_ATTR(aid, aid, D); +STA_ATTR(key_idx_compression, key_idx_compression, D); +STA_ATTR(dev, dev->name, S); +STA_ATTR(vlan_id, vlan_id, D); +STA_ATTR(rx_packets, rx_packets, LU); +STA_ATTR(tx_packets, tx_packets, LU); +STA_ATTR(rx_bytes, rx_bytes, LU); +STA_ATTR(tx_bytes, tx_bytes, LU); +STA_ATTR(rx_duplicates, num_duplicates, LU); +STA_ATTR(rx_fragments, rx_fragments, LU); +STA_ATTR(rx_dropped, rx_dropped, LU); +STA_ATTR(tx_fragments, tx_fragments, LU); +STA_ATTR(tx_filtered, tx_filtered_count, LU); +STA_ATTR(txrate, txrate, RATE); +STA_ATTR(last_txrate, last_txrate, RATE); +STA_ATTR(tx_retry_failed, tx_retry_failed, LU); +STA_ATTR(tx_retry_count, tx_retry_count, LU); +STA_ATTR(last_rssi, last_rssi, D); +STA_ATTR(last_signal, last_signal, D); +STA_ATTR(last_noise, last_noise, D); +STA_ATTR(channel_use, channel_use, D); +STA_ATTR(wep_weak_iv_count, wep_weak_iv_count, D); + +static ssize_t show_sta_flags(const struct sta_info *sta, char *buf) +{ + return sprintf(buf, "%s%s%s%s%s%s%s%s%s", + sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "", + sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "", + sta->flags & WLAN_STA_PS ? "PS\n" : "", + sta->flags & WLAN_STA_TIM ? "TIM\n" : "", + sta->flags & WLAN_STA_PERM ? "PERM\n" : "", + sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "", + sta->flags & WLAN_STA_SHORT_PREAMBLE ? + "SHORT PREAMBLE\n" : "", + sta->flags & WLAN_STA_WME ? "WME\n" : "", + sta->flags & WLAN_STA_WDS ? "WDS\n" : ""); +} +__STA_ATTR(flags); + +static ssize_t show_sta_num_ps_buf_frames(const struct sta_info *sta, char *buf) +{ + return sprintf(buf, "%u\n", skb_queue_len(&sta->ps_tx_buf)); +} +__STA_ATTR(num_ps_buf_frames); + +static ssize_t show_sta_last_ack_rssi(const struct sta_info *sta, char *buf) +{ + return sprintf(buf, "%d %d %d\n", sta->last_ack_rssi[0], + sta->last_ack_rssi[1], sta->last_ack_rssi[2]); +} +__STA_ATTR(last_ack_rssi); + +static ssize_t show_sta_last_ack_ms(const struct sta_info *sta, char *buf) +{ + return sprintf(buf, "%d\n", sta->last_ack ? + jiffies_to_msecs(jiffies - sta->last_ack) : -1); +} +__STA_ATTR(last_ack_ms); + +static ssize_t show_sta_inactive_ms(const struct sta_info *sta, char *buf) +{ + return sprintf(buf, "%d\n", jiffies_to_msecs(jiffies - sta->last_rx)); +} +__STA_ATTR(inactive_ms); + +static ssize_t show_sta_last_seq_ctrl(const struct sta_info *sta, char *buf) +{ + int i; + char *p = buf; + + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) + p += sprintf(p, "%x ", sta->last_seq_ctrl[i]); + p += sprintf(p, "\n"); + return (p - buf); +} +__STA_ATTR(last_seq_ctrl); + +#ifdef CONFIG_D80211_DEBUG_COUNTERS +static ssize_t show_sta_wme_rx_queue(const struct sta_info *sta, char *buf) +{ + int i; + char *p = buf; + + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) + p += sprintf(p, "%u ", sta->wme_rx_queue[i]); + p += sprintf(p, "\n"); + return (p - buf); +} +__STA_ATTR(wme_rx_queue); + +static ssize_t show_sta_wme_tx_queue(const struct sta_info *sta, char *buf) +{ + int i; + char *p = buf; + + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) + p += sprintf(p, "%u ", sta->wme_tx_queue[i]); + p += sprintf(p, "\n"); + return (p - buf); +} +__STA_ATTR(wme_tx_queue); +#endif + +static struct attribute *sta_ktype_attrs[] = { + &sta_attr_aid.attr, + &sta_attr_key_idx_compression.attr, + &sta_attr_dev.attr, + &sta_attr_vlan_id.attr, + &sta_attr_rx_packets.attr, + &sta_attr_tx_packets.attr, + &sta_attr_rx_bytes.attr, + &sta_attr_tx_bytes.attr, + &sta_attr_rx_duplicates.attr, + &sta_attr_rx_fragments.attr, + &sta_attr_rx_dropped.attr, + &sta_attr_tx_fragments.attr, + &sta_attr_tx_filtered.attr, + &sta_attr_txrate.attr, + &sta_attr_last_txrate.attr, + &sta_attr_tx_retry_failed.attr, + &sta_attr_tx_retry_count.attr, + &sta_attr_last_rssi.attr, + &sta_attr_last_signal.attr, + &sta_attr_last_noise.attr, + &sta_attr_channel_use.attr, + &sta_attr_wep_weak_iv_count.attr, + + &sta_attr_flags.attr, + &sta_attr_num_ps_buf_frames.attr, + &sta_attr_last_ack_rssi.attr, + &sta_attr_last_ack_ms.attr, + &sta_attr_inactive_ms.attr, + &sta_attr_last_seq_ctrl.attr, +#ifdef CONFIG_D80211_DEBUG_COUNTERS + &sta_attr_wme_rx_queue.attr, + &sta_attr_wme_tx_queue.attr, +#endif + NULL +}; + +/* keys attributtes */ + +struct key_attribute { + struct attribute attr; + ssize_t (*show)(const struct ieee80211_key *, char *buf); + ssize_t (*store)(struct ieee80211_key *, const char *buf, + size_t count); +}; + +#define KEY_SHOW(name, field, format_string) \ +static ssize_t show_key_##name(const struct ieee80211_key *key, char *buf)\ +{ \ + return sprintf(buf, format_string, key->field); \ +} +#define KEY_SHOW_D(name, field) KEY_SHOW(name, field, "%d\n") + +#define __KEY_ATTR(name) \ +static struct key_attribute key_attr_##name = \ + __ATTR(name, S_IRUSR, show_key_##name, NULL) + +#define KEY_ATTR(name, field, format) \ + KEY_SHOW_##format(name, field) \ + __KEY_ATTR(name) + +KEY_ATTR(length, keylen, D); +KEY_ATTR(sw_encrypt, force_sw_encrypt, D); +KEY_ATTR(index, keyidx, D); +KEY_ATTR(hw_index, hw_key_idx, D); +KEY_ATTR(tx_rx_count, tx_rx_count, D); + +static ssize_t show_key_algorithm(const struct ieee80211_key *key, char *buf) +{ + char *alg; + + switch (key->alg) { + case ALG_WEP: + alg = "WEP"; + break; + case ALG_TKIP: + alg = "TKIP"; + break; + case ALG_CCMP: + alg = "CCMP"; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", alg); +} +__KEY_ATTR(algorithm); + +static ssize_t show_key_tx_spec(const struct ieee80211_key *key, char *buf) +{ + const u8 *tpn; + + switch (key->alg) { + case ALG_WEP: + return sprintf(buf, "\n"); + case ALG_TKIP: + return sprintf(buf, "%08x %04x\n", key->u.tkip.iv32, + key->u.tkip.iv16); + case ALG_CCMP: + tpn = key->u.ccmp.tx_pn; + return sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", tpn[0], + tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); + default: + return 0; + } +} +__KEY_ATTR(tx_spec); + +static ssize_t show_key_rx_spec(const struct ieee80211_key *key, char *buf) +{ + int i; + const u8 *rpn; + char *p = buf; + + switch (key->alg) { + case ALG_WEP: + return sprintf(buf, "\n"); + case ALG_TKIP: + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) + p += sprintf(p, "%08x %04x\n", + key->u.tkip.iv32_rx[i], + key->u.tkip.iv16_rx[i]); + return (p - buf); + case ALG_CCMP: + for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { + rpn = key->u.ccmp.rx_pn[i]; + p += sprintf(p, "%02x%02x%02x%02x%02x%02x\n", rpn[0], + rpn[1], rpn[2], rpn[3], rpn[4], rpn[5]); + } + return (p - buf); + default: + return 0; + } +} +__KEY_ATTR(rx_spec); + +static ssize_t show_key_replays(const struct ieee80211_key *key, char *buf) +{ + if (key->alg != ALG_CCMP) + return 0; + return sprintf(buf, "%u\n", key->u.ccmp.replays); +} +__KEY_ATTR(replays); + +static ssize_t show_key_key(const struct ieee80211_key *key, char *buf) +{ + int i; + char *p = buf; + + for (i = 0; i < key->keylen; i++) + p += sprintf(p, "%02x", key->key[i]); + p += sprintf(p, "\n"); + return (p - buf); +} +__KEY_ATTR(key); + +static struct attribute *key_ktype_attrs[] = { + &key_attr_length.attr, + &key_attr_sw_encrypt.attr, + &key_attr_index.attr, + &key_attr_hw_index.attr, + &key_attr_tx_rx_count.attr, + &key_attr_algorithm.attr, + &key_attr_tx_spec.attr, + &key_attr_rx_spec.attr, + &key_attr_replays.attr, + &key_attr_key.attr, + NULL +}; + +/* structures and functions */ + +static struct kobj_type sta_ktype = { + .release = sta_info_release, + .sysfs_ops = &sta_ktype_ops, + .default_attrs = sta_ktype_attrs, +}; + +static struct kobj_type key_ktype = { + .release = ieee80211_key_release, + .sysfs_ops = &key_ktype_ops, + .default_attrs = key_ktype_attrs, +}; + +static ssize_t sta_sysfs_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct sta_attribute *sta_attr; + struct sta_info *sta; + + sta_attr = container_of(attr, struct sta_attribute, attr); + sta = container_of(kobj, struct sta_info, kobj); + return sta_attr->show(sta, buf); +} + +static ssize_t key_sysfs_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct key_attribute *key_attr; + struct ieee80211_key *key; + + key_attr = container_of(attr, struct key_attribute, attr); + key = container_of(kobj, struct ieee80211_key, kobj); + return key_attr->show(key, buf); +} + +int ieee80211_sta_kset_sysfs_register(struct ieee80211_local *local) +{ + int res; + + res = kobject_set_name(&local->sta_kset.kobj, "sta"); + if (res) + return res; + local->sta_kset.kobj.parent = &local->class_dev.kobj; + local->sta_kset.ktype = &sta_ktype; + return kset_register(&local->sta_kset); +} + +void ieee80211_sta_kset_sysfs_unregister(struct ieee80211_local *local) +{ + kset_unregister(&local->sta_kset); +} + +int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata) +{ + int res; + + res = kobject_set_name(&sdata->key_kset.kobj, "keys"); + if (res) + return res; + sdata->key_kset.kobj.parent = &sdata->dev->class_dev.kobj; + sdata->key_kset.ktype = &key_ktype; + return kset_register(&sdata->key_kset); +} + +void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata) +{ + kset_unregister(&sdata->key_kset); +} + +int ieee80211_sta_sysfs_add(struct sta_info *sta) +{ + return kobject_add(&sta->kobj); +} + +void ieee80211_sta_sysfs_remove(struct sta_info *sta) +{ + kobject_del(&sta->kobj); +} + +void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset) +{ + key->kobj.kset = kset; + if (!kset) + key->kobj.ktype = &key_ktype; +} + +int ieee80211_key_sysfs_add(struct ieee80211_key *key) +{ + return kobject_add(&key->kobj); +} + +void ieee80211_key_sysfs_remove(struct ieee80211_key *key) +{ + if (key) + kobject_del(&key->kobj); +} + +int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata) +{ + return sysfs_create_link(&sdata->key_kset.kobj, + &sdata->default_key->kobj, "default"); +} + +void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata) +{ + sysfs_remove_link(&sdata->key_kset.kobj, "default"); +} |