aboutsummaryrefslogtreecommitdiffstats
path: root/iw_if.h
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-02-05 19:04:33 +0000
committerJonathan McCrohan <jmccrohan@gmail.com>2012-02-05 19:04:33 +0000
commitf3410da7f0bd208a5f2d792131b215454e782e93 (patch)
tree6e79c9acde383b91f5f21eb3a72f33e9c7fbbfce /iw_if.h
parent03dfbc2efa31d3c4fd7e576111883ea488e3e179 (diff)
downloadwavemon-f3410da7f0bd208a5f2d792131b215454e782e93.tar.gz
Imported Upstream version 0.7.3upstream/0.7.3
Diffstat (limited to 'iw_if.h')
-rw-r--r--iw_if.h250
1 files changed, 193 insertions, 57 deletions
diff --git a/iw_if.h b/iw_if.h
index 2a81496..0aab63f 100644
--- a/iw_if.h
+++ b/iw_if.h
@@ -49,14 +49,41 @@
*/
#define NOISE_DBM_SANE_MIN -127
-/* Static network interface information - see netdevice(7) */
-struct if_info { /* modified ifreq */
+/**
+ * struct if_info - wireless interface network information
+ * @hwaddr: MAC address
+ * @addr: IPv4 interface address
+ * @netmask: IPv4 interface netmask
+ * @bcast: IPv4 interface broadcast address
+ * @mtu: interface MTU
+ * @txqlen: tx queue length
+ * @flags: interface flags
+ * See also netdevice(7)
+ */
+struct if_info {
struct ether_addr hwaddr;
struct in_addr addr,
netmask,
bcast;
+ uint16_t mtu;
+ short txqlen;
+ short flags;
+};
+extern bool if_is_up(int skfd, const char *ifname);
+extern int if_set_up(int skfd, const char *ifname);
+extern void if_getinf(const char *ifname, struct if_info *info);
+
+/**
+ * struct iw_key - Encoding information
+ * @key: encryption key
+ * @size: length of @key in bytes
+ * @flags: flags reported by SIOCGIWENCODE
+ */
+struct iw_key {
+ uint8_t key[IW_ENCODING_TOKEN_MAX];
+ uint16_t size;
+ uint16_t flags;
};
-extern void if_getinf(char *ifname, struct if_info *info);
/**
* struct iw_dyn_info - modified iw_req
@@ -81,9 +108,9 @@ extern void if_getinf(char *ifname, struct if_info *info);
* @sens: sensitivity threshold of the card
* @bitrate: bitrate (client mode)
*
- * @key: encryption key
- * @key_size: length of @key in bytes
- * @key_flags: bitmask with information about @key
+ * @keys: array of encryption keys
+ * @nkeys: length of @keys
+ * @active_key: index of current key into @keys (counting from 1)
*
*/
struct iw_dyn_info {
@@ -95,14 +122,12 @@ struct iw_dyn_info {
cap_nickname:1,
cap_freq:1,
cap_sens:1,
- cap_bitrate:1,
cap_txpower:1,
cap_retry:1,
cap_rts:1,
cap_frag:1,
cap_mode:1,
cap_ap:1,
- cap_key:1,
cap_power:1,
cap_aplist:1;
@@ -122,11 +147,41 @@ struct iw_dyn_info {
int32_t sens;
unsigned long bitrate;
- char key[IW_ENCODING_TOKEN_MAX];
- uint16_t key_size;
- uint16_t key_flags;
+ struct iw_key *keys;
+ uint8_t nkeys;
+ uint8_t active_key;
};
+/* Return the number of encryption keys marked 'active' in @info */
+static inline uint8_t dyn_info_active_keys(struct iw_dyn_info *info)
+{
+ int i, num_active = 0;
+
+ for (i = 0; i < info->nkeys; i++)
+ num_active += info->keys[i].size &&
+ !(info->keys[i].flags & IW_ENCODE_DISABLED);
+ return num_active;
+}
+
+/* Return the number of 40-bit/104-bit keys in @info */
+static inline uint8_t dyn_info_wep_keys(struct iw_dyn_info *info)
+{
+ int i, num_wep = 0;
+
+ for (i = 0; i < info->nkeys; i++)
+ if (!(info->keys[i].flags & IW_ENCODE_DISABLED))
+ num_wep += info->keys[i].size == 5 ||
+ info->keys[i].size == 13;
+ return num_wep;
+}
+extern void dyn_info_get(struct iw_dyn_info *info,
+ const char *ifname, struct iw_range *ir);
+extern void dyn_info_cleanup(struct iw_dyn_info *info);
+
+
+/**
+ * struct if_stat - Packet/byte counts for interfaces
+ */
struct if_stat {
unsigned long long rx_packets,
tx_packets;
@@ -134,7 +189,7 @@ struct if_stat {
tx_bytes;
};
-extern void if_getstat(char *ifname, struct if_stat *stat);
+extern void if_getstat(const char *ifname, struct if_stat *stat);
/*
* Structs to communicate WiFi statistics
@@ -146,6 +201,7 @@ struct iw_levelstat {
};
#define IW_LSTAT_INIT { 0, 0, IW_QUAL_LEVEL_INVALID | IW_QUAL_NOISE_INVALID }
+extern void iw_getinf_range(const char *ifname, struct iw_range *range);
extern void iw_sanitize(struct iw_range *range,
struct iw_quality *qual,
struct iw_levelstat *dbm);
@@ -162,52 +218,82 @@ struct iw_stat {
struct iw_levelstat dbm;
};
+/*
+ * Periodic sampling of wireless statistics via timer alarm
+ */
extern void iw_getstat(struct iw_stat *stat);
extern void iw_cache_update(struct iw_stat *stat);
-extern void iw_getinf_dyn(char *ifname, struct iw_dyn_info *info);
-extern void iw_getinf_range(char *ifname, struct iw_range *range);
+extern void sampling_init(void (*sampling_handler)(int));
+extern void sampling_do_poll(void);
+static inline void sampling_stop(void) { alarm(0); }
+
+/*
+ * Organization of scan results
+ */
+/**
+ * struct scan_result - Ranked list of scan results
+ * @ap_addr: MAC address
+ * @essid: station SSID (may be empty)
+ * @mode: operation mode (type of station)
+ * @freq: frequency/channel information
+ * @qual: signal quality information
+ * @has_key: whether using encryption or not
+ * @flags: properties gathered from Information Elements
+ * @next: next, lower-ranking entry
+ */
+struct scan_result {
+ struct ether_addr ap_addr;
+ char essid[IW_ESSID_MAX_SIZE + 2];
+ int mode;
+ double freq;
+ struct iw_quality qual;
+
+ int has_key:1;
+ uint32_t flags;
+
+ struct scan_result *next;
+};
-extern void (*iw_stat_redraw) (void);
+typedef int (*scan_cmp_func)(const struct scan_result *, const struct scan_result *);
+extern int cmp_sig(const struct scan_result *a, const struct scan_result *b);
+extern int cmp_freq_sig(const struct scan_result *a, const struct scan_result *b);
+
+extern struct scan_result *get_scan_list(int skfd, const char *ifname, int we_version,
+ scan_cmp_func cmp_scan_result);
+extern void free_scan_result(struct scan_result *head);
/*
- * Helper routines
+ * General helper routines
*/
static inline const char *iw_opmode(const uint8_t mode)
{
- static char *modes[] = { "Auto",
- "Ad-Hoc",
- "Managed",
- "Master",
- "Repeater",
- "Secondary",
- "Monitor",
- "Mesh"
+ static char *modes[] = {
+ [IW_MODE_AUTO] = "Auto",
+ [IW_MODE_ADHOC] = "Ad-Hoc",
+ [IW_MODE_INFRA] = "Managed",
+ [IW_MODE_MASTER] = "Master",
+ [IW_MODE_REPEAT] = "Repeater",
+ [IW_MODE_SECOND] = "Secondary",
+ [IW_MODE_MONITOR] = "Monitor",
+ [IW_MODE_MESH] = "Mesh"
};
return mode < ARRAY_SIZE(modes) ? modes[mode] : "Unknown/bug";
}
-static inline bool is_zero_ether_addr(const uint8_t *mac)
-{
- return ! (mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]);
-}
-
-static inline bool is_broadcast_ether_addr(const uint8_t *mac)
-{
- return (mac[0] & mac[1] & mac[2] & mac[3] & mac[4] & mac[5]) == 0xff;
-}
-
/* Print a mac-address, include leading zeroes (unlike ether_ntoa(3)) */
static inline char *ether_addr(const struct ether_addr *ea)
{
- static char str[MAC_ADDR_MAX];
-
- sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X",
- ea->ether_addr_octet[0], ea->ether_addr_octet[1],
- ea->ether_addr_octet[2], ea->ether_addr_octet[3],
- ea->ether_addr_octet[4], ea->ether_addr_octet[5]);
- return str;
+ static char mac[MAC_ADDR_MAX];
+ char *d = mac, *a = ether_ntoa(ea);
+next_chunk:
+ if (a[0] == '\0' || a[1] == '\0' || a[1] == ':')
+ *d++ = '0';
+ while ((*d++ = conf.cisco_mac ? (*a == ':' ? '.' : *a) : toupper(*a)))
+ if (*a++ == ':')
+ goto next_chunk;
+ return mac;
}
/* Print mac-address translation from /etc/ethers if available */
@@ -223,21 +309,20 @@ static inline char *ether_lookup(const struct ether_addr *ea)
/* Format an Ethernet mac address */
static inline char *mac_addr(const struct sockaddr *sa)
{
- struct ether_addr zero = { {0} };
-
if (sa->sa_family != ARPHRD_ETHER)
- return ether_addr(&zero);
- return ether_lookup((struct ether_addr *)sa->sa_data);
+ return "00:00:00:00:00:00";
+ return ether_lookup((const struct ether_addr *)sa->sa_data);
}
/* Format a (I)BSSID */
static inline char *format_bssid(const struct sockaddr *ap)
{
- const struct ether_addr *bssid = (struct ether_addr *)ap->sa_data;
+ uint8_t bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+ uint8_t zero_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- if (is_zero_ether_addr(bssid->ether_addr_octet))
+ if (memcmp(ap->sa_data, zero_addr, ETH_ALEN) == 0)
return "Not-Associated";
- if (is_broadcast_ether_addr(bssid->ether_addr_octet))
+ if (memcmp(ap->sa_data, bcast_addr, ETH_ALEN) == 0)
return "Invalid";
return mac_addr(ap);
}
@@ -259,6 +344,16 @@ static inline uint8_t prefix_len(const struct in_addr *netmask)
return bit_count(netmask->s_addr);
}
+/* Absolute power measurement in dBm (IW_QUAL_DBM): map into -192 .. 63 range */
+static inline int u8_to_dbm(const int power)
+{
+ return power > 63 ? power - 0x100 : power;
+}
+static inline uint8_t dbm_to_u8(const int dbm)
+{
+ return dbm < 0 ? dbm + 0x100 : dbm;
+}
+
/* Convert log dBm values to linear mW */
static inline double dbm2mw(const double in)
{
@@ -366,6 +461,18 @@ static inline float freq_to_hz(const struct iw_freq *freq)
return freq->m * pow(10, freq->e);
}
+/* Return frequency or 0 on error. Based on iw_channel_to_freq() */
+static inline double channel_to_freq(uint8_t chan, const struct iw_range *range)
+{
+ int c;
+
+ for (c = 0; c < range->num_frequency; c++)
+ /* Check if it actually has stored a frequency */
+ if (range->freq[c].i == chan && range->freq[c].m > 1000)
+ return freq_to_hz(&range->freq[c]);
+ return 0.0;
+}
+
/* Return channel number or -1 on error. Based on iw_freq_to_channel() */
static inline int freq_to_channel(double freq, const struct iw_range *range)
{
@@ -381,32 +488,62 @@ static inline int freq_to_channel(double freq, const struct iw_range *range)
}
/* print @key in cleartext if it is in ASCII format, use hex format otherwise */
-static inline char *format_key(char *key, uint8_t key_len)
+static inline char *format_key(const struct iw_key *const iwk)
{
static char buf[128];
- int len = 0, i, is_printable;
+ int i, is_printable = 0, len = 0;
- for (i = 0, is_printable = 1; i < key_len && is_printable; i++)
- is_printable = isprint(key[i]);
+ /* Over-estimate key size: 2 chars per hex digit plus '-' */
+ assert(iwk != NULL && iwk->size * 3 < sizeof(buf));
+
+ for (i = 0; i < iwk->size && (is_printable = isprint(iwk->key[i])); i++)
+ ;
if (is_printable)
len += sprintf(buf, "\"");
- for (i = 0; i < key_len; i++)
+ for (i = 0; i < iwk->size; i++)
if (is_printable) {
- len += sprintf(buf + len, "%c", key[i]);
+ len += sprintf(buf + len, "%c", iwk->key[i]);
} else {
if (i > 0 && (i & 1) == 0)
len += sprintf(buf + len, "-");
- len += sprintf(buf + len, "%2X", key[i]);
+ len += sprintf(buf + len, "%02X", iwk->key[i]);
}
if (is_printable)
- sprintf(buf + len, "\"");
+ len += sprintf(buf + len, "\"");
+
+ sprintf(buf + len, " (%u bits)", iwk->size * 8);
+
+ return buf;
+}
+/* Human-readable representation of IW_ENC_CAPA_ types */
+static inline const char *format_enc_capab(const uint32_t capa, const char *sep)
+{
+ static char buf[32];
+ size_t len = 0, max = sizeof(buf);
+
+ if (capa & IW_ENC_CAPA_WPA)
+ len = snprintf(buf, max, "WPA");
+ if (capa & IW_ENC_CAPA_WPA2)
+ len += snprintf(buf + len, max - len, "%sWPA2", len ? sep : "");
+ if (capa & IW_ENC_CAPA_CIPHER_TKIP)
+ len += snprintf(buf + len, max - len, "%sTKIP", len ? sep : "");
+ if (capa & IW_ENC_CAPA_CIPHER_CCMP)
+ len += snprintf(buf + len, max - len, "%sCCMP", len ? sep : "");
+ buf[len] = '\0';
return buf;
}
+/* Display only the supported WPA type */
+#define IW_WPA_MASK (IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2)
+static inline const char *format_wpa(struct iw_range *ir)
+{
+ return format_enc_capab(ir->enc_capa & IW_WPA_MASK, "/");
+}
+
static inline char *format_retry(const struct iw_param *retry,
const struct iw_range *range)
{
@@ -448,4 +585,3 @@ static inline char *format_retry(const struct iw_param *retry,
return buf;
}
-