2 * iwinfo - Wireless Information Library - Madwifi Backend
4 * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
6 * The iwinfo library is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * The iwinfo library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with the iwinfo library. If not, see http://www.gnu.org/licenses/.
18 * The signal handling code is derived from the official madwifi tools,
19 * wlanconfig.c in particular. The encryption property handling was
20 * inspired by the hostapd madwifi driver.
23 #include "iwinfo_madwifi.h"
24 #include "iwinfo_wext.h"
26 static int ioctl_socket
= -1;
28 static int madwifi_ioctl(struct iwreq
*wrq
, const char *ifname
, int cmd
, void *data
, size_t len
)
31 if( ioctl_socket
== -1 )
32 ioctl_socket
= socket(AF_INET
, SOCK_DGRAM
, 0);
34 strncpy(wrq
->ifr_name
, ifname
, IFNAMSIZ
);
40 memcpy(wrq
->u
.name
, data
, len
);
44 wrq
->u
.data
.pointer
= data
;
45 wrq
->u
.data
.length
= len
;
49 return ioctl(ioctl_socket
, cmd
, wrq
);
52 static int get80211priv(const char *ifname
, int op
, void *data
, size_t len
)
56 if( madwifi_ioctl(&iwr
, ifname
, op
, data
, len
) < 0 )
59 return iwr
.u
.data
.length
;
63 int madwifi_probe(const char *ifname
)
69 sprintf(path
, "/proc/sys/net/%s/%%parent", ifname
);
72 if( (fd
= open(path
, O_RDONLY
)) > -1 )
74 if( read(fd
, name
, 4) == 4 )
75 ret
= strncmp(name
, "wifi", 4) ? 0 : 1;
83 int madwifi_get_mode(const char *ifname
, char *buf
)
85 return wext_get_mode(ifname
, buf
);
88 int madwifi_get_ssid(const char *ifname
, char *buf
)
90 return wext_get_ssid(ifname
, buf
);
93 int madwifi_get_bssid(const char *ifname
, char *buf
)
95 return wext_get_bssid(ifname
, buf
);
98 int madwifi_get_channel(const char *ifname
, int *buf
)
103 struct ieee80211req_chaninfo chans
;
105 if( madwifi_ioctl(&wrq
, ifname
, SIOCGIWFREQ
, NULL
, 0) >= 0 )
107 /* Madwifi returns a Hz frequency, get it's freq list to find channel index */
108 freq
= (uint16_t)(wrq
.u
.freq
.m
/ 100000);
110 if( get80211priv(ifname
, IEEE80211_IOCTL_GETCHANINFO
, &chans
, sizeof(chans
)) >= 0 )
114 for( i
= 0; i
< chans
.ic_nchans
; i
++ )
116 if( freq
== chans
.ic_chans
[i
].ic_freq
)
118 *buf
= chans
.ic_chans
[i
].ic_ieee
;
130 int madwifi_get_frequency(const char *ifname
, int *buf
)
134 if( madwifi_ioctl(&wrq
, ifname
, SIOCGIWFREQ
, NULL
, 0) >= 0 )
136 *buf
= (uint16_t)(wrq
.u
.freq
.m
/ 100000);
143 int madwifi_get_bitrate(const char *ifname
, int *buf
)
145 unsigned int mode
, len
, rate
, rate_count
;
146 uint8_t tmp
[24*1024];
149 struct ieee80211req_sta_info
*si
;
151 if( madwifi_ioctl(&wrq
, ifname
, SIOCGIWMODE
, NULL
, 0) >= 0 )
155 /* Calculate bitrate average from associated stations in ad-hoc mode */
158 rate
= rate_count
= 0;
160 if( (len
= get80211priv(ifname
, IEEE80211_IOCTL_STA_INFO
, tmp
, 24*1024)) > 0 )
165 si
= (struct ieee80211req_sta_info
*) cp
;
167 if( si
->isi_rssi
> 0 )
170 rate
+= ((si
->isi_rates
[si
->isi_txrate
] & IEEE80211_RATE_VAL
) / 2);
175 } while (len
>= sizeof(struct ieee80211req_sta_info
));
178 *buf
= (rate
== 0 || rate_count
== 0) ? 0 : (rate
/ rate_count
) * 1000;
182 /* Return whatever wext tells us ... */
183 return wext_get_bitrate(ifname
, buf
);
189 int madwifi_get_signal(const char *ifname
, int *buf
)
191 unsigned int mode
, len
, rssi
, rssi_count
;
192 uint8_t tmp
[24*1024];
195 struct ieee80211req_sta_info
*si
;
197 if( madwifi_ioctl(&wrq
, ifname
, SIOCGIWMODE
, NULL
, 0) >= 0 )
201 /* Calculate signal average from associated stations in ap or ad-hoc mode */
204 rssi
= rssi_count
= 0;
206 if( (len
= get80211priv(ifname
, IEEE80211_IOCTL_STA_INFO
, tmp
, 24*1024)) > 0 )
211 si
= (struct ieee80211req_sta_info
*) cp
;
213 if( si
->isi_rssi
> 0 )
216 rssi
-= (si
->isi_rssi
- 95);
221 } while (len
>= sizeof(struct ieee80211req_sta_info
));
224 *buf
= (rssi
== 0 || rssi_count
== 0) ? 1 : -(rssi
/ rssi_count
);
228 /* Return whatever wext tells us ... */
229 return wext_get_signal(ifname
, buf
);
235 int madwifi_get_noise(const char *ifname
, int *buf
)
237 return wext_get_noise(ifname
, buf
);
240 int madwifi_get_quality(const char *ifname
, int *buf
)
242 unsigned int mode
, len
, quality
, quality_count
;
243 uint8_t tmp
[24*1024];
246 struct ieee80211req_sta_info
*si
;
248 if( madwifi_ioctl(&wrq
, ifname
, SIOCGIWMODE
, NULL
, 0) >= 0 )
252 /* Calculate signal average from associated stations in ad-hoc mode */
255 quality
= quality_count
= 0;
257 if( (len
= get80211priv(ifname
, IEEE80211_IOCTL_STA_INFO
, tmp
, 24*1024)) > 0 )
262 si
= (struct ieee80211req_sta_info
*) cp
;
264 if( si
->isi_rssi
> 0 )
267 quality
+= si
->isi_rssi
;
272 } while (len
>= sizeof(struct ieee80211req_sta_info
));
275 *buf
= (quality
== 0 || quality_count
== 0) ? 0 : (quality
/ quality_count
);
279 /* Return whatever wext tells us ... */
280 return wext_get_quality(ifname
, buf
);
286 int madwifi_get_quality_max(const char *ifname
, int *buf
)
288 return wext_get_quality_max(ifname
, buf
);
291 int madwifi_get_enctype(const char *ifname
, char *buf
)
294 struct ieee80211req_key wk
;
295 int wpa_version
= 0, ciphers
= 0, key_type
= 0;
296 char cipher_string
[32];
298 sprintf(buf
, "Unknown");
300 memset(&wrq
, 0, sizeof(wrq
));
301 memset(&wk
, 0, sizeof(wk
));
302 memset(wk
.ik_macaddr
, 0xff, IEEE80211_ADDR_LEN
);
304 /* Get key information */
305 if( get80211priv(ifname
, IEEE80211_IOCTL_GETKEY
, &wk
, sizeof(wk
)) >= 0 )
306 key_type
= wk
.ik_type
;
308 /* Get wpa protocol version */
309 wrq
.u
.mode
= IEEE80211_PARAM_WPA
;
310 if( madwifi_ioctl(&wrq
, ifname
, IEEE80211_IOCTL_GETPARAM
, NULL
, 0) >= 0 )
311 wpa_version
= wrq
.u
.mode
;
313 /* Get used pairwise ciphers */
314 wrq
.u
.mode
= IEEE80211_PARAM_UCASTCIPHERS
;
315 if( madwifi_ioctl(&wrq
, ifname
, IEEE80211_IOCTL_GETPARAM
, NULL
, 0) >= 0 )
317 ciphers
= wrq
.u
.mode
;
319 if( wpa_version
> 0 )
321 memset(cipher_string
, 0, sizeof(cipher_string
));
323 /* Looks like mixed wpa/wpa2 ? */
324 if( (ciphers
& (1<<IEEE80211_CIPHER_TKIP
)) && (ciphers
& (1<<IEEE80211_CIPHER_AES_CCM
)) )
328 if( (ciphers
& (1<<IEEE80211_CIPHER_TKIP
)) )
329 strcat(cipher_string
, "TKIP, ");
331 if( (ciphers
& (1<<IEEE80211_CIPHER_AES_CCM
)) )
332 strcat(cipher_string
, "CCMP, ");
334 if( (ciphers
& (1<<IEEE80211_CIPHER_AES_OCB
)) )
335 strcat(cipher_string
, "AES-OCB, ");
337 if( (ciphers
& (1<<IEEE80211_CIPHER_CKIP
)) )
338 strcat(cipher_string
, "CKIP, ");
340 cipher_string
[strlen(cipher_string
)-2] = 0;
346 sprintf(buf
, "mixed WPA/WPA2 (%s)", cipher_string
);
350 sprintf(buf
, "WPA2 (%s)", cipher_string
);
354 sprintf(buf
, "WPA (%s)", cipher_string
);
358 sprintf(buf
, "%s", (key_type
== 0) ? "WEP" : "None");
365 int madwifi_get_assoclist(const char *ifname
, char *buf
, int *len
)
369 uint8_t tmp
[24*1024];
370 struct ieee80211req_sta_info
*si
;
371 struct iwinfo_assoclist_entry entry
;
373 if( (tl
= get80211priv(ifname
, IEEE80211_IOCTL_STA_INFO
, tmp
, 24*1024)) > 0 )
378 if( madwifi_get_noise(ifname
, &noise
) )
382 si
= (struct ieee80211req_sta_info
*) cp
;
384 entry
.signal
= (si
->isi_rssi
- 95);
386 memcpy(entry
.mac
, &si
->isi_macaddr
, 6);
387 memcpy(&buf
[bl
], &entry
, sizeof(struct iwinfo_assoclist_entry
));
389 bl
+= sizeof(struct iwinfo_assoclist_entry
);
392 } while (tl
>= sizeof(struct ieee80211req_sta_info
));
401 int madwifi_get_txpwrlist(const char *ifname
, char *buf
, int *len
)
403 return wext_get_txpwrlist(ifname
, buf
, len
);
406 int madwifi_get_scanlist(const char *ifname
, char *buf
, int *len
)
408 return wext_get_scanlist(ifname
, buf
, len
);
411 int madwifi_get_mbssid_support(const char *ifname
, int *buf
)
413 /* We assume that multi bssid is always possible */