1 /* $Id: wl.c,v 1.18 2008/05/13 04:42:17 hacki Exp $ */
4 * Copyright (c) 2005, 2006 Marcus Glocker <marcus@nazgul.ch>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 /* Ported to FreeBSD by Nathan Lay <nslay@hotmail.com> 4/30/06 */
21 #include <sys/param.h>
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
26 #include <dev/ic/if_wi_ieee.h>
29 #include <dev/wi/if_wavelan_ieee.h>
34 #include <net/if_media.h>
35 #include <net80211/ieee80211.h>
36 #include <net80211/ieee80211_ioctl.h>
44 * global variables for this file
47 static char *speed
[25] = {
65 static char *speed
[] = {
82 "DS/354Kbps", "0.354",
83 "DS/512Kbps", "0.512",
92 * 0 = wep disabled, 1 = wep enabled, -1 = error
95 get_wep(const char *interface
)
99 struct ieee80211_nwkey nwkey
;
102 struct ieee80211req nwkey
;
105 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
108 memset(&nwkey
, 0, sizeof(nwkey
));
110 nwkey
.i_type
= IEEE80211_IOC_WEP
;
112 strlcpy(nwkey
.i_name
, interface
, sizeof(nwkey
.i_name
));
114 if ((inwkey
= ioctl(s
, SIOCG80211NWKEY
, (caddr_t
)&nwkey
)) == -1) {
120 if ((inwkey
= ioctl(s
, SIOCG80211
, (caddr_t
)&nwkey
)) == -1) {
128 if (inwkey
== 0 && nwkey
.i_wepon
> 0)
132 if (inwkey
== 0 && nwkey
.i_val
> 0)
143 * <channel number> = success, 0 = no data, -1 = error
146 get_channel(const char *interface
)
150 struct ieee80211chanreq channel
;
153 struct ieee80211req channel
;
156 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
159 memset(&channel
, 0, sizeof(channel
));
161 channel
.i_type
= IEEE80211_IOC_CHANNEL
;
163 strlcpy(channel
.i_name
, interface
, sizeof(channel
.i_name
));
165 if ((ichan
= ioctl(s
, SIOCG80211CHANNEL
, (caddr_t
)&channel
)) == -1) {
171 if ((ichan
= ioctl(s
, SIOCG80211
, (caddr_t
)&channel
)) == -1) {
180 if (channel
.i_channel
< 1000)
181 return (channel
.i_channel
);
184 if (channel
.i_val
< 1000)
185 return (channel
.i_val
);
194 * get signal strength
196 * <signal strength> = success, 0 = no data, -1 = error
199 get_signal(const char *interface
, const char *network
)
204 struct ieee80211_nodereq_all na
;
205 struct ieee80211_nodereq nr
[8];
209 uint8_t buf
[24 * 1024], *cp
;
210 struct ieee80211req na
;
212 char network_id
[IEEE80211_NWID_LEN
+ 1];
214 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
217 memset(&na
, 0, sizeof(na
));
219 memset(&nr
, 0, sizeof(nr
));
221 na
.na_size
= sizeof(nr
);
222 strlcpy(na
.na_ifname
, interface
, sizeof(na
.na_ifname
));
225 strlcpy(na
.i_name
, interface
, sizeof(na
.i_name
));
226 na
.i_type
= IEEE80211_IOC_SCAN_RESULTS
;
228 na
.i_len
= sizeof(buf
);
231 if (ioctl(s
, SIOCG80211ALLNODES
, &na
) == -1) {
237 if (ioctl(s
, SIOCG80211
, (caddr_t
)&na
) == -1) {
245 for (i
= 0; i
< na
.na_nodes
; i
++) {
246 if (nr
[i
].nr_nwid_len
< sizeof(network_id
))
247 len
= nr
[i
].nr_nwid_len
+ 1;
249 len
= sizeof(network_id
);
250 strlcpy(network_id
, (const char *)nr
[i
].nr_nwid
, len
);
251 if (!strcmp(network_id
, network
))
252 return (nr
[i
].nr_rssi
);
256 /* This is how ifconfig does it */
260 struct ieee80211req_scan_result
*sr
;
262 sr
= (struct ieee80211req_scan_result
*)cp
;
263 vp
= (u_int8_t
*)(sr
+ 1);
264 strlcpy(network_id
, (const char *)vp
, sr
->isr_ssid_len
+ 1);
265 if (!strcmp(network_id
, network
))
266 return (sr
->isr_rssi
);
269 if (sr
->isr_len
<= 0) /* Some weird lockup */
271 } while (len
>= sizeof(struct ieee80211req_scan_result
));
279 * get signal strength for wi interfaces
281 * <signal strength> = success, -1 = error
284 get_wi_signal(const char *interface
)
293 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
296 bzero((char *)&wreq
, sizeof(wreq
));
297 bzero((char *)&ifr
, sizeof(ifr
));
299 wreq
.wi_len
= WI_MAX_DATALEN
;
300 wreq
.wi_type
= WI_RID_COMMS_QUALITY
;
301 ifr
.ifr_data
= (caddr_t
)&wreq
;
302 strlcpy(ifr
.ifr_name
, interface
, sizeof(ifr
.ifr_name
));
304 if (ioctl(s
, SIOCGWAVELAN
, &ifr
) == -1) {
311 link
= wreq
.wi_val
[0];
313 * for future reference ...
314 * level = wreq.wi_val[1];
315 * noise = wreq.wi_val[2];
317 return (letoh16(link
));
320 return (wreq
.wi_val
[1]);
328 * <pointer to speed> = success, NULL = no data / error
331 get_speed(const char *interface
)
334 struct ifmediareq ifmr
;
335 const struct ifmedia_description
*desc
;
337 const struct ifmedia_description ifm_subtype_descriptions
[] =
338 IFM_SUBTYPE_DESCRIPTIONS
;
341 const struct ifmedia_description ifm_subtype_descriptions
[] =
342 IFM_SUBTYPE_IEEE80211_DESCRIPTIONS
;
345 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
348 memset(&ifmr
, 0, sizeof(ifmr
));
349 strlcpy(ifmr
.ifm_name
, interface
, sizeof(ifmr
.ifm_name
));
350 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)&ifmr
) == -1) {
356 mword
= ifmr
.ifm_active
;
357 for (desc
= ifm_subtype_descriptions
; desc
->ifmt_string
!= NULL
;
359 if (IFM_TYPE_MATCH(desc
->ifmt_word
, mword
) &&
360 IFM_SUBTYPE(desc
->ifmt_word
) == IFM_SUBTYPE(mword
))
361 return (translate_speed(desc
->ifmt_string
));
371 * <pointer to status> = success, NULL = no data / error
374 get_status(const char *interface
)
378 static char status
[64];
379 const struct ifmedia_status_description
*ifms
;
380 const struct ifmedia_status_description ifm_status_descriptions
[] =
381 IFM_STATUS_DESCRIPTIONS
;
382 const int ifm_status_valid_list
[] =
383 IFM_STATUS_VALID_LIST
;
388 struct ifmediareq ifmr
;
390 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
393 memset(&ifmr
, 0, sizeof(ifmr
));
394 strlcpy(ifmr
.ifm_name
, interface
, sizeof(ifmr
.ifm_name
));
395 if (ioctl(s
, SIOCGIFMEDIA
, (caddr_t
)&ifmr
) == -1) {
402 for (bitno
= 0; ifm_status_valid_list
[bitno
] != 0; bitno
++) {
403 for (ifms
= ifm_status_descriptions
; ifms
->ifms_valid
!= 0;
405 if (ifms
->ifms_type
!= IFM_TYPE(ifmr
.ifm_current
) ||
406 ifms
->ifms_valid
!= ifm_status_valid_list
[bitno
])
408 strlcpy(status
, IFM_STATUS_DESC(ifms
, ifmr
.ifm_status
),
418 if (ifmr
.ifm_status
& IFM_ACTIVE
)
420 return ("no carrier");
426 * get wireless network id
428 * pointer to network id = success, NULL = no data / error
431 get_nwid(const char *interface
)
434 static char network_id
[IEEE80211_NWID_LEN
+ 1];
437 struct ieee80211_nwid nwid
;
440 struct ieee80211req nwid
;
443 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1)
447 memset(&ifr
, 0, sizeof(ifr
));
448 ifr
.ifr_data
= (caddr_t
)&nwid
;
449 strlcpy(ifr
.ifr_name
, interface
, sizeof(ifr
.ifr_name
));
452 memset(&nwid
, 0, sizeof(nwid
));
453 strlcpy(nwid
.i_name
, interface
, sizeof(nwid
.i_name
));
454 nwid
.i_type
= IEEE80211_IOC_SSID
;
455 nwid
.i_data
= network_id
;
456 nwid
.i_len
= sizeof(network_id
);
459 if ((inwid
= ioctl(s
, SIOCG80211NWID
, (caddr_t
)&ifr
)) == -1) {
465 if ((inwid
= ioctl(s
, SIOCG80211
, (caddr_t
)&nwid
)) == -1) {
473 if (nwid
.i_len
< sizeof(network_id
))
474 len
= nwid
.i_len
+ 1;
476 len
= sizeof(network_id
);
478 strlcpy(network_id
, (const char *)nwid
.i_nwid
, len
);
481 network_id
[len
- 1] = '\0';
492 * scans interfaces and returns the first found wireless interface
494 * <pointer to wnic> = success, NULL = no nic found
500 char nic
[IF_NAMESIZE
];
501 struct ifaddrs
*ifap
= NULL
, *ifa
= NULL
;
503 memset(nic
, 0, sizeof(nic
));
505 if (getifaddrs(&ifap
) != 0)
506 errx(1, "getifaddrs");
508 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
509 if (strcmp(nic
, ifa
->ifa_name
)) {
510 if (get_wep(ifa
->ifa_name
) != -1) {
511 r
= strdup(ifa
->ifa_name
);
515 strlcpy(nic
, ifa
->ifa_name
, sizeof(nic
));
525 * check if the monitored interface still exists
527 * 0 = interface gone, 1 = interface exists
530 check_nic(const char *interface
)
533 char nic
[IF_NAMESIZE
];
534 struct ifaddrs
*ifap
= NULL
, *ifa
= NULL
;
536 memset(nic
, 0, sizeof(nic
));
538 if (getifaddrs(&ifap
) != 0)
539 errx(1, "getifaddrs");
541 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
542 if (strcmp(nic
, ifa
->ifa_name
)) {
543 if (!strcmp(ifa
->ifa_name
, interface
)) {
548 strlcpy(nic
, ifa
->ifa_name
, sizeof(nic
));
558 * translate the result of media speed to human readable string
560 * <pointer to speed> = success, NULL = no data / error
563 translate_speed(const char *mode
)
567 for (i
= 0; speed
[i
] != NULL
; i
++) {
568 if (!strcmp(mode
, speed
[i
]))
569 return (speed
[i
+ 1]);