add libiwinfo (moved from LuCI trunk)

SVN-Revision: 29403
owl
Jo-Philipp Wich 2011-12-03 13:57:38 +00:00
parent ac82296c53
commit b222319c0b
24 changed files with 10947 additions and 0 deletions

112
package/iwinfo/Makefile Normal file
View File

@ -0,0 +1,112 @@
#
# Copyright (C) 2010-2011 Jo-Philipp Wich <xm@subsignal.org>
#
# This is free software, licensed under the GPL 2 license.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=libiwinfo
PKG_RELEASE:=18
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/libiwinfo
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Generalized Wireless Information Library (iwinfo)
DEPENDS:=+PACKAGE_kmod-mac80211:libnl-tiny
MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
endef
define Package/libiwinfo/description
Wireless information library with consistent interface for proprietary Broadcom,
madwifi, nl80211 and wext driver interfaces.
endef
define Package/libiwinfo-lua
SUBMENU:=Lua
SECTION:=lang
CATEGORY:=Languages
TITLE:=libiwinfo Lua binding
DEPENDS:=+libiwinfo +liblua +lua
MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
endef
define Package/libiwinfo-lua/description
This is the Lua binding for the iwinfo library. It provides access to all enabled
backends.
endef
define Package/iwinfo
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Generalized Wireless Information utility
DEPENDS:=+libiwinfo
MAINTAINER:=Jo-Philipp Wich <xm@subsignal.org>
endef
define Package/iwinfo/description
Command line frontend for the wireless information library.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
IWINFO_BACKENDS := \
$(if $(CONFIG_PACKAGE_kmod-brcm-wl),wl) \
$(if $(CONFIG_PACKAGE_kmod-brcm-wl-mini),wl) \
$(if $(CONFIG_PACKAGE_kmod-brcm-wl-mimo),wl) \
$(if $(CONFIG_PACKAGE_kmod-madwifi),madwifi) \
$(if $(CONFIG_PACKAGE_kmod-mac80211),nl80211)
TARGET_CFLAGS += \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
-I$(STAGING_DIR)/usr/include \
-D_GNU_SOURCE
MAKE_FLAGS += \
FPIC="$(FPIC)" \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
BACKENDS="$(IWINFO_BACKENDS)"
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/iwinfo
$(CP) $(PKG_BUILD_DIR)/include/iwinfo.h $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/include/iwinfo/* $(1)/usr/include/iwinfo/
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so $(1)/usr/lib/libiwinfo.so
$(INSTALL_DIR) $(1)/usr/lib/lua
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so
endef
define Package/libiwinfo/install
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so $(1)/usr/lib/libiwinfo.so
endef
define Package/libiwinfo-lua/install
$(INSTALL_DIR) $(1)/usr/lib/lua
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so
endef
define Package/iwinfo/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/bin/iwinfo
endef
$(eval $(call BuildPackage,libiwinfo))
$(eval $(call BuildPackage,libiwinfo-lua))
$(eval $(call BuildPackage,iwinfo))

339
package/iwinfo/src/COPYING Normal file
View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,44 @@
IWINFO_BACKENDS = $(BACKENDS)
IWINFO_CFLAGS = $(CFLAGS) -std=gnu99 -fstrict-aliasing -Iinclude
IWINFO_LIB = libiwinfo.so
IWINFO_LIB_LDFLAGS = $(LDFLAGS) -shared
IWINFO_LIB_OBJ = iwinfo_utils.o iwinfo_wext.o iwinfo_wext_scan.o iwinfo_lib.o
IWINFO_LUA = iwinfo.so
IWINFO_LUA_LDFLAGS = $(LDFLAGS) -shared -L. -liwinfo -llua
IWINFO_LUA_OBJ = iwinfo_lua.o
IWINFO_CLI = iwinfo
IWINFO_CLI_LDFLAGS = $(LDFLAGS) -L. -liwinfo
IWINFO_CLI_OBJ = iwinfo_cli.o
ifneq ($(filter wl,$(IWINFO_BACKENDS)),)
IWINFO_CFLAGS += -DUSE_WL
IWINFO_LIB_OBJ += iwinfo_wl.o
endif
ifneq ($(filter madwifi,$(IWINFO_BACKENDS)),)
IWINFO_CFLAGS += -DUSE_MADWIFI
IWINFO_LIB_OBJ += iwinfo_madwifi.o
endif
ifneq ($(filter nl80211,$(IWINFO_BACKENDS)),)
IWINFO_CFLAGS += -DUSE_NL80211
IWINFO_CLI_LDFLAGS += -lnl-tiny
IWINFO_LIB_LDFLAGS += -lnl-tiny
IWINFO_LIB_OBJ += iwinfo_nl80211.o
endif
%.o: %.c
$(CC) $(IWINFO_CFLAGS) $(FPIC) -c -o $@ $<
compile: clean $(IWINFO_LIB_OBJ) $(IWINFO_LUA_OBJ) $(IWINFO_CLI_OBJ)
$(CC) $(IWINFO_LIB_LDFLAGS) -o $(IWINFO_LIB) $(IWINFO_LIB_OBJ)
$(CC) $(IWINFO_LUA_LDFLAGS) -o $(IWINFO_LUA) $(IWINFO_LUA_OBJ)
$(CC) $(IWINFO_CLI_LDFLAGS) -o $(IWINFO_CLI) $(IWINFO_CLI_OBJ)
clean:
rm -f *.o $(IWINFO_LIB) $(IWINFO_LUA) $(IWINFO_CLI)

View File

@ -0,0 +1,143 @@
#ifndef __IWINFO_H_
#define __IWINFO_H_
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <glob.h>
#include <ctype.h>
#include <dirent.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#define IWINFO_BUFSIZE 24 * 1024
#define IWINFO_ESSID_MAX_SIZE 32
#define IWINFO_80211_A (1 << 0)
#define IWINFO_80211_B (1 << 1)
#define IWINFO_80211_G (1 << 2)
#define IWINFO_80211_N (1 << 3)
#define IWINFO_CIPHER_NONE (1 << 0)
#define IWINFO_CIPHER_WEP40 (1 << 1)
#define IWINFO_CIPHER_TKIP (1 << 2)
#define IWINFO_CIPHER_WRAP (1 << 3)
#define IWINFO_CIPHER_CCMP (1 << 4)
#define IWINFO_CIPHER_WEP104 (1 << 5)
#define IWINFO_CIPHER_AESOCB (1 << 6)
#define IWINFO_CIPHER_CKIP (1 << 7)
#define IWINFO_KMGMT_NONE (1 << 0)
#define IWINFO_KMGMT_8021x (1 << 1)
#define IWINFO_KMGMT_PSK (1 << 2)
#define IWINFO_AUTH_OPEN (1 << 0)
#define IWINFO_AUTH_SHARED (1 << 1)
extern const char *IWINFO_CIPHER_NAMES[];
extern const char *IWINFO_KMGMT_NAMES[];
extern const char *IWINFO_AUTH_NAMES[];
struct iwinfo_assoclist_entry {
uint8_t mac[6];
int8_t signal;
int8_t noise;
};
struct iwinfo_txpwrlist_entry {
uint8_t dbm;
uint16_t mw;
};
struct iwinfo_freqlist_entry {
uint8_t channel;
uint32_t mhz;
uint8_t restricted;
};
struct iwinfo_crypto_entry {
uint8_t enabled;
uint8_t wpa_version;
uint8_t group_ciphers;
uint8_t pair_ciphers;
uint8_t auth_suites;
uint8_t auth_algs;
};
struct iwinfo_scanlist_entry {
uint8_t mac[6];
uint8_t ssid[IWINFO_ESSID_MAX_SIZE+1];
uint8_t mode[8];
uint8_t channel;
uint8_t signal;
uint8_t quality;
uint8_t quality_max;
struct iwinfo_crypto_entry crypto;
};
struct iwinfo_country_entry {
uint16_t iso3166;
uint8_t ccode[4];
};
struct iwinfo_iso3166_label {
uint16_t iso3166;
uint8_t name[28];
};
extern const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[];
struct iwinfo_ops {
int (*channel)(const char *, int *);
int (*frequency)(const char *, int *);
int (*txpower)(const char *, int *);
int (*bitrate)(const char *, int *);
int (*signal)(const char *, int *);
int (*noise)(const char *, int *);
int (*quality)(const char *, int *);
int (*quality_max)(const char *, int *);
int (*mbssid_support)(const char *, int *);
int (*hwmodelist)(const char *, int *);
int (*mode)(const char *, char *);
int (*ssid)(const char *, char *);
int (*bssid)(const char *, char *);
int (*country)(const char *, char *);
int (*encryption)(const char *, char *);
int (*assoclist)(const char *, char *, int *);
int (*txpwrlist)(const char *, char *, int *);
int (*scanlist)(const char *, char *, int *);
int (*freqlist)(const char *, char *, int *);
int (*countrylist)(const char *, char *, int *);
void (*close)(void);
};
const char * iwinfo_type(const char *ifname);
const struct iwinfo_ops * iwinfo_backend(const char *ifname);
void iwinfo_finish(void);
#include "iwinfo/wext.h"
#ifdef USE_WL
#include "iwinfo/wl.h"
#endif
#ifdef USE_MADWIFI
#include "iwinfo/madwifi.h"
#endif
#ifdef USE_NL80211
#include "iwinfo/nl80211.h"
#endif
#endif

View File

@ -0,0 +1,107 @@
/*
* Custom OID/ioctl definitions for
* Broadcom 802.11abg Networking Device Driver
*
* Definitions subject to change without notice.
*
* Copyright 2006, Broadcom Corporation
* All Rights Reserved.
*
* THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
* KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
* SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
*
*/
#ifndef _BROADCOM_H
#define _BROADCOM_H
#define WL_MCSSET_LEN 16
#define WL_MAX_STA_COUNT 32
#define WL_BSS_RSSI_OFFSET 82
#define WL_BSS_NOISE_OFFSET 84
#define WLC_IOCTL_MAGIC 0x14e46c77
#define WLC_IOCTL_MAXLEN 8192
#define WLC_CNTRY_BUF_SZ 4
#define WLC_GET_MAGIC 0
#define WLC_GET_RATE 12
#define WLC_GET_INFRA 19
#define WLC_GET_AUTH 21
#define WLC_GET_BSSID 23
#define WLC_GET_SSID 25
#define WLC_GET_CHANNEL 29
#define WLC_GET_PASSIVE 48
#define WLC_GET_COUNTRY 83
#define WLC_GET_REVINFO 98
#define WLC_GET_AP 117
#define WLC_GET_RSSI 127
#define WLC_GET_WSEC 133
#define WLC_GET_PHY_NOISE 135
#define WLC_GET_BSS_INFO 136
#define WLC_GET_ASSOCLIST 159
#define WLC_GET_WPA_AUTH 164
#define WLC_GET_COUNTRY_LIST 261
#define WLC_GET_VAR 262
struct wl_ether_addr {
uint8_t octet[6];
};
struct wl_maclist {
uint count;
struct wl_ether_addr ea[1];
};
typedef struct wl_sta_rssi {
int rssi;
char mac[6];
uint16_t foo;
} wl_sta_rssi_t;
typedef struct wlc_ssid {
uint32_t ssid_len;
unsigned char ssid[32];
} wlc_ssid_t;
/* Linux network driver ioctl encoding */
typedef struct wl_ioctl {
uint32_t cmd; /* common ioctl definition */
void *buf; /* pointer to user buffer */
uint32_t len; /* length of user buffer */
uint8_t set; /* get or set request (optional) */
uint32_t used; /* bytes read or written (optional) */
uint32_t needed; /* bytes needed (optional) */
} wl_ioctl_t;
/* Revision info */
typedef struct wlc_rev_info {
uint vendorid; /* PCI vendor id */
uint deviceid; /* device id of chip */
uint radiorev; /* radio revision */
uint chiprev; /* chip revision */
uint corerev; /* core revision */
uint boardid; /* board identifier (usu. PCI sub-device id) */
uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */
uint boardrev; /* board revision */
uint driverrev; /* driver version */
uint ucoderev; /* microcode version */
uint bus; /* bus type */
uint chipnum; /* chip number */
} wlc_rev_info_t;
typedef struct wl_country_list {
uint32_t buflen;
uint32_t band_set;
uint32_t band;
uint32_t count;
char country_abbrev[1];
} wl_country_list_t;
#endif

View File

@ -0,0 +1,158 @@
/*
* Header bits derived from MadWifi source:
* Copyright (c) 2001 Atsushi Onoe
* Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Distributed under the terms of the GPLv2 license.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MADWIFI_H
#define _MADWIFI_H
/* ieee80211.h */
#define IEEE80211_ADDR_LEN 6
#define IEEE80211_RATE_VAL 0x7f
/* ieee80211_crypto.h */
#define IEEE80211_KEYBUF_SIZE 16
#define IEEE80211_MICBUF_SIZE 16
#define IEEE80211_TID_SIZE 17
#define IEEE80211_CIPHER_WEP 0
#define IEEE80211_CIPHER_TKIP 1
#define IEEE80211_CIPHER_AES_OCB 2
#define IEEE80211_CIPHER_AES_CCM 3
#define IEEE80211_CIPHER_CKIP 5
#define IEEE80211_CIPHER_NONE 6
#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE + 1)
/* ieee80211_ioctl.h */
#define IEEE80211_KEY_DEFAULT 0x80
#define IEEE80211_CHAN_MAX 255
#define IEEE80211_CHAN_BYTES 32
#define IEEE80211_RATE_MAXSIZE 15
#define IEEE80211_IOCTL_GETKEY (SIOCDEVPRIVATE+3)
#define IEEE80211_IOCTL_STA_STATS (SIOCDEVPRIVATE+5)
#define IEEE80211_IOCTL_STA_INFO (SIOCDEVPRIVATE+6)
#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1)
#define IEEE80211_IOCTL_GETMODE (SIOCIWFIRSTPRIV+3)
#define IEEE80211_IOCTL_GETCHANLIST (SIOCIWFIRSTPRIV+7)
#define IEEE80211_IOCTL_GETCHANINFO (SIOCIWFIRSTPRIV+13)
#define SIOC80211IFCREATE (SIOCDEVPRIVATE+7)
#define SIOC80211IFDESTROY (SIOCDEVPRIVATE+8)
#define IEEE80211_CLONE_BSSID 0x0001 /* allocate unique mac/bssid */
#define IEEE80211_NO_STABEACONS 0x0002 /* Do not setup the station beacon timers */
struct ieee80211_clone_params {
char icp_name[IFNAMSIZ]; /* device name */
u_int16_t icp_opmode; /* operating mode */
u_int16_t icp_flags; /* see below */
};
enum ieee80211_opmode {
IEEE80211_M_STA = 1, /* infrastructure station */
IEEE80211_M_IBSS = 0, /* IBSS (adhoc) station */
IEEE80211_M_AHDEMO = 3, /* Old lucent compatible adhoc demo */
IEEE80211_M_HOSTAP = 6, /* Software Access Point */
IEEE80211_M_MONITOR = 8, /* Monitor mode */
IEEE80211_M_WDS = 2, /* WDS link */
};
enum {
IEEE80211_PARAM_AUTHMODE = 3, /* authentication mode */
IEEE80211_PARAM_MCASTCIPHER = 5, /* multicast/default cipher */
IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */
IEEE80211_PARAM_UCASTCIPHERS = 7, /* unicast cipher suites */
IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */
};
/*
* Authentication mode.
*/
enum ieee80211_authmode {
IEEE80211_AUTH_NONE = 0,
IEEE80211_AUTH_OPEN = 1, /* open */
IEEE80211_AUTH_SHARED = 2, /* shared-key */
IEEE80211_AUTH_8021X = 3, /* 802.1x */
IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */
/* NB: these are used only for ioctls */
IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x/PSK */
};
struct ieee80211_channel {
u_int16_t ic_freq; /* setting in MHz */
u_int16_t ic_flags; /* see below */
u_int8_t ic_ieee; /* IEEE channel number */
int8_t ic_maxregpower; /* maximum regulatory tx power in dBm */
int8_t ic_maxpower; /* maximum tx power in dBm */
int8_t ic_minpower; /* minimum tx power in dBm */
u_int8_t ic_scanflags;
u_int8_t ic_idletime; /* phy idle time in % */
};
struct ieee80211req_key {
u_int8_t ik_type; /* key/cipher type */
u_int8_t ik_pad;
u_int16_t ik_keyix; /* key index */
u_int8_t ik_keylen; /* key length in bytes */
u_int8_t ik_flags;
u_int8_t ik_macaddr[IEEE80211_ADDR_LEN];
u_int64_t ik_keyrsc; /* key receive sequence counter */
u_int64_t ik_keytsc; /* key transmit sequence counter */
u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
};
struct ieee80211req_chanlist {
u_int8_t ic_channels[IEEE80211_CHAN_BYTES];
};
struct ieee80211req_chaninfo {
u_int ic_nchans;
struct ieee80211_channel ic_chans[IEEE80211_CHAN_MAX];
};
struct ieee80211req_sta_info {
u_int16_t isi_len; /* length (mult of 4) */
u_int16_t isi_freq; /* MHz */
u_int16_t isi_flags; /* channel flags */
u_int16_t isi_state; /* state flags */
u_int8_t isi_authmode; /* authentication algorithm */
u_int8_t isi_rssi;
int8_t isi_noise;
u_int16_t isi_capinfo; /* capabilities */
u_int8_t isi_athflags; /* Atheros capabilities */
u_int8_t isi_erp; /* ERP element */
u_int8_t isi_macaddr[IEEE80211_ADDR_LEN];
u_int8_t isi_nrates; /* negotiated rates */
u_int8_t isi_rates[IEEE80211_RATE_MAXSIZE];
u_int8_t isi_txrate; /* index to isi_rates[] */
u_int16_t isi_ie_len; /* IE length */
u_int16_t isi_associd; /* assoc response */
u_int16_t isi_txpower; /* current tx power */
u_int16_t isi_vlan; /* vlan tag */
u_int16_t isi_txseqs[17]; /* seq to be transmitted */
u_int16_t isi_rxseqs[17]; /* seq previous for qos frames*/
u_int16_t isi_inact; /* inactivity timer */
u_int8_t isi_uapsd; /* UAPSD queues */
u_int8_t isi_opmode; /* sta operating mode */
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
/*
* iwinfo - Wireless Information Library - Lua Headers
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_LUALUB_H_
#define __IWINFO_LUALIB_H_
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "iwinfo.h"
#include "iwinfo/wext_scan.h"
#define IWINFO_META "iwinfo"
#define IWINFO_WEXT_META "iwinfo.wext"
#ifdef USE_WL
#define IWINFO_WL_META "iwinfo.wl"
#endif
#ifdef USE_MADWIFI
#define IWINFO_MADWIFI_META "iwinfo.madwifi"
#endif
#ifdef USE_NL80211
#define IWINFO_NL80211_META "iwinfo.nl80211"
#endif
#define LUA_REG(type,op) \
{ #op, iwinfo_L_##type##_##op }
#define LUA_WRAP_INT(type,op) \
static int iwinfo_L_##type##_##op(lua_State *L) \
{ \
const char *ifname = luaL_checkstring(L, 1); \
int rv; \
if( !type##_get_##op(ifname, &rv) ) \
lua_pushnumber(L, rv); \
else \
lua_pushnil(L); \
return 1; \
}
#define LUA_WRAP_STRING(type,op) \
static int iwinfo_L_##type##_##op(lua_State *L) \
{ \
const char *ifname = luaL_checkstring(L, 1); \
char rv[IWINFO_BUFSIZE]; \
memset(rv, 0, IWINFO_BUFSIZE); \
if( !type##_get_##op(ifname, rv) ) \
lua_pushstring(L, rv); \
else \
lua_pushnil(L); \
return 1; \
}
#define LUA_WRAP_LIST(type,op) \
static int iwinfo_L_##type##_##op(lua_State *L) \
{ \
return iwinfo_L_##op(L, type##_get_##op); \
}
#endif

View File

@ -0,0 +1,75 @@
/*
* iwinfo - Wireless Information Library - Madwifi Headers
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_MADWIFI_H_
#define __IWINFO_MADWIFI_H_
#include <fcntl.h>
#include "iwinfo.h"
#include "iwinfo/utils.h"
#include "iwinfo/api/madwifi.h"
int madwifi_probe(const char *ifname);
int madwifi_get_mode(const char *ifname, char *buf);
int madwifi_get_ssid(const char *ifname, char *buf);
int madwifi_get_bssid(const char *ifname, char *buf);
int madwifi_get_country(const char *ifname, char *buf);
int madwifi_get_channel(const char *ifname, int *buf);
int madwifi_get_frequency(const char *ifname, int *buf);
int madwifi_get_txpower(const char *ifname, int *buf);
int madwifi_get_bitrate(const char *ifname, int *buf);
int madwifi_get_signal(const char *ifname, int *buf);
int madwifi_get_noise(const char *ifname, int *buf);
int madwifi_get_quality(const char *ifname, int *buf);
int madwifi_get_quality_max(const char *ifname, int *buf);
int madwifi_get_encryption(const char *ifname, char *buf);
int madwifi_get_assoclist(const char *ifname, char *buf, int *len);
int madwifi_get_txpwrlist(const char *ifname, char *buf, int *len);
int madwifi_get_scanlist(const char *ifname, char *buf, int *len);
int madwifi_get_freqlist(const char *ifname, char *buf, int *len);
int madwifi_get_countrylist(const char *ifname, char *buf, int *len);
int madwifi_get_hwmodelist(const char *ifname, int *buf);
int madwifi_get_mbssid_support(const char *ifname, int *buf);
void madwifi_close(void);
static const struct iwinfo_ops madwifi_ops = {
.channel = madwifi_get_channel,
.frequency = madwifi_get_frequency,
.txpower = madwifi_get_txpower,
.bitrate = madwifi_get_bitrate,
.signal = madwifi_get_signal,
.noise = madwifi_get_noise,
.quality = madwifi_get_quality,
.quality_max = madwifi_get_quality_max,
.mbssid_support = madwifi_get_mbssid_support,
.hwmodelist = madwifi_get_hwmodelist,
.mode = madwifi_get_mode,
.ssid = madwifi_get_ssid,
.bssid = madwifi_get_bssid,
.country = madwifi_get_country,
.encryption = madwifi_get_encryption,
.assoclist = madwifi_get_assoclist,
.txpwrlist = madwifi_get_txpwrlist,
.scanlist = madwifi_get_scanlist,
.freqlist = madwifi_get_freqlist,
.countrylist = madwifi_get_countrylist,
.close = madwifi_close
};
#endif

View File

@ -0,0 +1,106 @@
/*
* iwinfo - Wireless Information Library - NL80211 Headers
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_NL80211_H_
#define __IWINFO_NL80211_H_
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <signal.h>
#include <sys/un.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include "iwinfo.h"
#include "iwinfo/utils.h"
#include "iwinfo/api/nl80211.h"
struct nl80211_state {
struct nl_sock *nl_sock;
struct nl_cache *nl_cache;
struct genl_family *nl80211;
};
struct nl80211_msg_conveyor {
struct nl_msg *msg;
struct nl_cb *cb;
};
struct nl80211_rssi_rate {
int16_t rate;
int8_t rssi;
};
struct nl80211_array_buf {
void *buf;
int count;
};
int nl80211_probe(const char *ifname);
int nl80211_get_mode(const char *ifname, char *buf);
int nl80211_get_ssid(const char *ifname, char *buf);
int nl80211_get_bssid(const char *ifname, char *buf);
int nl80211_get_country(const char *ifname, char *buf);
int nl80211_get_channel(const char *ifname, int *buf);
int nl80211_get_frequency(const char *ifname, int *buf);
int nl80211_get_txpower(const char *ifname, int *buf);
int nl80211_get_bitrate(const char *ifname, int *buf);
int nl80211_get_signal(const char *ifname, int *buf);
int nl80211_get_noise(const char *ifname, int *buf);
int nl80211_get_quality(const char *ifname, int *buf);
int nl80211_get_quality_max(const char *ifname, int *buf);
int nl80211_get_encryption(const char *ifname, char *buf);
int nl80211_get_assoclist(const char *ifname, char *buf, int *len);
int nl80211_get_txpwrlist(const char *ifname, char *buf, int *len);
int nl80211_get_scanlist(const char *ifname, char *buf, int *len);
int nl80211_get_freqlist(const char *ifname, char *buf, int *len);
int nl80211_get_countrylist(const char *ifname, char *buf, int *len);
int nl80211_get_hwmodelist(const char *ifname, int *buf);
int nl80211_get_mbssid_support(const char *ifname, int *buf);
void nl80211_close(void);
static const struct iwinfo_ops nl80211_ops = {
.channel = nl80211_get_channel,
.frequency = nl80211_get_frequency,
.txpower = nl80211_get_txpower,
.bitrate = nl80211_get_bitrate,
.signal = nl80211_get_signal,
.noise = nl80211_get_noise,
.quality = nl80211_get_quality,
.quality_max = nl80211_get_quality_max,
.mbssid_support = nl80211_get_mbssid_support,
.hwmodelist = nl80211_get_hwmodelist,
.mode = nl80211_get_mode,
.ssid = nl80211_get_ssid,
.bssid = nl80211_get_bssid,
.country = nl80211_get_country,
.encryption = nl80211_get_encryption,
.assoclist = nl80211_get_assoclist,
.txpwrlist = nl80211_get_txpwrlist,
.scanlist = nl80211_get_scanlist,
.freqlist = nl80211_get_freqlist,
.countrylist = nl80211_get_countrylist,
.close = nl80211_close
};
#endif

View File

@ -0,0 +1,40 @@
/*
* iwinfo - Wireless Information Library - Utility Headers
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_UTILS_H_
#define __IWINFO_UTILS_H_
#include <sys/socket.h>
#include <net/if.h>
#include "iwinfo.h"
#define LOG10_MAGIC 1.25892541179
int iwinfo_ioctl(int cmd, void *ifr);
int iwinfo_dbm2mw(int in);
int iwinfo_mw2dbm(int in);
int iwinfo_ifup(const char *ifname);
int iwinfo_ifdown(const char *ifname);
int iwinfo_ifmac(const char *ifname);
void iwinfo_close(void);
#endif

View File

@ -0,0 +1,76 @@
/*
* iwinfo - Wireless Information Library - Linux Wireless Extension Headers
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_WEXT_H_
#define __IWINFO_WEXT_H_
#include <fcntl.h>
#include "iwinfo.h"
#include "iwinfo/utils.h"
#include "iwinfo/api/wext.h"
int wext_probe(const char *ifname);
int wext_get_mode(const char *ifname, char *buf);
int wext_get_ssid(const char *ifname, char *buf);
int wext_get_bssid(const char *ifname, char *buf);
int wext_get_country(const char *ifname, char *buf);
int wext_get_channel(const char *ifname, int *buf);
int wext_get_frequency(const char *ifname, int *buf);
int wext_get_txpower(const char *ifname, int *buf);
int wext_get_bitrate(const char *ifname, int *buf);
int wext_get_signal(const char *ifname, int *buf);
int wext_get_noise(const char *ifname, int *buf);
int wext_get_quality(const char *ifname, int *buf);
int wext_get_quality_max(const char *ifname, int *buf);
int wext_get_encryption(const char *ifname, char *buf);
int wext_get_assoclist(const char *ifname, char *buf, int *len);
int wext_get_txpwrlist(const char *ifname, char *buf, int *len);
int wext_get_scanlist(const char *ifname, char *buf, int *len);
int wext_get_freqlist(const char *ifname, char *buf, int *len);
int wext_get_countrylist(const char *ifname, char *buf, int *len);
int wext_get_hwmodelist(const char *ifname, int *buf);
int wext_get_mbssid_support(const char *ifname, int *buf);
void wext_close(void);
static const struct iwinfo_ops wext_ops = {
.channel = wext_get_channel,
.frequency = wext_get_frequency,
.txpower = wext_get_txpower,
.bitrate = wext_get_bitrate,
.signal = wext_get_signal,
.noise = wext_get_noise,
.quality = wext_get_quality,
.quality_max = wext_get_quality_max,
.mbssid_support = wext_get_mbssid_support,
.hwmodelist = wext_get_hwmodelist,
.mode = wext_get_mode,
.ssid = wext_get_ssid,
.bssid = wext_get_bssid,
.country = wext_get_country,
.encryption = wext_get_encryption,
.assoclist = wext_get_assoclist,
.txpwrlist = wext_get_txpwrlist,
.scanlist = wext_get_scanlist,
.freqlist = wext_get_freqlist,
.countrylist = wext_get_countrylist,
.close = wext_close
};
#endif

View File

@ -0,0 +1,380 @@
/*
* iwinfo - Wireless Information Library - Linux Wireless Extension Headers
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_WEXT_SCAN_H_
#define __IWINFO_WEXT_SCAN_H_
#include <fcntl.h>
#include "iwinfo.h"
#include "iwinfo/utils.h"
#include "iwinfo/api/wext.h"
typedef struct stream_descr
{
char * end; /* End of the stream */
char * current; /* Current event in stream of events */
char * value; /* Current value in event */
} stream_descr;
/*
* Describe how a standard IOCTL looks like.
*/
struct iw_ioctl_description
{
uint8_t header_type; /* NULL, iw_point or other */
uint8_t token_type; /* Future */
uint16_t token_size; /* Granularity of payload */
uint16_t min_tokens; /* Min acceptable token number */
uint16_t max_tokens; /* Max acceptable token number */
uint32_t flags; /* Special handling of the request */
};
/* Type of headers we know about (basically union iwreq_data) */
#define IW_HEADER_TYPE_NULL 0 /* Not available */
#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
#define IW_HEADER_TYPE_UINT 4 /* __u32 */
#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
/* Handling flags */
/* Most are not implemented. I just use them as a reminder of some
* cool features we might need one day ;-) */
#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
/* Wrapper level flags */
#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */
/* SET : Omit payload from generated iwevent */
#define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */
/* Driver level flags */
#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
/*
* Meta-data about all the standard Wireless Extension request we
* know about.
*/
static const struct iw_ioctl_description standard_ioctl_descr[] = {
[SIOCSIWCOMMIT - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_NULL,
},
[SIOCGIWNAME - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_CHAR,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWNWID - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
.flags = IW_DESCR_FLAG_EVENT,
},
[SIOCGIWNWID - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWFREQ - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_FREQ,
.flags = IW_DESCR_FLAG_EVENT,
},
[SIOCGIWFREQ - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_FREQ,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWMODE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_UINT,
.flags = IW_DESCR_FLAG_EVENT,
},
[SIOCGIWMODE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_UINT,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWSENS - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWSENS - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWRANGE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_NULL,
},
[SIOCGIWRANGE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = sizeof(struct iw_range),
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWPRIV - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_NULL,
},
[SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */
.header_type = IW_HEADER_TYPE_NULL,
},
[SIOCSIWSTATS - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_NULL,
},
[SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */
.header_type = IW_HEADER_TYPE_NULL,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWSPY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct sockaddr),
.max_tokens = IW_MAX_SPY,
},
[SIOCGIWSPY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct sockaddr) +
sizeof(struct iw_quality),
.max_tokens = IW_MAX_SPY,
},
[SIOCSIWTHRSPY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct iw_thrspy),
.min_tokens = 1,
.max_tokens = 1,
},
[SIOCGIWTHRSPY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct iw_thrspy),
.min_tokens = 1,
.max_tokens = 1,
},
[SIOCSIWAP - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR,
},
[SIOCGIWAP - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWMLME - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.min_tokens = sizeof(struct iw_mlme),
.max_tokens = sizeof(struct iw_mlme),
},
[SIOCGIWAPLIST - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct sockaddr) +
sizeof(struct iw_quality),
.max_tokens = IW_MAX_AP,
.flags = IW_DESCR_FLAG_NOMAX,
},
[SIOCSIWSCAN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.min_tokens = 0,
.max_tokens = sizeof(struct iw_scan_req),
},
[SIOCGIWSCAN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_SCAN_MAX_DATA,
.flags = IW_DESCR_FLAG_NOMAX,
},
[SIOCSIWESSID - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_ESSID_MAX_SIZE + 1,
.flags = IW_DESCR_FLAG_EVENT,
},
[SIOCGIWESSID - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_ESSID_MAX_SIZE + 1,
.flags = IW_DESCR_FLAG_DUMP,
},
[SIOCSIWNICKN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_ESSID_MAX_SIZE + 1,
},
[SIOCGIWNICKN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_ESSID_MAX_SIZE + 1,
},
[SIOCSIWRATE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWRATE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWRTS - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWRTS - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWFRAG - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWFRAG - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWTXPOW - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWTXPOW - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWRETRY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWRETRY - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWENCODE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_ENCODING_TOKEN_MAX,
.flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT,
},
[SIOCGIWENCODE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_ENCODING_TOKEN_MAX,
.flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT,
},
[SIOCSIWPOWER - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWPOWER - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWMODUL - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWMODUL - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWGENIE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_GENERIC_IE_MAX,
},
[SIOCGIWGENIE - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_GENERIC_IE_MAX,
},
[SIOCSIWAUTH - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCGIWAUTH - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
[SIOCSIWENCODEEXT - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.min_tokens = sizeof(struct iw_encode_ext),
.max_tokens = sizeof(struct iw_encode_ext) +
IW_ENCODING_TOKEN_MAX,
},
[SIOCGIWENCODEEXT - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.min_tokens = sizeof(struct iw_encode_ext),
.max_tokens = sizeof(struct iw_encode_ext) +
IW_ENCODING_TOKEN_MAX,
},
[SIOCSIWPMKSA - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.min_tokens = sizeof(struct iw_pmksa),
.max_tokens = sizeof(struct iw_pmksa),
},
};
/*
* Meta-data about all the additional standard Wireless Extension events
* we know about.
*/
static const struct iw_ioctl_description standard_event_descr[] = {
[IWEVTXDROP - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR,
},
[IWEVQUAL - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_QUAL,
},
[IWEVCUSTOM - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_CUSTOM_MAX,
},
[IWEVREGISTERED - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR,
},
[IWEVEXPIRED - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR,
},
[IWEVGENIE - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_GENERIC_IE_MAX,
},
[IWEVMICHAELMICFAILURE - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = sizeof(struct iw_michaelmicfailure),
},
[IWEVASSOCREQIE - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_GENERIC_IE_MAX,
},
[IWEVASSOCRESPIE - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = IW_GENERIC_IE_MAX,
},
[IWEVPMKIDCAND - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = 1,
.max_tokens = sizeof(struct iw_pmkid_cand),
},
};
/* Size (in bytes) of various events */
static const int event_type_size[] = {
IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
0,
IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
0,
IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
0,
IW_EV_POINT_PK_LEN, /* Without variable payload */
IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
};
static const unsigned int standard_ioctl_num =
(sizeof(standard_ioctl_descr) / sizeof(struct iw_ioctl_description));
static const unsigned int standard_event_num =
(sizeof(standard_event_descr) / sizeof(struct iw_ioctl_description));
#define IW_IE_CYPHER_NUM 8
#define IW_IE_KEY_MGMT_NUM 3
#endif

View File

@ -0,0 +1,76 @@
/*
* iwinfo - Wireless Information Library - Broadcom wl.o Headers
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __IWINFO_WL_H_
#define __IWINFO_WL_H_
#include <fcntl.h>
#include "iwinfo.h"
#include "iwinfo/utils.h"
#include "iwinfo/api/broadcom.h"
int wl_probe(const char *ifname);
int wl_get_mode(const char *ifname, char *buf);
int wl_get_ssid(const char *ifname, char *buf);
int wl_get_bssid(const char *ifname, char *buf);
int wl_get_country(const char *ifname, char *buf);
int wl_get_channel(const char *ifname, int *buf);
int wl_get_frequency(const char *ifname, int *buf);
int wl_get_txpower(const char *ifname, int *buf);
int wl_get_bitrate(const char *ifname, int *buf);
int wl_get_signal(const char *ifname, int *buf);
int wl_get_noise(const char *ifname, int *buf);
int wl_get_quality(const char *ifname, int *buf);
int wl_get_quality_max(const char *ifname, int *buf);
int wl_get_enctype(const char *ifname, char *buf);
int wl_get_encryption(const char *ifname, char *buf);
int wl_get_assoclist(const char *ifname, char *buf, int *len);
int wl_get_txpwrlist(const char *ifname, char *buf, int *len);
int wl_get_scanlist(const char *ifname, char *buf, int *len);
int wl_get_freqlist(const char *ifname, char *buf, int *len);
int wl_get_countrylist(const char *ifname, char *buf, int *len);
int wl_get_hwmodelist(const char *ifname, int *buf);
int wl_get_mbssid_support(const char *ifname, int *buf);
void wl_close(void);
static const struct iwinfo_ops wl_ops = {
.channel = wl_get_channel,
.frequency = wl_get_frequency,
.txpower = wl_get_txpower,
.bitrate = wl_get_bitrate,
.signal = wl_get_signal,
.noise = wl_get_noise,
.quality = wl_get_quality,
.quality_max = wl_get_quality_max,
.mbssid_support = wl_get_mbssid_support,
.hwmodelist = wl_get_hwmodelist,
.mode = wl_get_mode,
.ssid = wl_get_ssid,
.bssid = wl_get_bssid,
.country = wl_get_country,
.encryption = wl_get_encryption,
.assoclist = wl_get_assoclist,
.txpwrlist = wl_get_txpwrlist,
.scanlist = wl_get_scanlist,
.freqlist = wl_get_freqlist,
.countrylist = wl_get_countrylist,
.close = wl_close
};
#endif

View File

@ -0,0 +1,683 @@
/*
* iwinfo - Wireless Information Library - Command line frontend
*
* Copyright (C) 2011 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#include <stdio.h>
#include "iwinfo.h"
static char * format_bssid(unsigned char *mac)
{
static char buf[18];
snprintf(buf, sizeof(buf), "%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return buf;
}
static char * format_ssid(char *ssid)
{
static char buf[IWINFO_ESSID_MAX_SIZE+3];
if (ssid && ssid[0])
snprintf(buf, sizeof(buf), "\"%s\"", ssid);
else
snprintf(buf, sizeof(buf), "unknown");
return buf;
}
static char * format_channel(int ch)
{
static char buf[8];
if (ch <= 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%d", ch);
return buf;
}
static char * format_frequency(int freq)
{
static char buf[10];
if (freq <= 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%.3f GHz", ((float)freq / 1000.0));
return buf;
}
static char * format_txpower(int pwr)
{
static char buf[10];
if (pwr < 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%d dBm", pwr);
return buf;
}
static char * format_quality(int qual)
{
static char buf[8];
if (qual < 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%d", qual);
return buf;
}
static char * format_quality_max(int qmax)
{
static char buf[8];
if (qmax < 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%d", qmax);
return buf;
}
static char * format_signal(int sig)
{
static char buf[10];
if (!sig)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%d dBm", sig);
return buf;
}
static char * format_noise(int noise)
{
static char buf[10];
if (!noise)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%d dBm", noise);
return buf;
}
static char * format_rate(int rate)
{
static char buf[14];
if (rate <= 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "%.1f MBit/s", ((float)rate / 1000.0));
return buf;
}
static char * format_enc_ciphers(int ciphers)
{
static char str[128] = { 0 };
char *pos = str;
if (ciphers & IWINFO_CIPHER_WEP40)
pos += sprintf(pos, "WEP-40, ");
if (ciphers & IWINFO_CIPHER_WEP104)
pos += sprintf(pos, "WEP-104, ");
if (ciphers & IWINFO_CIPHER_TKIP)
pos += sprintf(pos, "TKIP, ");
if (ciphers & IWINFO_CIPHER_CCMP)
pos += sprintf(pos, "CCMP, ");
if (ciphers & IWINFO_CIPHER_WRAP)
pos += sprintf(pos, "WRAP, ");
if (ciphers & IWINFO_CIPHER_AESOCB)
pos += sprintf(pos, "AES-OCB, ");
if (ciphers & IWINFO_CIPHER_CKIP)
pos += sprintf(pos, "CKIP, ");
if (!ciphers || (ciphers & IWINFO_CIPHER_NONE))
pos += sprintf(pos, "NONE, ");
*(pos - 2) = 0;
return str;
}
static char * format_enc_suites(int suites)
{
static char str[64] = { 0 };
char *pos = str;
if (suites & IWINFO_KMGMT_PSK)
pos += sprintf(pos, "PSK/");
if (suites & IWINFO_KMGMT_8021x)
pos += sprintf(pos, "802.1X/");
if (!suites || (suites & IWINFO_KMGMT_NONE))
pos += sprintf(pos, "NONE/");
*(pos - 1) = 0;
return str;
}
static char * format_encryption(struct iwinfo_crypto_entry *c)
{
static char buf[512];
if (!c)
{
snprintf(buf, sizeof(buf), "unknown");
}
else if (c->enabled)
{
/* WEP */
if (c->auth_algs && !c->wpa_version)
{
if ((c->auth_algs & IWINFO_AUTH_OPEN) &&
(c->auth_algs & IWINFO_AUTH_SHARED))
{
snprintf(buf, sizeof(buf), "WEP Open/Shared (%s)",
format_enc_ciphers(c->pair_ciphers));
}
else if (c->auth_algs & IWINFO_AUTH_OPEN)
{
snprintf(buf, sizeof(buf), "WEP Open System (%s)",
format_enc_ciphers(c->pair_ciphers));
}
else if (c->auth_algs & IWINFO_AUTH_SHARED)
{
snprintf(buf, sizeof(buf), "WEP Shared Auth (%s)",
format_enc_ciphers(c->pair_ciphers));
}
}
/* WPA */
else if (c->wpa_version)
{
switch (c->wpa_version) {
case 3:
snprintf(buf, sizeof(buf), "mixed WPA/WPA2 %s (%s)",
format_enc_suites(c->auth_suites),
format_enc_ciphers(c->pair_ciphers & c->group_ciphers));
break;
case 2:
snprintf(buf, sizeof(buf), "WPA2 %s (%s)",
format_enc_suites(c->auth_suites),
format_enc_ciphers(c->pair_ciphers & c->group_ciphers));
break;
case 1:
snprintf(buf, sizeof(buf), "WPA %s (%s)",
format_enc_suites(c->auth_suites),
format_enc_ciphers(c->pair_ciphers & c->group_ciphers));
break;
}
}
else
{
snprintf(buf, sizeof(buf), "none");
}
}
else
{
snprintf(buf, sizeof(buf), "none");
}
return buf;
}
static char * format_hwmodes(int modes)
{
static char buf[12];
if (modes <= 0)
snprintf(buf, sizeof(buf), "unknown");
else
snprintf(buf, sizeof(buf), "802.11%s%s%s%s",
(modes & IWINFO_80211_A) ? "a" : "",
(modes & IWINFO_80211_B) ? "b" : "",
(modes & IWINFO_80211_G) ? "g" : "",
(modes & IWINFO_80211_N) ? "n" : "");
return buf;
}
static const char * print_type(const struct iwinfo_ops *iw, const char *ifname)
{
const char *type = iwinfo_type(ifname);
return type ? type : "unknown";
}
static char * print_ssid(const struct iwinfo_ops *iw, const char *ifname)
{
char buf[IWINFO_ESSID_MAX_SIZE+1] = { 0 };
if (iw->ssid(ifname, buf))
memset(buf, 0, sizeof(buf));
return format_ssid(buf);
}
static char * print_bssid(const struct iwinfo_ops *iw, const char *ifname)
{
static char buf[18] = { 0 };
if (iw->bssid(ifname, buf))
snprintf(buf, sizeof(buf), "00:00:00:00:00:00");
return buf;
}
static char * print_mode(const struct iwinfo_ops *iw, const char *ifname)
{
static char buf[128];
if (iw->mode(ifname, buf))
snprintf(buf, sizeof(buf), "unknown");
return buf;
}
static char * print_channel(const struct iwinfo_ops *iw, const char *ifname)
{
int ch;
if (iw->channel(ifname, &ch))
ch = -1;
return format_channel(ch);
}
static char * print_frequency(const struct iwinfo_ops *iw, const char *ifname)
{
int freq;
if (iw->frequency(ifname, &freq))
freq = -1;
return format_frequency(freq);
}
static char * print_txpower(const struct iwinfo_ops *iw, const char *ifname)
{
int pwr;
if (iw->txpower(ifname, &pwr))
pwr = -1;
return format_txpower(pwr);
}
static char * print_quality(const struct iwinfo_ops *iw, const char *ifname)
{
int qual;
if (iw->quality(ifname, &qual))
qual = -1;
return format_quality(qual);
}
static char * print_quality_max(const struct iwinfo_ops *iw, const char *ifname)
{
int qmax;
if (iw->quality_max(ifname, &qmax))
qmax = -1;
return format_quality_max(qmax);
}
static char * print_signal(const struct iwinfo_ops *iw, const char *ifname)
{
int sig;
if (iw->signal(ifname, &sig))
sig = 0;
return format_signal(sig);
}
static char * print_noise(const struct iwinfo_ops *iw, const char *ifname)
{
int noise;
if (iw->noise(ifname, &noise))
noise = 0;
return format_noise(noise);
}
static char * print_rate(const struct iwinfo_ops *iw, const char *ifname)
{
int rate;
if (iw->bitrate(ifname, &rate))
rate = -1;
return format_rate(rate);
}
static char * print_encryption(const struct iwinfo_ops *iw, const char *ifname)
{
struct iwinfo_crypto_entry c = { 0 };
if (iw->encryption(ifname, (char *)&c))
return format_encryption(NULL);
return format_encryption(&c);
}
static char * print_hwmodes(const struct iwinfo_ops *iw, const char *ifname)
{
int modes;
if (iw->hwmodelist(ifname, &modes))
modes = -1;
return format_hwmodes(modes);
}
static char * print_mbssid_supp(const struct iwinfo_ops *iw, const char *ifname)
{
int supp;
static char buf[4];
if (iw->mbssid_support(ifname, &supp))
snprintf(buf, sizeof(buf), "no");
else
snprintf(buf, sizeof(buf), "%s", supp ? "yes" : "no");
return buf;
}
static void print_info(const struct iwinfo_ops *iw, const char *ifname)
{
printf("%-9s ESSID: %s\n",
ifname,
print_ssid(iw, ifname));
printf(" Access Point: %s\n",
print_bssid(iw, ifname));
printf(" Type: %s HW Mode(s): %s\n",
print_type(iw, ifname),
print_hwmodes(iw, ifname));
printf(" Mode: %s Channel: %s (%s)\n",
print_mode(iw, ifname),
print_channel(iw, ifname),
print_frequency(iw, ifname));
printf(" Tx-Power: %s Link Quality: %s/%s\n",
print_txpower(iw, ifname),
print_quality(iw, ifname),
print_quality_max(iw, ifname));
printf(" Signal: %s Noise: %s\n",
print_signal(iw, ifname),
print_noise(iw, ifname));
printf(" Bit Rate: %s\n",
print_rate(iw, ifname));
printf(" Encryption: %s\n",
print_encryption(iw, ifname));
printf(" Supports VAPs: %s\n",
print_mbssid_supp(iw, ifname));
}
static void print_scanlist(const struct iwinfo_ops *iw, const char *ifname)
{
int i, x, len;
char buf[IWINFO_BUFSIZE];
struct iwinfo_scanlist_entry *e;
if (iw->scanlist(ifname, buf, &len))
{
printf("Scanning not possible\n\n");
return;
}
else if (len <= 0)
{
printf("No scan results\n\n");
return;
}
for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_scanlist_entry), x++)
{
e = (struct iwinfo_scanlist_entry *) &buf[i];
printf("Cell %02d - Address: %s\n",
x,
format_bssid(e->mac));
printf(" ESSID: %s\n",
format_ssid(e->ssid));
printf(" Mode: %s Channel: %s\n",
e->mode ? (char *)e->mode : "unknown",
format_channel(e->channel));
printf(" Signal: %s Quality: %s/%s\n",
format_signal(e->signal - 0x100),
format_quality(e->quality),
format_quality_max(e->quality_max));
printf(" Encryption: %s\n\n",
format_encryption(&e->crypto));
}
}
static void print_txpwrlist(const struct iwinfo_ops *iw, const char *ifname)
{
int len, pwr, i;
char buf[IWINFO_BUFSIZE];
struct iwinfo_txpwrlist_entry *e;
if (iw->txpwrlist(ifname, buf, &len) || len <= 0)
{
printf("No TX power information available\n");
return;
}
if (iw->txpower(ifname, &pwr))
pwr = -1;
for (i = 0; i < len; i += sizeof(struct iwinfo_txpwrlist_entry))
{
e = (struct iwinfo_txpwrlist_entry *) &buf[i];
printf("%s%3d dBm (%4d mW)\n",
(pwr == e->dbm) ? "*" : " ",
e->dbm,
e->mw);
}
}
static void print_freqlist(const struct iwinfo_ops *iw, const char *ifname)
{
int i, len, ch;
char buf[IWINFO_BUFSIZE];
struct iwinfo_freqlist_entry *e;
if (iw->freqlist(ifname, buf, &len) || len <= 0)
{
printf("No frequency information available\n");
return;
}
if (iw->channel(ifname, &ch))
ch = -1;
for (i = 0; i < len; i += sizeof(struct iwinfo_freqlist_entry))
{
e = (struct iwinfo_freqlist_entry *) &buf[i];
printf("%s %s (Channel %s)%s\n",
(ch == e->channel) ? "*" : " ",
format_frequency(e->mhz),
format_channel(e->channel),
e->restricted ? " [restricted]" : "");
}
}
static void print_assoclist(const struct iwinfo_ops *iw, const char *ifname)
{
int i, len;
char buf[IWINFO_BUFSIZE];
struct iwinfo_assoclist_entry *e;
if (iw->assoclist(ifname, buf, &len))
{
printf("No information available\n");
return;
}
else if (len <= 0)
{
printf("No station connected\n");
return;
}
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
{
e = (struct iwinfo_assoclist_entry *) &buf[i];
printf("%s %s / %s (SNR %d)\n",
format_bssid(e->mac),
format_signal(e->signal),
format_noise(e->noise),
(e->signal - e->noise));
}
}
static char * lookup_country(char *buf, int len, int iso3166)
{
int i;
struct iwinfo_country_entry *c;
for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
{
c = (struct iwinfo_country_entry *) &buf[i];
if (c->iso3166 == iso3166)
return c->ccode;
}
return NULL;
}
static void print_countrylist(const struct iwinfo_ops *iw, const char *ifname)
{
int len;
char buf[IWINFO_BUFSIZE];
char *ccode;
char curcode[3];
const struct iwinfo_iso3166_label *l;
if (iw->countrylist(ifname, buf, &len))
{
printf("No country code information available\n");
return;
}
if (iw->country(ifname, curcode))
memset(curcode, 0, sizeof(curcode));
for (l = IWINFO_ISO3166_NAMES; l->iso3166; l++)
{
if ((ccode = lookup_country(buf, len, l->iso3166)) != NULL)
{
printf("%s %4s %c%c\n",
strncmp(ccode, curcode, 2) ? " " : "*",
ccode, (l->iso3166 / 256), (l->iso3166 % 256));
}
}
}
int main(int argc, char **argv)
{
int i;
const struct iwinfo_ops *iw;
if (argc < 3)
{
fprintf(stderr,
"Usage:\n"
" iwinfo <device> info\n"
" iwinfo <device> scan\n"
" iwinfo <device> txpowerlist\n"
" iwinfo <device> freqlist\n"
" iwinfo <device> assoclist\n"
" iwinfo <device> countrylist\n"
);
return 1;
}
iw = iwinfo_backend(argv[1]);
if (!iw)
{
fprintf(stderr, "No such wireless device: %s\n", argv[1]);
return 1;
}
for (i = 2; i < argc; i++)
{
switch(argv[i][0])
{
case 'i':
print_info(iw, argv[1]);
break;
case 's':
print_scanlist(iw, argv[1]);
break;
case 't':
print_txpwrlist(iw, argv[1]);
break;
case 'f':
print_freqlist(iw, argv[1]);
break;
case 'a':
print_assoclist(iw, argv[1]);
break;
case 'c':
print_countrylist(iw, argv[1]);
break;
default:
fprintf(stderr, "Unknown command: %s\n", argv[i]);
return 1;
}
}
iwinfo_finish();
return 0;
}

View File

@ -0,0 +1,376 @@
/*
* iwinfo - Wireless Information Library - Lua Bindings
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#include "iwinfo.h"
/*
* name constants
*/
const char *IWINFO_CIPHER_NAMES[] = {
"NONE",
"WEP40",
"TKIP",
"WRAP",
"CCMP",
"WEP104",
"AES-OCB",
"CKIP",
};
const char *IWINFO_KMGMT_NAMES[] = {
"NONE",
"802.1X",
"PSK",
};
const char *IWINFO_AUTH_NAMES[] = {
"OPEN",
"SHARED",
};
/*
* ISO3166 country labels
*/
const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[] = {
{ 0x3030 /* 00 */, "World" },
{ 0x4144 /* AD */, "Andorra" },
{ 0x4145 /* AE */, "United Arab Emirates" },
{ 0x4146 /* AF */, "Afghanistan" },
{ 0x4147 /* AG */, "Antigua and Barbuda" },
{ 0x4149 /* AI */, "Anguilla" },
{ 0x414C /* AL */, "Albania" },
{ 0x414D /* AM */, "Armenia" },
{ 0x414E /* AN */, "Netherlands Antilles" },
{ 0x414F /* AO */, "Angola" },
{ 0x4151 /* AQ */, "Antarctica" },
{ 0x4152 /* AR */, "Argentina" },
{ 0x4153 /* AS */, "American Samoa" },
{ 0x4154 /* AT */, "Austria" },
{ 0x4155 /* AU */, "Australia" },
{ 0x4157 /* AW */, "Aruba" },
{ 0x4158 /* AX */, "Aland Islands" },
{ 0x415A /* AZ */, "Azerbaijan" },
{ 0x4241 /* BA */, "Bosnia and Herzegovina" },
{ 0x4242 /* BB */, "Barbados" },
{ 0x4244 /* BD */, "Bangladesh" },
{ 0x4245 /* BE */, "Belgium" },
{ 0x4246 /* BF */, "Burkina Faso" },
{ 0x4247 /* BG */, "Bulgaria" },
{ 0x4248 /* BH */, "Bahrain" },
{ 0x4249 /* BI */, "Burundi" },
{ 0x424A /* BJ */, "Benin" },
{ 0x424C /* BL */, "Saint Barthelemy" },
{ 0x424D /* BM */, "Bermuda" },
{ 0x424E /* BN */, "Brunei Darussalam" },
{ 0x424F /* BO */, "Bolivia" },
{ 0x4252 /* BR */, "Brazil" },
{ 0x4253 /* BS */, "Bahamas" },
{ 0x4254 /* BT */, "Bhutan" },
{ 0x4256 /* BV */, "Bouvet Island" },
{ 0x4257 /* BW */, "Botswana" },
{ 0x4259 /* BY */, "Belarus" },
{ 0x425A /* BZ */, "Belize" },
{ 0x4341 /* CA */, "Canada" },
{ 0x4343 /* CC */, "Cocos (Keeling) Islands" },
{ 0x4344 /* CD */, "Congo" },
{ 0x4346 /* CF */, "Central African Republic" },
{ 0x4347 /* CG */, "Congo" },
{ 0x4348 /* CH */, "Switzerland" },
{ 0x4349 /* CI */, "Cote d'Ivoire" },
{ 0x434B /* CK */, "Cook Islands" },
{ 0x434C /* CL */, "Chile" },
{ 0x434D /* CM */, "Cameroon" },
{ 0x434E /* CN */, "China" },
{ 0x434F /* CO */, "Colombia" },
{ 0x4352 /* CR */, "Costa Rica" },
{ 0x4355 /* CU */, "Cuba" },
{ 0x4356 /* CV */, "Cape Verde" },
{ 0x4358 /* CX */, "Christmas Island" },
{ 0x4359 /* CY */, "Cyprus" },
{ 0x435A /* CZ */, "Czech Republic" },
{ 0x4445 /* DE */, "Germany" },
{ 0x444A /* DJ */, "Djibouti" },
{ 0x444B /* DK */, "Denmark" },
{ 0x444D /* DM */, "Dominica" },
{ 0x444F /* DO */, "Dominican Republic" },
{ 0x445A /* DZ */, "Algeria" },
{ 0x4543 /* EC */, "Ecuador" },
{ 0x4545 /* EE */, "Estonia" },
{ 0x4547 /* EG */, "Egypt" },
{ 0x4548 /* EH */, "Western Sahara" },
{ 0x4552 /* ER */, "Eritrea" },
{ 0x4553 /* ES */, "Spain" },
{ 0x4554 /* ET */, "Ethiopia" },
{ 0x4649 /* FI */, "Finland" },
{ 0x464A /* FJ */, "Fiji" },
{ 0x464B /* FK */, "Falkland Islands" },
{ 0x464D /* FM */, "Micronesia" },
{ 0x464F /* FO */, "Faroe Islands" },
{ 0x4652 /* FR */, "France" },
{ 0x4741 /* GA */, "Gabon" },
{ 0x4742 /* GB */, "United Kingdom" },
{ 0x4744 /* GD */, "Grenada" },
{ 0x4745 /* GE */, "Georgia" },
{ 0x4746 /* GF */, "French Guiana" },
{ 0x4747 /* GG */, "Guernsey" },
{ 0x4748 /* GH */, "Ghana" },
{ 0x4749 /* GI */, "Gibraltar" },
{ 0x474C /* GL */, "Greenland" },
{ 0x474D /* GM */, "Gambia" },
{ 0x474E /* GN */, "Guinea" },
{ 0x4750 /* GP */, "Guadeloupe" },
{ 0x4751 /* GQ */, "Equatorial Guinea" },
{ 0x4752 /* GR */, "Greece" },
{ 0x4753 /* GS */, "South Georgia" },
{ 0x4754 /* GT */, "Guatemala" },
{ 0x4755 /* GU */, "Guam" },
{ 0x4757 /* GW */, "Guinea-Bissau" },
{ 0x4759 /* GY */, "Guyana" },
{ 0x484B /* HK */, "Hong Kong" },
{ 0x484D /* HM */, "Heard and McDonald Islands" },
{ 0x484E /* HN */, "Honduras" },
{ 0x4852 /* HR */, "Croatia" },
{ 0x4854 /* HT */, "Haiti" },
{ 0x4855 /* HU */, "Hungary" },
{ 0x4944 /* ID */, "Indonesia" },
{ 0x4945 /* IE */, "Ireland" },
{ 0x494C /* IL */, "Israel" },
{ 0x494D /* IM */, "Isle of Man" },
{ 0x494E /* IN */, "India" },
{ 0x494F /* IO */, "Chagos Islands" },
{ 0x4951 /* IQ */, "Iraq" },
{ 0x4952 /* IR */, "Iran" },
{ 0x4953 /* IS */, "Iceland" },
{ 0x4954 /* IT */, "Italy" },
{ 0x4A45 /* JE */, "Jersey" },
{ 0x4A4D /* JM */, "Jamaica" },
{ 0x4A4F /* JO */, "Jordan" },
{ 0x4A50 /* JP */, "Japan" },
{ 0x4B45 /* KE */, "Kenya" },
{ 0x4B47 /* KG */, "Kyrgyzstan" },
{ 0x4B48 /* KH */, "Cambodia" },
{ 0x4B49 /* KI */, "Kiribati" },
{ 0x4B4D /* KM */, "Comoros" },
{ 0x4B4E /* KN */, "Saint Kitts and Nevis" },
{ 0x4B50 /* KP */, "North Korea" },
{ 0x4B52 /* KR */, "South Korea" },
{ 0x4B57 /* KW */, "Kuwait" },
{ 0x4B59 /* KY */, "Cayman Islands" },
{ 0x4B5A /* KZ */, "Kazakhstan" },
{ 0x4C41 /* LA */, "Laos" },
{ 0x4C42 /* LB */, "Lebanon" },
{ 0x4C43 /* LC */, "Saint Lucia" },
{ 0x4C49 /* LI */, "Liechtenstein" },
{ 0x4C4B /* LK */, "Sri Lanka" },
{ 0x4C52 /* LR */, "Liberia" },
{ 0x4C53 /* LS */, "Lesotho" },
{ 0x4C54 /* LT */, "Lithuania" },
{ 0x4C55 /* LU */, "Luxembourg" },
{ 0x4C56 /* LV */, "Latvia" },
{ 0x4C59 /* LY */, "Libyan Arab Jamahiriya" },
{ 0x4D41 /* MA */, "Morocco" },
{ 0x4D43 /* MC */, "Monaco" },
{ 0x4D44 /* MD */, "Moldova" },
{ 0x4D45 /* ME */, "Montenegro" },
{ 0x4D46 /* MF */, "Saint Martin (French part)" },
{ 0x4D47 /* MG */, "Madagascar" },
{ 0x4D48 /* MH */, "Marshall Islands" },
{ 0x4D4B /* MK */, "Macedonia" },
{ 0x4D4C /* ML */, "Mali" },
{ 0x4D4D /* MM */, "Myanmar" },
{ 0x4D4E /* MN */, "Mongolia" },
{ 0x4D4F /* MO */, "Macao" },
{ 0x4D50 /* MP */, "Northern Mariana Islands" },
{ 0x4D51 /* MQ */, "Martinique" },
{ 0x4D52 /* MR */, "Mauritania" },
{ 0x4D53 /* MS */, "Montserrat" },
{ 0x4D54 /* MT */, "Malta" },
{ 0x4D55 /* MU */, "Mauritius" },
{ 0x4D56 /* MV */, "Maldives" },
{ 0x4D57 /* MW */, "Malawi" },
{ 0x4D58 /* MX */, "Mexico" },
{ 0x4D59 /* MY */, "Malaysia" },
{ 0x4D5A /* MZ */, "Mozambique" },
{ 0x4E41 /* NA */, "Namibia" },
{ 0x4E43 /* NC */, "New Caledonia" },
{ 0x4E45 /* NE */, "Niger" },
{ 0x4E46 /* NF */, "Norfolk Island" },
{ 0x4E47 /* NG */, "Nigeria" },
{ 0x4E49 /* NI */, "Nicaragua" },
{ 0x4E4C /* NL */, "Netherlands" },
{ 0x4E4F /* NO */, "Norway" },
{ 0x4E50 /* NP */, "Nepal" },
{ 0x4E52 /* NR */, "Nauru" },
{ 0x4E55 /* NU */, "Niue" },
{ 0x4E5A /* NZ */, "New Zealand" },
{ 0x4F4D /* OM */, "Oman" },
{ 0x5041 /* PA */, "Panama" },
{ 0x5045 /* PE */, "Peru" },
{ 0x5046 /* PF */, "French Polynesia" },
{ 0x5047 /* PG */, "Papua New Guinea" },
{ 0x5048 /* PH */, "Philippines" },
{ 0x504B /* PK */, "Pakistan" },
{ 0x504C /* PL */, "Poland" },
{ 0x504D /* PM */, "Saint Pierre and Miquelon" },
{ 0x504E /* PN */, "Pitcairn" },
{ 0x5052 /* PR */, "Puerto Rico" },
{ 0x5053 /* PS */, "Palestinian Territory" },
{ 0x5054 /* PT */, "Portugal" },
{ 0x5057 /* PW */, "Palau" },
{ 0x5059 /* PY */, "Paraguay" },
{ 0x5141 /* QA */, "Qatar" },
{ 0x5245 /* RE */, "Reunion" },
{ 0x524F /* RO */, "Romania" },
{ 0x5253 /* RS */, "Serbia" },
{ 0x5255 /* RU */, "Russian Federation" },
{ 0x5257 /* RW */, "Rwanda" },
{ 0x5341 /* SA */, "Saudi Arabia" },
{ 0x5342 /* SB */, "Solomon Islands" },
{ 0x5343 /* SC */, "Seychelles" },
{ 0x5344 /* SD */, "Sudan" },
{ 0x5345 /* SE */, "Sweden" },
{ 0x5347 /* SG */, "Singapore" },
{ 0x5348 /* SH */, "St. Helena and Dependencies" },
{ 0x5349 /* SI */, "Slovenia" },
{ 0x534A /* SJ */, "Svalbard and Jan Mayen" },
{ 0x534B /* SK */, "Slovakia" },
{ 0x534C /* SL */, "Sierra Leone" },
{ 0x534D /* SM */, "San Marino" },
{ 0x534E /* SN */, "Senegal" },
{ 0x534F /* SO */, "Somalia" },
{ 0x5352 /* SR */, "Suriname" },
{ 0x5354 /* ST */, "Sao Tome and Principe" },
{ 0x5356 /* SV */, "El Salvador" },
{ 0x5359 /* SY */, "Syrian Arab Republic" },
{ 0x535A /* SZ */, "Swaziland" },
{ 0x5443 /* TC */, "Turks and Caicos Islands" },
{ 0x5444 /* TD */, "Chad" },
{ 0x5446 /* TF */, "French Southern Territories" },
{ 0x5447 /* TG */, "Togo" },
{ 0x5448 /* TH */, "Thailand" },
{ 0x544A /* TJ */, "Tajikistan" },
{ 0x544B /* TK */, "Tokelau" },
{ 0x544C /* TL */, "Timor-Leste" },
{ 0x544D /* TM */, "Turkmenistan" },
{ 0x544E /* TN */, "Tunisia" },
{ 0x544F /* TO */, "Tonga" },
{ 0x5452 /* TR */, "Turkey" },
{ 0x5454 /* TT */, "Trinidad and Tobago" },
{ 0x5456 /* TV */, "Tuvalu" },
{ 0x5457 /* TW */, "Taiwan" },
{ 0x545A /* TZ */, "Tanzania" },
{ 0x5541 /* UA */, "Ukraine" },
{ 0x5547 /* UG */, "Uganda" },
{ 0x554D /* UM */, "U.S. Minor Outlying Islands" },
{ 0x5553 /* US */, "United States" },
{ 0x5559 /* UY */, "Uruguay" },
{ 0x555A /* UZ */, "Uzbekistan" },
{ 0x5641 /* VA */, "Vatican City State" },
{ 0x5643 /* VC */, "St. Vincent and Grenadines" },
{ 0x5645 /* VE */, "Venezuela" },
{ 0x5647 /* VG */, "Virgin Islands, British" },
{ 0x5649 /* VI */, "Virgin Islands, U.S." },
{ 0x564E /* VN */, "Viet Nam" },
{ 0x5655 /* VU */, "Vanuatu" },
{ 0x5746 /* WF */, "Wallis and Futuna" },
{ 0x5753 /* WS */, "Samoa" },
{ 0x5945 /* YE */, "Yemen" },
{ 0x5954 /* YT */, "Mayotte" },
{ 0x5A41 /* ZA */, "South Africa" },
{ 0x5A4D /* ZM */, "Zambia" },
{ 0x5A57 /* ZW */, "Zimbabwe" },
{ 0, "" }
};
const char * iwinfo_type(const char *ifname)
{
#ifdef USE_NL80211
if (nl80211_probe(ifname))
return "nl80211";
else
#endif
#ifdef USE_MADWIFI
if (madwifi_probe(ifname))
return "madwifi";
else
#endif
#ifdef USE_WL
if (wl_probe(ifname))
return "wl";
else
#endif
if (wext_probe(ifname))
return "wext";
return NULL;
}
const struct iwinfo_ops * iwinfo_backend(const char *ifname)
{
const char *type;
struct iwinfo_ops *ops;
type = iwinfo_type(ifname);
if (!type)
return NULL;
#ifdef USE_NL80211
if (!strcmp(type, "nl80211"))
return &nl80211_ops;
else
#endif
#ifdef USE_MADWIFI
if (!strcmp(type, "madwifi"))
return &madwifi_ops;
else
#endif
#ifdef USE_WL
if (!strcmp(type, "wl"))
return &wl_ops;
else
#endif
if (!strcmp(type, "wext"))
return &wext_ops;
return NULL;
}
void iwinfo_finish(void)
{
#ifdef USE_WL
wl_close();
#endif
#ifdef USE_MADWIFI
madwifi_close();
#endif
#ifdef USE_NL80211
nl80211_close();
#endif
wext_close();
iwinfo_close();
}

View File

@ -0,0 +1,769 @@
/*
* iwinfo - Wireless Information Library - Lua Bindings
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*/
#include "iwinfo/lua.h"
/* Determine type */
static int iwinfo_L_type(lua_State *L)
{
const char *ifname = luaL_checkstring(L, 1);
const char *type = iwinfo_type(ifname);
if (type)
lua_pushstring(L, type);
else
lua_pushnil(L);
return 1;
}
/* Shutdown backends */
static int iwinfo_L__gc(lua_State *L)
{
iwinfo_finish();
return 0;
}
/*
* Build a short textual description of the crypto info
*/
static char * iwinfo_crypto_print_ciphers(int ciphers)
{
static char str[128] = { 0 };
char *pos = str;
if (ciphers & IWINFO_CIPHER_WEP40)
pos += sprintf(pos, "WEP-40, ");
if (ciphers & IWINFO_CIPHER_WEP104)
pos += sprintf(pos, "WEP-104, ");
if (ciphers & IWINFO_CIPHER_TKIP)
pos += sprintf(pos, "TKIP, ");
if (ciphers & IWINFO_CIPHER_CCMP)
pos += sprintf(pos, "CCMP, ");
if (ciphers & IWINFO_CIPHER_WRAP)
pos += sprintf(pos, "WRAP, ");
if (ciphers & IWINFO_CIPHER_AESOCB)
pos += sprintf(pos, "AES-OCB, ");
if (ciphers & IWINFO_CIPHER_CKIP)
pos += sprintf(pos, "CKIP, ");
if (!ciphers || (ciphers & IWINFO_CIPHER_NONE))
pos += sprintf(pos, "NONE, ");
*(pos - 2) = 0;
return str;
}
static char * iwinfo_crypto_print_suites(int suites)
{
static char str[64] = { 0 };
char *pos = str;
if (suites & IWINFO_KMGMT_PSK)
pos += sprintf(pos, "PSK/");
if (suites & IWINFO_KMGMT_8021x)
pos += sprintf(pos, "802.1X/");
if (!suites || (suites & IWINFO_KMGMT_NONE))
pos += sprintf(pos, "NONE/");
*(pos - 1) = 0;
return str;
}
static char * iwinfo_crypto_desc(struct iwinfo_crypto_entry *c)
{
static char desc[512] = { 0 };
if (c)
{
if (c->enabled)
{
/* WEP */
if (c->auth_algs && !c->wpa_version)
{
if ((c->auth_algs & IWINFO_AUTH_OPEN) &&
(c->auth_algs & IWINFO_AUTH_SHARED))
{
sprintf(desc, "WEP Open/Shared (%s)",
iwinfo_crypto_print_ciphers(c->pair_ciphers));
}
else if (c->auth_algs & IWINFO_AUTH_OPEN)
{
sprintf(desc, "WEP Open System (%s)",
iwinfo_crypto_print_ciphers(c->pair_ciphers));
}
else if (c->auth_algs & IWINFO_AUTH_SHARED)
{
sprintf(desc, "WEP Shared Auth (%s)",
iwinfo_crypto_print_ciphers(c->pair_ciphers));
}
}
/* WPA */
else if (c->wpa_version)
{
switch (c->wpa_version) {
case 3:
sprintf(desc, "mixed WPA/WPA2 %s (%s)",
iwinfo_crypto_print_suites(c->auth_suites),
iwinfo_crypto_print_ciphers(
c->pair_ciphers & c->group_ciphers));
break;
case 2:
sprintf(desc, "WPA2 %s (%s)",
iwinfo_crypto_print_suites(c->auth_suites),
iwinfo_crypto_print_ciphers(
c->pair_ciphers & c->group_ciphers));
break;
case 1:
sprintf(desc, "WPA %s (%s)",
iwinfo_crypto_print_suites(c->auth_suites),
iwinfo_crypto_print_ciphers(
c->pair_ciphers & c->group_ciphers));
break;
}
}
else
{
sprintf(desc, "None");
}
}
else
{
sprintf(desc, "None");
}
}
else
{
sprintf(desc, "Unknown");
}
return desc;
}
/* Build Lua table from crypto data */
static void iwinfo_L_cryptotable(lua_State *L, struct iwinfo_crypto_entry *c)
{
int i, j;
lua_newtable(L);
lua_pushboolean(L, c->enabled);
lua_setfield(L, -2, "enabled");
lua_pushstring(L, iwinfo_crypto_desc(c));
lua_setfield(L, -2, "description");
lua_pushboolean(L, (c->enabled && !c->wpa_version));
lua_setfield(L, -2, "wep");
lua_pushinteger(L, c->wpa_version);
lua_setfield(L, -2, "wpa");
lua_newtable(L);
for (i = 0, j = 1; i < 8; i++)
{
if (c->pair_ciphers & (1 << i))
{
lua_pushstring(L, IWINFO_CIPHER_NAMES[i]);
lua_rawseti(L, -2, j++);
}
}
lua_setfield(L, -2, "pair_ciphers");
lua_newtable(L);
for (i = 0, j = 1; i < 8; i++)
{
if (c->group_ciphers & (1 << i))
{
lua_pushstring(L, IWINFO_CIPHER_NAMES[i]);
lua_rawseti(L, -2, j++);
}
}
lua_setfield(L, -2, "group_ciphers");
lua_newtable(L);
for (i = 0, j = 1; i < 8; i++)
{
if (c->auth_suites & (1 << i))
{
lua_pushstring(L, IWINFO_KMGMT_NAMES[i]);
lua_rawseti(L, -2, j++);
}
}
lua_setfield(L, -2, "auth_suites");
lua_newtable(L);
for (i = 0, j = 1; i < 8; i++)
{
if (c->auth_algs & (1 << i))
{
lua_pushstring(L, IWINFO_AUTH_NAMES[i]);
lua_rawseti(L, -2, j++);
}
}
lua_setfield(L, -2, "auth_algs");
}
/* Wrapper for assoclist */
static int iwinfo_L_assoclist(lua_State *L, int (*func)(const char *, char *, int *))
{
int i, len;
char rv[IWINFO_BUFSIZE];
char macstr[18];
const char *ifname = luaL_checkstring(L, 1);
struct iwinfo_assoclist_entry *e;
lua_newtable(L);
memset(rv, 0, sizeof(rv));
if (!(*func)(ifname, rv, &len))
{
for (i = 0; i < len; i += sizeof(struct iwinfo_assoclist_entry))
{
e = (struct iwinfo_assoclist_entry *) &rv[i];
sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X",
e->mac[0], e->mac[1], e->mac[2],
e->mac[3], e->mac[4], e->mac[5]);
lua_newtable(L);
lua_pushnumber(L, e->signal);
lua_setfield(L, -2, "signal");
lua_pushnumber(L, e->noise);
lua_setfield(L, -2, "noise");
lua_setfield(L, -2, macstr);
}
}
return 1;
}
/* Wrapper for tx power list */
static int iwinfo_L_txpwrlist(lua_State *L, int (*func)(const char *, char *, int *))
{
int i, x, len;
char rv[IWINFO_BUFSIZE];
const char *ifname = luaL_checkstring(L, 1);
struct iwinfo_txpwrlist_entry *e;
lua_newtable(L);
memset(rv, 0, sizeof(rv));
if (!(*func)(ifname, rv, &len))
{
for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_txpwrlist_entry), x++)
{
e = (struct iwinfo_txpwrlist_entry *) &rv[i];
lua_newtable(L);
lua_pushnumber(L, e->mw);
lua_setfield(L, -2, "mw");
lua_pushnumber(L, e->dbm);
lua_setfield(L, -2, "dbm");
lua_rawseti(L, -2, x);
}
}
return 1;
}
/* Wrapper for scan list */
static int iwinfo_L_scanlist(lua_State *L, int (*func)(const char *, char *, int *))
{
int i, x, len;
char rv[IWINFO_BUFSIZE];
char macstr[18];
const char *ifname = luaL_checkstring(L, 1);
struct iwinfo_scanlist_entry *e;
lua_newtable(L);
memset(rv, 0, sizeof(rv));
if (!(*func)(ifname, rv, &len))
{
for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_scanlist_entry), x++)
{
e = (struct iwinfo_scanlist_entry *) &rv[i];
lua_newtable(L);
/* BSSID */
sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X",
e->mac[0], e->mac[1], e->mac[2],
e->mac[3], e->mac[4], e->mac[5]);
lua_pushstring(L, macstr);
lua_setfield(L, -2, "bssid");
/* ESSID */
if (e->ssid[0])
{
lua_pushstring(L, (char *) e->ssid);
lua_setfield(L, -2, "ssid");
}
/* Channel */
lua_pushinteger(L, e->channel);
lua_setfield(L, -2, "channel");
/* Mode */
lua_pushstring(L, (char *) e->mode);
lua_setfield(L, -2, "mode");
/* Quality, Signal */
lua_pushinteger(L, e->quality);
lua_setfield(L, -2, "quality");
lua_pushinteger(L, e->quality_max);
lua_setfield(L, -2, "quality_max");
lua_pushnumber(L, (e->signal - 0x100));
lua_setfield(L, -2, "signal");
/* Crypto */
iwinfo_L_cryptotable(L, &e->crypto);
lua_setfield(L, -2, "encryption");
lua_rawseti(L, -2, x);
}
}
return 1;
}
/* Wrapper for frequency list */
static int iwinfo_L_freqlist(lua_State *L, int (*func)(const char *, char *, int *))
{
int i, x, len;
char rv[IWINFO_BUFSIZE];
const char *ifname = luaL_checkstring(L, 1);
struct iwinfo_freqlist_entry *e;
lua_newtable(L);
memset(rv, 0, sizeof(rv));
if (!(*func)(ifname, rv, &len))
{
for (i = 0, x = 1; i < len; i += sizeof(struct iwinfo_freqlist_entry), x++)
{
e = (struct iwinfo_freqlist_entry *) &rv[i];
lua_newtable(L);
/* MHz */
lua_pushinteger(L, e->mhz);
lua_setfield(L, -2, "mhz");
/* Channel */
lua_pushinteger(L, e->channel);
lua_setfield(L, -2, "channel");
/* Restricted (DFS/TPC/Radar) */
lua_pushboolean(L, e->restricted);
lua_setfield(L, -2, "restricted");
lua_rawseti(L, -2, x);
}
}
return 1;
}
/* Wrapper for crypto settings */
static int iwinfo_L_encryption(lua_State *L, int (*func)(const char *, char *))
{
const char *ifname = luaL_checkstring(L, 1);
struct iwinfo_crypto_entry c = { 0 };
if (!(*func)(ifname, (char *)&c))
{
iwinfo_L_cryptotable(L, &c);
return 1;
}
lua_pushnil(L);
return 1;
}
/* Wrapper for hwmode list */
static int iwinfo_L_hwmodelist(lua_State *L, int (*func)(const char *, int *))
{
const char *ifname = luaL_checkstring(L, 1);
int hwmodes = 0;
if (!(*func)(ifname, &hwmodes))
{
lua_newtable(L);
lua_pushboolean(L, hwmodes & IWINFO_80211_A);
lua_setfield(L, -2, "a");
lua_pushboolean(L, hwmodes & IWINFO_80211_B);
lua_setfield(L, -2, "b");
lua_pushboolean(L, hwmodes & IWINFO_80211_G);
lua_setfield(L, -2, "g");
lua_pushboolean(L, hwmodes & IWINFO_80211_N);
lua_setfield(L, -2, "n");
return 1;
}
lua_pushnil(L);
return 1;
}
/* Wrapper for mbbsid_support */
static int iwinfo_L_mbssid_support(lua_State *L, int (*func)(const char *, int *))
{
const char *ifname = luaL_checkstring(L, 1);
int support = 0;
if (!(*func)(ifname, &support))
{
lua_pushboolean(L, support);
return 1;
}
lua_pushnil(L);
return 1;
}
/* Wrapper for country list */
static char * iwinfo_L_country_lookup(char *buf, int len, int iso3166)
{
int i;
struct iwinfo_country_entry *c;
for (i = 0; i < len; i += sizeof(struct iwinfo_country_entry))
{
c = (struct iwinfo_country_entry *) &buf[i];
if (c->iso3166 == iso3166)
return c->ccode;
}
return NULL;
}
static int iwinfo_L_countrylist(lua_State *L, int (*func)(const char *, char *, int *))
{
int len, i, j;
char rv[IWINFO_BUFSIZE], alpha2[3];
char *ccode;
const char *ifname = luaL_checkstring(L, 1);
const struct iwinfo_iso3166_label *l;
lua_newtable(L);
memset(rv, 0, sizeof(rv));
if (!(*func)(ifname, rv, &len))
{
for (l = IWINFO_ISO3166_NAMES, j = 1; l->iso3166; l++)
{
if ((ccode = iwinfo_L_country_lookup(rv, len, l->iso3166)) != NULL)
{
sprintf(alpha2, "%c%c",
(l->iso3166 / 256), (l->iso3166 % 256));
lua_newtable(L);
lua_pushstring(L, alpha2);
lua_setfield(L, -2, "alpha2");
lua_pushstring(L, ccode);
lua_setfield(L, -2, "ccode");
lua_pushstring(L, l->name);
lua_setfield(L, -2, "name");
lua_rawseti(L, -2, j++);
}
}
}
return 1;
}
#ifdef USE_WL
/* Broadcom */
LUA_WRAP_INT(wl,channel)
LUA_WRAP_INT(wl,frequency)
LUA_WRAP_INT(wl,txpower)
LUA_WRAP_INT(wl,bitrate)
LUA_WRAP_INT(wl,signal)
LUA_WRAP_INT(wl,noise)
LUA_WRAP_INT(wl,quality)
LUA_WRAP_INT(wl,quality_max)
LUA_WRAP_STRING(wl,mode)
LUA_WRAP_STRING(wl,ssid)
LUA_WRAP_STRING(wl,bssid)
LUA_WRAP_STRING(wl,country)
LUA_WRAP_LIST(wl,assoclist)
LUA_WRAP_LIST(wl,txpwrlist)
LUA_WRAP_LIST(wl,scanlist)
LUA_WRAP_LIST(wl,freqlist)
LUA_WRAP_LIST(wl,countrylist)
LUA_WRAP_LIST(wl,hwmodelist)
LUA_WRAP_LIST(wl,encryption)
LUA_WRAP_LIST(wl,mbssid_support)
#endif
#ifdef USE_MADWIFI
/* Madwifi */
LUA_WRAP_INT(madwifi,channel)
LUA_WRAP_INT(madwifi,frequency)
LUA_WRAP_INT(madwifi,txpower)
LUA_WRAP_INT(madwifi,bitrate)
LUA_WRAP_INT(madwifi,signal)
LUA_WRAP_INT(madwifi,noise)
LUA_WRAP_INT(madwifi,quality)
LUA_WRAP_INT(madwifi,quality_max)
LUA_WRAP_STRING(madwifi,mode)
LUA_WRAP_STRING(madwifi,ssid)
LUA_WRAP_STRING(madwifi,bssid)
LUA_WRAP_STRING(madwifi,country)
LUA_WRAP_LIST(madwifi,assoclist)
LUA_WRAP_LIST(madwifi,txpwrlist)
LUA_WRAP_LIST(madwifi,scanlist)
LUA_WRAP_LIST(madwifi,freqlist)
LUA_WRAP_LIST(madwifi,countrylist)
LUA_WRAP_LIST(madwifi,hwmodelist)
LUA_WRAP_LIST(madwifi,encryption)
LUA_WRAP_LIST(madwifi,mbssid_support)
#endif
#ifdef USE_NL80211
/* NL80211 */
LUA_WRAP_INT(nl80211,channel)
LUA_WRAP_INT(nl80211,frequency)
LUA_WRAP_INT(nl80211,txpower)
LUA_WRAP_INT(nl80211,bitrate)
LUA_WRAP_INT(nl80211,signal)
LUA_WRAP_INT(nl80211,noise)
LUA_WRAP_INT(nl80211,quality)
LUA_WRAP_INT(nl80211,quality_max)
LUA_WRAP_STRING(nl80211,mode)
LUA_WRAP_STRING(nl80211,ssid)
LUA_WRAP_STRING(nl80211,bssid)
LUA_WRAP_STRING(nl80211,country)
LUA_WRAP_LIST(nl80211,assoclist)
LUA_WRAP_LIST(nl80211,txpwrlist)
LUA_WRAP_LIST(nl80211,scanlist)
LUA_WRAP_LIST(nl80211,freqlist)
LUA_WRAP_LIST(nl80211,countrylist)
LUA_WRAP_LIST(nl80211,hwmodelist)
LUA_WRAP_LIST(nl80211,encryption)
LUA_WRAP_LIST(nl80211,mbssid_support)
#endif
/* Wext */
LUA_WRAP_INT(wext,channel)
LUA_WRAP_INT(wext,frequency)
LUA_WRAP_INT(wext,txpower)
LUA_WRAP_INT(wext,bitrate)
LUA_WRAP_INT(wext,signal)
LUA_WRAP_INT(wext,noise)
LUA_WRAP_INT(wext,quality)
LUA_WRAP_INT(wext,quality_max)
LUA_WRAP_STRING(wext,mode)
LUA_WRAP_STRING(wext,ssid)
LUA_WRAP_STRING(wext,bssid)
LUA_WRAP_STRING(wext,country)
LUA_WRAP_LIST(wext,assoclist)
LUA_WRAP_LIST(wext,txpwrlist)
LUA_WRAP_LIST(wext,scanlist)
LUA_WRAP_LIST(wext,freqlist)
LUA_WRAP_LIST(wext,countrylist)
LUA_WRAP_LIST(wext,hwmodelist)
LUA_WRAP_LIST(wext,encryption)
LUA_WRAP_LIST(wext,mbssid_support)
#ifdef USE_WL
/* Broadcom table */
static const luaL_reg R_wl[] = {
LUA_REG(wl,channel),
LUA_REG(wl,frequency),
LUA_REG(wl,txpower),
LUA_REG(wl,bitrate),
LUA_REG(wl,signal),
LUA_REG(wl,noise),
LUA_REG(wl,quality),
LUA_REG(wl,quality_max),
LUA_REG(wl,mode),
LUA_REG(wl,ssid),
LUA_REG(wl,bssid),
LUA_REG(wl,country),
LUA_REG(wl,assoclist),
LUA_REG(wl,txpwrlist),
LUA_REG(wl,scanlist),
LUA_REG(wl,freqlist),
LUA_REG(wl,countrylist),
LUA_REG(wl,hwmodelist),
LUA_REG(wl,encryption),
LUA_REG(wl,mbssid_support),
{ NULL, NULL }
};
#endif
#ifdef USE_MADWIFI
/* Madwifi table */
static const luaL_reg R_madwifi[] = {
LUA_REG(madwifi,channel),
LUA_REG(madwifi,frequency),
LUA_REG(madwifi,txpower),
LUA_REG(madwifi,bitrate),
LUA_REG(madwifi,signal),
LUA_REG(madwifi,noise),
LUA_REG(madwifi,quality),
LUA_REG(madwifi,quality_max),
LUA_REG(madwifi,mode),
LUA_REG(madwifi,ssid),
LUA_REG(madwifi,bssid),
LUA_REG(madwifi,country),
LUA_REG(madwifi,assoclist),
LUA_REG(madwifi,txpwrlist),
LUA_REG(madwifi,scanlist),
LUA_REG(madwifi,freqlist),
LUA_REG(madwifi,countrylist),
LUA_REG(madwifi,hwmodelist),
LUA_REG(madwifi,encryption),
LUA_REG(madwifi,mbssid_support),
{ NULL, NULL }
};
#endif
#ifdef USE_NL80211
/* NL80211 table */
static const luaL_reg R_nl80211[] = {
LUA_REG(nl80211,channel),
LUA_REG(nl80211,frequency),
LUA_REG(nl80211,txpower),
LUA_REG(nl80211,bitrate),
LUA_REG(nl80211,signal),
LUA_REG(nl80211,noise),
LUA_REG(nl80211,quality),
LUA_REG(nl80211,quality_max),
LUA_REG(nl80211,mode),
LUA_REG(nl80211,ssid),
LUA_REG(nl80211,bssid),
LUA_REG(nl80211,country),
LUA_REG(nl80211,assoclist),
LUA_REG(nl80211,txpwrlist),
LUA_REG(nl80211,scanlist),
LUA_REG(nl80211,freqlist),
LUA_REG(nl80211,countrylist),
LUA_REG(nl80211,hwmodelist),
LUA_REG(nl80211,encryption),
LUA_REG(nl80211,mbssid_support),
{ NULL, NULL }
};
#endif
/* Wext table */
static const luaL_reg R_wext[] = {
LUA_REG(wext,channel),
LUA_REG(wext,frequency),
LUA_REG(wext,txpower),
LUA_REG(wext,bitrate),
LUA_REG(wext,signal),
LUA_REG(wext,noise),
LUA_REG(wext,quality),
LUA_REG(wext,quality_max),
LUA_REG(wext,mode),
LUA_REG(wext,ssid),
LUA_REG(wext,bssid),
LUA_REG(wext,country),
LUA_REG(wext,assoclist),
LUA_REG(wext,txpwrlist),
LUA_REG(wext,scanlist),
LUA_REG(wext,freqlist),
LUA_REG(wext,countrylist),
LUA_REG(wext,hwmodelist),
LUA_REG(wext,encryption),
LUA_REG(wext,mbssid_support),
{ NULL, NULL }
};
/* Common */
static const luaL_reg R_common[] = {
{ "type", iwinfo_L_type },
{ "__gc", iwinfo_L__gc },
{ NULL, NULL }
};
LUALIB_API int luaopen_iwinfo(lua_State *L) {
luaL_register(L, IWINFO_META, R_common);
#ifdef USE_WL
luaL_newmetatable(L, IWINFO_WL_META);
luaL_register(L, NULL, R_wl);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setfield(L, -2, "wl");
#endif
#ifdef USE_MADWIFI
luaL_newmetatable(L, IWINFO_MADWIFI_META);
luaL_register(L, NULL, R_madwifi);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setfield(L, -2, "madwifi");
#endif
#ifdef USE_NL80211
luaL_newmetatable(L, IWINFO_NL80211_META);
luaL_register(L, NULL, R_nl80211);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setfield(L, -2, "nl80211");
#endif
luaL_newmetatable(L, IWINFO_WEXT_META);
luaL_register(L, NULL, R_wext);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setfield(L, -2, "wext");
return 1;
}

View File

@ -0,0 +1,989 @@
/*
* iwinfo - Wireless Information Library - Madwifi Backend
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*
* The signal handling code is derived from the official madwifi tools,
* wlanconfig.c in particular. The encryption property handling was
* inspired by the hostapd madwifi driver.
*/
#include "iwinfo/madwifi.h"
#include "iwinfo/wext.h"
/*
* Madwifi ISO 3166 to Country/Region Code mapping.
*/
static struct ISO3166_to_CCode
{
u_int16_t iso3166;
u_int16_t ccode;
} CountryCodes[] = {
{ 0x3030 /* 00 */, 0 }, /* World */
{ 0x4145 /* AE */, 784 }, /* U.A.E. */
{ 0x414C /* AL */, 8 }, /* Albania */
{ 0x414D /* AM */, 51 }, /* Armenia */
{ 0x4152 /* AR */, 32 }, /* Argentina */
{ 0x4154 /* AT */, 40 }, /* Austria */
{ 0x4155 /* AU */, 36 }, /* Australia */
{ 0x415A /* AZ */, 31 }, /* Azerbaijan */
{ 0x4245 /* BE */, 56 }, /* Belgium */
{ 0x4247 /* BG */, 100 }, /* Bulgaria */
{ 0x4248 /* BH */, 48 }, /* Bahrain */
{ 0x424E /* BN */, 96 }, /* Brunei Darussalam */
{ 0x424F /* BO */, 68 }, /* Bolivia */
{ 0x4252 /* BR */, 76 }, /* Brazil */
{ 0x4259 /* BY */, 112 }, /* Belarus */
{ 0x425A /* BZ */, 84 }, /* Belize */
{ 0x4341 /* CA */, 124 }, /* Canada */
{ 0x4348 /* CH */, 756 }, /* Switzerland */
{ 0x434C /* CL */, 152 }, /* Chile */
{ 0x434E /* CN */, 156 }, /* People's Republic of China */
{ 0x434F /* CO */, 170 }, /* Colombia */
{ 0x4352 /* CR */, 188 }, /* Costa Rica */
{ 0x4359 /* CY */, 196 }, /* Cyprus */
{ 0x435A /* CZ */, 203 }, /* Czech Republic */
{ 0x4445 /* DE */, 276 }, /* Germany */
{ 0x444B /* DK */, 208 }, /* Denmark */
{ 0x444F /* DO */, 214 }, /* Dominican Republic */
{ 0x445A /* DZ */, 12 }, /* Algeria */
{ 0x4543 /* EC */, 218 }, /* Ecuador */
{ 0x4545 /* EE */, 233 }, /* Estonia */
{ 0x4547 /* EG */, 818 }, /* Egypt */
{ 0x4553 /* ES */, 724 }, /* Spain */
{ 0x4649 /* FI */, 246 }, /* Finland */
{ 0x464F /* FO */, 234 }, /* Faeroe Islands */
{ 0x4652 /* FR */, 250 }, /* France */
{ 0x4652 /* FR */, 255 }, /* France2 */
{ 0x4742 /* GB */, 826 }, /* United Kingdom */
{ 0x4745 /* GE */, 268 }, /* Georgia */
{ 0x4752 /* GR */, 300 }, /* Greece */
{ 0x4754 /* GT */, 320 }, /* Guatemala */
{ 0x484B /* HK */, 344 }, /* Hong Kong S.A.R., P.R.C. */
{ 0x484E /* HN */, 340 }, /* Honduras */
{ 0x4852 /* HR */, 191 }, /* Croatia */
{ 0x4855 /* HU */, 348 }, /* Hungary */
{ 0x4944 /* ID */, 360 }, /* Indonesia */
{ 0x4945 /* IE */, 372 }, /* Ireland */
{ 0x494C /* IL */, 376 }, /* Israel */
{ 0x494E /* IN */, 356 }, /* India */
{ 0x4951 /* IQ */, 368 }, /* Iraq */
{ 0x4952 /* IR */, 364 }, /* Iran */
{ 0x4953 /* IS */, 352 }, /* Iceland */
{ 0x4954 /* IT */, 380 }, /* Italy */
{ 0x4A4D /* JM */, 388 }, /* Jamaica */
{ 0x4A4F /* JO */, 400 }, /* Jordan */
{ 0x4A50 /* JP */, 392 }, /* Japan */
{ 0x4A50 /* JP */, 393 }, /* Japan (JP1) */
{ 0x4A50 /* JP */, 394 }, /* Japan (JP0) */
{ 0x4A50 /* JP */, 395 }, /* Japan (JP1-1) */
{ 0x4A50 /* JP */, 396 }, /* Japan (JE1) */
{ 0x4A50 /* JP */, 397 }, /* Japan (JE2) */
{ 0x4A50 /* JP */, 399 }, /* Japan (JP6) */
{ 0x4A50 /* JP */, 900 }, /* Japan */
{ 0x4A50 /* JP */, 901 }, /* Japan */
{ 0x4A50 /* JP */, 902 }, /* Japan */
{ 0x4A50 /* JP */, 903 }, /* Japan */
{ 0x4A50 /* JP */, 904 }, /* Japan */
{ 0x4A50 /* JP */, 905 }, /* Japan */
{ 0x4A50 /* JP */, 906 }, /* Japan */
{ 0x4A50 /* JP */, 907 }, /* Japan */
{ 0x4A50 /* JP */, 908 }, /* Japan */
{ 0x4A50 /* JP */, 909 }, /* Japan */
{ 0x4A50 /* JP */, 910 }, /* Japan */
{ 0x4A50 /* JP */, 911 }, /* Japan */
{ 0x4A50 /* JP */, 912 }, /* Japan */
{ 0x4A50 /* JP */, 913 }, /* Japan */
{ 0x4A50 /* JP */, 914 }, /* Japan */
{ 0x4A50 /* JP */, 915 }, /* Japan */
{ 0x4A50 /* JP */, 916 }, /* Japan */
{ 0x4A50 /* JP */, 917 }, /* Japan */
{ 0x4A50 /* JP */, 918 }, /* Japan */
{ 0x4A50 /* JP */, 919 }, /* Japan */
{ 0x4A50 /* JP */, 920 }, /* Japan */
{ 0x4A50 /* JP */, 921 }, /* Japan */
{ 0x4A50 /* JP */, 922 }, /* Japan */
{ 0x4A50 /* JP */, 923 }, /* Japan */
{ 0x4A50 /* JP */, 924 }, /* Japan */
{ 0x4A50 /* JP */, 925 }, /* Japan */
{ 0x4A50 /* JP */, 926 }, /* Japan */
{ 0x4A50 /* JP */, 927 }, /* Japan */
{ 0x4A50 /* JP */, 928 }, /* Japan */
{ 0x4A50 /* JP */, 929 }, /* Japan */
{ 0x4A50 /* JP */, 930 }, /* Japan */
{ 0x4A50 /* JP */, 931 }, /* Japan */
{ 0x4A50 /* JP */, 932 }, /* Japan */
{ 0x4A50 /* JP */, 933 }, /* Japan */
{ 0x4A50 /* JP */, 934 }, /* Japan */
{ 0x4A50 /* JP */, 935 }, /* Japan */
{ 0x4A50 /* JP */, 936 }, /* Japan */
{ 0x4A50 /* JP */, 937 }, /* Japan */
{ 0x4A50 /* JP */, 938 }, /* Japan */
{ 0x4A50 /* JP */, 939 }, /* Japan */
{ 0x4A50 /* JP */, 940 }, /* Japan */
{ 0x4A50 /* JP */, 941 }, /* Japan */
{ 0x4B45 /* KE */, 404 }, /* Kenya */
{ 0x4B50 /* KP */, 408 }, /* North Korea */
{ 0x4B52 /* KR */, 410 }, /* South Korea */
{ 0x4B52 /* KR */, 411 }, /* South Korea */
{ 0x4B57 /* KW */, 414 }, /* Kuwait */
{ 0x4B5A /* KZ */, 398 }, /* Kazakhstan */
{ 0x4C42 /* LB */, 422 }, /* Lebanon */
{ 0x4C49 /* LI */, 438 }, /* Liechtenstein */
{ 0x4C54 /* LT */, 440 }, /* Lithuania */
{ 0x4C55 /* LU */, 442 }, /* Luxembourg */
{ 0x4C56 /* LV */, 428 }, /* Latvia */
{ 0x4C59 /* LY */, 434 }, /* Libya */
{ 0x4D41 /* MA */, 504 }, /* Morocco */
{ 0x4D43 /* MC */, 492 }, /* Principality of Monaco */
{ 0x4D4B /* MK */, 807 }, /* the Former Yugoslav Republic of Macedonia */
{ 0x4D4F /* MO */, 446 }, /* Macau */
{ 0x4D58 /* MX */, 484 }, /* Mexico */
{ 0x4D59 /* MY */, 458 }, /* Malaysia */
{ 0x4E49 /* NI */, 558 }, /* Nicaragua */
{ 0x4E4C /* NL */, 528 }, /* Netherlands */
{ 0x4E4F /* NO */, 578 }, /* Norway */
{ 0x4E5A /* NZ */, 554 }, /* New Zealand */
{ 0x4F4D /* OM */, 512 }, /* Oman */
{ 0x5041 /* PA */, 591 }, /* Panama */
{ 0x5045 /* PE */, 604 }, /* Peru */
{ 0x5048 /* PH */, 608 }, /* Republic of the Philippines */
{ 0x504B /* PK */, 586 }, /* Islamic Republic of Pakistan */
{ 0x504C /* PL */, 616 }, /* Poland */
{ 0x5052 /* PR */, 630 }, /* Puerto Rico */
{ 0x5054 /* PT */, 620 }, /* Portugal */
{ 0x5059 /* PY */, 600 }, /* Paraguay */
{ 0x5141 /* QA */, 634 }, /* Qatar */
{ 0x524F /* RO */, 642 }, /* Romania */
{ 0x5255 /* RU */, 643 }, /* Russia */
{ 0x5341 /* SA */, 682 }, /* Saudi Arabia */
{ 0x5345 /* SE */, 752 }, /* Sweden */
{ 0x5347 /* SG */, 702 }, /* Singapore */
{ 0x5349 /* SI */, 705 }, /* Slovenia */
{ 0x534B /* SK */, 703 }, /* Slovak Republic */
{ 0x5356 /* SV */, 222 }, /* El Salvador */
{ 0x5359 /* SY */, 760 }, /* Syria */
{ 0x5448 /* TH */, 764 }, /* Thailand */
{ 0x544E /* TN */, 788 }, /* Tunisia */
{ 0x5452 /* TR */, 792 }, /* Turkey */
{ 0x5454 /* TT */, 780 }, /* Trinidad y Tobago */
{ 0x5457 /* TW */, 158 }, /* Taiwan */
{ 0x5541 /* UA */, 804 }, /* Ukraine */
{ 0x554B /* UK */, 826 }, /* United Kingdom */
{ 0x5553 /* US */, 840 }, /* United States */
{ 0x5553 /* US */, 842 }, /* United States (Public Safety)*/
{ 0x5559 /* UY */, 858 }, /* Uruguay */
{ 0x555A /* UZ */, 860 }, /* Uzbekistan */
{ 0x5645 /* VE */, 862 }, /* Venezuela */
{ 0x564E /* VN */, 704 }, /* Viet Nam */
{ 0x5945 /* YE */, 887 }, /* Yemen */
{ 0x5A41 /* ZA */, 710 }, /* South Africa */
{ 0x5A57 /* ZW */, 716 }, /* Zimbabwe */
};
static int madwifi_wrq(struct iwreq *wrq, const char *ifname, int cmd, void *data, size_t len)
{
strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
if( data != NULL )
{
if( len < IFNAMSIZ )
{
memcpy(wrq->u.name, data, len);
}
else
{
wrq->u.data.pointer = data;
wrq->u.data.length = len;
}
}
return iwinfo_ioctl(cmd, wrq);
}
static int get80211priv(const char *ifname, int op, void *data, size_t len)
{
struct iwreq iwr;
if( madwifi_wrq(&iwr, ifname, op, data, len) < 0 )
return -1;
return iwr.u.data.length;
}
static char * madwifi_isvap(const char *ifname, const char *wifiname)
{
int fd, ln;
char path[32];
char *ret = NULL;
static char name[IFNAMSIZ];
if( strlen(ifname) <= 9 )
{
sprintf(path, "/proc/sys/net/%s/%%parent", ifname);
if( (fd = open(path, O_RDONLY)) > -1 )
{
if( wifiname != NULL )
{
if( read(fd, name, strlen(wifiname)) == strlen(wifiname) )
ret = strncmp(name, wifiname, strlen(wifiname))
? NULL : name;
}
else if( (ln = read(fd, name, IFNAMSIZ)) >= 4 )
{
name[ln-1] = 0;
ret = name;
}
(void) close(fd);
}
}
return ret;
}
static int madwifi_iswifi(const char *ifname)
{
int ret;
char path[32];
struct stat s;
ret = 0;
if( strlen(ifname) <= 7 )
{
sprintf(path, "/proc/sys/dev/%s/diversity", ifname);
if( ! stat(path, &s) )
ret = (s.st_mode & S_IFREG);
}
return ret;
}
static char * madwifi_ifadd(const char *ifname)
{
char *wifidev = NULL;
struct ifreq ifr = { 0 };
struct ieee80211_clone_params cp = { 0 };
static char nif[IFNAMSIZ] = { 0 };
if( !(wifidev = madwifi_isvap(ifname, NULL)) && madwifi_iswifi(ifname) )
wifidev = (char *)ifname;
if( wifidev )
{
snprintf(nif, sizeof(nif), "tmp.%s", ifname);
strncpy(cp.icp_name, nif, IFNAMSIZ);
cp.icp_opmode = IEEE80211_M_STA;
cp.icp_flags = IEEE80211_CLONE_BSSID;
strncpy(ifr.ifr_name, wifidev, IFNAMSIZ);
ifr.ifr_data = (void *)&cp;
if( !iwinfo_ioctl(SIOC80211IFCREATE, &ifr) )
{
return nif;
}
else
{
cp.icp_opmode = IEEE80211_M_MONITOR;
if( !iwinfo_ioctl(SIOC80211IFCREATE, &ifr) )
return nif;
}
}
return NULL;
}
static void madwifi_ifdel(const char *ifname)
{
struct ifreq ifr = { 0 };
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
iwinfo_ioctl(SIOC80211IFDESTROY, &ifr);
}
int madwifi_probe(const char *ifname)
{
return ( !!madwifi_isvap(ifname, NULL) || madwifi_iswifi(ifname) );
}
void madwifi_close(void)
{
/* Nop */
}
int madwifi_get_mode(const char *ifname, char *buf)
{
return wext_get_mode(ifname, buf);
}
int madwifi_get_ssid(const char *ifname, char *buf)
{
return wext_get_ssid(ifname, buf);
}
int madwifi_get_bssid(const char *ifname, char *buf)
{
return wext_get_bssid(ifname, buf);
}
int madwifi_get_channel(const char *ifname, int *buf)
{
int i;
uint16_t freq;
struct iwreq wrq;
struct ieee80211req_chaninfo chans;
if( madwifi_wrq(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 )
{
/* Madwifi returns a Hz frequency, get it's freq list to find channel index */
freq = (uint16_t)(wrq.u.freq.m / 100000);
if( get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO, &chans, sizeof(chans)) >= 0 )
{
*buf = 0;
for( i = 0; i < chans.ic_nchans; i++ )
{
if( freq == chans.ic_chans[i].ic_freq )
{
*buf = chans.ic_chans[i].ic_ieee;
break;
}
}
return 0;
}
}
return -1;
}
int madwifi_get_frequency(const char *ifname, int *buf)
{
struct iwreq wrq;
if( madwifi_wrq(&wrq, ifname, SIOCGIWFREQ, NULL, 0) >= 0 )
{
*buf = (uint16_t)(wrq.u.freq.m / 100000);
return 0;
}
return -1;
}
int madwifi_get_txpower(const char *ifname, int *buf)
{
return wext_get_txpower(ifname, buf);
}
int madwifi_get_bitrate(const char *ifname, int *buf)
{
unsigned int mode, len, rate, rate_count;
uint8_t tmp[24*1024];
uint8_t *cp;
struct iwreq wrq;
struct ieee80211req_sta_info *si;
if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 )
{
mode = wrq.u.mode;
/* Calculate bitrate average from associated stations in ad-hoc mode */
if( mode == 1 )
{
rate = rate_count = 0;
if( (len = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
{
cp = tmp;
do {
si = (struct ieee80211req_sta_info *) cp;
if( si->isi_rssi > 0 )
{
rate_count++;
rate += ((si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL) / 2);
}
cp += si->isi_len;
len -= si->isi_len;
} while (len >= sizeof(struct ieee80211req_sta_info));
}
*buf = (rate == 0 || rate_count == 0) ? 0 : (rate / rate_count) * 1000;
return 0;
}
/* Return whatever wext tells us ... */
return wext_get_bitrate(ifname, buf);
}
return -1;
}
int madwifi_get_signal(const char *ifname, int *buf)
{
unsigned int mode, len, rssi, rssi_count;
uint8_t tmp[24*1024];
uint8_t *cp;
struct iwreq wrq;
struct ieee80211req_sta_info *si;
if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 )
{
mode = wrq.u.mode;
/* Calculate signal average from associated stations in ap or ad-hoc mode */
if( mode == 1 )
{
rssi = rssi_count = 0;
if( (len = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
{
cp = tmp;
do {
si = (struct ieee80211req_sta_info *) cp;
if( si->isi_rssi > 0 )
{
rssi_count++;
rssi -= (si->isi_rssi - 95);
}
cp += si->isi_len;
len -= si->isi_len;
} while (len >= sizeof(struct ieee80211req_sta_info));
}
*buf = (rssi == 0 || rssi_count == 0) ? 1 : -(rssi / rssi_count);
return 0;
}
/* Return whatever wext tells us ... */
return wext_get_signal(ifname, buf);
}
return -1;
}
int madwifi_get_noise(const char *ifname, int *buf)
{
return wext_get_noise(ifname, buf);
}
int madwifi_get_quality(const char *ifname, int *buf)
{
unsigned int mode, len, quality, quality_count;
uint8_t tmp[24*1024];
uint8_t *cp;
struct iwreq wrq;
struct ieee80211req_sta_info *si;
if( madwifi_wrq(&wrq, ifname, SIOCGIWMODE, NULL, 0) >= 0 )
{
mode = wrq.u.mode;
/* Calculate signal average from associated stations in ad-hoc mode */
if( mode == 1 )
{
quality = quality_count = 0;
if( (len = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
{
cp = tmp;
do {
si = (struct ieee80211req_sta_info *) cp;
if( si->isi_rssi > 0 )
{
quality_count++;
quality += si->isi_rssi;
}
cp += si->isi_len;
len -= si->isi_len;
} while (len >= sizeof(struct ieee80211req_sta_info));
}
*buf = (quality == 0 || quality_count == 0) ? 0 : (quality / quality_count);
return 0;
}
/* Return whatever wext tells us ... */
return wext_get_quality(ifname, buf);
}
return -1;
}
int madwifi_get_quality_max(const char *ifname, int *buf)
{
return wext_get_quality_max(ifname, buf);
}
int madwifi_get_encryption(const char *ifname, char *buf)
{
int ciphers = 0, key_len = 0;
char keybuf[IW_ENCODING_TOKEN_MAX];
struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf;
struct iwreq wrq;
struct ieee80211req_key wk;
memset(&wrq, 0, sizeof(wrq));
/* Obtain key info */
if( madwifi_wrq(&wrq, ifname, SIOCGIWENCODE, keybuf, sizeof(keybuf)) < 0 )
return -1;
#if 0
/* Have any encryption? */
if( (wrq.u.data.flags & IW_ENCODE_DISABLED) || (wrq.u.data.length == 0) )
return 0;
#endif
/* Save key len */
key_len = wrq.u.data.length;
/* Get wpa protocol version */
wrq.u.mode = IEEE80211_PARAM_WPA;
if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
c->wpa_version = wrq.u.mode;
/* Get authentication suites */
wrq.u.mode = IEEE80211_PARAM_AUTHMODE;
if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
{
switch(wrq.u.mode) {
case IEEE80211_AUTH_8021X:
c->auth_suites |= IWINFO_KMGMT_8021x;
break;
case IEEE80211_AUTH_WPA:
c->auth_suites |= IWINFO_KMGMT_PSK;
break;
case IEEE80211_AUTH_OPEN:
c->auth_algs |= IWINFO_AUTH_OPEN;
break;
case IEEE80211_AUTH_SHARED:
c->auth_algs |= IWINFO_AUTH_SHARED;
break;
default:
c->auth_suites |= IWINFO_KMGMT_NONE;
break;
}
}
memset(&wk, 0, sizeof(wk));
memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
/* Get key information */
if( get80211priv(ifname, IEEE80211_IOCTL_GETKEY, &wk, sizeof(wk)) >= 0 )
{
/* Type 0 == WEP */
if( (wk.ik_type == 0) && (c->auth_algs == 0) )
c->auth_algs = (IWINFO_AUTH_OPEN | IWINFO_AUTH_SHARED);
}
/* Get used pairwise ciphers */
wrq.u.mode = IEEE80211_PARAM_UCASTCIPHERS;
if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
{
ciphers = wrq.u.mode;
if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_TKIP) )
c->pair_ciphers |= IWINFO_CIPHER_TKIP;
if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_AES_CCM) )
c->pair_ciphers |= IWINFO_CIPHER_CCMP;
if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_AES_OCB) )
c->pair_ciphers |= IWINFO_CIPHER_AESOCB;
if( c->wpa_version && ciphers & (1 << IEEE80211_CIPHER_CKIP) )
c->pair_ciphers |= IWINFO_CIPHER_CKIP;
if( !c->pair_ciphers && ciphers & (1 << IEEE80211_CIPHER_WEP) )
{
switch(key_len) {
case 13:
c->pair_ciphers |= IWINFO_CIPHER_WEP104;
break;
case 5:
c->pair_ciphers |= IWINFO_CIPHER_WEP40;
break;
case 0:
break;
default:
c->pair_ciphers = IWINFO_CIPHER_WEP40 |
IWINFO_CIPHER_WEP104;
break;
}
}
if( ciphers & (1 << IEEE80211_CIPHER_NONE) )
c->pair_ciphers |= IWINFO_CIPHER_NONE;
}
/* Get used group cipher */
wrq.u.mode = IEEE80211_PARAM_MCASTCIPHER;
if( madwifi_wrq(&wrq, ifname, IEEE80211_IOCTL_GETPARAM, NULL, 0) >= 0 )
{
ciphers = c->wpa_version ? wrq.u.mode : IEEE80211_CIPHER_WEP;
switch(ciphers) {
case IEEE80211_CIPHER_TKIP:
c->group_ciphers |= IWINFO_CIPHER_TKIP;
break;
case IEEE80211_CIPHER_AES_CCM:
c->group_ciphers |= IWINFO_CIPHER_CCMP;
break;
case IEEE80211_CIPHER_AES_OCB:
c->group_ciphers |= IWINFO_CIPHER_AESOCB;
break;
case IEEE80211_CIPHER_CKIP:
c->group_ciphers |= IWINFO_CIPHER_CKIP;
break;
case IEEE80211_CIPHER_WEP:
switch(key_len) {
case 13:
c->group_ciphers |= IWINFO_CIPHER_WEP104;
break;
case 5:
c->group_ciphers |= IWINFO_CIPHER_WEP40;
break;
default:
break;
}
break;
case IEEE80211_CIPHER_NONE:
c->group_ciphers |= IWINFO_CIPHER_NONE;
break;
default:
break;
}
}
c->enabled = (c->wpa_version || (c->auth_algs && c->pair_ciphers)) ? 1 : 0;
return 0;
}
int madwifi_get_assoclist(const char *ifname, char *buf, int *len)
{
int bl, tl, noise;
uint8_t *cp;
uint8_t tmp[24*1024];
struct ieee80211req_sta_info *si;
struct iwinfo_assoclist_entry entry;
if( (tl = get80211priv(ifname, IEEE80211_IOCTL_STA_INFO, tmp, 24*1024)) > 0 )
{
cp = tmp;
bl = 0;
if( madwifi_get_noise(ifname, &noise) )
noise = 0;
do {
si = (struct ieee80211req_sta_info *) cp;
entry.signal = (si->isi_rssi - 95);
entry.noise = noise;
memcpy(entry.mac, &si->isi_macaddr, 6);
memcpy(&buf[bl], &entry, sizeof(struct iwinfo_assoclist_entry));
bl += sizeof(struct iwinfo_assoclist_entry);
cp += si->isi_len;
tl -= si->isi_len;
} while (tl >= sizeof(struct ieee80211req_sta_info));
*len = bl;
return 0;
}
return -1;
}
int madwifi_get_txpwrlist(const char *ifname, char *buf, int *len)
{
int rc = -1;
char *res;
/* A wifiX device? */
if( madwifi_iswifi(ifname) )
{
if( (res = madwifi_ifadd(ifname)) != NULL )
{
rc = wext_get_txpwrlist(res, buf, len);
madwifi_ifdel(res);
}
}
/* Its an athX ... */
else if( !!madwifi_isvap(ifname, NULL) )
{
rc = wext_get_txpwrlist(ifname, buf, len);
}
return rc;
}
int madwifi_get_scanlist(const char *ifname, char *buf, int *len)
{
int ret;
char *res;
DIR *proc;
struct dirent *e;
ret = -1;
/* We got a wifiX device passed, try to lookup a vap on it */
if( madwifi_iswifi(ifname) )
{
if( (proc = opendir("/proc/sys/net/")) != NULL )
{
while( (e = readdir(proc)) != NULL )
{
if( !!madwifi_isvap(e->d_name, ifname) )
{
if( iwinfo_ifup(e->d_name) )
{
ret = wext_get_scanlist(e->d_name, buf, len);
break;
}
}
}
closedir(proc);
}
/* Still nothing found, try to create a vap */
if( ret == -1 )
{
if( (res = madwifi_ifadd(ifname)) != NULL )
{
if( iwinfo_ifup(res) )
{
wext_get_scanlist(res, buf, len);
sleep(1);
wext_get_scanlist(res, buf, len);
sleep(1);
ret = wext_get_scanlist(res, buf, len);
}
iwinfo_ifdown(res);
madwifi_ifdel(res);
}
}
}
/* Got athX device? */
else if( !!madwifi_isvap(ifname, NULL) )
{
ret = wext_get_scanlist(ifname, buf, len);
}
return ret;
}
int madwifi_get_freqlist(const char *ifname, char *buf, int *len)
{
int i, bl;
int rc = -1;
char *res;
struct ieee80211req_chaninfo chans;
struct iwinfo_freqlist_entry entry;
/* A wifiX device? */
if( madwifi_iswifi(ifname) )
{
if( (res = madwifi_ifadd(ifname)) != NULL )
{
rc = get80211priv(res, IEEE80211_IOCTL_GETCHANINFO,
&chans, sizeof(chans));
madwifi_ifdel(res);
}
}
/* Its an athX ... */
else if( !!madwifi_isvap(ifname, NULL) )
{
rc = get80211priv(ifname, IEEE80211_IOCTL_GETCHANINFO,
&chans, sizeof(chans));
}
/* Got chaninfo? */
if( rc >= 0 )
{
bl = 0;
for( i = 0; i < chans.ic_nchans; i++ )
{
entry.mhz = chans.ic_chans[i].ic_freq;
entry.channel = chans.ic_chans[i].ic_ieee;
entry.restricted = 0;
memcpy(&buf[bl], &entry, sizeof(struct iwinfo_freqlist_entry));
bl += sizeof(struct iwinfo_freqlist_entry);
}
*len = bl;
return 0;
}
return -1;
}
int madwifi_get_country(const char *ifname, char *buf)
{
int i, fd, ccode = -1;
char buffer[34];
char *wifi = madwifi_iswifi(ifname)
? (char *)ifname : madwifi_isvap(ifname, NULL);
struct ISO3166_to_CCode *e;
if( wifi )
{
snprintf(buffer, sizeof(buffer), "/proc/sys/dev/%s/countrycode", wifi);
if( (fd = open(buffer, O_RDONLY)) > -1 )
{
memset(buffer, 0, sizeof(buffer));
if( read(fd, buffer, sizeof(buffer)-1) > 0 )
ccode = atoi(buffer);
close(fd);
}
}
for( i = 0; i < (sizeof(CountryCodes)/sizeof(CountryCodes[0])); i++ )
{
e = &CountryCodes[i];
if( e->ccode == ccode )
{
sprintf(buf, "%c%c", e->iso3166 / 256, e->iso3166 % 256);
return 0;
}
}
return -1;
}
int madwifi_get_countrylist(const char *ifname, char *buf, int *len)
{
int i, count;
struct ISO3166_to_CCode *e, *p = NULL;
struct iwinfo_country_entry *c = (struct iwinfo_country_entry *)buf;
count = 0;
for( int i = 0; i < (sizeof(CountryCodes)/sizeof(CountryCodes[0])); i++ )
{
e = &CountryCodes[i];
if( !p || (e->iso3166 != p->iso3166) )
{
c->iso3166 = e->iso3166;
snprintf(c->ccode, sizeof(c->ccode), "%i", e->ccode);
c++;
count++;
}
p = e;
}
*len = (count * sizeof(struct iwinfo_country_entry));
return 0;
}
int madwifi_get_hwmodelist(const char *ifname, int *buf)
{
char chans[IWINFO_BUFSIZE] = { 0 };
struct iwinfo_freqlist_entry *e = NULL;
int len = 0;
if( !madwifi_get_freqlist(ifname, chans, &len) )
{
for( e = (struct iwinfo_freqlist_entry *)chans; e->channel; e++ )
{
if( e->channel <= 14 )
{
*buf |= IWINFO_80211_B;
*buf |= IWINFO_80211_G;
}
else
{
*buf |= IWINFO_80211_A;
}
}
return 0;
}
return -1;
}
int madwifi_get_mbssid_support(const char *ifname, int *buf)
{
/* Test whether we can create another interface */
char *nif = madwifi_ifadd(ifname);
if( nif )
{
*buf = iwinfo_ifup(nif);
iwinfo_ifdown(nif);
madwifi_ifdel(nif);
return 0;
}
return -1;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,126 @@
/*
* iwinfo - Wireless Information Library - Shared utility routines
*
* Copyright (C) 2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*
* The signal handling code is derived from the official madwifi tools,
* wlanconfig.c in particular. The encryption property handling was
* inspired by the hostapd madwifi driver.
*/
#include "iwinfo/utils.h"
static int ioctl_socket = -1;
static int iwinfo_ioctl_socket(void)
{
/* Prepare socket */
if( ioctl_socket == -1 )
{
ioctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
fcntl(ioctl_socket, F_SETFD, fcntl(ioctl_socket, F_GETFD) | FD_CLOEXEC);
}
return ioctl_socket;
}
int iwinfo_ioctl(int cmd, void *ifr)
{
int s = iwinfo_ioctl_socket();
return ioctl(s, cmd, ifr);
}
int iwinfo_dbm2mw(int in)
{
double res = 1.0;
int ip = in / 10;
int fp = in % 10;
int k;
for(k = 0; k < ip; k++) res *= 10;
for(k = 0; k < fp; k++) res *= LOG10_MAGIC;
return (int)res;
}
int iwinfo_mw2dbm(int in)
{
double fin = (double) in;
int res = 0;
while(fin > 10.0)
{
res += 10;
fin /= 10.0;
}
while(fin > 1.000001)
{
res += 1;
fin /= LOG10_MAGIC;
}
return (int)res;
}
int iwinfo_ifup(const char *ifname)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if( iwinfo_ioctl(SIOCGIFFLAGS, &ifr) )
return 0;
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
return !iwinfo_ioctl(SIOCSIFFLAGS, &ifr);
}
int iwinfo_ifdown(const char *ifname)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if( iwinfo_ioctl(SIOCGIFFLAGS, &ifr) )
return 0;
ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
return !iwinfo_ioctl(SIOCSIFFLAGS, &ifr);
}
int iwinfo_ifmac(const char *ifname)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if( iwinfo_ioctl(SIOCGIFHWADDR, &ifr) )
return 0;
ifr.ifr_hwaddr.sa_data[1]++;
ifr.ifr_hwaddr.sa_data[2]++;
return !iwinfo_ioctl(SIOCSIFHWADDR, &ifr);
}
void iwinfo_close(void)
{
if( ioctl_socket > -1 )
close(ioctl_socket);
}

View File

@ -0,0 +1,462 @@
/*
* iwinfo - Wireless Information Library - Linux Wireless Extension Backend
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*
* Parts of this code are derived from the Linux wireless tools, iwlib.c,
* iwlist.c and iwconfig.c in particular.
*/
#include "iwinfo.h"
#include "iwinfo/wext.h"
static double wext_freq2float(const struct iw_freq *in)
{
int i;
double res = (double) in->m;
for(i = 0; i < in->e; i++) res *= 10;
return res;
}
static inline int wext_freq2mhz(const struct iw_freq *in)
{
int i;
if( in->e == 6 )
{
return in->m;
}
else
{
return (int)(wext_freq2float(in) / 1000000);
}
}
static inline int wext_ioctl(const char *ifname, int cmd, struct iwreq *wrq)
{
if( !strncmp(ifname, "mon.", 4) )
strncpy(wrq->ifr_name, &ifname[4], IFNAMSIZ);
else
strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
return iwinfo_ioctl(cmd, wrq);
}
int wext_probe(const char *ifname)
{
struct iwreq wrq;
if(wext_ioctl(ifname, SIOCGIWNAME, &wrq) >= 0)
return 1;
return 0;
}
void wext_close(void)
{
/* Nop */
}
int wext_get_mode(const char *ifname, char *buf)
{
struct iwreq wrq;
if(wext_ioctl(ifname, SIOCGIWMODE, &wrq) >= 0)
{
switch(wrq.u.mode)
{
case 0:
sprintf(buf, "Auto");
break;
case 1:
sprintf(buf, "Ad-Hoc");
break;
case 2:
sprintf(buf, "Client");
break;
case 3:
sprintf(buf, "Master");
break;
case 4:
sprintf(buf, "Repeater");
break;
case 5:
sprintf(buf, "Secondary");
break;
case 6:
sprintf(buf, "Monitor");
break;
default:
sprintf(buf, "Unknown");
}
return 0;
}
return -1;
}
int wext_get_ssid(const char *ifname, char *buf)
{
struct iwreq wrq;
wrq.u.essid.pointer = (caddr_t) buf;
wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
wrq.u.essid.flags = 0;
if(wext_ioctl(ifname, SIOCGIWESSID, &wrq) >= 0)
return 0;
return -1;
}
int wext_get_bssid(const char *ifname, char *buf)
{
struct iwreq wrq;
if(wext_ioctl(ifname, SIOCGIWAP, &wrq) >= 0)
{
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
(uint8_t)wrq.u.ap_addr.sa_data[0], (uint8_t)wrq.u.ap_addr.sa_data[1],
(uint8_t)wrq.u.ap_addr.sa_data[2], (uint8_t)wrq.u.ap_addr.sa_data[3],
(uint8_t)wrq.u.ap_addr.sa_data[4], (uint8_t)wrq.u.ap_addr.sa_data[5]);
return 0;
}
return -1;
}
int wext_get_bitrate(const char *ifname, int *buf)
{
struct iwreq wrq;
if(wext_ioctl(ifname, SIOCGIWRATE, &wrq) >= 0)
{
*buf = (wrq.u.bitrate.value / 1000);
return 0;
}
return -1;
}
int wext_get_channel(const char *ifname, int *buf)
{
struct iwreq wrq;
struct iw_range range;
double freq;
int i;
if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0)
{
if( wrq.u.freq.m >= 1000 )
{
freq = wext_freq2float(&wrq.u.freq);
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof(struct iw_range);
wrq.u.data.flags = 0;
if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
{
for(i = 0; i < range.num_frequency; i++)
{
if( wext_freq2float(&range.freq[i]) == freq )
{
*buf = range.freq[i].i;
return 0;
}
}
}
}
else
{
*buf = wrq.u.freq.m;
return 0;
}
}
return -1;
}
int wext_get_frequency(const char *ifname, int *buf)
{
struct iwreq wrq;
struct iw_range range;
int i, channel;
if(wext_ioctl(ifname, SIOCGIWFREQ, &wrq) >= 0)
{
/* We got a channel number instead ... */
if( wrq.u.freq.m < 1000 )
{
channel = wrq.u.freq.m;
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof(struct iw_range);
wrq.u.data.flags = 0;
if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
{
for(i = 0; i < range.num_frequency; i++)
{
if( range.freq[i].i == channel )
{
*buf = wext_freq2mhz(&range.freq[i]);
return 0;
}
}
}
}
else
{
*buf = wext_freq2mhz(&wrq.u.freq);
return 0;
}
}
return -1;
}
int wext_get_txpower(const char *ifname, int *buf)
{
struct iwreq wrq;
wrq.u.txpower.flags = 0;
if(wext_ioctl(ifname, SIOCGIWTXPOW, &wrq) >= 0)
{
if(wrq.u.txpower.flags & IW_TXPOW_MWATT)
*buf = iwinfo_mw2dbm(wrq.u.txpower.value);
else
*buf = wrq.u.txpower.value;
return 0;
}
return -1;
}
int wext_get_signal(const char *ifname, int *buf)
{
struct iwreq wrq;
struct iw_statistics stats;
wrq.u.data.pointer = (caddr_t) &stats;
wrq.u.data.length = sizeof(struct iw_statistics);
wrq.u.data.flags = 1;
if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
{
*buf = (stats.qual.updated & IW_QUAL_DBM)
? (stats.qual.level - 0x100) : stats.qual.level;
return 0;
}
return -1;
}
int wext_get_noise(const char *ifname, int *buf)
{
struct iwreq wrq;
struct iw_statistics stats;
wrq.u.data.pointer = (caddr_t) &stats;
wrq.u.data.length = sizeof(struct iw_statistics);
wrq.u.data.flags = 1;
if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
{
*buf = (stats.qual.updated & IW_QUAL_DBM)
? (stats.qual.noise - 0x100) : stats.qual.noise;
return 0;
}
return -1;
}
int wext_get_quality(const char *ifname, int *buf)
{
struct iwreq wrq;
struct iw_statistics stats;
wrq.u.data.pointer = (caddr_t) &stats;
wrq.u.data.length = sizeof(struct iw_statistics);
wrq.u.data.flags = 1;
if(wext_ioctl(ifname, SIOCGIWSTATS, &wrq) >= 0)
{
*buf = stats.qual.qual;
return 0;
}
return -1;
}
int wext_get_quality_max(const char *ifname, int *buf)
{
struct iwreq wrq;
struct iw_range range;
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof(struct iw_range);
wrq.u.data.flags = 0;
if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
{
*buf = range.max_qual.qual;
return 0;
}
return -1;
}
int wext_get_assoclist(const char *ifname, char *buf, int *len)
{
/* Stub */
return -1;
}
int wext_get_txpwrlist(const char *ifname, char *buf, int *len)
{
struct iwreq wrq;
struct iw_range range;
struct iwinfo_txpwrlist_entry entry;
int i;
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof(struct iw_range);
wrq.u.data.flags = 0;
if( (wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0) &&
(range.num_txpower > 0) && (range.num_txpower <= IW_MAX_TXPOWER) &&
!(range.txpower_capa & IW_TXPOW_RELATIVE)
) {
for( i = 0; i < range.num_txpower; i++ )
{
if( range.txpower_capa & IW_TXPOW_MWATT )
{
entry.dbm = iwinfo_mw2dbm(range.txpower[i]);
entry.mw = range.txpower[i];
}
/* Madwifi does neither set mW not dBm caps, also iwlist assumes
* dBm if mW is not set, so don't check here... */
else /* if( range.txpower_capa & IW_TXPOW_DBM ) */
{
entry.dbm = range.txpower[i];
entry.mw = iwinfo_dbm2mw(range.txpower[i]);
}
memcpy(&buf[i*sizeof(entry)], &entry, sizeof(entry));
}
*len = i * sizeof(entry);
return 0;
}
return -1;
}
int wext_get_freqlist(const char *ifname, char *buf, int *len)
{
struct iwreq wrq;
struct iw_range range;
struct iwinfo_freqlist_entry entry;
int i, bl;
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof(struct iw_range);
wrq.u.data.flags = 0;
if(wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0)
{
bl = 0;
for(i = 0; i < range.num_frequency; i++)
{
entry.mhz = wext_freq2mhz(&range.freq[i]);
entry.channel = range.freq[i].i;
entry.restricted = 0;
memcpy(&buf[bl], &entry, sizeof(struct iwinfo_freqlist_entry));
bl += sizeof(struct iwinfo_freqlist_entry);
}
*len = bl;
return 0;
}
return -1;
}
int wext_get_country(const char *ifname, char *buf)
{
sprintf(buf, "00");
return 0;
}
int wext_get_countrylist(const char *ifname, char *buf, int *len)
{
/* Stub */
return -1;
}
int wext_get_hwmodelist(const char *ifname, int *buf)
{
char chans[IWINFO_BUFSIZE] = { 0 };
struct iwinfo_freqlist_entry *e = NULL;
int len = 0;
if( !wext_get_freqlist(ifname, chans, &len) )
{
for( e = (struct iwinfo_freqlist_entry *)chans; e->channel; e++ )
{
if( e->channel <= 14 )
{
*buf |= IWINFO_80211_B;
*buf |= IWINFO_80211_G;
}
else
{
*buf |= IWINFO_80211_A;
}
}
return 0;
}
return -1;
}
int wext_get_encryption(const char *ifname, char *buf)
{
/* No reliable crypto info in wext */
return -1;
}
int wext_get_mbssid_support(const char *ifname, int *buf)
{
/* No multi bssid support atm */
return -1;
}

View File

@ -0,0 +1,646 @@
/*
* iwinfo - Wireless Information Library - Linux Wireless Extension Backend
*
* Copyright (C) 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*
* Parts of this code are derived from the Linux wireless tools, iwlib.c,
* iwlist.c and iwconfig.c in particular.
*/
#include "iwinfo.h"
#include "iwinfo/wext_scan.h"
static int wext_ioctl(const char *ifname, int cmd, struct iwreq *wrq)
{
strncpy(wrq->ifr_name, ifname, IFNAMSIZ);
return iwinfo_ioctl(cmd, wrq);
}
static inline double wext_freq2float(const struct iw_freq *in)
{
int i;
double res = (double) in->m;
for(i = 0; i < in->e; i++) res *= 10;
return res;
}
static inline int wext_extract_event(struct stream_descr *stream, struct iw_event *iwe, int wev)
{
const struct iw_ioctl_description *descr = NULL;
int event_type = 0;
unsigned int event_len = 1;
char *pointer;
unsigned cmd_index; /* *MUST* be unsigned */
/* Check for end of stream */
if((stream->current + IW_EV_LCP_PK_LEN) > stream->end)
return 0;
/* Extract the event header (to get the event id).
* Note : the event may be unaligned, therefore copy... */
memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN);
/* Check invalid events */
if(iwe->len <= IW_EV_LCP_PK_LEN)
return -1;
/* Get the type and length of that event */
if(iwe->cmd <= SIOCIWLAST)
{
cmd_index = iwe->cmd - SIOCIWFIRST;
if(cmd_index < standard_ioctl_num)
descr = &(standard_ioctl_descr[cmd_index]);
}
else
{
cmd_index = iwe->cmd - IWEVFIRST;
if(cmd_index < standard_event_num)
descr = &(standard_event_descr[cmd_index]);
}
if(descr != NULL)
event_type = descr->header_type;
/* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */
event_len = event_type_size[event_type];
/* Fixup for earlier version of WE */
if((wev <= 18) && (event_type == IW_HEADER_TYPE_POINT))
event_len += IW_EV_POINT_OFF;
/* Check if we know about this event */
if(event_len <= IW_EV_LCP_PK_LEN)
{
/* Skip to next event */
stream->current += iwe->len;
return 2;
}
event_len -= IW_EV_LCP_PK_LEN;
/* Set pointer on data */
if(stream->value != NULL)
pointer = stream->value; /* Next value in event */
else
pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */
/* Copy the rest of the event (at least, fixed part) */
if((pointer + event_len) > stream->end)
{
/* Go to next event */
stream->current += iwe->len;
return -2;
}
/* Fixup for WE-19 and later : pointer no longer in the stream */
/* Beware of alignement. Dest has local alignement, not packed */
if( (wev > 18) && (event_type == IW_HEADER_TYPE_POINT) )
memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len);
else
memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
/* Skip event in the stream */
pointer += event_len;
/* Special processing for iw_point events */
if(event_type == IW_HEADER_TYPE_POINT)
{
/* Check the length of the payload */
unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN);
if(extra_len > 0)
{
/* Set pointer on variable part (warning : non aligned) */
iwe->u.data.pointer = pointer;
/* Check that we have a descriptor for the command */
if(descr == NULL)
/* Can't check payload -> unsafe... */
iwe->u.data.pointer = NULL; /* Discard paylod */
else
{
/* Those checks are actually pretty hard to trigger,
* because of the checks done in the kernel... */
unsigned int token_len = iwe->u.data.length * descr->token_size;
/* Ugly fixup for alignement issues.
* If the kernel is 64 bits and userspace 32 bits,
* we have an extra 4+4 bytes.
* Fixing that in the kernel would break 64 bits userspace. */
if((token_len != extra_len) && (extra_len >= 4))
{
uint16_t alt_dlen = *((uint16_t *) pointer);
unsigned int alt_token_len = alt_dlen * descr->token_size;
if((alt_token_len + 8) == extra_len)
{
/* Ok, let's redo everything */
pointer -= event_len;
pointer += 4;
/* Dest has local alignement, not packed */
memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len);
pointer += event_len + 4;
iwe->u.data.pointer = pointer;
token_len = alt_token_len;
}
}
/* Discard bogus events which advertise more tokens than
* what they carry... */
if(token_len > extra_len)
iwe->u.data.pointer = NULL; /* Discard paylod */
/* Check that the advertised token size is not going to
* produce buffer overflow to our caller... */
if((iwe->u.data.length > descr->max_tokens)
&& !(descr->flags & IW_DESCR_FLAG_NOMAX))
iwe->u.data.pointer = NULL; /* Discard paylod */
/* Same for underflows... */
if(iwe->u.data.length < descr->min_tokens)
iwe->u.data.pointer = NULL; /* Discard paylod */
}
}
else
/* No data */
iwe->u.data.pointer = NULL;
/* Go to next event */
stream->current += iwe->len;
}
else
{
/* Ugly fixup for alignement issues.
* If the kernel is 64 bits and userspace 32 bits,
* we have an extra 4 bytes.
* Fixing that in the kernel would break 64 bits userspace. */
if((stream->value == NULL)
&& ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4)
|| ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) ||
(event_type == IW_HEADER_TYPE_QUAL))) ))
{
pointer -= event_len;
pointer += 4;
/* Beware of alignement. Dest has local alignement, not packed */
memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len);
pointer += event_len;
}
/* Is there more value in the event ? */
if((pointer + event_len) <= (stream->current + iwe->len))
/* Go to next value */
stream->value = pointer;
else
{
/* Go to next event */
stream->value = NULL;
stream->current += iwe->len;
}
}
return 1;
}
static inline void wext_fill_wpa(unsigned char *iebuf, int buflen, struct iwinfo_scanlist_entry *e)
{
int ielen = iebuf[1] + 2;
int offset = 2; /* Skip the IE id, and the length. */
unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
unsigned char *wpa_oui;
int i;
uint16_t ver = 0;
uint16_t cnt = 0;
int wpa1 = 0, wpa2 = 0;
char buf[256];
struct iwinfo_crypto_entry *ce = &e->crypto;
if(ielen > buflen)
ielen = buflen;
switch(iebuf[0])
{
case 0x30: /* WPA2 */
/* Check if we have enough data */
if(ielen < 4)
return;
wpa_oui = wpa2_oui;
break;
case 0xdd: /* WPA or else */
wpa_oui = wpa1_oui;
/* Not all IEs that start with 0xdd are WPA.
* * So check that the OUI is valid. */
if((ielen < 8) || ((memcmp(&iebuf[offset], wpa_oui, 3) != 0)
&& (iebuf[offset+3] == 0x01)))
return;
offset += 4;
break;
default:
return;
}
/* Pick version number (little endian) */
ver = iebuf[offset] | (iebuf[offset + 1] << 8);
offset += 2;
if(iebuf[0] == 0xdd)
wpa1 = 1;
if(iebuf[0] == 0x30)
wpa2 = 1;
if( wpa1 && (ce->wpa_version == 2) )
ce->wpa_version = 3;
else if( wpa2 && (ce->wpa_version == 1) )
ce->wpa_version = 3;
else if( wpa1 && !ce->wpa_version )
ce->wpa_version = 1;
else if( wpa2 && !ce->wpa_version )
ce->wpa_version = 2;
if(ielen < (offset + 4))
{
ce->group_ciphers |= (1<<2); /* TKIP */
ce->pair_ciphers |= (1<<2); /* TKIP */
ce->auth_suites |= (1<<2); /* PSK */
return;
}
if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
ce->group_ciphers |= (1<<7); /* Proprietary */
else
ce->group_ciphers |= (1<<iebuf[offset+3]);
offset += 4;
if(ielen < (offset + 2))
{
ce->pair_ciphers |= (1<<2); /* TKIP */
ce->auth_suites |= (1<<2); /* PSK */
return;
}
/* Otherwise, we have some number of pairwise ciphers. */
cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
offset += 2;
if(ielen < (offset + 4*cnt))
return;
*buf = '\0';
for(i = 0; i < cnt; i++)
{
if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
ce->pair_ciphers |= (1<<7); /* Proprietary */
else if(iebuf[offset+3] <= IW_IE_CYPHER_NUM)
ce->pair_ciphers |= (1<<iebuf[offset+3]);
//else
// ce->pair_ciphers[ce->pair_cipher_num++] = 255; /* Unknown */
offset += 4;
}
/* Check if we are done */
if(ielen < (offset + 2))
return;
/* Now, we have authentication suites. */
cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
offset += 2;
*buf = '\0';
if(ielen < (offset + 4*cnt))
return;
for(i = 0; i < cnt; i++)
{
if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
ce->auth_suites |= (1<<7); /* Proprietary */
else if(iebuf[offset+3] <= IW_IE_KEY_MGMT_NUM)
ce->auth_suites |= (1<<iebuf[offset+3]);
//else
// ce->auth_suites[ce->auth_suite_num++] = 255; /* Unknown */
offset += 4;
}
}
static inline void wext_fill_entry(struct stream_descr *stream, struct iw_event *event,
struct iw_range *iw_range, int has_range, struct iwinfo_scanlist_entry *e)
{
int i;
double freq;
/* Now, let's decode the event */
switch(event->cmd)
{
case SIOCGIWAP:
memcpy(e->mac, &event->u.ap_addr.sa_data, 6);
break;
case SIOCGIWFREQ:
if( event->u.freq.m >= 1000 )
{
freq = wext_freq2float(&(event->u.freq));
for(i = 0; i < iw_range->num_frequency; i++)
{
if( wext_freq2float(&iw_range->freq[i]) == freq )
{
e->channel = iw_range->freq[i].i;
break;
}
}
}
else
{
e->channel = event->u.freq.m;
}
break;
case SIOCGIWMODE:
switch(event->u.mode)
{
case 1:
sprintf((char *) e->mode, "Ad-Hoc");
break;
case 2:
case 3:
sprintf((char *) e->mode, "Master");
break;
default:
sprintf((char *) e->mode, "Unknown");
}
break;
case SIOCGIWESSID:
if( event->u.essid.pointer && event->u.essid.length && event->u.essid.flags )
memcpy(e->ssid, event->u.essid.pointer, event->u.essid.length);
break;
case SIOCGIWENCODE:
e->crypto.enabled = !(event->u.data.flags & IW_ENCODE_DISABLED);
break;
case IWEVQUAL:
e->signal = event->u.qual.level;
e->quality = event->u.qual.qual;
e->quality_max = iw_range->max_qual.qual;
break;
#if 0
case SIOCGIWRATE:
if(state->val_index == 0)
{
lua_pushstring(L, "bitrates");
lua_newtable(L);
}
//iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value);
snprintf(buffer, sizeof(buffer), "%d", event->u.bitrate.value);
lua_pushinteger(L, state->val_index + 1);
lua_pushstring(L, buffer);
lua_settable(L, -3);
/* Check for termination */
if(stream->value == NULL)
{
lua_settable(L, -3);
state->val_index = 0;
} else
state->val_index++;
break;
#endif
case IWEVGENIE:
i = 0;
while(i <= (event->u.data.length - 2))
{
switch(((unsigned char *)event->u.data.pointer)[i])
{
case 0xdd: /* WPA1 (and other) */
case 0x30: /* WPA2 */
wext_fill_wpa((unsigned char *)event->u.data.pointer + i,
event->u.data.length, e);
break;
}
i += ((unsigned char *)event->u.data.pointer)[i+1] + 2;
}
break;
}
}
int wext_get_scanlist(const char *ifname, char *buf, int *len)
{
struct iwreq wrq;
struct iw_scan_req scanopt; /* Options for 'set' */
unsigned char *buffer = NULL; /* Results */
int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */
struct iw_range range;
int has_range = 1;
struct timeval tv; /* Select timeout */
int timeout = 15000000; /* 15s */
int entrylen = 0;
struct iwinfo_scanlist_entry e;
wrq.u.data.pointer = (caddr_t) &range;
wrq.u.data.length = sizeof(struct iw_range);
wrq.u.data.flags = 0;
if( wext_ioctl(ifname, SIOCGIWRANGE, &wrq) >= 0 )
{
/* Init timeout value -> 250ms between set and first get */
tv.tv_sec = 0;
tv.tv_usec = 250000;
/* Clean up set args */
memset(&scanopt, 0, sizeof(scanopt));
wrq.u.data.pointer = NULL;
wrq.u.data.flags = 0;
wrq.u.data.length = 0;
/* Initiate Scanning */
if( wext_ioctl(ifname, SIOCSIWSCAN, &wrq) >= 0 )
{
timeout -= tv.tv_usec;
/* Forever */
while(1)
{
fd_set rfds; /* File descriptors for select */
int last_fd; /* Last fd */
int ret;
/* Guess what ? We must re-generate rfds each time */
FD_ZERO(&rfds);
last_fd = -1;
/* In here, add the rtnetlink fd in the list */
/* Wait until something happens */
ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
/* Check if there was an error */
if(ret < 0)
{
if(errno == EAGAIN || errno == EINTR)
continue;
return -1;
}
/* Check if there was a timeout */
if(ret == 0)
{
unsigned char *newbuf;
realloc:
/* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */
newbuf = realloc(buffer, buflen);
if(newbuf == NULL)
{
if(buffer)
free(buffer);
return -1;
}
buffer = newbuf;
/* Try to read the results */
wrq.u.data.pointer = buffer;
wrq.u.data.flags = 0;
wrq.u.data.length = buflen;
if( wext_ioctl(ifname, SIOCGIWSCAN, &wrq) )
{
/* Check if buffer was too small (WE-17 only) */
if((errno == E2BIG) && (range.we_version_compiled > 16))
{
/* Some driver may return very large scan results, either
* because there are many cells, or because they have many
* large elements in cells (like IWEVCUSTOM). Most will
* only need the regular sized buffer. We now use a dynamic
* allocation of the buffer to satisfy everybody. Of course,
* as we don't know in advance the size of the array, we try
* various increasing sizes. Jean II */
/* Check if the driver gave us any hints. */
if(wrq.u.data.length > buflen)
buflen = wrq.u.data.length;
else
buflen *= 2;
/* Try again */
goto realloc;
}
/* Check if results not available yet */
if(errno == EAGAIN)
{
/* Restart timer for only 100ms*/
tv.tv_sec = 0;
tv.tv_usec = 100000;
timeout -= tv.tv_usec;
if(timeout > 0)
continue; /* Try again later */
}
/* Bad error */
free(buffer);
return -1;
} else {
/* We have the results, go to process them */
break;
}
}
}
if( wrq.u.data.length )
{
struct iw_event iwe;
struct stream_descr stream;
int ret;
int first = 1;
memset(&stream, 0, sizeof(stream));
stream.current = (char *)buffer;
stream.end = (char *)buffer + wrq.u.data.length;
do
{
/* Extract an event and print it */
ret = wext_extract_event(&stream, &iwe, range.we_version_compiled);
if(ret >= 0)
{
if( (iwe.cmd == SIOCGIWAP) || (ret == 0) )
{
if( first )
{
first = 0;
}
else if( (entrylen + sizeof(struct iwinfo_scanlist_entry)) <= IWINFO_BUFSIZE )
{
/* if encryption is off, clear the crypto strunct */
if( !e.crypto.enabled )
memset(&e.crypto, 0, sizeof(struct iwinfo_crypto_entry));
memcpy(&buf[entrylen], &e, sizeof(struct iwinfo_scanlist_entry));
entrylen += sizeof(struct iwinfo_scanlist_entry);
}
else
{
/* we exceed the callers buffer size, abort here ... */
break;
}
memset(&e, 0, sizeof(struct iwinfo_scanlist_entry));
}
wext_fill_entry(&stream, &iwe, &range, has_range, &e);
}
} while(ret > 0);
free(buffer);
*len = entrylen;
return 0;
}
*len = 0;
free(buffer);
return 0;
}
}
return -1;
}

View File

@ -0,0 +1,558 @@
/*
* iwinfo - Wireless Information Library - Broadcom wl.o Backend
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The iwinfo library is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The iwinfo library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the iwinfo library. If not, see http://www.gnu.org/licenses/.
*
* This code is based on the wlc.c utility published by OpenWrt.org .
*/
#include "iwinfo/wl.h"
#include "iwinfo/wext.h"
static int wl_ioctl(const char *name, int cmd, void *buf, int len)
{
struct ifreq ifr;
wl_ioctl_t ioc;
/* do it */
ioc.cmd = cmd;
ioc.buf = buf;
ioc.len = len;
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ifr.ifr_data = (caddr_t) &ioc;
return iwinfo_ioctl(SIOCDEVPRIVATE, &ifr);
}
static struct wl_maclist * wl_read_assoclist(const char *ifname)
{
struct wl_maclist *macs;
int maclen = 4 + WL_MAX_STA_COUNT * 6;
if( (macs = (struct wl_maclist *) malloc(maclen)) != NULL )
{
memset(macs, 0, maclen);
macs->count = WL_MAX_STA_COUNT;
if( !wl_ioctl(ifname, WLC_GET_ASSOCLIST, macs, maclen) )
return macs;
free(macs);
}
return NULL;
}
int wl_probe(const char *ifname)
{
int magic;
if( !wl_ioctl(ifname, WLC_GET_MAGIC, &magic, sizeof(magic)) && (magic == WLC_IOCTL_MAGIC))
return 1;
return 0;
}
void wl_close(void)
{
/* Nop */
}
int wl_get_mode(const char *ifname, char *buf)
{
int ret = -1;
int ap, infra, passive;
if( (ret = wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap))) )
return ret;
if( (ret = wl_ioctl(ifname, WLC_GET_INFRA, &infra, sizeof(infra))) )
return ret;
if( (ret = wl_ioctl(ifname, WLC_GET_PASSIVE, &passive, sizeof(passive))) )
return ret;
if( passive )
sprintf(buf, "Monitor");
else if( !infra )
sprintf(buf, "Ad-Hoc");
else if( ap )
sprintf(buf, "Master");
else
sprintf(buf, "Client");
return 0;
}
int wl_get_ssid(const char *ifname, char *buf)
{
int ret = -1;
wlc_ssid_t ssid;
if( !(ret = wl_ioctl(ifname, WLC_GET_SSID, &ssid, sizeof(ssid))) )
memcpy(buf, ssid.ssid, ssid.ssid_len);
return ret;
}
int wl_get_bssid(const char *ifname, char *buf)
{
int ret = -1;
char bssid[6];
if( !(ret = wl_ioctl(ifname, WLC_GET_BSSID, bssid, 6)) )
sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
(uint8_t)bssid[0], (uint8_t)bssid[1], (uint8_t)bssid[2],
(uint8_t)bssid[3], (uint8_t)bssid[4], (uint8_t)bssid[5]
);
return ret;
}
int wl_get_channel(const char *ifname, int *buf)
{
return wl_ioctl(ifname, WLC_GET_CHANNEL, buf, sizeof(buf));
}
int wl_get_frequency(const char *ifname, int *buf)
{
return wext_get_frequency(ifname, buf);
}
int wl_get_txpower(const char *ifname, int *buf)
{
return wext_get_txpower(ifname, buf);
}
int wl_get_bitrate(const char *ifname, int *buf)
{
int ret = -1;
int rate = 0;
if( !(ret = wl_ioctl(ifname, WLC_GET_RATE, &rate, sizeof(rate))) && (rate > 0))
*buf = ((rate / 2) * 1000) + ((rate & 1) ? 500 : 0);
return ret;
}
int wl_get_signal(const char *ifname, int *buf)
{
unsigned int ap, rssi, i, rssi_count;
int ioctl_req_version = 0x2000;
char tmp[WLC_IOCTL_MAXLEN];
struct wl_maclist *macs = NULL;
wl_sta_rssi_t starssi;
memset(tmp, 0, WLC_IOCTL_MAXLEN);
memcpy(tmp, &ioctl_req_version, sizeof(ioctl_req_version));
wl_ioctl(ifname, WLC_GET_BSS_INFO, tmp, WLC_IOCTL_MAXLEN);
if( !wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap)) && !ap )
{
*buf = tmp[WL_BSS_RSSI_OFFSET];
}
else
{
rssi = rssi_count = 0;
/* Calculate average rssi from conntected stations */
if( (macs = wl_read_assoclist(ifname)) != NULL )
{
for( i = 0; i < macs->count; i++ )
{
memcpy(starssi.mac, &macs->ea[i], 6);
if( !wl_ioctl(ifname, WLC_GET_RSSI, &starssi, 12) )
{
rssi -= starssi.rssi;
rssi_count++;
}
}
free(macs);
}
*buf = (rssi == 0 || rssi_count == 0) ? 1 : -(rssi / rssi_count);
}
return 0;
}
int wl_get_noise(const char *ifname, int *buf)
{
unsigned int ap, noise;
int ioctl_req_version = 0x2000;
char tmp[WLC_IOCTL_MAXLEN];
memset(tmp, 0, WLC_IOCTL_MAXLEN);
memcpy(tmp, &ioctl_req_version, sizeof(ioctl_req_version));
wl_ioctl(ifname, WLC_GET_BSS_INFO, tmp, WLC_IOCTL_MAXLEN);
if ((wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap)) < 0) || ap)
{
if (wl_ioctl(ifname, WLC_GET_PHY_NOISE, &noise, sizeof(noise)) < 0)
noise = 0;
}
else
{
noise = tmp[WL_BSS_NOISE_OFFSET];
}
*buf = noise;
return 0;
}
int wl_get_quality(const char *ifname, int *buf)
{
return wext_get_quality(ifname, buf);
}
int wl_get_quality_max(const char *ifname, int *buf)
{
return wext_get_quality_max(ifname, buf);
}
int wl_get_encryption(const char *ifname, char *buf)
{
uint32_t wsec, wauth, wpa;
struct iwinfo_crypto_entry *c = (struct iwinfo_crypto_entry *)buf;
if( wl_ioctl(ifname, WLC_GET_WPA_AUTH, &wpa, sizeof(uint32_t)) ||
wl_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(uint32_t)) ||
wl_ioctl(ifname, WLC_GET_AUTH, &wauth, sizeof(uint32_t)) )
return -1;
switch(wsec)
{
case 2:
c->pair_ciphers |= IWINFO_CIPHER_TKIP;
break;
case 4:
c->pair_ciphers |= IWINFO_CIPHER_CCMP;
break;
case 6:
c->pair_ciphers |= IWINFO_CIPHER_TKIP;
c->pair_ciphers |= IWINFO_CIPHER_CCMP;
break;
}
switch(wpa)
{
case 0:
if( wsec && !wauth )
c->auth_algs |= IWINFO_AUTH_OPEN;
else if( wsec && wauth )
c->auth_algs |= IWINFO_AUTH_SHARED;
/* ToDo: evaluate WEP key lengths */
c->pair_ciphers = IWINFO_CIPHER_WEP40 | IWINFO_CIPHER_WEP104;
c->auth_suites |= IWINFO_KMGMT_NONE;
break;
case 2:
c->wpa_version = 1;
c->auth_suites |= IWINFO_KMGMT_8021x;
break;
case 4:
c->wpa_version = 1;
c->auth_suites |= IWINFO_KMGMT_PSK;
break;
case 32:
case 64:
c->wpa_version = 2;
c->auth_suites |= IWINFO_KMGMT_8021x;
break;
case 66:
c->wpa_version = 3;
c->auth_suites |= IWINFO_KMGMT_8021x;
break;
case 128:
c->wpa_version = 2;
c->auth_suites |= IWINFO_KMGMT_PSK;
break;
case 132:
c->wpa_version = 3;
c->auth_suites |= IWINFO_KMGMT_PSK;
break;
default:
break;
}
c->enabled = (c->wpa_version || c->auth_algs) ? 1 : 0;
c->group_ciphers = c->pair_ciphers;
return 0;
}
int wl_get_enctype(const char *ifname, char *buf)
{
uint32_t wsec, wpa;
char algo[11];
if( wl_ioctl(ifname, WLC_GET_WPA_AUTH, &wpa, sizeof(uint32_t)) ||
wl_ioctl(ifname, WLC_GET_WSEC, &wsec, sizeof(uint32_t)) )
return -1;
switch(wsec)
{
case 2:
sprintf(algo, "TKIP");
break;
case 4:
sprintf(algo, "CCMP");
break;
case 6:
sprintf(algo, "TKIP, CCMP");
break;
}
switch(wpa)
{
case 0:
sprintf(buf, "%s", wsec ? "WEP" : "None");
break;
case 2:
sprintf(buf, "WPA 802.1X (%s)", algo);
break;
case 4:
sprintf(buf, "WPA PSK (%s)", algo);
break;
case 32:
sprintf(buf, "802.1X (%s)", algo);
break;
case 64:
sprintf(buf, "WPA2 802.1X (%s)", algo);
break;
case 66:
sprintf(buf, "mixed WPA/WPA2 802.1X (%s)", algo);
break;
case 128:
sprintf(buf, "WPA2 PSK (%s)", algo);
break;
case 132:
sprintf(buf, "mixed WPA/WPA2 PSK (%s)", algo);
break;
default:
sprintf(buf, "Unknown");
}
return 0;
}
int wl_get_assoclist(const char *ifname, char *buf, int *len)
{
int i, j, noise;
int ap, infra, passive;
char line[128];
char macstr[18];
char devstr[IFNAMSIZ];
struct wl_maclist *macs;
struct wl_sta_rssi rssi;
struct iwinfo_assoclist_entry entry;
FILE *arp;
ap = infra = passive = 0;
wl_ioctl(ifname, WLC_GET_AP, &ap, sizeof(ap));
wl_ioctl(ifname, WLC_GET_INFRA, &infra, sizeof(infra));
wl_ioctl(ifname, WLC_GET_PASSIVE, &passive, sizeof(passive));
if( wl_get_noise(ifname, &noise) )
noise = 0;
if( (ap || infra || passive) && ((macs = wl_read_assoclist(ifname)) != NULL) )
{
for( i = 0, j = 0; i < macs->count; i++, j += sizeof(struct iwinfo_assoclist_entry) )
{
memcpy(rssi.mac, &macs->ea[i], 6);
if( !wl_ioctl(ifname, WLC_GET_RSSI, &rssi, sizeof(struct wl_sta_rssi)) )
entry.signal = (rssi.rssi - 0x100);
else
entry.signal = 0;
entry.noise = noise;
memcpy(entry.mac, &macs->ea[i], 6);
memcpy(&buf[j], &entry, sizeof(entry));
}
*len = j;
free(macs);
return 0;
}
else if( (arp = fopen("/proc/net/arp", "r")) != NULL )
{
j = 0;
while( fgets(line, sizeof(line), arp) != NULL )
{
if( sscanf(line, "%*s 0x%*d 0x%*d %17s %*s %s", macstr, devstr) && !strcmp(devstr, ifname) )
{
rssi.mac[0] = strtol(&macstr[0], NULL, 16);
rssi.mac[1] = strtol(&macstr[3], NULL, 16);
rssi.mac[2] = strtol(&macstr[6], NULL, 16);
rssi.mac[3] = strtol(&macstr[9], NULL, 16);
rssi.mac[4] = strtol(&macstr[12], NULL, 16);
rssi.mac[5] = strtol(&macstr[15], NULL, 16);
if( !wl_ioctl(ifname, WLC_GET_RSSI, &rssi, sizeof(struct wl_sta_rssi)) )
entry.signal = (rssi.rssi - 0x100);
else
entry.signal = 0;
entry.noise = noise;
memcpy(entry.mac, rssi.mac, 6);
memcpy(&buf[j], &entry, sizeof(entry));
j += sizeof(entry);
}
}
*len = j;
(void) fclose(arp);
return 0;
}
return -1;
}
int wl_get_txpwrlist(const char *ifname, char *buf, int *len)
{
struct iwinfo_txpwrlist_entry entry;
uint8_t dbm[8] = { 0, 6, 8, 10, 12, 14, 16, 18 };
uint8_t mw[8] = { 1, 3, 6, 10, 15, 25, 39, 63 };
int i;
for( i = 0; i < 8; i++ )
{
entry.dbm = dbm[i];
entry.mw = mw[i];
memcpy(&buf[i*sizeof(entry)], &entry, sizeof(entry));
}
*len = 8 * sizeof(entry);
return 0;
}
int wl_get_scanlist(const char *ifname, char *buf, int *len)
{
return wext_get_scanlist(ifname, buf, len);
}
int wl_get_freqlist(const char *ifname, char *buf, int *len)
{
return wext_get_freqlist(ifname, buf, len);
}
int wl_get_country(const char *ifname, char *buf)
{
char ccode[WLC_CNTRY_BUF_SZ];
if( !wl_ioctl(ifname, WLC_GET_COUNTRY, ccode, WLC_CNTRY_BUF_SZ) )
{
/* IL0 -> World */
if( !strcmp(ccode, "IL0") )
sprintf(buf, "00");
/* YU -> RS */
else if( !strcmp(ccode, "YU") )
sprintf(buf, "RS");
else
memcpy(buf, ccode, 2);
return 0;
}
return -1;
}
int wl_get_countrylist(const char *ifname, char *buf, int *len)
{
int i, count;
char cdata[WLC_IOCTL_MAXLEN];
struct iwinfo_country_entry *c = (struct iwinfo_country_entry *)buf;
wl_country_list_t *cl = (wl_country_list_t *)cdata;
cl->buflen = sizeof(cdata);
if( !wl_ioctl(ifname, WLC_GET_COUNTRY_LIST, cl, cl->buflen) )
{
for( i = 0, count = 0; i < cl->count; i++, c++ )
{
sprintf(c->ccode, &cl->country_abbrev[i * WLC_CNTRY_BUF_SZ]);
c->iso3166 = c->ccode[0] * 256 + c->ccode[1];
/* IL0 -> World */
if( !strcmp(c->ccode, "IL0") )
c->iso3166 = 0x3030;
/* YU -> RS */
else if( !strcmp(c->ccode, "YU") )
c->iso3166 = 0x5253;
}
*len = (i * sizeof(struct iwinfo_country_entry));
return 0;
}
return -1;
}
int wl_get_hwmodelist(const char *ifname, int *buf)
{
return wext_get_hwmodelist(ifname, buf);
}
int wl_get_mbssid_support(const char *ifname, int *buf)
{
wlc_rev_info_t revinfo;
/* Multi bssid support only works on corerev >= 9 */
if( !wl_ioctl(ifname, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)) )
{
if( revinfo.corerev >= 9 )
{
*buf = 1;
return 0;
}
}
return -1;
}