From f3410da7f0bd208a5f2d792131b215454e782e93 Mon Sep 17 00:00:00 2001 From: Jonathan McCrohan Date: Sun, 5 Feb 2012 19:04:33 +0000 Subject: Imported Upstream version 0.7.3 --- iw_if.h | 250 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 193 insertions(+), 57 deletions(-) (limited to 'iw_if.h') 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; } - -- cgit v1.2.3