2 * iwinfo - Wireless Information Library - Linux Wireless Extension 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 * Parts of this code are derived from the Linux wireless tools, iwlib.c,
19 * iwlist.c and iwconfig.c in particular.
23 #include "iwinfo_wext.h"
25 #define LOG10_MAGIC 1.25892541179
27 static int ioctl_socket
= -1;
29 static double wext_freq2float(const struct iw_freq
*in
)
32 double res
= (double) in
->m
;
33 for(i
= 0; i
< in
->e
; i
++) res
*= 10;
37 static int wext_freq2mhz(const struct iw_freq
*in
)
48 for(i
= 0; i
< in
->e
; i
++)
51 return (int)(mhz
/ 100000);
55 int wext_dbm2mw(int in
)
62 for(k
= 0; k
< ip
; k
++) res
*= 10;
63 for(k
= 0; k
< fp
; k
++) res
*= LOG10_MAGIC
;
68 int wext_mw2dbm(int in
)
70 double fin
= (double) in
;
88 static int wext_ioctl(const char *ifname
, int cmd
, struct iwreq
*wrq
)
91 if( ioctl_socket
== -1 )
93 ioctl_socket
= socket(AF_INET
, SOCK_DGRAM
, 0);
94 fcntl(ioctl_socket
, F_SETFD
, fcntl(ioctl_socket
, F_GETFD
) | FD_CLOEXEC
);
97 if( !strncmp(ifname
, "mon.", 4) )
98 strncpy(wrq
->ifr_name
, &ifname
[4], IFNAMSIZ
);
100 strncpy(wrq
->ifr_name
, ifname
, IFNAMSIZ
);
102 return ioctl(ioctl_socket
, cmd
, wrq
);
106 int wext_probe(const char *ifname
)
110 if(wext_ioctl(ifname
, SIOCGIWNAME
, &wrq
) >= 0)
116 int wext_get_mode(const char *ifname
, char *buf
)
120 if(wext_ioctl(ifname
, SIOCGIWMODE
, &wrq
) >= 0)
125 sprintf(buf
, "Auto");
129 sprintf(buf
, "Ad-Hoc");
133 sprintf(buf
, "Client");
137 sprintf(buf
, "Master");
141 sprintf(buf
, "Repeater");
145 sprintf(buf
, "Secondary");
149 sprintf(buf
, "Monitor");
153 sprintf(buf
, "Unknown");
162 int wext_get_ssid(const char *ifname
, char *buf
)
166 wrq
.u
.essid
.pointer
= (caddr_t
) buf
;
167 wrq
.u
.essid
.length
= IW_ESSID_MAX_SIZE
+ 1;
168 wrq
.u
.essid
.flags
= 0;
170 if(wext_ioctl(ifname
, SIOCGIWESSID
, &wrq
) >= 0)
176 int wext_get_bssid(const char *ifname
, char *buf
)
180 if(wext_ioctl(ifname
, SIOCGIWAP
, &wrq
) >= 0)
182 sprintf(buf
, "%02X:%02X:%02X:%02X:%02X:%02X",
183 (uint8_t)wrq
.u
.ap_addr
.sa_data
[0], (uint8_t)wrq
.u
.ap_addr
.sa_data
[1],
184 (uint8_t)wrq
.u
.ap_addr
.sa_data
[2], (uint8_t)wrq
.u
.ap_addr
.sa_data
[3],
185 (uint8_t)wrq
.u
.ap_addr
.sa_data
[4], (uint8_t)wrq
.u
.ap_addr
.sa_data
[5]);
193 int wext_get_bitrate(const char *ifname
, int *buf
)
197 if(wext_ioctl(ifname
, SIOCGIWRATE
, &wrq
) >= 0)
199 *buf
= (wrq
.u
.bitrate
.value
/ 1000);
206 int wext_get_channel(const char *ifname
, int *buf
)
209 struct iw_range range
;
213 if(wext_ioctl(ifname
, SIOCGIWFREQ
, &wrq
) >= 0)
215 if( wrq
.u
.freq
.m
>= 1000 )
217 freq
= wext_freq2float(&wrq
.u
.freq
);
218 wrq
.u
.data
.pointer
= (caddr_t
) &range
;
219 wrq
.u
.data
.length
= sizeof(struct iw_range
);
220 wrq
.u
.data
.flags
= 0;
222 if(wext_ioctl(ifname
, SIOCGIWRANGE
, &wrq
) >= 0)
224 for(i
= 0; i
< range
.num_frequency
; i
++)
226 if( wext_freq2float(&range
.freq
[i
]) == freq
)
228 *buf
= range
.freq
[i
].i
;
244 int wext_get_frequency(const char *ifname
, int *buf
)
247 struct iw_range range
;
250 if(wext_ioctl(ifname
, SIOCGIWFREQ
, &wrq
) >= 0)
252 /* We got a channel number instead ... */
253 if( wrq
.u
.freq
.m
< 1000 )
255 channel
= wrq
.u
.freq
.m
;
256 wrq
.u
.data
.pointer
= (caddr_t
) &range
;
257 wrq
.u
.data
.length
= sizeof(struct iw_range
);
258 wrq
.u
.data
.flags
= 0;
260 if(wext_ioctl(ifname
, SIOCGIWRANGE
, &wrq
) >= 0)
262 for(i
= 0; i
< range
.num_frequency
; i
++)
264 if( range
.freq
[i
].i
== channel
)
266 *buf
= wext_freq2mhz(&range
.freq
[i
]);
274 *buf
= wext_freq2mhz(&wrq
.u
.freq
);
282 int wext_get_txpower(const char *ifname
, int *buf
)
286 wrq
.u
.txpower
.flags
= 0;
288 if(wext_ioctl(ifname
, SIOCGIWTXPOW
, &wrq
) >= 0)
290 if(wrq
.u
.txpower
.flags
& IW_TXPOW_MWATT
)
291 *buf
= wext_mw2dbm(wrq
.u
.txpower
.value
);
293 *buf
= wrq
.u
.txpower
.value
;
301 int wext_get_signal(const char *ifname
, int *buf
)
304 struct iw_statistics stats
;
306 wrq
.u
.data
.pointer
= (caddr_t
) &stats
;
307 wrq
.u
.data
.length
= sizeof(struct iw_statistics
);
308 wrq
.u
.data
.flags
= 1;
310 if(wext_ioctl(ifname
, SIOCGIWSTATS
, &wrq
) >= 0)
312 *buf
= (stats
.qual
.updated
& IW_QUAL_DBM
)
313 ? (stats
.qual
.level
- 0x100) : stats
.qual
.level
;
321 int wext_get_noise(const char *ifname
, int *buf
)
324 struct iw_statistics stats
;
326 wrq
.u
.data
.pointer
= (caddr_t
) &stats
;
327 wrq
.u
.data
.length
= sizeof(struct iw_statistics
);
328 wrq
.u
.data
.flags
= 1;
330 if(wext_ioctl(ifname
, SIOCGIWSTATS
, &wrq
) >= 0)
332 *buf
= (stats
.qual
.updated
& IW_QUAL_DBM
)
333 ? (stats
.qual
.noise
- 0x100) : stats
.qual
.noise
;
341 int wext_get_quality(const char *ifname
, int *buf
)
344 struct iw_statistics stats
;
346 wrq
.u
.data
.pointer
= (caddr_t
) &stats
;
347 wrq
.u
.data
.length
= sizeof(struct iw_statistics
);
348 wrq
.u
.data
.flags
= 1;
350 if(wext_ioctl(ifname
, SIOCGIWSTATS
, &wrq
) >= 0)
352 *buf
= stats
.qual
.qual
;
359 int wext_get_quality_max(const char *ifname
, int *buf
)
362 struct iw_range range
;
364 wrq
.u
.data
.pointer
= (caddr_t
) &range
;
365 wrq
.u
.data
.length
= sizeof(struct iw_range
);
366 wrq
.u
.data
.flags
= 0;
368 if(wext_ioctl(ifname
, SIOCGIWRANGE
, &wrq
) >= 0)
370 *buf
= range
.max_qual
.qual
;
377 int wext_get_assoclist(const char *ifname
, char *buf
, int *len
)
383 int wext_get_txpwrlist(const char *ifname
, char *buf
, int *len
)
386 struct iw_range range
;
387 struct iwinfo_txpwrlist_entry entry
;
390 wrq
.u
.data
.pointer
= (caddr_t
) &range
;
391 wrq
.u
.data
.length
= sizeof(struct iw_range
);
392 wrq
.u
.data
.flags
= 0;
394 if( (wext_ioctl(ifname
, SIOCGIWRANGE
, &wrq
) >= 0) &&
395 (range
.num_txpower
> 0) && (range
.num_txpower
<= IW_MAX_TXPOWER
) &&
396 !(range
.txpower_capa
& IW_TXPOW_RELATIVE
)
398 for( i
= 0; i
< range
.num_txpower
; i
++ )
400 if( range
.txpower_capa
& IW_TXPOW_DBM
)
402 entry
.dbm
= range
.txpower
[i
];
403 entry
.mw
= wext_dbm2mw(range
.txpower
[i
]);
406 else if( range
.txpower_capa
& IW_TXPOW_MWATT
)
408 entry
.dbm
= wext_mw2dbm(range
.txpower
[i
]);
409 entry
.mw
= range
.txpower
[i
];
412 memcpy(&buf
[i
*sizeof(entry
)], &entry
, sizeof(entry
));
415 *len
= i
* sizeof(entry
);
422 int wext_get_freqlist(const char *ifname
, char *buf
, int *len
)
425 struct iw_range range
;
426 struct iwinfo_freqlist_entry entry
;
429 wrq
.u
.data
.pointer
= (caddr_t
) &range
;
430 wrq
.u
.data
.length
= sizeof(struct iw_range
);
431 wrq
.u
.data
.flags
= 0;
433 if(wext_ioctl(ifname
, SIOCGIWRANGE
, &wrq
) >= 0)
437 for(i
= 0; i
< range
.num_frequency
; i
++)
439 entry
.mhz
= wext_freq2mhz(&range
.freq
[i
]);
440 entry
.channel
= range
.freq
[i
].i
;
442 memcpy(&buf
[bl
], &entry
, sizeof(struct iwinfo_freqlist_entry
));
443 bl
+= sizeof(struct iwinfo_freqlist_entry
);
453 int wext_get_country(const char *ifname
, char *buf
)
459 int wext_get_countrylist(const char *ifname
, char *buf
, int *len
)
465 int wext_get_encryption(const char *ifname
, char *buf
)
467 /* No reliable crypto info in wext */
471 int wext_get_mbssid_support(const char *ifname
, int *buf
)
473 /* No multi bssid support atm */