1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-04-21 12:27:27 +03:00

packages: sort network related packages into package/network/

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@33688 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
nbd
2012-10-10 12:32:29 +00:00
parent eecf5b1752
commit 9c8997d54d
344 changed files with 0 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
# Copyright (C) 2006-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=arptables
PKG_VERSION:=0.0.3-4
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@SF/ebtables
PKG_MD5SUM:=1d4ab05761f063b0751645d8f2b8f8e5
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-v$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/arptables
SECTION:=net
CATEGORY:=Network
SUBMENU:=Firewall
TITLE:=ARP firewalling software
DEPENDS:=+kmod-arptables
URL:=http://ebtables.sourceforge.net
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
COPT_FLAGS="$(TARGET_CFLAGS)" \
KERNEL_DIR="./include/linux"
endef
define Package/arptables/install
$(INSTALL_DIR) $(1)/usr/sbin
$(CP) $(PKG_BUILD_DIR)/$(PKG_NAME) $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,arptables))
@@ -0,0 +1,19 @@
Index: arptables-v0.0.3-4/libarptc/libarptc_incl.c
===================================================================
--- arptables-v0.0.3-4.orig/libarptc/libarptc_incl.c 2010-03-08 16:49:28.000000000 +0100
+++ arptables-v0.0.3-4/libarptc/libarptc_incl.c 2012-08-14 12:10:29.527945144 +0200
@@ -11,14 +11,6 @@
/* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
COPYING for details). */
-#ifndef __OPTIMIZE__
-STRUCT_ENTRY_TARGET *
-GET_TARGET(STRUCT_ENTRY *e)
-{
- return (void *)e + e->target_offset;
-}
-#endif
-
static int sockfd = -1;
static void *arptc_fn = NULL;
+65
View File
@@ -0,0 +1,65 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=comgt
PKG_VERSION:=0.32
PKG_RELEASE:=21
PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tgz
PKG_SOURCE_URL:=@SF/comgt
PKG_MD5SUM:=db2452680c3d953631299e331daf49ef
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME).$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/comgt
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Option/Vodafone 3G/GPRS control tool
DEPENDS:=+chat
URL:=http://www.pharscape.org/comgt.html
endef
define Package/comgt/description
comgt is a scripting language interpreter useful for establishing
communications on serial lines and through PCMCIA modems as well as GPRS
and 3G datacards.
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS)" \
LDFLAGS="" \
comgt
endef
define Package/comgt/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/comgt $(1)/usr/bin/
ln -s comgt $(1)/usr/bin/gcom
$(INSTALL_DIR) $(1)/etc/chatscripts
$(INSTALL_DATA) ./files/3g.chat $(1)/etc/chatscripts/3g.chat
$(INSTALL_DATA) ./files/evdo.chat $(1)/etc/chatscripts/evdo.chat
$(INSTALL_DIR) $(1)/etc/gcom
$(INSTALL_DATA) ./files/setpin.gcom $(1)/etc/gcom/setpin.gcom
$(INSTALL_DATA) ./files/setmode.gcom $(1)/etc/gcom/setmode.gcom
$(INSTALL_DATA) ./files/getcardinfo.gcom $(1)/etc/gcom/getcardinfo.gcom
$(INSTALL_DATA) ./files/getstrength.gcom $(1)/etc/gcom/getstrength.gcom
$(INSTALL_DATA) ./files/getcarrier.gcom $(1)/etc/gcom/getcarrier.gcom
$(INSTALL_DATA) ./files/getcnum.gcom $(1)/etc/gcom/getcnum.gcom
$(INSTALL_DATA) ./files/getimsi.gcom $(1)/etc/gcom/getimsi.gcom
$(INSTALL_DIR) $(1)/etc/hotplug.d/tty
$(INSTALL_DATA) ./files/3g.usb $(1)/etc/hotplug.d/tty/30-3g
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/3g.sh $(1)/lib/netifd/proto/3g.sh
endef
$(eval $(call BuildPackage,comgt))
+12
View File
@@ -0,0 +1,12 @@
ABORT BUSY
ABORT 'NO CARRIER'
ABORT ERROR
REPORT CONNECT
TIMEOUT 10
"" "AT&F"
OK "ATE1"
OK 'AT+CGDCONT=1,"IP","$USE_APN"'
SAY "Calling UMTS/GPRS"
TIMEOUT 30
OK "ATD*99***1#"
CONNECT ' '
+97
View File
@@ -0,0 +1,97 @@
#!/bin/sh
INCLUDE_ONLY=1
. ../netifd-proto.sh
. ./ppp.sh
init_proto "$@"
proto_3g_init_config() {
no_device=1
available=1
ppp_generic_init_config
proto_config_add_string "device"
proto_config_add_string "apn"
proto_config_add_string "service"
proto_config_add_string "pincode"
}
proto_3g_setup() {
local interface="$1"
local chat
json_get_var device device
json_get_var apn apn
json_get_var service service
json_get_var pincode pincode
[ -e "$device" ] || {
proto_set_available "$interface" 0
return 1
}
case "$service" in
cdma|evdo)
chat="/etc/chatscripts/evdo.chat"
;;
*)
chat="/etc/chatscripts/3g.chat"
cardinfo=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom)
if echo "$cardinfo" | grep -q Novatel; then
case "$service" in
umts_only) CODE=2;;
gprs_only) CODE=1;;
*) CODE=0;;
esac
export MODE="AT\$NWRAT=${CODE},2"
elif echo "$cardinfo" | grep -q Option; then
case "$service" in
umts_only) CODE=1;;
gprs_only) CODE=0;;
*) CODE=3;;
esac
export MODE="AT_OPSYS=${CODE}"
elif echo "$cardinfo" | grep -q "Sierra Wireless"; then
SIERRA=1
elif echo "$cardinfo" | grep -qi huawei; then
case "$service" in
umts_only) CODE="14,2";;
gprs_only) CODE="13,1";;
*) CODE="2,2";;
esac
export MODE="AT^SYSCFG=${CODE},3FFFFFFF,2,4"
fi
if [ -n "$pincode" ]; then
PINCODE="$pincode" gcom -d "$device" -s /etc/gcom/setpin.gcom || {
proto_notify_error "$interface" PIN_FAILED
proto_block_restart "$interface"
return 1
}
fi
[ -n "$MODE" ] && gcom -d "$device" -s /etc/gcom/setmode.gcom
# wait for carrier to avoid firmware stability bugs
[ -n "$SIERRA" ] && {
gcom -d "$device" -s /etc/gcom/getcarrier.gcom || return 1
}
;;
esac
connect="${apn:+USE_APN=$apn }/usr/sbin/chat -t5 -v -E -f $chat"
ppp_generic_setup "$interface" \
noaccomp \
nopcomp \
novj \
nobsdcomp \
noauth \
lock \
crtscts \
115200 "$device"
return 0
}
proto_3g_teardown() {
proto_kill_command "$interface"
}
add_protocol 3g
+33
View File
@@ -0,0 +1,33 @@
#!/bin/sh
. /lib/functions.sh
. /lib/netifd/netifd-proto.sh
find_3g_iface() {
local cfg="$1"
local tty="$2"
local proto
config_get proto "$cfg" proto
[ "$proto" = 3g ] || return 0
# bypass state vars here because 00-netstate could clobber .device
local dev=$(uci_get network "$cfg" device)
if [ "${dev##*/}" = "${tty##*/}" ]; then
if [ "$ACTION" = add ]; then
available=1
else
available=0
fi
proto_set_available "$cfg" $available
fi
}
case "$DEVICENAME" in
tty*)
[ -e "/dev/$DEVICENAME" ] || [ "$ACTION" = remove ] || exit 0
config_load network
config_foreach find_3g_iface interface "/dev/$DEVICENAME"
;;
esac
@@ -0,0 +1,17 @@
# This is a simple chat script based off of the one provided by Sierra Wireless
# for CDMA connections. It should work for both Sprint and Verizon networks.
ABORT BUSY
ABORT 'NO CARRIER'
ABORT ERROR
ABORT 'NO DIAL TONE'
ABORT 'NO ANSWER'
ABORT DELAYED
REPORT CONNECT
TIMEOUT 10
'' AT
OK ATZ
SAY 'Calling CDMA/EVDO'
TIMEOUT 30
OK ATDT#777
CONNECT ''
@@ -0,0 +1,14 @@
opengt
set com 115200n81
set comecho off
set senddelay 0.02
waitquiet 0.2 0.2
flash 0.1
:start
send "ATI^m"
get 1 "" $s
print $s
:continue
exit 0
@@ -0,0 +1,20 @@
opengt
set senddelay 0.05
waitquiet 1 0.2
let c=1
:loop
inc c
send "AT+CGATT?^m"
waitfor 5 "+CGATT: 1","+CGATT: 0"
print "\n."
if % = -1 goto error
if c > 10 goto toolong
if % = 0 goto out
sleep 2
if % = 1 goto loop
:toolong
exit 1
:error
exit 0
:out
exit 0
@@ -0,0 +1,20 @@
opengt
set com 115200n81
set comecho off
set senddelay 0.02
waitquiet 0.2 0.2
flash 0.1
:start
send "AT+CNUM^m"
get 1 "^m" $n
get 1 ":" $n
get 1 "\"" $n
get 1 "\"" $n
get 1 "\"" $n
get 1 "\"" $n
let n = len($n)
if n<1 goto continue
print $n
:continue
exit 0
@@ -0,0 +1,17 @@
opengt
set com 115200n81
set comecho off
set senddelay 0.02
waitquiet 0.2 0.2
flash 0.1
:start
send "AT+CIMI^m"
get 1 "^m" $s
get 1 "^m" $s
let x = len($s)
if x<2 goto continue
let $s = $right($s, x-1)
print $s
:continue
exit 0
@@ -0,0 +1,14 @@
opengt
set com 115200n81
set comecho off
set senddelay 0.02
waitquiet 0.2 0.2
flash 0.1
:start
send "AT+CSQ^m"
get 1 "" $s
print $s
:continue
exit 0
@@ -0,0 +1,26 @@
# set wwan mode from environment
opengt
set com 115200n81
set senddelay 0.02
waitquiet 1 0.2
flash 0.1
:start
print "Trying to set mode\n"
send $env("MODE")
send "^m"
waitfor 15 "OK","ERR","ERROR"
if % = 0 goto continue
if % = 1 goto modeerror
if % = 2 goto modeerror
print "Timeout setting WWAN mode!\n"
exit 1
:modeerror
print "Error setting WWAN mode!\n"
exit 1
:continue
exit 0
@@ -0,0 +1,55 @@
# set pin code from evnironment "$PINCODE"
opengt
set com 115200n81
set senddelay 0.05
waitquiet 3 0.5
flash 0.1
let c=0
:start
send "AT+CPIN?^m"
waitfor 15 "SIM PUK","SIM PIN","READY","ERROR","ERR"
if % = -1 goto timeout
if % = 0 goto ready
if % = 1 goto setpin
if % = 2 goto ready
if % = 3 goto checkrepeat
if % = 4 goto checkrepeat
:checkrepeat
inc c
if c>3 goto pinerror
waitquiet 12 0.5
goto start
:timeout
print "timeout checking for PIN."
exit 1
:ready
print "SIM ready\n"
goto continue
exit 0
:setpin
# check if output was "SIM PIN2", that's ok.
waitfor 1 "2"
if % = 0 goto ready
print "Trying to set PIN\n"
send "AT+CPIN=\""
send $env("PINCODE")
send "\"^m"
waitfor 20 "OK","ERR"
if % = -1 goto pinerror
if % = 0 goto continue
if % = 1 goto pinerror
:pinerror
print "Error setting PIN, check card manually\n"
exit 1
:continue
print "PIN set successfully\n"
exit 0
@@ -0,0 +1,23 @@
--- a/Makefile
+++ b/Makefile
@@ -32,6 +32,7 @@ SCRIPTPATH = /etc/comgt/
SCRIPTSRC = ./scripts/
BIN = $(CPROG)
MANP = comgt.1 sigmon.1
+CC = cc
CFLAGS = -c
LDFLAGS =
@@ -70,10 +71,5 @@ clean:
-rm *~
-rm $(SCRIPTSRC)*~
-
-comgt: comgt.o
- cc comgt.o $(LDFLAGS) -o comgt
-
-comgt.o: comgt.c comgt.h
- cc comgt.c $(CFLAGS)
-
+comgt: comgt.c comgt.h
+ $(CC) $(CFLAGS) -o comgt $< $(LDFLAGS)
+71
View File
@@ -0,0 +1,71 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=ebtables
PKG_VERSION:=2.0.10-4
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@SF/ebtables
PKG_MD5SUM:=506742a3d44b9925955425a659c1a8d0
PKG_BUILD_DIR:=$(BUILD_DIR)/ebtables-v$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/ebtables
SECTION:=net
CATEGORY:=Network
SUBMENU:=Firewall
DEPENDS:=+kmod-ebtables
TITLE:=Ethernet bridge firewall administration utility
URL:=http://ebtables.sourceforge.net/
endef
define Package/ebtables-utils
$(call Package/ebtables)
DEPENDS += ebtables
TITLE:=ebtables save/restore utilities
endef
define Package/ebtables/description
The ebtables program is a filtering tool for a bridging firewall. The
filtering is focussed on the Link Layer Ethernet frame fields. Apart
from filtering, it also gives the ability to alter the Ethernet MAC
addresses and implement a brouter.
endef
define Package/ebtables-utils/description
$(call Package/ebtables/description)
endef
MAKE_VARS += EXT_LIBSI="$(LIBGCC_S)"
MAKE_FLAGS += \
CFLAGS="$(TARGET_CFLAGS)" \
LIBDIR="/usr/lib/ebtables"
define Package/ebtables/install
$(INSTALL_DIR) $(1)/etc
$(INSTALL_DATA) $(PKG_BUILD_DIR)/ethertypes $(1)/etc/
$(INSTALL_DIR) $(1)/usr/lib/ebtables
$(INSTALL_BIN) $(PKG_BUILD_DIR)/lib*.so $(1)/usr/lib/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/extensions/*.so $(1)/usr/lib/ebtables/
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ebtables $(1)/usr/sbin/
endef
define Package/ebtables-utils/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ebtables-save $(1)/usr/sbin/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ebtables-restore $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,ebtables))
$(eval $(call BuildPackage,ebtables-utils))
+42
View File
@@ -0,0 +1,42 @@
#
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=ifenslave
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/ifenslave
SECTION:=net
CATEGORY:=Network
DEPENDS:=+kmod-bonding
TITLE:=A utility to manipulate kernel ethernet bonding devices
VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE)
URL:=http://www.kernel.org
endef
define Package/ifenslave/description
ifenslave is needed to add/remove interfaces to/from ethernet bond devices.
endef
define Build/Prepare
endef
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/ifenslave \
$(LINUX_DIR)/Documentation/networking/ifenslave.c
endef
define Package/ifenslave/install
$(INSTALL_DIR) $(1)/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ifenslave $(1)/sbin/
endef
$(eval $(call BuildPackage,ifenslave))
+115
View File
@@ -0,0 +1,115 @@
#
# Copyright (C) 2006-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=iproute2
PKG_VERSION:=3.3.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=http://kernel.org/pub/linux/utils/net/iproute2/
PKG_MD5SUM:=308e7145218dd552c2766fe527e239e1
PKG_BUILD_PARALLEL:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/iproute2-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/iproute2/Default
SECTION:=net
CATEGORY:=Network
URL:=http://linux-net.osdl.org/index.php/Iproute2
endef
define Package/ip
$(call Package/iproute2/Default)
SUBMENU:=Routing and Redirection
DEPENDS:= +libnl-tiny
TITLE:=Routing control utility
endef
define Package/ip/conffiles
/etc/iproute2/rt_tables
endef
define Package/tc
$(call Package/iproute2/Default)
TITLE:=Traffic control utility
DEPENDS:=+kmod-sched-core
endef
define Package/genl
$(call Package/iproute2/Default)
TITLE:=General netlink utility frontend
endef
define Package/ss
$(call Package/iproute2/Default)
TITLE:=Socket statistics utility
endef
define Build/Configure
$(SED) "s,-I/usr/include/db3,," $(PKG_BUILD_DIR)/Makefile
$(SED) "s,^KERNEL_INCLUDE.*,KERNEL_INCLUDE=$(LINUX_DIR)/include," \
$(PKG_BUILD_DIR)/Makefile
$(SED) "s,^LIBC_INCLUDE.*,LIBC_INCLUDE=$(STAGING_DIR)/include," \
$(PKG_BUILD_DIR)/Makefile
echo "static const char SNAPSHOT[] = \"$(PKG_VERSION)-$(PKG_RELEASE)-openwrt\";" \
> $(PKG_BUILD_DIR)/include/SNAPSHOT.h
endef
ifdef CONFIG_USE_EGLIBC
ifndef CONFIG_EGLIBC_VERSION_2_13
TARGET_CFLAGS += -DHAVE_SETNS
endif
endif
MAKE_FLAGS += \
EXTRA_CCOPTS="$(TARGET_CFLAGS) -I../include -I$(STAGING_DIR)/usr/include/libnl-tiny" \
KERNEL_INCLUDE="$(LINUX_DIR)/include" \
FPIC="$(FPIC)"
define Build/Compile
+$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS)
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/include/libnetlink.h $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/lib/libnetlink.a $(1)/usr/lib/
endef
define Package/ip/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/etc/iproute2
$(INSTALL_DATA) $(PKG_BUILD_DIR)/etc/iproute2/rt_tables $(1)/etc/iproute2
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/sbin/
endef
define Package/tc/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/sbin/
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_BIN) ./files/30-teql $(1)/etc/hotplug.d/iface/
endef
define Package/genl/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/genl/genl $(1)/usr/sbin/
endef
define Package/ss/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/misc/ss $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,ip))
$(eval $(call BuildPackage,tc))
$(eval $(call BuildPackage,genl))
$(eval $(call BuildPackage,ss))
@@ -0,0 +1,23 @@
#!/bin/sh
. /lib/functions.sh
if [ "$ACTION" != "ifup" ]; then
exit
fi
config_load network
config_get teql $INTERFACE teql
if [ "$teql" != "" ]; then
logger Adding device $DEVICE to TEQL master $teql
insmod sch_teql
tc qdisc add dev $DEVICE root $teql
# The kernel doesn't let us bring it up until it has at least one
# slave. So bring it up now, if it isn't already.
if ! cat /sys/class/net/$teql/carrier &>/dev/null; then
ifup $teql &
fi
fi
@@ -0,0 +1,121 @@
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -193,6 +193,33 @@ struct tc_sfq_xstats {
__s32 allot;
};
+/* ESFQ section */
+
+enum
+{
+ /* traditional */
+ TCA_SFQ_HASH_CLASSIC,
+ TCA_SFQ_HASH_DST,
+ TCA_SFQ_HASH_SRC,
+ TCA_SFQ_HASH_FWMARK,
+ /* conntrack */
+ TCA_SFQ_HASH_CTORIGDST,
+ TCA_SFQ_HASH_CTORIGSRC,
+ TCA_SFQ_HASH_CTREPLDST,
+ TCA_SFQ_HASH_CTREPLSRC,
+ TCA_SFQ_HASH_CTNATCHG,
+};
+
+struct tc_esfq_qopt
+{
+ unsigned quantum; /* Bytes per round allocated to flow */
+ int perturb_period; /* Period of hash perturbation */
+ __u32 limit; /* Maximal packets in queue */
+ unsigned divisor; /* Hash divisor */
+ unsigned flows; /* Maximal number of flows */
+ unsigned hash_kind; /* Hash function to use for flow identification */
+};
+
/* RED section */
enum {
@@ -633,4 +660,84 @@ struct tc_qfq_stats {
__u32 lmax;
};
+/* CODEL */
+
+enum {
+ TCA_CODEL_UNSPEC,
+ TCA_CODEL_TARGET,
+ TCA_CODEL_LIMIT,
+ TCA_CODEL_INTERVAL,
+ TCA_CODEL_ECN,
+ __TCA_CODEL_MAX
+};
+
+#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1)
+
+struct tc_codel_xstats {
+ __u32 maxpacket; /* largest packet we've seen so far */
+ __u32 count; /* how many drops we've done since the last time we
+ * entered dropping state
+ */
+ __u32 lastcount; /* count at entry to dropping state */
+ __u32 ldelay; /* in-queue delay seen by most recently dequeued packet */
+ __s32 drop_next; /* time to drop next packet */
+ __u32 drop_overlimit; /* number of time max qdisc packet limit was hit */
+ __u32 ecn_mark; /* number of packets we ECN marked instead of dropped */
+ __u32 dropping; /* are we in dropping state ? */
+};
+
+/* FQ_CODEL */
+
+enum {
+ TCA_FQ_CODEL_UNSPEC,
+ TCA_FQ_CODEL_TARGET,
+ TCA_FQ_CODEL_LIMIT,
+ TCA_FQ_CODEL_INTERVAL,
+ TCA_FQ_CODEL_ECN,
+ TCA_FQ_CODEL_FLOWS,
+ TCA_FQ_CODEL_QUANTUM,
+ __TCA_FQ_CODEL_MAX
+};
+
+#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1)
+
+enum {
+ TCA_FQ_CODEL_XSTATS_QDISC,
+ TCA_FQ_CODEL_XSTATS_CLASS,
+};
+
+struct tc_fq_codel_qd_stats {
+ __u32 maxpacket; /* largest packet we've seen so far */
+ __u32 drop_overlimit; /* number of time max qdisc
+ * packet limit was hit
+ */
+ __u32 ecn_mark; /* number of packets we ECN marked
+ * instead of being dropped
+ */
+ __u32 new_flow_count; /* number of time packets
+ * created a 'new flow'
+ */
+ __u32 new_flows_len; /* count of flows in new list */
+ __u32 old_flows_len; /* count of flows in old list */
+};
+
+struct tc_fq_codel_cl_stats {
+ __s32 deficit;
+ __u32 ldelay; /* in-queue delay seen by most recently
+ * dequeued packet
+ */
+ __u32 count;
+ __u32 lastcount;
+ __u32 dropping;
+ __s32 drop_next;
+};
+
+struct tc_fq_codel_xstats {
+ __u32 type;
+ union {
+ struct tc_fq_codel_qd_stats qdisc_stats;
+ struct tc_fq_codel_cl_stats class_stats;
+ };
+};
+
#endif
@@ -0,0 +1,7 @@
--- /dev/null
+++ b/Config
@@ -0,0 +1,4 @@
+# Fixed config to disable ATM support even if present on host system
+TC_CONFIG_ATM:=n
+TC_CONFIG_ACTION_GACT=y
+TC_CONFIG_ACTION_PROB=y
@@ -0,0 +1,22 @@
---
ip/ipxfrm.c | 2 --
1 file changed, 2 deletions(-)
--- a/ip/ipxfrm.c
+++ b/ip/ipxfrm.c
@@ -468,7 +468,6 @@ void xfrm_selector_print(struct xfrm_sel
switch (sel->proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
- case IPPROTO_SCTP:
case IPPROTO_DCCP:
default: /* XXX */
if (sel->sport_mask)
@@ -1263,7 +1262,6 @@ static int xfrm_selector_upspec_parse(st
switch (sel->proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
- case IPPROTO_SCTP:
case IPPROTO_DCCP:
break;
default:
@@ -0,0 +1,59 @@
--- a/netem/maketable.c
+++ b/netem/maketable.c
@@ -10,7 +10,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <malloc.h>
+#endif
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
--- a/netem/normal.c
+++ b/netem/normal.c
@@ -8,8 +8,12 @@
#include <string.h>
#include <limits.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <linux/types.h>
#include <linux/pkt_sched.h>
+#else
+#define NETEM_DIST_SCALE 8192
+#endif
#define TABLESIZE 16384
#define TABLEFACTOR NETEM_DIST_SCALE
--- a/netem/pareto.c
+++ b/netem/pareto.c
@@ -7,8 +7,12 @@
#include <math.h>
#include <limits.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <linux/types.h>
#include <linux/pkt_sched.h>
+#else
+#define NETEM_DIST_SCALE 8192
+#endif
static const double a=3.0;
#define TABLESIZE 16384
--- a/netem/paretonormal.c
+++ b/netem/paretonormal.c
@@ -15,10 +15,13 @@
#include <string.h>
#include <math.h>
#include <limits.h>
+#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <malloc.h>
-
#include <linux/types.h>
#include <linux/pkt_sched.h>
+#else
+#define NETEM_DIST_SCALE 8192
+#endif
#define TABLESIZE 16384
#define TABLEFACTOR NETEM_DIST_SCALE
@@ -0,0 +1,219 @@
---
include/linux/pkt_sched.h | 59 +++++++++++++
tc/Makefile | 1
tc/q_esfq.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 260 insertions(+)
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -8,6 +8,7 @@ SHARED_LIBS ?= y
TCMODULES :=
TCMODULES += q_fifo.o
TCMODULES += q_sfq.o
+TCMODULES += q_esfq.o
TCMODULES += q_red.o
TCMODULES += q_prio.o
TCMODULES += q_tbf.o
--- /dev/null
+++ b/tc/q_esfq.c
@@ -0,0 +1,200 @@
+/*
+ * q_esfq.c ESFQ.
+ *
+ * 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.
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
+ * Alexander Clouter, <alex@digriz.org.uk>
+ * Corey Hickey, <bugfood-c@fatooh.org>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... esfq [ perturb SECS ] [ quantum BYTES ] [ depth FLOWS ]\n\t[ divisor HASHBITS ] [ limit PKTS ] [ hash HASHTYPE]\n");
+ fprintf(stderr,"Where: \n");
+ fprintf(stderr,"HASHTYPE := { classic | src | dst | ctorigdst | ctorigsrc | ctrepldst | ctreplsrc | ctnatchg }\n");
+}
+
+#define usage() return(-1)
+
+static int esfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
+{
+ int ok=0;
+ struct tc_esfq_qopt opt;
+
+ memset(&opt, 0, sizeof(opt));
+
+ opt.hash_kind= TCA_SFQ_HASH_CLASSIC;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "quantum") == 0) {
+ NEXT_ARG();
+ if (get_size(&opt.quantum, *argv)) {
+ fprintf(stderr, "Illegal \"quantum\"\n");
+ return -1;
+ }
+ ok++;
+ } else if (strcmp(*argv, "perturb") == 0) {
+ NEXT_ARG();
+ if (get_integer(&opt.perturb_period, *argv, 0)) {
+ fprintf(stderr, "Illegal \"perturb\"\n");
+ return -1;
+ }
+ ok++;
+ } else if (strcmp(*argv, "depth") == 0) {
+ NEXT_ARG();
+ if (get_integer((int *) &opt.flows, *argv, 0)) {
+ fprintf(stderr, "Illegal \"depth\"\n");
+ return -1;
+ }
+ ok++;
+ } else if (strcmp(*argv, "divisor") == 0) {
+ NEXT_ARG();
+ if (get_integer((int *) &opt.divisor, *argv, 0)) {
+ fprintf(stderr, "Illegal \"divisor\"\n");
+ return -1;
+ }
+ if(opt.divisor >= 14) {
+ fprintf(stderr, "Illegal \"divisor\": must be < 14\n");
+ return -1;
+ }
+ opt.divisor=pow(2,opt.divisor);
+ ok++;
+ } else if (strcmp(*argv, "limit") == 0) {
+ NEXT_ARG();
+ if (get_integer((int *) &opt.limit, *argv, 0)) {
+ fprintf(stderr, "Illegal \"limit\"\n");
+ return -1;
+ }
+ ok++;
+ } else if (strcmp(*argv, "hash") == 0) {
+ NEXT_ARG();
+ if(strcmp(*argv, "classic") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_CLASSIC;
+ } else
+ if(strcmp(*argv, "dst") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_DST;
+ } else
+ if(strcmp(*argv, "src") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_SRC;
+ } else
+ if(strcmp(*argv, "ctorigsrc") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_CTORIGSRC;
+ } else
+ if(strcmp(*argv, "ctorigdst") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_CTORIGDST;
+ } else
+ if(strcmp(*argv, "ctreplsrc") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_CTREPLSRC;
+ } else
+ if(strcmp(*argv, "ctrepldst") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_CTREPLDST;
+ } else
+ if(strcmp(*argv, "ctnatchg") == 0) {
+ opt.hash_kind= TCA_SFQ_HASH_CTNATCHG;
+ } else {
+ fprintf(stderr, "Illegal \"hash\"\n");
+ explain();
+ return -1;
+ }
+ ok++;
+ } else if (strcmp(*argv, "help") == 0) {
+ explain();
+ return -1;
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain();
+ return -1;
+ }
+ argc--; argv++;
+ }
+
+ if (ok)
+ addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
+ return 0;
+}
+
+static int esfq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+ struct tc_esfq_qopt *qopt;
+ SPRINT_BUF(b1);
+
+ if (opt == NULL)
+ return 0;
+
+ if (RTA_PAYLOAD(opt) < sizeof(*qopt))
+ return -1;
+ qopt = RTA_DATA(opt);
+ fprintf(f, "quantum %s ", sprint_size(qopt->quantum, b1));
+ if (show_details) {
+ fprintf(f, "limit %up flows %u/%u ",
+ qopt->limit, qopt->flows, qopt->divisor);
+ }
+ if (qopt->perturb_period)
+ fprintf(f, "perturb %dsec ", qopt->perturb_period);
+
+ fprintf(f,"hash: ");
+ switch(qopt->hash_kind)
+ {
+ case TCA_SFQ_HASH_CLASSIC:
+ fprintf(f,"classic");
+ break;
+ case TCA_SFQ_HASH_DST:
+ fprintf(f,"dst");
+ break;
+ case TCA_SFQ_HASH_SRC:
+ fprintf(f,"src");
+ break;
+ case TCA_SFQ_HASH_CTORIGSRC:
+ fprintf(f,"ctorigsrc");
+ break;
+ case TCA_SFQ_HASH_CTORIGDST:
+ fprintf(f,"ctorigdst");
+ break;
+ case TCA_SFQ_HASH_CTREPLSRC:
+ fprintf(f,"ctreplsrc");
+ break;
+ case TCA_SFQ_HASH_CTREPLDST:
+ fprintf(f,"ctrepldst");
+ break;
+ case TCA_SFQ_HASH_CTNATCHG:
+ fprintf(f,"ctnatchg");
+ break;
+ default:
+ fprintf(f,"Unknown");
+ }
+ return 0;
+}
+
+static int esfq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
+{
+ return 0;
+}
+
+
+struct qdisc_util esfq_qdisc_util = {
+ .id = "esfq",
+ .parse_qopt = esfq_parse_opt,
+ .print_qopt = esfq_print_opt,
+ .print_xstats = esfq_print_xstats,
+};
@@ -0,0 +1,11 @@
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -1,7 +1,7 @@
SSOBJ=ss.o ssfilter.o
LNSTATOBJ=lnstat.o lnstat_util.o
-TARGETS=ss nstat ifstat rtacct arpd lnstat
+TARGETS=ss nstat ifstat rtacct lnstat
include ../Config
@@ -0,0 +1,11 @@
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prot
CFLAGS = $(CCOPTS) -I../include $(DEFINES)
YACCFLAGS = -d -t -v
-SUBDIRS=lib ip tc misc netem genl
+SUBDIRS=lib ip tc misc genl
LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a
LDLIBS += $(LIBNETLINK)
@@ -0,0 +1,13 @@
---
tc/q_fifo.c | 1 +
1 file changed, 1 insertion(+)
--- a/tc/q_fifo.c
+++ b/tc/q_fifo.c
@@ -98,5 +98,6 @@ struct qdisc_util pfifo_head_drop_qdisc_
extern int prio_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt);
struct qdisc_util pfifo_fast_qdisc_util = {
.id = "pfifo_fast",
+ .parse_qopt = fifo_parse_opt,
.print_qopt = prio_print_opt,
};
@@ -0,0 +1,11 @@
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ ADDLIB+=ipx_ntop.o ipx_pton.o
CC = gcc
HOSTCC = gcc
-CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall
+CCOPTS = -D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall $(EXTRA_CCOPTS)
CFLAGS = $(CCOPTS) -I../include $(DEFINES)
YACCFLAGS = -d -t -v
@@ -0,0 +1,8 @@
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -1,4 +1,4 @@
-CFLAGS += -fPIC
+CFLAGS+=$(FPIC)
UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o
@@ -0,0 +1,84 @@
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -38,6 +38,7 @@ TCMODULES += m_mirred.o
TCMODULES += m_nat.o
TCMODULES += m_pedit.o
TCMODULES += m_skbedit.o
+TCMODULES += m_connmark.o
TCMODULES += m_csum.o
TCMODULES += p_ip.o
TCMODULES += p_icmp.o
--- /dev/null
+++ b/tc/m_connmark.c
@@ -0,0 +1,71 @@
+/*
+ * m_connmark.c Connection tracking marking import
+ *
+ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "utils.h"
+#include "tc_util.h"
+
+static void
+explain(void)
+{
+ fprintf(stderr, "Usage: ... connmark\n");
+}
+
+static void
+usage(void)
+{
+ explain();
+ exit(-1);
+}
+
+static int
+parse_connmark(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
+ struct nlmsghdr *n)
+{
+ int argc = *argc_p;
+ char **argv = *argv_p;
+
+ if (matches(*argv, "connmark") != 0)
+ return -1;
+
+ NEXT_ARG();
+
+ *argc_p = argc;
+ *argv_p = argv;
+ return 0;
+}
+
+static int print_connmark(struct action_util *au, FILE *f, struct rtattr *arg)
+{
+ if (arg == NULL)
+ return -1;
+
+ fprintf(f, " connmark");
+
+ return 0;
+}
+
+struct action_util connmark_action_util = {
+ .id = "connmark",
+ .parse_aopt = parse_connmark,
+ .print_aopt = print_connmark,
+};
@@ -0,0 +1,437 @@
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -49,6 +49,8 @@ TCMODULES += em_cmp.o
TCMODULES += em_u32.o
TCMODULES += em_meta.o
TCMODULES += q_mqprio.o
+TCMODULES += q_codel.o
+TCMODULES += q_fq_codel.o
TCSO :=
ifeq ($(TC_CONFIG_ATM),y)
--- /dev/null
+++ b/tc/q_codel.c
@@ -0,0 +1,188 @@
+/*
+ * Codel - The Controlled-Delay Active Queue Management algorithm
+ *
+ * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
+ * Copyright (C) 2011-2012 Van Jacobson <van@pollere.com>
+ * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... codel [ limit PACKETS ] [ target TIME]\n");
+ fprintf(stderr, " [ interval TIME ] [ ecn ]\n");
+}
+
+static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
+ struct nlmsghdr *n)
+{
+ unsigned limit = 0;
+ unsigned target = 0;
+ unsigned interval = 0;
+ int ecn = -1;
+ struct rtattr *tail;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "limit") == 0) {
+ NEXT_ARG();
+ if (get_unsigned(&limit, *argv, 0)) {
+ fprintf(stderr, "Illegal \"limit\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "target") == 0) {
+ NEXT_ARG();
+ if (get_time(&target, *argv)) {
+ fprintf(stderr, "Illegal \"target\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "interval") == 0) {
+ NEXT_ARG();
+ if (get_time(&interval, *argv)) {
+ fprintf(stderr, "Illegal \"interval\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "ecn") == 0) {
+ ecn = 1;
+ } else if (strcmp(*argv, "noecn") == 0) {
+ ecn = 0;
+ } else if (strcmp(*argv, "help") == 0) {
+ explain();
+ return -1;
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain();
+ return -1;
+ }
+ argc--; argv++;
+ }
+
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ if (limit)
+ addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit));
+ if (interval)
+ addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval));
+ if (target)
+ addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target));
+ if (ecn != -1)
+ addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn));
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ return 0;
+}
+
+static int codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+ struct rtattr *tb[TCA_CODEL_MAX + 1];
+ unsigned limit;
+ unsigned interval;
+ unsigned target;
+ unsigned ecn;
+ SPRINT_BUF(b1);
+
+ if (opt == NULL)
+ return 0;
+
+ parse_rtattr_nested(tb, TCA_CODEL_MAX, opt);
+
+ if (tb[TCA_CODEL_LIMIT] &&
+ RTA_PAYLOAD(tb[TCA_CODEL_LIMIT]) >= sizeof(__u32)) {
+ limit = rta_getattr_u32(tb[TCA_CODEL_LIMIT]);
+ fprintf(f, "limit %up ", limit);
+ }
+ if (tb[TCA_CODEL_TARGET] &&
+ RTA_PAYLOAD(tb[TCA_CODEL_TARGET]) >= sizeof(__u32)) {
+ target = rta_getattr_u32(tb[TCA_CODEL_TARGET]);
+ fprintf(f, "target %s ", sprint_time(target, b1));
+ }
+ if (tb[TCA_CODEL_INTERVAL] &&
+ RTA_PAYLOAD(tb[TCA_CODEL_INTERVAL]) >= sizeof(__u32)) {
+ interval = rta_getattr_u32(tb[TCA_CODEL_INTERVAL]);
+ fprintf(f, "interval %s ", sprint_time(interval, b1));
+ }
+ if (tb[TCA_CODEL_ECN] &&
+ RTA_PAYLOAD(tb[TCA_CODEL_ECN]) >= sizeof(__u32)) {
+ ecn = rta_getattr_u32(tb[TCA_CODEL_ECN]);
+ if (ecn)
+ fprintf(f, "ecn ");
+ }
+
+ return 0;
+}
+
+static int codel_print_xstats(struct qdisc_util *qu, FILE *f,
+ struct rtattr *xstats)
+{
+ struct tc_codel_xstats *st;
+ SPRINT_BUF(b1);
+
+ if (xstats == NULL)
+ return 0;
+
+ if (RTA_PAYLOAD(xstats) < sizeof(*st))
+ return -1;
+
+ st = RTA_DATA(xstats);
+ fprintf(f, " count %u lastcount %u ldelay %s",
+ st->count, st->lastcount, sprint_time(st->ldelay, b1));
+ if (st->dropping)
+ fprintf(f, " dropping");
+ if (st->drop_next < 0)
+ fprintf(f, " drop_next -%s", sprint_time(-st->drop_next, b1));
+ else
+ fprintf(f, " drop_next %s", sprint_time(st->drop_next, b1));
+ fprintf(f, "\n maxpacket %u ecn_mark %u drop_overlimit %u",
+ st->maxpacket, st->ecn_mark, st->drop_overlimit);
+ return 0;
+
+}
+
+struct qdisc_util codel_qdisc_util = {
+ .id = "codel",
+ .parse_qopt = codel_parse_opt,
+ .print_qopt = codel_print_opt,
+ .print_xstats = codel_print_xstats,
+};
--- /dev/null
+++ b/tc/q_fq_codel.c
@@ -0,0 +1,232 @@
+/*
+ * Fair Queue Codel
+ *
+ * Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "utils.h"
+#include "tc_util.h"
+
+static void explain(void)
+{
+ fprintf(stderr, "Usage: ... fq_codel [ limit PACKETS ] [ flows NUMBER ]\n");
+ fprintf(stderr, " [ target TIME] [ interval TIME ]\n");
+ fprintf(stderr, " [ quantum BYTES ] [ [no]ecn ]\n");
+}
+
+static int fq_codel_parse_opt(struct qdisc_util *qu, int argc, char **argv,
+ struct nlmsghdr *n)
+{
+ unsigned limit = 0;
+ unsigned flows = 0;
+ unsigned target = 0;
+ unsigned interval = 0;
+ unsigned quantum = 0;
+ int ecn = -1;
+ struct rtattr *tail;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "limit") == 0) {
+ NEXT_ARG();
+ if (get_unsigned(&limit, *argv, 0)) {
+ fprintf(stderr, "Illegal \"limit\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "flows") == 0) {
+ NEXT_ARG();
+ if (get_unsigned(&flows, *argv, 0)) {
+ fprintf(stderr, "Illegal \"flows\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "quantum") == 0) {
+ NEXT_ARG();
+ if (get_unsigned(&quantum, *argv, 0)) {
+ fprintf(stderr, "Illegal \"quantum\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "target") == 0) {
+ NEXT_ARG();
+ if (get_time(&target, *argv)) {
+ fprintf(stderr, "Illegal \"target\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "interval") == 0) {
+ NEXT_ARG();
+ if (get_time(&interval, *argv)) {
+ fprintf(stderr, "Illegal \"interval\"\n");
+ return -1;
+ }
+ } else if (strcmp(*argv, "ecn") == 0) {
+ ecn = 1;
+ } else if (strcmp(*argv, "noecn") == 0) {
+ ecn = 0;
+ } else if (strcmp(*argv, "help") == 0) {
+ explain();
+ return -1;
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ explain();
+ return -1;
+ }
+ argc--; argv++;
+ }
+
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ if (limit)
+ addattr_l(n, 1024, TCA_FQ_CODEL_LIMIT, &limit, sizeof(limit));
+ if (flows)
+ addattr_l(n, 1024, TCA_FQ_CODEL_FLOWS, &flows, sizeof(flows));
+ if (quantum)
+ addattr_l(n, 1024, TCA_FQ_CODEL_QUANTUM, &quantum, sizeof(quantum));
+ if (interval)
+ addattr_l(n, 1024, TCA_FQ_CODEL_INTERVAL, &interval, sizeof(interval));
+ if (target)
+ addattr_l(n, 1024, TCA_FQ_CODEL_TARGET, &target, sizeof(target));
+ if (ecn != -1)
+ addattr_l(n, 1024, TCA_FQ_CODEL_ECN, &ecn, sizeof(ecn));
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ return 0;
+}
+
+static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+ struct rtattr *tb[TCA_FQ_CODEL_MAX + 1];
+ unsigned limit;
+ unsigned flows;
+ unsigned interval;
+ unsigned target;
+ unsigned ecn;
+ unsigned quantum;
+ SPRINT_BUF(b1);
+
+ if (opt == NULL)
+ return 0;
+
+ parse_rtattr_nested(tb, TCA_FQ_CODEL_MAX, opt);
+
+ if (tb[TCA_FQ_CODEL_LIMIT] &&
+ RTA_PAYLOAD(tb[TCA_FQ_CODEL_LIMIT]) >= sizeof(__u32)) {
+ limit = rta_getattr_u32(tb[TCA_FQ_CODEL_LIMIT]);
+ fprintf(f, "limit %up ", limit);
+ }
+ if (tb[TCA_FQ_CODEL_FLOWS] &&
+ RTA_PAYLOAD(tb[TCA_FQ_CODEL_FLOWS]) >= sizeof(__u32)) {
+ flows = rta_getattr_u32(tb[TCA_FQ_CODEL_FLOWS]);
+ fprintf(f, "flows %u ", flows);
+ }
+ if (tb[TCA_FQ_CODEL_QUANTUM] &&
+ RTA_PAYLOAD(tb[TCA_FQ_CODEL_QUANTUM]) >= sizeof(__u32)) {
+ quantum = rta_getattr_u32(tb[TCA_FQ_CODEL_QUANTUM]);
+ fprintf(f, "quantum %u ", quantum);
+ }
+ if (tb[TCA_FQ_CODEL_TARGET] &&
+ RTA_PAYLOAD(tb[TCA_FQ_CODEL_TARGET]) >= sizeof(__u32)) {
+ target = rta_getattr_u32(tb[TCA_FQ_CODEL_TARGET]);
+ fprintf(f, "target %s ", sprint_time(target, b1));
+ }
+ if (tb[TCA_FQ_CODEL_INTERVAL] &&
+ RTA_PAYLOAD(tb[TCA_FQ_CODEL_INTERVAL]) >= sizeof(__u32)) {
+ interval = rta_getattr_u32(tb[TCA_FQ_CODEL_INTERVAL]);
+ fprintf(f, "interval %s ", sprint_time(interval, b1));
+ }
+ if (tb[TCA_FQ_CODEL_ECN] &&
+ RTA_PAYLOAD(tb[TCA_FQ_CODEL_ECN]) >= sizeof(__u32)) {
+ ecn = rta_getattr_u32(tb[TCA_FQ_CODEL_ECN]);
+ if (ecn)
+ fprintf(f, "ecn ");
+ }
+
+ return 0;
+}
+
+static int fq_codel_print_xstats(struct qdisc_util *qu, FILE *f,
+ struct rtattr *xstats)
+{
+ struct tc_fq_codel_xstats *st;
+ SPRINT_BUF(b1);
+
+ if (xstats == NULL)
+ return 0;
+
+ if (RTA_PAYLOAD(xstats) < sizeof(*st))
+ return -1;
+
+ st = RTA_DATA(xstats);
+ if (st->type == TCA_FQ_CODEL_XSTATS_QDISC) {
+ fprintf(f, " maxpacket %u drop_overlimit %u new_flow_count %u ecn_mark %u",
+ st->qdisc_stats.maxpacket,
+ st->qdisc_stats.drop_overlimit,
+ st->qdisc_stats.new_flow_count,
+ st->qdisc_stats.ecn_mark);
+ fprintf(f, "\n new_flows_len %u old_flows_len %u",
+ st->qdisc_stats.new_flows_len,
+ st->qdisc_stats.old_flows_len);
+ }
+ if (st->type == TCA_FQ_CODEL_XSTATS_CLASS) {
+ fprintf(f, " deficit %d count %u lastcount %u ldelay %s",
+ st->class_stats.deficit,
+ st->class_stats.count,
+ st->class_stats.lastcount,
+ sprint_time(st->class_stats.ldelay, b1));
+ if (st->class_stats.dropping) {
+ fprintf(f, " dropping");
+ if (st->class_stats.drop_next < 0)
+ fprintf(f, " drop_next -%s",
+ sprint_time(-st->class_stats.drop_next, b1));
+ else
+ fprintf(f, " drop_next %s",
+ sprint_time(st->class_stats.drop_next, b1));
+ }
+ }
+ return 0;
+
+}
+
+struct qdisc_util fq_codel_qdisc_util = {
+ .id = "fq_codel",
+ .parse_qopt = fq_codel_parse_opt,
+ .print_qopt = fq_codel_print_opt,
+ .print_xstats = fq_codel_print_xstats,
+};
+475
View File
@@ -0,0 +1,475 @@
#
# Copyright (C) 2006-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=iptables
PKG_VERSION:=1.4.10
PKG_RELEASE:=4
PKG_MD5SUM:=f382fe693f0b59d87bd47bea65eca198
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=http://www.netfilter.org/projects/iptables/files \
ftp://ftp.be.netfilter.org/pub/netfilter/iptables/ \
ftp://ftp.de.netfilter.org/pub/netfilter/iptables/ \
ftp://ftp.no.netfilter.org/pub/netfilter/iptables/
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
ifneq ($(CONFIG_EXTERNAL_KERNEL_TREE),"")
PATCH_DIR:=
endif
include $(INCLUDE_DIR)/package.mk
ifeq ($(DUMP),)
-include $(LINUX_DIR)/.config
include $(INCLUDE_DIR)/netfilter.mk
STAMP_CONFIGURED:=$(strip $(STAMP_CONFIGURED))_$(shell $(SH_FUNC) grep 'NETFILTER' $(LINUX_DIR)/.config | md5s)
endif
define Package/iptables/Default
SECTION:=net
CATEGORY:=Network
SUBMENU:=Firewall
URL:=http://netfilter.org/
endef
define Package/iptables/Module
$(call Package/iptables/Default)
DEPENDS:=iptables $(1)
endef
define Package/iptables
$(call Package/iptables/Default)
TITLE:=IPv4 firewall administration tool
MENU:=1
DEPENDS+= +kmod-ipt-core +libip4tc +libxtables
endef
define Package/iptables/description
IPv4 firewall administration tool.
Matches:
- icmp
- tcp
- udp
- comment
- limit
- mac
- multiport
Targets:
- ACCEPT
- DROP
- REJECT
- LOG
- TCPMSS
Tables:
- filter
- mangle
endef
define Package/iptables-mod-conntrack-extra
$(call Package/iptables/Module, +kmod-ipt-conntrack-extra)
TITLE:=Extra connection tracking extensions
endef
define Package/iptables-mod-conntrack-extra/description
Extra iptables extensions for connection tracking.
Matches:
- connbytes
- connmark
- recent
- helper
Targets:
- CONNMARK
endef
define Package/iptables-mod-filter
$(call Package/iptables/Module, +kmod-ipt-filter)
TITLE:=Content inspection extensions
endef
define Package/iptables-mod-filter/description
iptables extensions for packet content inspection.
Includes support for:
Matches:
- layer7
- string
endef
define Package/iptables-mod-ipopt
$(call Package/iptables/Module, +kmod-ipt-ipopt)
TITLE:=IP/Packet option extensions
endef
define Package/iptables-mod-ipopt/description
iptables extensions for matching/changing IP packet options.
Matches:
- dscp
- ecn
- length
- mark
- statistic
- tcpmss
- time
- unclean
- hl
Targets:
- DSCP
- CLASSIFY
- ECN
- MARK
- HL
endef
define Package/iptables-mod-ipsec
$(call Package/iptables/Module, +kmod-ipt-ipsec)
TITLE:=IPsec extensions
endef
define Package/iptables-mod-ipsec/description
iptables extensions for matching ipsec traffic.
Matches:
- ah
- esp
- policy
endef
define Package/iptables-mod-ipset
$(call Package/iptables/Module,)
TITLE:=IPset iptables extensions
endef
define Package/iptables-mod-ipset/description
IPset iptables extensions.
Matches:
- set
Targets:
- SET
endef
define Package/iptables-mod-nat-extra
$(call Package/iptables/Module, +kmod-ipt-nat-extra)
TITLE:=Extra NAT extensions
endef
define Package/iptables-mod-nat-extra/description
iptables extensions for extra NAT targets.
Targets:
- MIRROR
- NETMAP
- REDIRECT
endef
define Package/iptables-mod-ulog
$(call Package/iptables/Module, +kmod-ipt-ulog)
TITLE:=user-space packet logging
endef
define Package/iptables-mod-ulog/description
iptables extensions for user-space packet logging.
Targets:
- ULOG
endef
define Package/iptables-mod-hashlimit
$(call Package/iptables/Module, +kmod-ipt-hashlimit)
TITLE:=hashlimit matching
endef
define Package/iptables-mod-hashlimit/description
iptables extensions for hashlimit matching
Matches:
- hashlimit
endef
define Package/iptables-mod-iprange
$(call Package/iptables/Module, +kmod-ipt-iprange)
TITLE:=IP range extension
endef
define Package/iptables-mod-iprange/description
iptables extensions for matching ip ranges.
Matches:
- iprange
endef
define Package/iptables-mod-extra
$(call Package/iptables/Module, +kmod-ipt-extra)
TITLE:=Other extra iptables extensions
endef
define Package/iptables-mod-extra/description
Other extra iptables extensions.
Matches:
- condition
- owner
- physdev (if ebtables is enabled)
- pkttype
- quota
endef
define Package/iptables-mod-led
$(call Package/iptables/Module, +kmod-ipt-led)
TITLE:=LED trigger iptables extension
endef
define Package/iptables-mod-led/description
iptables extension for triggering a LED.
Targets:
- LED
endef
define Package/iptables-mod-tproxy
$(call Package/iptables/Module, +kmod-ipt-tproxy)
TITLE:=Transparent proxy iptables extensions
endef
define Package/iptables-mod-tproxy/description
Transparent proxy iptables extensions.
Matches:
- socket
Targets:
- TPROXY
endef
define Package/iptables-mod-tee
$(call Package/iptables/Module, +kmod-ipt-tee)
TITLE:=TEE iptables extensions
endef
define Package/iptables-mod-tee/description
TEE iptables extensions.
Targets:
- TEE
endef
define Package/iptables-mod-u32
$(call Package/iptables/Module, +kmod-ipt-u32)
TITLE:=U32 iptables extensions
endef
define Package/iptables-mod-u32/description
U32 iptables extensions.
Matches:
- u32
endef
define Package/ip6tables
$(call Package/iptables/Default)
DEPENDS:=+kmod-ip6tables +libip6tc +libxtables
CATEGORY:=IPv6
TITLE:=IPv6 firewall administration tool
MENU:=1
endef
define Package/libiptc
$(call Package/iptables/Default)
SECTION:=libs
CATEGORY:=Libraries
DEPENDS:=+libip4tc +libip6tc
TITLE:=IPv4/IPv6 firewall - shared libiptc library (compatibility stub)
endef
define Package/libip4tc
$(call Package/iptables/Default)
SECTION:=libs
CATEGORY:=Libraries
TITLE:=IPv4 firewall - shared libiptc library
endef
define Package/libip6tc
$(call Package/iptables/Default)
SECTION:=libs
CATEGORY:=Libraries
TITLE:=IPv6 firewall - shared libiptc library
endef
define Package/libxtables
$(call Package/iptables/Default)
SECTION:=libs
CATEGORY:=Libraries
TITLE:=IPv4/IPv6 firewall - shared xtables library
endef
define Package/libipq
$(call Package/iptables/Default)
SECTION:=libs
CATEGORY:=Libraries
TITLE:=IPv4/IPv6 firewall - shared libipq library
endef
TARGET_CPPFLAGS := \
-I$(PKG_BUILD_DIR)/include \
-I$(LINUX_DIR)/user_headers/include \
$(TARGET_CPPFLAGS)
TARGET_CFLAGS += \
-I$(PKG_BUILD_DIR)/include \
-I$(LINUX_DIR)/user_headers/include
CONFIGURE_ARGS += \
--enable-shared \
--enable-devel \
$(if $(CONFIG_IPV6),--enable-ipv6,--disable-ipv6) \
--enable-libipq \
--with-kernel="$(LINUX_DIR)/user_headers" \
--with-xtlibdir=/usr/lib/iptables \
--enable-static
MAKE_FLAGS := \
$(TARGET_CONFIGURE_OPTS) \
COPT_FLAGS="$(TARGET_CFLAGS)" \
KERNEL_DIR="$(LINUX_DIR)/user_headers/" PREFIX=/usr \
KBUILD_OUTPUT="$(LINUX_DIR)" \
BUILTIN_MODULES="$(patsubst ipt_%,%,$(patsubst xt_%,%,$(IPT_BUILTIN) $(IPT_CONNTRACK-m) $(IPT_NAT-m)))"
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(INSTALL_DIR) $(1)/usr/include/iptables
$(INSTALL_DIR) $(1)/usr/include/net/netfilter
# XXX: iptables header fixup, some headers are not installed by iptables anymore
$(CP) $(PKG_BUILD_DIR)/include/net/netfilter/*.h $(1)/usr/include/net/netfilter/
$(CP) $(PKG_BUILD_DIR)/include/iptables/*.h $(1)/usr/include/iptables/
$(CP) $(PKG_BUILD_DIR)/include/iptables.h $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/include/libipq/libipq.h $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/include/libipulog $(1)/usr/include/
$(CP) $(PKG_BUILD_DIR)/include/libiptc $(1)/usr/include/
$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libxtables.so* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libip*tc.so* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libipq.so* $(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/xtables.pc $(1)/usr/lib/pkgconfig/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libiptc.pc $(1)/usr/lib/pkgconfig/
endef
define Package/iptables/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/iptables $(1)/usr/sbin/
$(LN) iptables $(1)/usr/sbin/iptables-save
$(LN) iptables $(1)/usr/sbin/iptables-restore
$(INSTALL_DIR) $(1)/usr/lib/iptables
endef
define Package/ip6tables/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ip6tables $(1)/usr/sbin/
$(LN) ip6tables $(1)/usr/sbin/ip6tables-save
$(LN) ip6tables $(1)/usr/sbin/ip6tables-restore
$(INSTALL_DIR) $(1)/usr/lib/iptables
(cd $(PKG_INSTALL_DIR)/usr/lib/iptables ; \
$(CP) libip6t_*.so $(1)/usr/lib/iptables/ \
)
endef
define Package/libiptc/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libiptc.so* $(1)/usr/lib/
endef
define Package/libip4tc/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libip4tc.so* $(1)/usr/lib/
endef
define Package/libip6tc/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libip6tc.so* $(1)/usr/lib/
endef
define Package/libxtables/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libxtables.so* $(1)/usr/lib/
endef
define Package/libipq/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libipq.so* $(1)/usr/lib/
endef
define BuildPlugin
define Package/$(1)/install
$(INSTALL_DIR) $$(1)/usr/lib/iptables
for m in $(patsubst xt_%,ipt_%,$(2)) $(patsubst ipt_%,xt_%,$(2)); do \
if [ -f $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so ]; then \
$(CP) $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so $$(1)/usr/lib/iptables/ ; \
fi; \
done
$(3)
endef
$$(eval $$(call BuildPackage,$(1)))
endef
L7_INSTALL:=\
$(INSTALL_DIR) $$(1)/etc/l7-protocols; \
$(CP) files/l7/*.pat $$(1)/etc/l7-protocols/
$(eval $(call BuildPackage,iptables))
$(eval $(call BuildPlugin,iptables-mod-conntrack-extra,$(IPT_CONNTRACK_EXTRA-m)))
$(eval $(call BuildPlugin,iptables-mod-extra,$(IPT_EXTRA-m)))
$(eval $(call BuildPlugin,iptables-mod-filter,$(IPT_FILTER-m),$(L7_INSTALL)))
$(eval $(call BuildPlugin,iptables-mod-ipopt,$(IPT_IPOPT-m)))
$(eval $(call BuildPlugin,iptables-mod-ipsec,$(IPT_IPSEC-m)))
$(eval $(call BuildPlugin,iptables-mod-ipset,ipt_set ipt_SET))
$(eval $(call BuildPlugin,iptables-mod-nat-extra,$(IPT_NAT_EXTRA-m)))
$(eval $(call BuildPlugin,iptables-mod-iprange,$(IPT_IPRANGE-m)))
$(eval $(call BuildPlugin,iptables-mod-ulog,$(IPT_ULOG-m)))
$(eval $(call BuildPlugin,iptables-mod-hashlimit,$(IPT_HASHLIMIT-m)))
$(eval $(call BuildPlugin,iptables-mod-led,$(IPT_LED-m)))
$(eval $(call BuildPlugin,iptables-mod-tproxy,$(IPT_TPROXY-m)))
$(eval $(call BuildPlugin,iptables-mod-tee,$(IPT_TEE-m)))
$(eval $(call BuildPlugin,iptables-mod-u32,$(IPT_U32-m)))
$(eval $(call BuildPackage,ip6tables))
$(eval $(call BuildPackage,libiptc))
$(eval $(call BuildPackage,libip4tc))
$(eval $(call BuildPackage,libip6tc))
$(eval $(call BuildPackage,libxtables))
$(eval $(call BuildPackage,libipq))
@@ -0,0 +1,28 @@
# AIM - AOL instant messenger (OSCAR and TOC)
# Pattern attributes: good slow notsofast
# Protocol groups: chat proprietary
# Wiki: http://www.protocolinfo.org/wiki/AIM
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually runs on port 5190
#
# This may also match ICQ traffic.
#
# This pattern has been tested and is believed to work well.
aim
# See http://gridley.res.carleton.edu/~straitm/final (and various other places)
# The first bit matches OSCAR signon and data commands, but not sure what
# \x03\x0b matches, but it works apparently.
# The next three bits match various parts of the TOC signon process.
# The third one is the magic number "*", then 0x01 for "signon", then up to four
# bytes ("up to" because l7-filter strips out nulls) which contain a sequence
# number (2 bytes) the data length (2 more) and 3 nulls (which don't count),
# then 0x01 for the version number (not sure if there ever has been another
# version)
# The fourth one is a command string, followed by some stuff, then the
# beginning of the "roasted" password
# This pattern is too slow!
^(\*[\x01\x02].*\x03\x0b|\*\x01.?.?.?.?\x01)|flapon|toc_signon.*0x
@@ -0,0 +1,25 @@
# Bittorrent - P2P filesharing / publishing tool - http://www.bittorrent.com
# Pattern attributes: good slow594 notsofast undermatch
# Protocol groups: p2p open_source
# Wiki: http://www.protocolinfo.org/wiki/Bittorrent
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# This pattern has been tested and is believed to work well.
# It will, however, not work on bittorrent streams that are encrypted, since
# it's impossible to match (well) encrypted data.
bittorrent
# Does not attempt to match the HTTP download of the tracker
# 0x13 is the length of "bittorrent protocol"
# Second two bits match UDP wierdness
# Next bit matches something Azureus does
# Ditto on the next bit. Could also match on "user-agent: azureus", but that's in the next
# packet and perhaps this will match multiple clients.
# bitcomet-specific strings contributed by liangjun.
# This is not a valid GNU basic regular expression (but that's ok).
^(\x13bittorrent protocol|azver\x01$|get /scrape\?info_hash=get /announce\?info_hash=|get /client/bitcomet/|GET /data\?fid=)|d1:ad2:id20:|\x08'7P\)[RP]
# This pattern is "fast", but won't catch as much
#^(\x13bittorrent protocol|azver\x01$|get /scrape\?info_hash=)
@@ -0,0 +1,37 @@
# eDonkey2000 - P2P filesharing - http://edonkey2000.com and others
# Pattern attributes: good veryfast fast overmatch
# Protocol groups: p2p
# Wiki: http://www.protocolinfo.org/wiki/EDonkey
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Tested recently (April/May 2006) with eMule 0.47a and eDonkey2000 1.4
# and a long time ago with something else.
#
# In addition to matching what you might expect, this matches much of
# what eMule does when you tell it to only connect to the KAD network.
# I don't quite know what to make of this.
# Thanks to Matt Skidmore <fox AT woozle.org>
edonkey
# http://gd.tuwien.ac.at/opsys/linux/sf/p/pdonkey/eDonkey-protocol-0.6
#
# In addition to \xe3, \xc5 and \xd4, I see a lot of \xe5.
# As of April 2006, I also see some \xe4.
#
# God this is a mess. What an irritating protocol.
# This will match about 2% of streams with random data in them!
# (But fortunately much fewer than 2% of streams that are other protocols.
# You can test this with the data in ../testing/)
^[\xc5\xd4\xe3-\xe5].?.?.?.?([\x01\x02\x05\x14\x15\x16\x18\x19\x1a\x1b\x1c\x20\x21\x32\x33\x34\x35\x36\x38\x40\x41\x42\x43\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58[\x60\x81\x82\x90\x91\x93\x96\x97\x98\x99\x9a\x9b\x9c\x9e\xa0\xa1\xa2\xa3\xa4]|\x59................?[ -~]|\x96....$)
# matches everything and too much
# ^(\xe3|\xc5|\xd4)
# ipp2p essentially uses "\xe3....\x47", which doesn't seem at all right to me.
# bandwidtharbitrator uses
# e0.*@.*6[a-z].*p$|e0.*@.*[a-z]6[a-z].*p0$|e.*@.*[0-9]6.*p$|emule|edonkey
# no comments to explain what all the mush is, of course...
@@ -0,0 +1,23 @@
# FastTrack - P2P filesharing (Kazaa, Morpheus, iMesh, Grokster, etc)
# Pattern attributes: good slow notsofast
# Protocol groups: p2p
# Wiki: http://www.protocolinfo.org/wiki/Fasttrack
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Tested with Kazaa Lite Resurrection 0.0.7.6F
#
# This appears to match the download connections well, but not the search
# connections (I think they are encrypted :-( ).
fasttrack
# while this is a valid http request, this will be caught because
# the http pattern matches the response (and therefore the next packet)
# Even so, it's best to put this match earlier in the chain.
# http://cvs.berlios.de/cgi-bin/viewcvs.cgi/gift-fasttrack/giFT-FastTrack/PROTOCOL?rev=HEAD&content-type=text/vnd.viewcvs-markup
# This pattern is kinda slow, but not too bad.
^get (/.download/[ -~]*|/.supernode[ -~]|/.status[ -~]|/.network[ -~]*|/.files|/.hash=[0-9a-f]*/[ -~]*) http/1.1|user-agent: kazaa|x-kazaa(-username|-network|-ip|-supernodeip|-xferid|-xferuid|tag)|^give [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?[0-9]?[0-9]?
# This isn't much faster:
#^get (/.download/.*|/.supernode.|/.status.|/.network.*|/.files|/.hash=[0-9a-f]*/.*) http/1.1|user-agent: kazaa|x-kazaa(-username|-network|-ip|-supernodeip|-xferid|-xferuid|tag)|^give [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?[0-9]?[0-9]?
@@ -0,0 +1,46 @@
# FTP - File Transfer Protocol - RFC 959
# Pattern attributes: great notsofast fast
# Protocol groups: document_retrieval ietf_internet_standard
# Wiki: http://protocolinfo.org/wiki/FTP
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually runs on port 21. Note that the data stream is on a dynamically
# assigned port, which means that you will need the FTP connection
# tracking module in your kernel to usefully match FTP data transfers.
#
# This pattern is well tested.
#
# Handles the first two things a server should say:
#
# First, the server says it's ready by sending "220". Most servers say
# something after 220, even though they don't have to, and it usually
# includes the string "ftp" (l7-filter is case insensitive). This
# includes proftpd, vsftpd, wuftpd, warftpd, pureftpd, Bulletproof FTP
# Server, and whatever ftp.microsoft.com uses. Almost all servers use only
# ASCII printable characters between the "220" and the "FTP", but non-English
# ones might use others.
#
# The next thing the server sends is a 331. All the above servers also
# send something including "password" after this code. By default, we
# do not match on this because it takes another packet and is more work
# for regexec.
ftp
# by default, we allow only ASCII
^220[\x09-\x0d -~]*ftp
# This covers UTF-8 as well
#^220[\x09-\x0d -~\x80-\xfd]*ftp
# This allows any characters and is about 4x faster than either of the above
# (which are about the same as each other)
#^220.*ftp
# This is much slower
#^220[\x09-\x0d -~]*ftp|331[\x09-\x0d -~]*password
# This pattern is more precise, but takes longer to match. (3 packets vs. 1)
#^220[\x09-\x0d -~]*\x0d\x0aUSER[\x09-\x0d -~]*\x0d\x0a331
# same as above, but slightly less precise and only takes 2 packets.
#^220[\x09-\x0d -~]*\x0d\x0aUSER[\x09-\x0d -~]*\x0d\x0a
@@ -0,0 +1,34 @@
# Gnutella - P2P filesharing
# Pattern attributes: good notsofast notsofast
# Protocol groups: p2p open_source
# Wiki: http://www.protocolinfo.org/wiki/Gnutella
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# This should match both Gnutella and "Gnutella2" ("Mike's protocol")
#
# Various clients use this protocol including Mactella, Shareaza,
# GTK-gnutella, Gnucleus, Gnotella, LimeWire, iMesh and BearShare.
#
# This is tested with gtk-gnutella and Shareaza.
# http://www.gnutella2.com/tiki-index.php?page=UDP%20Transceiver
# http://rfc-gnutella.sf.net/
# http://www.gnutella2.com/tiki-index.php?page=Gnutella2%20Specification
# http://en.wikipedia.org/wiki/Shareaza
gnutella
# The first part matches UDP messages - All start with "GND", then have
# a flag byte which is either \x00, \x01 or \x02, then two sequence bytes
# that can be anything, then a fragment number, which must start at 1.
# The rest matches TCP first client message or first server message (in case
# we can't see client messages). Some parts of this are empirical rather than
# document based. Assumes version is between 0.0 and 2.9. (usually is
# 0.4 or 0.6). I'm guessing at many of the user-agents.
# The last bit is emprical and probably only matches Limewire.
^(gnd[\x01\x02]?.?.?\x01|gnutella connect/[012]\.[0-9]\x0d\x0a|get /uri-res/n2r\?urn:sha1:|get /.*user-agent: (gtk-gnutella|bearshare|mactella|gnucleus|gnotella|limewire|imesh)|get /.*content-type: application/x-gnutella-packets|giv [0-9]*:[0-9a-f]*/|queue [0-9a-f]* [1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?:[1-9][0-9]?[0-9]?[0-9]?|gnutella.*content-type: application/x-gnutella|...................?lime)
# Needlessly precise, at the expense of time
#^(gnd[\x01\x02]?.?.?\x01|gnutella connect/[012]\.[0-9]\x0d\x0a|get /uri-res/n2r\?urn:sha1:|get /[\x09-\x0d -~]*user-agent: (gtk-gnutella|bearshare|mactella|gnucleus|gnotella|limewire|imesh)|get /[\x09-\x0d -~]*content-type: application/x-gnutella-packets|giv [0-9]*:[0-9a-f]*/|queue [0-9a-f]* [1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?\.[1-9][0-9]?[0-9]?:[1-9][0-9]?[0-9]?[0-9]?|gnutella[\x09-\x0d -~]*content-type: application/x-gnutella|..................lime)
@@ -0,0 +1,28 @@
# HTTP - HyperText Transfer Protocol - RFC 2616
# Pattern attributes: great slow notsofast superset
# Protocol groups: document_retrieval ietf_draft_standard
# Wiki: http://protocolinfo.org/wiki/HTTP
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually runs on port 80
#
# This pattern has been tested and is believed to work well.
#
# this intentionally catches the response from the server rather than
# the request so that other protocols which use http (like kazaa) can be
# caught based on specific http requests regardless of the ordering of
# filters... also matches posts
# Sites that serve really long cookies may break this by pushing the
# server response too far away from the beginning of the connection. To
# fix this, increase the kernel's data buffer length.
http
# Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF (rfc 2616)
# As specified in rfc 2616 a status code is preceeded and followed by a
# space.
http/(0\.9|1\.0|1\.1) [1-5][0-9][0-9] [\x09-\x0d -~]*(connection:|content-type:|content-length:|date:)|post [\x09-\x0d -~]* http/[01]\.[019]
# A slightly faster version that might be good enough:
#http/(0\.9|1\.0|1\.1) [1-5][0-9][0-9]|post [\x09-\x0d -~]* http/[01]\.[019]
# old pattern(s):
#(http[\x09-\x0d -~]*(200 ok|302 |304 )[\x09-\x0d -~]*(connection:|content-type:|content-length:))|^(post [\x09-\x0d -~]* http/)
@@ -0,0 +1,15 @@
# Ident - Identification Protocol - RFC 1413
# Pattern attributes: good fast fast
# Protocol groups: networking ietf_proposed_standard
# Wiki: http://www.protocolinfo.org/wiki/Ident
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually runs on port 113
#
# This pattern is believed to work.
ident
# "number , numberCRLF" possibly without the CR and/or LF.
# ^$ is appropriate because the first packet should never have anything
# else in it.
^[1-9][0-9]?[0-9]?[0-9]?[0-9]?[\x09-\x0d]*,[\x09-\x0d]*[1-9][0-9]?[0-9]?[0-9]?[0-9]?(\x0d\x0a|[\x0d\x0a])?$
@@ -0,0 +1,20 @@
# IRC - Internet Relay Chat - RFC 1459
# Pattern attributes: great veryfast fast
# Protocol groups: chat ietf_proposed_standard
# Wiki: http://www.protocolinfo.org/wiki/IRC
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually runs on port 6666 or 6667
# Note that chat traffic runs on these ports, but IRC-DCC traffic (which
# can use much more bandwidth) uses a dynamically assigned port, so you
# must have the IRC connection tracking module in your kernel to classify
# this.
#
# This pattern has been tested and is believed to work well.
irc
# First thing that happens is that the client sends NICK and USER, in
# either order. This allows MIRC color codes (\x02-\x0d instead of
# \x09-\x0d).
^(nick[\x09-\x0d -~]*user[\x09-\x0d -~]*:|user[\x09-\x0d -~]*:[\x02-\x0d -~]*nick[\x09-\x0d -~]*\x0d\x0a)
@@ -0,0 +1,24 @@
# Jabber (XMPP) - open instant messenger protocol - RFC 3920 - http://jabber.org
# Pattern attributes: good notsofast notsofast
# Protocol groups: chat ietf_proposed_standard
# Wiki: http://www.protocolinfo.org/wiki/Jabber
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# This pattern has been tested with Gaim and Gabber. It is only tested
# with non-SSL mode Jabber with no proxies.
# Thanks to Jan Hudec for some improvements.
# Jabber seems to take a long time to set up a connection. I'm
# connecting with Gabber 0.8.8 to 12jabber.org and the first 8 packets
# is this:
# <stream:stream to='12jabber.com' xmlns='jabber:client'
# xmlns:stream='http://etherx.jabber.org/streams'><?xml
# version='1.0'?><stream:stream
# xmlns:stream='http://etherx.jabber.org/streams' id='3f73e951'
# xmlns='jabber:client' from='12jabber.com'>
#
# No mention of my username or password yet, you'll note.
jabber
<stream:stream[\x09-\x0d ][ -~]*[\x09-\x0d ]xmlns=['"]jabber
@@ -0,0 +1,28 @@
# MSN Messenger - Microsoft Network chat client
# Pattern attributes: good slow notsofast
# Protocol groups: chat proprietary
# Wiki: http://www.protocolinfo.org/wiki/MSN_Messenger
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually uses TCP port 1863
# http://www.hypothetic.org/docs/msn/index.php
# http://msnpiki.msnfanatic.com/
#
# This pattern has been tested and is believed to work well.
msnmessenger
# First branch: login
# ver: allow versions up to 99.
# I've never seen a cvr other than cvr0. Maybe this will be trouble later?
# Can't anchor at the beginning because sometimes this is encapsulated in
# HTTP. But either way, the first packet ends like this.
# Second/Third branches: accepting/sending a message
# I will assume that these can also be encapsulated in HTTP, although I have
# not checked. Example of each direction:
# ANS 1 quadong@hotmail.com 1139803431.29427 17522047
# USR 1 quadong@hotmail.com 530423708.968145.366138
# Branches are written entirely separately for better performance.
ver [0-9]+ msnp[1-9][0-9]? [\x09-\x0d -~]*cvr0\x0d\x0a$|usr 1 [!-~]+ [0-9. ]+\x0d\x0a$|ans 1 [!-~]+ [0-9. ]+\x0d\x0a$
@@ -0,0 +1,17 @@
# (S)NTP - (Simple) Network Time Protocol - RFCs 1305 and 2030
# Pattern attributes: good fast fast overmatch
# Protocol groups: time_synchronization ietf_draft_standard
# Wiki: http://www.protocolinfo.org/wiki/NTP
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# This pattern is tested and is believed to work.
# client|server
# Requires the server's timestamp to be in the present or future (of 2005).
# Tested with ntpdate on Linux.
# Assumes version 2, 3 or 4.
# Note that ntp packets are always 48 bytes, so you should match on that too.
ntp
^([\x13\x1b\x23\xd3\xdb\xe3]|[\x14\x1c$].......?.?.?.?.?.?.?.?.?[\xc6-\xff])
@@ -0,0 +1,50 @@
# POP3 - Post Office Protocol version 3 (popular e-mail protocol) - RFC 1939
# Pattern attributes: great veryfast fast
# Protocol groups: mail ietf_internet_standard
# Wiki: http://www.protocolinfo.org/wiki/POP
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# This pattern has been tested somewhat.
# this is a difficult protocol to match because of the relative lack of
# distinguishing information. Read on.
pop3
# this the most conservative pattern. It should definitely work.
#^(\+ok|-err)
# this pattern assumes that the server says _something_ after +ok or -err
# I think this is probably the way to go.
^(\+ok |-err )
# more that 90% of servers seem to say "pop" after "+ok", but not all.
#^(\+ok .*pop)
# Here's another tack. I think this is my second favorite.
#^(\+ok [\x09-\x0d -~]*(ready|hello|pop|starting)|-err [\x09-\x0d -~]*(invalid|unknown|unimplemented|unrecognized|command))
# this matches the server saying "you have N messages that are M bytes",
# which the client probably asks for early in the session (not tested)
#\+ok [0-9]+ [0-9]+
# some sample servers:
# RFC example: +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us>
# mail.dreamhost.com: +OK Hello there.
# pop.carleton.edu: +OK POP3D(*) Server PMDFV6.2.2 at Fri, 12 Sep 2003 19:28:10 -0500 (CDT) (APOP disabled)
# mail.earthlink.net: +OK NGPopper vEL_4_38 at earthlink.net ready <25509.1063412951@falcon>
# *.email.umn.edu: +OK Cubic Circle's v1.22 1998/04/11 POP3 ready <7d1e0000da67623f@aquamarine.tc.umn.edu>
# mail.yale.edu: +OK POP3 pantheon-po01 v2002.81 server ready
# mail.gustavus.edu: +OK POP3 solen v2001.78 server ready
# mail.reed.edu: +OK POP3 letra.reed.edu v2002.81 server ready
# mail.bowdoin.edu: +OK mail.bowdoin.edu POP3 service (iPlanet Messaging Server 5.2 HotFix 1.15 (built Apr 28 2003))
# pop.colby.edu: +OK Qpopper (version 4.0.5) at basalt starting.
# mail.mac.com: +OK Netscape Messaging Multiplexor ready
# various error strings:
#-ERR Invalid command.
#-ERR invalid command
#-ERR unimplemented
#-ERR Invalid command, try one of: USER name, PASS string, QUIT
#-ERR Unknown AUTHORIZATION state command
#-ERR Unrecognized command
#-ERR Unknown command: "sadf'".
@@ -0,0 +1,40 @@
# SMTP - Simple Mail Transfer Protocol - RFC 2821 (See also RFC 1869)
# Pattern attributes: great notsofast fast
# Protocol groups: mail ietf_internet_standard
# Wiki: http://www.protocolinfo.org/wiki/SMTP
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# usually runs on port 25
#
# This pattern has been tested and is believed to work well.
# As usual, no text is required after "220", but all known servers have some
# there. It (almost?) always has string "smtp" in it. The RFC examples
# does not, so we match those too, just in case anyone has copied them
# literally.
#
# Some examples:
# 220 mail.stalker.com ESMTP CommuniGate Pro 4.1.3
# 220 mail.vieodata.com ESMTP Merak 6.1.0; Mon, 15 Sep 2003 13:48:11 -0400
# 220 mail.ut.caldera.com ESMTP
# 220 persephone.pmail.gen.nz ESMTP server ready.
# 220 smtp1.superb.net ESMTP
# 220 mail.kerio.com Kerio MailServer 5.6.7 ESMTP ready
# 220-mail.deerfield.com ESMTP VisNetic.MailServer.v6.0.9.0; Mon, 15 Sep 2003 13:4
# 220 altn.com ESMTP MDaemon 6.8.5; Mon, 15 Sep 2003 12:46:42 -0500
# 220 X1 NT-ESMTP Server ipsmin0165atl2.interland.net (IMail 6.06 73062-3)
# 220 mail.icewarp.com ESMTP Merak 6.1.1; Mon, 15 Sep 2003 19:43:23 +0200
# 220-mail.email-scan.com ESMTP
# 220 smaug.dreamhost.com ESMTP
# 220 kona.carleton.edu -- Server ESMTP (PMDF V6.2#30648)
# 220 letra.reed.edu ESMTP Sendmail 8.12.9/8.12.9; Mon, 15 Sep 2003 10:35:57 -0700 (PDT)
# 220-swan.mail.pas.earthlink.net ESMTP Exim 3.33 #1 Mon, 15 Sep 2003 10:32:15 -0700
#
# RFC examples:
# 220 xyz.com Simple Mail Transfer Service Ready (RFC example)
# 220 dbc.mtview.ca.us SMTP service ready
smtp
^220[\x09-\x0d -~]* (e?smtp|simple mail)
userspace pattern=^220[\x09-\x0d -~]* (E?SMTP|[Ss]imple [Mm]ail)
userspace flags=REG_NOSUB REG_EXTENDED
@@ -0,0 +1,16 @@
# SSL and TLS - Secure Socket Layer / Transport Layer Security - RFC 2246
# Pattern attributes: good notsofast fast superset
# Protocol groups: secure ietf_proposed_standard
# Wiki: http://www.protocolinfo.org/wiki/SSL
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# Usually runs on port 443
#
# This is a superset of validcertssl. For it to match, it must be first.
#
# This pattern has been tested and is believed to work well.
ssl
# Server Hello with certificate | Client Hello
# This allows SSL 3.X, which includes TLS 1.0, known internally as SSL 3.1
^(.?.?\x16\x03.*\x16\x03|.?.?\x01\x03\x01?.*\x0b)
@@ -0,0 +1,23 @@
# VNC - Virtual Network Computing. Also known as RFB - Remote Frame Buffer
# Pattern attributes: great veryfast fast
# Protocol groups: remote_access
# Wiki: http://www.protocolinfo.org/wiki/VNC
# Copyright (C) 2008 Matthew Strait, Ethan Sommer; See ../LICENSE
#
# http://www.realvnc.com/documentation.html
#
# This pattern has been verified with vnc v3.3.7 on WinXP and Linux
#
# Thanks to Trevor Paskett <tpaskett AT cymphonix.com> for this pattern.
vnc
# Assumes single digit major and minor version numbers
# This message should be all alone in the first packet, so ^$ is appropriate
^rfb 00[1-9]\.00[0-9]\x0a$
# This is a more restrictive version which assumes the version numbers
# are ones actually in existance at the time of this writing, i.e. 3.3,
# 3.7 and 3.8 (with some clients wrongly reporting 3.5). It should be
# slightly faster, but probably not worth the extra maintenance.
# ^rfb 003\.00[3578]\x0a$
@@ -0,0 +1,371 @@
--- /dev/null
+++ b/extensions/libxt_layer7.c
@@ -0,0 +1,368 @@
+/*
+ Shared library add-on to iptables for layer 7 matching support.
+
+ By Matthew Strait <quadong@users.sf.net>, Oct 2003-Aug 2008.
+
+ http://l7-filter.sf.net
+
+ 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.
+ http://www.gnu.org/licenses/gpl.txt
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <dirent.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_layer7.h>
+
+#define MAX_FN_LEN 256
+
+static char l7dir[MAX_FN_LEN] = "\0";
+
+/* Function which prints out usage message. */
+static void help(void)
+{
+ printf(
+ "layer7 match options:\n"
+ " --l7dir <directory> : Look for patterns here instead of /etc/l7-protocols/\n"
+ " (--l7dir must be specified before --l7proto if used)\n"
+ "[!] --l7proto <name>: Match named protocol using /etc/l7-protocols/.../name.pat\n");
+}
+
+static const struct option opts[] = {
+ { .name = "l7proto", .has_arg = 1, .val = 'p' },
+ { .name = "l7dir", .has_arg = 1, .val = 'd' },
+ { .name = NULL }
+};
+
+/* reads filename, puts protocol info into layer7_protocol_info, number of protocols to numprotos */
+static int parse_protocol_file(char * filename, const char * protoname, struct xt_layer7_info *info)
+{
+ FILE * f;
+ char * line = NULL;
+ size_t len = 0;
+
+ enum { protocol, pattern, done } datatype = protocol;
+
+ f = fopen(filename, "r");
+
+ if(!f)
+ return 0;
+
+ while(getline(&line, &len, f) != -1)
+ {
+ if(strlen(line) < 2 || line[0] == '#')
+ continue;
+
+ /* strip the pesky newline... */
+ if(line[strlen(line) - 1] == '\n')
+ line[strlen(line) - 1] = '\0';
+
+ if(datatype == protocol)
+ {
+ /* Ignore everything on the line beginning with the
+ first space or tab . For instance, this allows the
+ protocol line in http.pat to be "http " (or
+ "http I am so cool") instead of just "http". */
+ if(strchr(line, ' ')){
+ char * space = strchr(line, ' ');
+ space[0] = '\0';
+ }
+ if(strchr(line, '\t')){
+ char * space = strchr(line, '\t');
+ space[0] = '\0';
+ }
+
+ /* sanity check. First non-comment non-blank
+ line must be the same as the file name. */
+ if(strcmp(line, protoname))
+ xtables_error(OTHER_PROBLEM,
+ "Protocol name (%s) doesn't match file name (%s). Bailing out\n",
+ line, filename);
+
+ if(strlen(line) >= MAX_PROTOCOL_LEN)
+ xtables_error(PARAMETER_PROBLEM,
+ "Protocol name in %s too long!", filename);
+ strncpy(info->protocol, line, MAX_PROTOCOL_LEN);
+
+ datatype = pattern;
+ }
+ else if(datatype == pattern)
+ {
+ if(strlen(line) >= MAX_PATTERN_LEN)
+ xtables_error(PARAMETER_PROBLEM, "Pattern in %s too long!", filename);
+ strncpy(info->pattern, line, MAX_PATTERN_LEN);
+
+ datatype = done;
+ break;
+ }
+ else
+ xtables_error(OTHER_PROBLEM, "Internal error");
+ }
+
+ if(datatype != done)
+ xtables_error(OTHER_PROBLEM, "Failed to get all needed data from %s", filename);
+
+ if(line) free(line);
+ fclose(f);
+
+ return 1;
+}
+
+static int hex2dec(char c)
+{
+ switch (c)
+ {
+ case '0' ... '9':
+ return c - '0';
+ case 'a' ... 'f':
+ return c - 'a' + 10;
+ case 'A' ... 'F':
+ return c - 'A' + 10;
+ default:
+ xtables_error(OTHER_PROBLEM, "hex2dec: bad value!\n");
+ return 0;
+ }
+}
+
+/* takes a string with \xHH escapes and returns one with the characters
+they stand for */
+static char * pre_process(char * s)
+{
+ char * result = malloc(strlen(s) + 1);
+ int sindex = 0, rrindex = 0;
+ while( sindex < strlen(s) )
+ {
+ if( sindex + 3 < strlen(s) &&
+ s[sindex] == '\\' && s[sindex+1] == 'x' &&
+ isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) )
+ {
+ /* carefully remember to call tolower here... */
+ result[rrindex] = tolower( hex2dec(s[sindex + 2])*16 +
+ hex2dec(s[sindex + 3] ) );
+
+ switch ( result[rrindex] )
+ {
+ case 0x24:
+ case 0x28:
+ case 0x29:
+ case 0x2a:
+ case 0x2b:
+ case 0x2e:
+ case 0x3f:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ case 0x7c:
+ fprintf(stderr,
+ "Warning: layer7 regexp contains a control character, %c, in hex (\\x%c%c).\n"
+ "I recommend that you write this as %c or \\%c, depending on what you meant.\n",
+ result[rrindex], s[sindex + 2], s[sindex + 3], result[rrindex], result[rrindex]);
+ break;
+ case 0x00:
+ fprintf(stderr,
+ "Warning: null (\\x00) in layer7 regexp. A null terminates the regexp string!\n");
+ break;
+ default:
+ break;
+ }
+
+
+ sindex += 3; /* 4 total */
+ }
+ else
+ result[rrindex] = tolower(s[sindex]);
+
+ sindex++;
+ rrindex++;
+ }
+ result[rrindex] = '\0';
+
+ return result;
+}
+
+#define MAX_SUBDIRS 128
+static char ** readl7dir(char * dirname)
+{
+ DIR * scratchdir;
+ struct dirent ** namelist;
+ char ** subdirs = malloc(MAX_SUBDIRS * sizeof(char *));
+
+ int n, d = 1;
+ subdirs[0] = "";
+
+ n = scandir(dirname, &namelist, 0, alphasort);
+
+ if (n < 0)
+ {
+ perror("scandir");
+ xtables_error(OTHER_PROBLEM, "Couldn't open %s\n", dirname);
+ }
+ else
+ {
+ while(n--)
+ {
+ char fulldirname[MAX_FN_LEN];
+
+ snprintf(fulldirname, MAX_FN_LEN, "%s/%s", dirname, namelist[n]->d_name);
+
+ if((scratchdir = opendir(fulldirname)) != NULL)
+ {
+ closedir(scratchdir);
+
+ if(!strcmp(namelist[n]->d_name, ".") ||
+ !strcmp(namelist[n]->d_name, ".."))
+ /* do nothing */ ;
+ else
+ {
+ subdirs[d] = malloc(strlen(namelist[n]->d_name) + 1);
+ strcpy(subdirs[d], namelist[n]->d_name);
+ d++;
+ if(d >= MAX_SUBDIRS - 1)
+ {
+ fprintf(stderr,
+ "Too many subdirectories, skipping the rest!\n");
+ break;
+ }
+ }
+ }
+ free(namelist[n]);
+ }
+ free(namelist);
+ }
+
+ subdirs[d] = NULL;
+
+ return subdirs;
+}
+
+static void parse_layer7_protocol(const char *s, struct xt_layer7_info *info)
+{
+ char filename[MAX_FN_LEN];
+ char * dir = NULL;
+ char ** subdirs;
+ int n = 0, done = 0;
+
+ if(strlen(l7dir) > 0) dir = l7dir;
+ else dir = "/etc/l7-protocols";
+
+ subdirs = readl7dir(dir);
+
+ while(subdirs[n] != NULL)
+ {
+ int c = snprintf(filename, MAX_FN_LEN, "%s/%s/%s.pat", dir, subdirs[n], s);
+
+ if(c > MAX_FN_LEN)
+ xtables_error(OTHER_PROBLEM,
+ "Filename beginning with %s is too long!\n", filename);
+
+ /* read in the pattern from the file */
+ if(parse_protocol_file(filename, s, info)){
+ done = 1;
+ break;
+ }
+
+ n++;
+ }
+
+ if(!done)
+ xtables_error(OTHER_PROBLEM,
+ "Couldn't find a pattern definition file for %s.\n", s);
+
+ /* process \xHH escapes and tolower everything. (our regex lib has no
+ case insensitivity option.) */
+ strncpy(info->pattern, pre_process(info->pattern), MAX_PATTERN_LEN);
+}
+
+/* Function which parses command options; returns true if it ate an option */
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_layer7_info *layer7info =
+ (struct xt_layer7_info *)(*match)->data;
+
+ switch (c) {
+ case 'p':
+ parse_layer7_protocol(argv[optind-1], layer7info);
+ if (invert)
+ layer7info->invert = true;
+ *flags = 1;
+ break;
+
+ case 'd':
+ if(strlen(argv[optind-1]) >= MAX_FN_LEN)
+ xtables_error(PARAMETER_PROBLEM, "directory name too long\n");
+
+ strncpy(l7dir, argv[optind-1], MAX_FN_LEN);
+
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Final check; must have specified --l7proto */
+static void final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "LAYER7 match: You must specify `--l7proto'");
+}
+
+static void print_protocol(char s[], int invert, int numeric)
+{
+ fputs("l7proto ", stdout);
+ if (invert) fputc('!', stdout);
+ printf("%s ", s);
+}
+
+/* Prints out the matchinfo. */
+static void print(const void *ip,
+ const struct xt_entry_match *match,
+ int numeric)
+{
+ printf("LAYER7 ");
+ print_protocol(((struct xt_layer7_info *)match->data)->protocol,
+ ((struct xt_layer7_info *)match->data)->invert, numeric);
+}
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_layer7_info *info =
+ (const struct xt_layer7_info*) match->data;
+
+ printf("--l7proto %s%s ", (info->invert)? "! ":"", info->protocol);
+}
+
+static struct xtables_match layer7 = {
+ .family = AF_INET,
+ .name = "layer7",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_layer7_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_layer7_info)),
+ .help = &help,
+ .parse = &parse,
+ .final_check = &final_check,
+ .print = &print,
+ .save = &save,
+ .extra_opts = opts
+};
+
+void _init(void)
+{
+ xtables_register_match(&layer7);
+}
@@ -0,0 +1,11 @@
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -69,7 +69,7 @@ static const char *hooknames[] = {
struct ipt_error_target
{
STRUCT_ENTRY_TARGET t;
- char error[TABLE_MAXNAMELEN];
+ char error[FUNCTION_MAXNAMELEN];
};
struct chain_head;
@@ -0,0 +1,265 @@
--- a/extensions/libxt_multiport.c
+++ b/extensions/libxt_multiport.c
@@ -15,21 +15,6 @@
#include <linux/netfilter/xt_multiport.h>
/* Function which prints out usage message. */
-static void multiport_help(void)
-{
- printf(
-"multiport match options:\n"
-" --source-ports port[,port,port...]\n"
-" --sports ...\n"
-" match source port(s)\n"
-" --destination-ports port[,port,port...]\n"
-" --dports ...\n"
-" match destination port(s)\n"
-" --ports port[,port,port]\n"
-" match both source and destination port(s)\n"
-" NOTE: this kernel does not support port ranges in multiport.\n");
-}
-
static void multiport_help_v1(void)
{
printf(
@@ -72,26 +57,6 @@ proto_to_name(u_int8_t proto)
}
}
-static unsigned int
-parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
-{
- char *buffer, *cp, *next;
- unsigned int i;
-
- buffer = strdup(portstring);
- if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
-
- for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next,i++)
- {
- next=strchr(cp, ',');
- if (next) *next++='\0';
- ports[i] = xtables_parse_port(cp, proto);
- }
- if (cp) xtables_error(PARAMETER_PROBLEM, "too many ports specified");
- free(buffer);
- return i;
-}
-
static void
parse_multi_ports_v1(const char *portstring,
struct xt_multiport_v1 *multiinfo,
@@ -155,73 +120,6 @@ check_proto(u_int16_t pnum, u_int8_t inv
/* Function which parses command options; returns true if it
ate an option */
static int
-__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
- struct xt_entry_match **match, u_int16_t pnum,
- u_int8_t invflags)
-{
- const char *proto;
- struct xt_multiport *multiinfo
- = (struct xt_multiport *)(*match)->data;
-
- switch (c) {
- case '1':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- proto = check_proto(pnum, invflags);
- multiinfo->count = parse_multi_ports(optarg,
- multiinfo->ports, proto);
- multiinfo->flags = XT_MULTIPORT_SOURCE;
- break;
-
- case '2':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- proto = check_proto(pnum, invflags);
- multiinfo->count = parse_multi_ports(optarg,
- multiinfo->ports, proto);
- multiinfo->flags = XT_MULTIPORT_DESTINATION;
- break;
-
- case '3':
- xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- proto = check_proto(pnum, invflags);
- multiinfo->count = parse_multi_ports(optarg,
- multiinfo->ports, proto);
- multiinfo->flags = XT_MULTIPORT_EITHER;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- xtables_error(PARAMETER_PROBLEM,
- "multiport does not support invert");
-
- if (*flags)
- xtables_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
-}
-
-static int
-multiport_parse(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_match **match)
-{
- const struct ipt_entry *entry = e;
- return __multiport_parse(c, argv, invert, flags, match,
- entry->ip.proto, entry->ip.invflags);
-}
-
-static int
-multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
- const void *e, struct xt_entry_match **match)
-{
- const struct ip6t_entry *entry = e;
- return __multiport_parse(c, argv, invert, flags, match,
- entry->ipv6.proto, entry->ipv6.invflags);
-}
-
-static int
__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
struct xt_entry_match **match, u_int16_t pnum,
u_int8_t invflags)
@@ -314,55 +212,6 @@ print_port(u_int16_t port, u_int8_t prot
}
/* Prints out the matchinfo. */
-static void
-__multiport_print(const struct xt_entry_match *match, int numeric,
- u_int16_t proto)
-{
- const struct xt_multiport *multiinfo
- = (const struct xt_multiport *)match->data;
- unsigned int i;
-
- printf("multiport ");
-
- switch (multiinfo->flags) {
- case XT_MULTIPORT_SOURCE:
- printf("sports ");
- break;
-
- case XT_MULTIPORT_DESTINATION:
- printf("dports ");
- break;
-
- case XT_MULTIPORT_EITHER:
- printf("ports ");
- break;
-
- default:
- printf("ERROR ");
- break;
- }
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], proto, numeric);
- }
- printf(" ");
-}
-
-static void multiport_print(const void *ip_void,
- const struct xt_entry_match *match, int numeric)
-{
- const struct ipt_ip *ip = ip_void;
- __multiport_print(match, numeric, ip->proto);
-}
-
-static void multiport_print6(const void *ip_void,
- const struct xt_entry_match *match, int numeric)
-{
- const struct ip6t_ip6 *ip = ip_void;
- __multiport_print(match, numeric, ip->proto);
-}
-
static void __multiport_print_v1(const struct xt_entry_match *match,
int numeric, u_int16_t proto)
{
@@ -419,48 +268,6 @@ static void multiport_print6_v1(const vo
}
/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void __multiport_save(const struct xt_entry_match *match,
- u_int16_t proto)
-{
- const struct xt_multiport *multiinfo
- = (const struct xt_multiport *)match->data;
- unsigned int i;
-
- switch (multiinfo->flags) {
- case XT_MULTIPORT_SOURCE:
- printf("--sports ");
- break;
-
- case XT_MULTIPORT_DESTINATION:
- printf("--dports ");
- break;
-
- case XT_MULTIPORT_EITHER:
- printf("--ports ");
- break;
- }
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], proto, 1);
- }
- printf(" ");
-}
-
-static void multiport_save(const void *ip_void,
- const struct xt_entry_match *match)
-{
- const struct ipt_ip *ip = ip_void;
- __multiport_save(match, ip->proto);
-}
-
-static void multiport_save6(const void *ip_void,
- const struct xt_entry_match *match)
-{
- const struct ip6t_ip6 *ip = ip_void;
- __multiport_save(match, ip->proto);
-}
-
static void __multiport_save_v1(const struct xt_entry_match *match,
u_int16_t proto)
{
@@ -514,34 +321,6 @@ static struct xtables_match multiport_mt
{
.family = NFPROTO_IPV4,
.name = "multiport",
- .revision = 0,
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_multiport)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
- .help = multiport_help,
- .parse = multiport_parse,
- .final_check = multiport_check,
- .print = multiport_print,
- .save = multiport_save,
- .extra_opts = multiport_opts,
- },
- {
- .family = NFPROTO_IPV6,
- .name = "multiport",
- .revision = 0,
- .version = XTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_multiport)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
- .help = multiport_help,
- .parse = multiport_parse6,
- .final_check = multiport_check,
- .print = multiport_print6,
- .save = multiport_save6,
- .extra_opts = multiport_opts,
- },
- {
- .family = NFPROTO_IPV4,
- .name = "multiport",
.version = XTABLES_VERSION,
.revision = 1,
.size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
@@ -0,0 +1,116 @@
From 20c706d4cba3227c9c44fb61c4d93b0ae84e1464 Mon Sep 17 00:00:00 2001
From: Tim Gardner <tim.gardner@canonical.com>
Date: Mon, 1 Mar 2010 19:00:29 -0700
Subject: [PATCH] xt_recent: Added XT_RECENT_REAP logic and man page documentation
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
---
extensions/libxt_recent.c | 20 ++++++++++++++++++++
extensions/libxt_recent.man | 5 +++++
include/linux/netfilter/xt_recent.h | 7 +++++++
3 files changed, 32 insertions(+), 0 deletions(-)
--- a/extensions/libxt_recent.c
+++ b/extensions/libxt_recent.c
@@ -20,6 +20,7 @@ static const struct option recent_opts[]
{.name = "name", .has_arg = true, .val = 208},
{.name = "rsource", .has_arg = false, .val = 209},
{.name = "rdest", .has_arg = false, .val = 210},
+ {.name = "reap", .has_arg = false, .val = 211},
XT_GETOPT_TABLEEND,
};
@@ -37,6 +38,7 @@ static void recent_help(void)
" --hitcount hits For check and update commands above.\n"
" Specifies that the match will only occur if source address seen hits times.\n"
" May be used in conjunction with the seconds option.\n"
+" --reap Remove entries that have expired. Can only be used with --seconds\n"
" --rttl For check and update commands above.\n"
" Specifies that the match will only occur if the source address and the TTL\n"
" match between this packet and the one which was set.\n"
@@ -63,6 +65,8 @@ static void recent_init(struct xt_entry_
(XT_RECENT_SET | XT_RECENT_CHECK | \
XT_RECENT_UPDATE | XT_RECENT_REMOVE)
+#define XT_RECENT_SECONDS 1 << 31
+
static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
@@ -104,6 +108,7 @@ static int recent_parse(int c, char **ar
case 204:
info->seconds = atoi(optarg);
+ *flags |= XT_RECENT_SECONDS;
break;
case 205:
@@ -139,6 +144,11 @@ static int recent_parse(int c, char **ar
info->side = XT_RECENT_DEST;
break;
+ case 211:
+ info->check_set |= XT_RECENT_REAP;
+ *flags |= XT_RECENT_REAP;
+ break;
+
default:
return 0;
}
@@ -157,6 +167,12 @@ static void recent_check(unsigned int fl
xtables_error(PARAMETER_PROBLEM,
"recent: --rttl may only be used with --rcheck or "
"--update");
+ if ((flags & XT_RECENT_REAP) &&
+ ((flags & (XT_RECENT_SET | XT_RECENT_REMOVE)) ||
+ (!(flags & XT_RECENT_SECONDS))))
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: --reap may only be used with --rcheck or "
+ "--update and --seconds");
}
static void recent_print(const void *ip, const struct xt_entry_match *match,
@@ -185,6 +201,8 @@ static void recent_print(const void *ip,
printf("side: source ");
if (info->side == XT_RECENT_DEST)
printf("side: dest ");
+ if (info->check_set & XT_RECENT_REAP)
+ printf("reap ");
}
static void recent_save(const void *ip, const struct xt_entry_match *match)
@@ -211,6 +229,8 @@ static void recent_save(const void *ip,
printf("--rsource ");
if (info->side == XT_RECENT_DEST)
printf("--rdest ");
+ if (info->check_set & XT_RECENT_REAP)
+ printf("--reap ");
}
static struct xtables_match recent_mt_reg = {
--- a/extensions/libxt_recent.man
+++ b/extensions/libxt_recent.man
@@ -41,6 +41,11 @@ This option must be used in conjunction
\fB\-\-update\fP. When used, this will narrow the match to only happen when the
address is in the list and was seen within the last given number of seconds.
.TP
+\fB\-\-reap\fP \fIreap\fP
+This option must be used in conjunction with \fB\-\-seconds\fP. When used, this
+will remove entries with the most recent timestamp older then \fB\-\-seconds\fP
+since the last packet was received.
+.TP
\fB\-\-hitcount\fP \fIhits\fP
This option must be used in conjunction with one of \fB\-\-rcheck\fP or
\fB\-\-update\fP. When used, this will narrow the match to only happen when the
--- a/include/linux/netfilter/xt_recent.h
+++ b/include/linux/netfilter/xt_recent.h
@@ -23,6 +23,9 @@ enum {
#define XT_RECENT_VALID_FLAGS (XT_RECENT_CHECK|XT_RECENT_SET|XT_RECENT_UPDATE|\
XT_RECENT_REMOVE|XT_RECENT_TTL|XT_RECENT_REAP)
+/* Only allowed with --rcheck and --update */
+#define XT_RECENT_MODIFIERS (XT_RECENT_TTL|XT_RECENT_REAP)
+
struct xt_recent_mtinfo {
__u32 seconds;
__u32 hit_count;
@@ -0,0 +1,18 @@
--- a/xtables.c
+++ b/xtables.c
@@ -305,6 +305,7 @@ static char *get_modprobe(void)
int xtables_insmod(const char *modname, const char *modprobe, bool quiet)
{
+#if 0
char *buf = NULL;
char *argv[4];
int status;
@@ -348,6 +349,7 @@ int xtables_insmod(const char *modname,
free(buf);
if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
return 0;
+#endif
return -1;
}
@@ -0,0 +1,92 @@
--- a/configure
+++ b/configure
@@ -10917,75 +10917,7 @@ $as_echo "no" >&6; }
fi
fi
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libnfnetlink" >&5
-$as_echo_n "checking for libnfnetlink... " >&6; }
-
-if test -n "$libnfnetlink_CFLAGS"; then
- pkg_cv_libnfnetlink_CFLAGS="$libnfnetlink_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= 1.0\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libnfnetlink >= 1.0") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- pkg_cv_libnfnetlink_CFLAGS=`$PKG_CONFIG --cflags "libnfnetlink >= 1.0" 2>/dev/null`
-else
- pkg_failed=yes
-fi
- else
- pkg_failed=untried
-fi
-if test -n "$libnfnetlink_LIBS"; then
- pkg_cv_libnfnetlink_LIBS="$libnfnetlink_LIBS"
- elif test -n "$PKG_CONFIG"; then
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnfnetlink >= 1.0\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libnfnetlink >= 1.0") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- pkg_cv_libnfnetlink_LIBS=`$PKG_CONFIG --libs "libnfnetlink >= 1.0" 2>/dev/null`
-else
- pkg_failed=yes
-fi
- else
- pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
- _pkg_short_errors_supported=yes
-else
- _pkg_short_errors_supported=no
-fi
- if test $_pkg_short_errors_supported = yes; then
- libnfnetlink_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libnfnetlink >= 1.0" 2>&1`
- else
- libnfnetlink_PKG_ERRORS=`$PKG_CONFIG --print-errors "libnfnetlink >= 1.0" 2>&1`
- fi
- # Put the nasty error message in config.log where it belongs
- echo "$libnfnetlink_PKG_ERRORS" >&5
-
- nfnetlink=0
-elif test $pkg_failed = untried; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- nfnetlink=0
-else
- libnfnetlink_CFLAGS=$pkg_cv_libnfnetlink_CFLAGS
- libnfnetlink_LIBS=$pkg_cv_libnfnetlink_LIBS
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- nfnetlink=1
-fi
- if test "$nfnetlink" = 1; then
+if false; then
HAVE_LIBNFNETLINK_TRUE=
HAVE_LIBNFNETLINK_FALSE='#'
else
--- a/configure.ac
+++ b/configure.ac
@@ -79,9 +79,7 @@ AM_CONDITIONAL([ENABLE_LARGEFILE], [test
AM_CONDITIONAL([ENABLE_DEVEL], [test "$enable_devel" = "yes"])
AM_CONDITIONAL([ENABLE_LIBIPQ], [test "$enable_libipq" = "yes"])
-PKG_CHECK_MODULES([libnfnetlink], [libnfnetlink >= 1.0],
- [nfnetlink=1], [nfnetlink=0])
-AM_CONDITIONAL([HAVE_LIBNFNETLINK], [test "$nfnetlink" = 1])
+AM_CONDITIONAL([HAVE_LIBNFNETLINK], [false])
regular_CFLAGS="${largefile_cflags} \
-D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations \
@@ -0,0 +1,16 @@
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
autoreconf -fi;
rm -Rf autom4te*.cache;
--- a/iptables-apply
+++ b/iptables-apply
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
#
# iptables-apply -- a safer way to update iptables remotely
#
@@ -0,0 +1,12 @@
--- iptables-1.4.10/include/linux/types.h.orig 2011-11-07 00:08:33.000000000 +0100
+++ iptables-1.4.10/include/linux/types.h 2011-11-07 00:09:25.000000000 +0100
@@ -34,5 +34,9 @@
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_TYPES_H */
@@ -0,0 +1,56 @@
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -40,9 +40,24 @@
pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod})
pf4_build_mod := $(filter-out @blacklist_modules@,${pf4_build_mod})
pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod})
-pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
-pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
-pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
+
+ifdef BUILTIN_MODULES
+pfx_build_static := $(filter $(BUILTIN_MODULES),${pfx_build_mod})
+pf4_build_static := $(filter $(BUILTIN_MODULES),${pf4_build_mod})
+pf6_build_static := $(filter $(BUILTIN_MODULES),${pf6_build_mod})
+else
+@ENABLE_STATIC_TRUE@ pfx_build_static := $(pfx_build_mod)
+@ENABLE_STATIC_TRUE@ pf4_build_static := $(pf4_build_mod)
+@ENABLE_STATIC_TRUE@ pf6_build_static := $(pf6_build_mod)
+endif
+
+pfx_build_mod := $(filter-out $(pfx_build_static),$(pfx_build_mod))
+pf4_build_mod := $(filter-out $(pf4_build_static),$(pf4_build_mod))
+pf6_build_mod := $(filter-out $(pf6_build_static),$(pf6_build_mod))
+
+pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_static})
+pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_static})
+pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_static})
pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
@@ -54,10 +69,10 @@
targets := libext4.a libext6.a matches4.man matches6.man \
targets4.man targets6.man
targets_install :=
-@ENABLE_STATIC_TRUE@ libext4_objs := ${pfx_objs} ${pf4_objs}
-@ENABLE_STATIC_TRUE@ libext6_objs := ${pfx_objs} ${pf6_objs}
-@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
-@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
+libext4_objs := ${pfx_objs} ${pf4_objs}
+libext6_objs := ${pfx_objs} ${pf6_objs}
+targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
+targets_install := $(strip ${targets_install} ${pfx_solibs} ${pf4_solibs} ${pf6_solibs})
.SECONDARY:
@@ -107,8 +122,8 @@
libext6.a: initext6.o ${libext6_objs}
${AM_VERBOSE_AR} ${AR} crs $@ $^;
-initext_func := $(addprefix xt_,${pfx_build_mod}) $(addprefix ipt_,${pf4_build_mod})
-initext6_func := $(addprefix xt_,${pfx_build_mod}) $(addprefix ip6t_,${pf6_build_mod})
+initext_func := $(addprefix xt_,${pfx_build_static}) $(addprefix ipt_,${pf4_build_static})
+initext6_func := $(addprefix xt_,${pfx_build_static}) $(addprefix ip6t_,${pf6_build_static})
.initext4.dd: FORCE
@echo "${initext_func}" >$@.tmp; \
+56
View File
@@ -0,0 +1,56 @@
#
# Copyright (C) 2007-2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=iw
PKG_VERSION:=3.6
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=http://wireless.kernel.org/download/iw/
PKG_MD5SUM:=1c18bfbbc8773629e5e8ac733a39540c
PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
include $(INCLUDE_DIR)/package.mk
define Package/iw
SECTION:=net
CATEGORY:=Network
TITLE:=cfg80211 interface configuration utility
URL:=http://wireless.kernel.org/en/users/Documentation/iw
DEPENDS:= +libnl-tiny @(!(TARGET_avr32||TARGET_etrax)||BROKEN)
endef
define Build/Configure
echo "const char iw_version[] = \"$(PKG_VERSION)\";" > $(PKG_BUILD_DIR)/version.c
rm -f $(PKG_BUILD_DIR)/version.sh
touch $(PKG_BUILD_DIR)/version.sh
chmod +x $(PKG_BUILD_DIR)/version.sh
endef
TARGET_CPPFLAGS:= \
-I$(STAGING_DIR)/usr/include/libnl-tiny \
$(TARGET_CPPFLAGS) \
-DCONFIG_LIBNL20 \
-D_GNU_SOURCE
MAKE_FLAGS += \
CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)" \
NL1FOUND="" NL2FOUND=Y \
NLLIBNAME="libnl-tiny" \
LIBS="-lm -lnl-tiny" \
V=1
define Package/iw/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iw $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,iw))
@@ -0,0 +1,96 @@
--- a/nl80211.h
+++ b/nl80211.h
@@ -565,6 +565,14 @@
* %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
*
+ * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
+ * its %NL80211_ATTR_WDEV identifier. It must have been created with
+ * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the
+ * P2P Device can be used for P2P operations, e.g. remain-on-channel and
+ * public action frame TX.
+ * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by
+ * its %NL80211_ATTR_WDEV identifier.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -708,6 +716,9 @@ enum nl80211_commands {
NL80211_CMD_CH_SWITCH_NOTIFY,
+ NL80211_CMD_START_P2P_DEVICE,
+ NL80211_CMD_STOP_P2P_DEVICE,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1506,6 +1517,8 @@ enum nl80211_attrs {
NL80211_ATTR_USER_REG_HINT_TYPE,
+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1575,6 +1588,10 @@ enum nl80211_attrs {
* @NL80211_IFTYPE_MESH_POINT: mesh point
* @NL80211_IFTYPE_P2P_CLIENT: P2P client
* @NL80211_IFTYPE_P2P_GO: P2P group owner
+ * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev
+ * and therefore can't be created in the normal ways, use the
+ * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
+ * commands to create and destroy one
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @NUM_NL80211_IFTYPES: number of defined interface types
*
@@ -1593,6 +1610,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_MESH_POINT,
NL80211_IFTYPE_P2P_CLIENT,
NL80211_IFTYPE_P2P_GO,
+ NL80211_IFTYPE_P2P_DEVICE,
/* keep last */
NUM_NL80211_IFTYPES,
@@ -1744,6 +1762,8 @@ enum nl80211_sta_bss_param {
* @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
* @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32)
* @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64)
+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -1768,6 +1788,8 @@ enum nl80211_sta_info {
NL80211_STA_INFO_STA_FLAGS,
NL80211_STA_INFO_BEACON_LOSS,
NL80211_STA_INFO_T_OFFSET,
+ NL80211_STA_INFO_CHAIN_SIGNAL,
+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
@@ -2994,12 +3016,18 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
* to work properly to suppport receiving regulatory hints from
* cellular base stations.
+ * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: If this is set, an active
+ * P2P Device (%NL80211_IFTYPE_P2P_DEVICE) requires its own channel
+ * in the interface combinations, even when it's only used for scan
+ * and remain-on-channel. This could be due to, for example, the
+ * remain-on-channel implementation requiring a channel context.
*/
enum nl80211_feature_flags {
- NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
- NL80211_FEATURE_HT_IBSS = 1 << 1,
- NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
- NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
+ NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
+ NL80211_FEATURE_HT_IBSS = 1 << 1,
+ NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
+ NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
+ NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4,
};
/**
@@ -0,0 +1,105 @@
--- a/station.c
+++ b/station.c
@@ -29,13 +29,47 @@ enum plink_actions {
PLINK_ACTION_BLOCK,
};
+static void print_sta_bitrate(struct nlattr *nla, const char *name)
+{
+ struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
+
+ static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ };
+
+ if (!nla)
+ return;
+
+ if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, nla, rate_policy)) {
+ fprintf(stderr, "failed to parse nested rate attributes!\n");
+ } else {
+ int rate = 0;
+ printf("\n\t%s:\t", name);
+ if (rinfo[NL80211_RATE_INFO_BITRATE32])
+ rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]);
+ else if (rinfo[NL80211_RATE_INFO_BITRATE])
+ rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+ if (rate > 0)
+ printf("%d.%d MBit/s", rate / 10, rate % 10);
+
+ if (rinfo[NL80211_RATE_INFO_MCS])
+ printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
+ if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+ printf(" 40Mhz");
+ if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+ printf(" short GI");
+ }
+}
static int print_sta_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
- struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
char mac_addr[20], state_name[10], dev[20];
struct nl80211_sta_flag_update *sta_flags;
static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
@@ -47,6 +81,7 @@ static int print_sta_handler(struct nl_m
[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
[NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
[NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
[NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
[NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
@@ -56,14 +91,6 @@ static int print_sta_handler(struct nl_m
{ .minlen = sizeof(struct nl80211_sta_flag_update) },
};
- static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
- [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
- [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
- [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
- [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
- [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
- };
-
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
@@ -119,28 +146,8 @@ static int print_sta_handler(struct nl_m
printf("\n\tToffset:\t%lld us",
(unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]));
- if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
- if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
- sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
- fprintf(stderr, "failed to parse nested rate attributes!\n");
- } else {
- int rate = 0;
- printf("\n\ttx bitrate:\t");
- if (rinfo[NL80211_RATE_INFO_BITRATE32])
- rate = nla_get_u32(rinfo[NL80211_RATE_INFO_BITRATE32]);
- else if (rinfo[NL80211_RATE_INFO_BITRATE])
- rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
- if (rate > 0)
- printf("%d.%d MBit/s", rate / 10, rate % 10);
-
- if (rinfo[NL80211_RATE_INFO_MCS])
- printf(" MCS %d", nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
- if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
- printf(" 40Mhz");
- if (rinfo[NL80211_RATE_INFO_SHORT_GI])
- printf(" short GI");
- }
- }
+ print_sta_bitrate(sinfo[NL80211_STA_INFO_TX_BITRATE], "tx bitrate");
+ print_sta_bitrate(sinfo[NL80211_STA_INFO_RX_BITRATE], "rx bitrate");
if (sinfo[NL80211_STA_INFO_LLID])
printf("\n\tmesh llid:\t%d",
@@ -0,0 +1,71 @@
--- a/station.c
+++ b/station.c
@@ -65,6 +65,33 @@ static void print_sta_bitrate(struct nla
}
}
+static char *get_chain_signal(struct nlattr *attr_list)
+{
+ struct nlattr *attr;
+ static char buf[64];
+ char *cur = buf;
+ int i = 0, rem;
+ const char *prefix;
+
+ if (!attr_list)
+ return "";
+
+ nla_for_each_nested(attr, attr_list, rem) {
+ if (i++ > 0)
+ prefix = ", ";
+ else
+ prefix = "[";
+
+ cur += snprintf(cur, sizeof(buf) - (cur - buf), "%s%d", prefix,
+ (int8_t) nla_get_u8(attr));
+ }
+
+ if (i)
+ snprintf(cur, sizeof(buf) - (cur - buf), "] ");
+
+ return buf;
+}
+
static int print_sta_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb[NL80211_ATTR_MAX + 1];
@@ -89,7 +116,10 @@ static int print_sta_handler(struct nl_m
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
[NL80211_STA_INFO_STA_FLAGS] =
{ .minlen = sizeof(struct nl80211_sta_flag_update) },
+ [NL80211_STA_INFO_CHAIN_SIGNAL] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_CHAIN_SIGNAL_AVG] = { .type = NLA_NESTED },
};
+ char *chain;
nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen(gnlh, 0), NULL);
@@ -136,12 +166,19 @@ static int print_sta_handler(struct nl_m
if (sinfo[NL80211_STA_INFO_TX_FAILED])
printf("\n\ttx failed:\t%u",
nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]));
+
+ chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL]);
if (sinfo[NL80211_STA_INFO_SIGNAL])
- printf("\n\tsignal: \t%d dBm",
- (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
+ printf("\n\tsignal: \t%d %sdBm",
+ (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]),
+ chain);
+
+ chain = get_chain_signal(sinfo[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
if (sinfo[NL80211_STA_INFO_SIGNAL_AVG])
- printf("\n\tsignal avg:\t%d dBm",
- (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]));
+ printf("\n\tsignal avg:\t%d %sdBm",
+ (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]),
+ chain);
+
if (sinfo[NL80211_STA_INFO_T_OFFSET])
printf("\n\tToffset:\t%lld us",
(unsigned long long)nla_get_u64(sinfo[NL80211_STA_INFO_T_OFFSET]));
@@ -0,0 +1,11 @@
--- a/station.c
+++ b/station.c
@@ -267,7 +267,7 @@ static int print_sta_handler(struct nl_m
}
if (sta_flags->mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
- printf("\n\tTDLS peer:\t\t");
+ printf("\n\tTDLS peer:\t");
if (sta_flags->set & BIT(NL80211_STA_FLAG_TDLS_PEER))
printf("yes");
else
@@ -0,0 +1,34 @@
--- a/phy.c
+++ b/phy.c
@@ -359,3 +359,31 @@ COMMAND(set, antenna, "<bitmap> | all |
NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna,
"Set a bitmap of allowed antennas to use for TX and RX.\n"
"The driver may reject antenna configurations it cannot support.");
+
+static int handle_antenna_gain(struct nl80211_state *state,
+ struct nl_cb *cb,
+ struct nl_msg *msg,
+ int argc, char **argv,
+ enum id_input id)
+{
+ char *endptr;
+ int dbm;
+
+ /* get the required args */
+ if (argc != 1)
+ return 1;
+
+ dbm = strtol(argv[0], &endptr, 10);
+ if (*endptr)
+ return 2;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_GAIN, dbm);
+
+ return 0;
+
+ nla_put_failure:
+ return -ENOBUFS;
+}
+COMMAND(set, antenna_gain, "<antenna gain in dBm>",
+ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna_gain,
+ "Specify antenna gain.");
+50
View File
@@ -0,0 +1,50 @@
#
# Copyright (C) 2012 Jo-Philipp Wich <jow@openwrt.org>
#
# This is free software, licensed under the Apache 2 license.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=iwcap
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/iwcap
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Simple radiotap capture utility
MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org>
endef
define Package/iwcap/description
The iwcap utility receives radiotap packet data from wifi monitor interfaces
and outputs it to pcap format. It gathers recived packets in a fixed ring
buffer to dump them on demand which is useful for background monitoring.
Alternatively the utility can stream the data to stdout to act as remote
capture drone for Wireshark or similar programs.
endef
define Build/Prepare
$(INSTALL_DIR) $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) \
-o $(PKG_BUILD_DIR)/iwcap $(PKG_BUILD_DIR)/iwcap.c
endef
define Package/iwcap/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/iwcap $(1)/usr/sbin/iwcap
endef
$(eval $(call BuildPackage,iwcap))
+582
View File
@@ -0,0 +1,582 @@
/*
* iwcap.c - A simply radiotap capture utility outputting pcap dumps
*
* Copyright 2012 Jo-Philipp Wich <jow@openwrt.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_packet.h>
#define ARPHRD_IEEE80211_RADIOTAP 803
#define DLT_IEEE802_11_RADIO 127
#define LEN_IEEE802_11_HDR 32
#define FRAMETYPE_MASK 0xFC
#define FRAMETYPE_BEACON 0x80
#define FRAMETYPE_DATA 0x08
#if __BYTE_ORDER == __BIG_ENDIAN
#define le16(x) __bswap_16(x)
#else
#define le16(x) (x)
#endif
uint8_t run_dump = 0;
uint8_t run_stop = 0;
uint8_t run_daemon = 0;
uint32_t frames_captured = 0;
uint32_t frames_filtered = 0;
int capture_sock = -1;
const char *ifname = NULL;
struct ringbuf {
uint32_t len; /* number of slots */
uint32_t fill; /* last used slot */
uint32_t slen; /* slot size */
void *buf; /* ring memory */
};
struct ringbuf_entry {
uint32_t len; /* used slot memory */
uint32_t olen; /* original data size */
uint32_t sec; /* epoch of slot creation */
uint32_t usec; /* epoch microseconds */
};
typedef struct pcap_hdr_s {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} pcap_hdr_t;
typedef struct pcaprec_hdr_s {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} pcaprec_hdr_t;
typedef struct ieee80211_radiotap_header {
u_int8_t it_version; /* set to 0 */
u_int8_t it_pad;
u_int16_t it_len; /* entire length */
u_int32_t it_present; /* fields present */
} __attribute__((__packed__)) radiotap_hdr_t;
int check_type(void)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(capture_sock, SIOCGIFHWADDR, &ifr) < 0)
return -1;
return (ifr.ifr_hwaddr.sa_family == ARPHRD_IEEE80211_RADIOTAP);
}
int set_promisc(int on)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(capture_sock, SIOCGIFFLAGS, &ifr) < 0)
return -1;
if (on && !(ifr.ifr_flags & IFF_PROMISC))
{
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(capture_sock, SIOCSIFFLAGS, &ifr))
return -1;
return 1;
}
else if (!on && (ifr.ifr_flags & IFF_PROMISC))
{
ifr.ifr_flags &= ~IFF_PROMISC;
if (ioctl(capture_sock, SIOCSIFFLAGS, &ifr))
return -1;
return 1;
}
return 0;
}
void sig_dump(int sig)
{
run_dump = 1;
}
void sig_teardown(int sig)
{
run_stop = 1;
}
void write_pcap_header(FILE *o)
{
pcap_hdr_t ghdr = {
.magic_number = 0xa1b2c3d4,
.version_major = 2,
.version_minor = 4,
.thiszone = 0,
.sigfigs = 0,
.snaplen = 0xFFFF,
.network = DLT_IEEE802_11_RADIO
};
fwrite(&ghdr, 1, sizeof(ghdr), o);
}
void write_pcap_frame(FILE *o, uint32_t *sec, uint32_t *usec,
uint16_t len, uint16_t olen)
{
struct timeval tv;
pcaprec_hdr_t fhdr;
if (!sec || !usec)
{
gettimeofday(&tv, NULL);
}
else
{
tv.tv_sec = *sec;
tv.tv_usec = *usec;
}
fhdr.ts_sec = tv.tv_sec;
fhdr.ts_usec = tv.tv_usec;
fhdr.incl_len = len;
fhdr.orig_len = olen;
fwrite(&fhdr, 1, sizeof(fhdr), o);
}
struct ringbuf * ringbuf_init(uint32_t num_item, uint16_t len_item)
{
static struct ringbuf r;
if (len_item <= 0)
return NULL;
r.buf = malloc(num_item * (len_item + sizeof(struct ringbuf_entry)));
if (r.buf)
{
r.len = num_item;
r.fill = 0;
r.slen = (len_item + sizeof(struct ringbuf_entry));
memset(r.buf, 0, num_item * len_item);
return &r;
}
return NULL;
}
struct ringbuf_entry * ringbuf_add(struct ringbuf *r)
{
struct timeval t;
struct ringbuf_entry *e;
gettimeofday(&t, NULL);
e = r->buf + (r->fill++ * r->slen);
r->fill %= r->len;
memset(e, 0, r->slen);
e->sec = t.tv_sec;
e->usec = t.tv_usec;
return e;
}
struct ringbuf_entry * ringbuf_get(struct ringbuf *r, int i)
{
struct ringbuf_entry *e = r->buf + (((r->fill + i) % r->len) * r->slen);
if (e->len > 0)
return e;
return NULL;
}
void ringbuf_free(struct ringbuf *r)
{
free(r->buf);
memset(r, 0, sizeof(*r));
}
void msg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (run_daemon)
vsyslog(LOG_INFO | LOG_USER, fmt, ap);
else
vfprintf(stderr, fmt, ap);
va_end(ap);
}
int main(int argc, char **argv)
{
int i, n;
struct ringbuf *ring;
struct ringbuf_entry *e;
struct sockaddr_ll local = {
.sll_family = AF_PACKET,
.sll_protocol = htons(ETH_P_ALL)
};
radiotap_hdr_t *rhdr;
uint8_t frametype;
uint8_t pktbuf[0xFFFF];
ssize_t pktlen;
FILE *o;
int opt;
uint8_t promisc = 0;
uint8_t streaming = 0;
uint8_t foreground = 0;
uint8_t filter_data = 0;
uint8_t filter_beacon = 0;
uint8_t header_written = 0;
uint32_t ringsz = 1024 * 1024; /* 1 Mbyte ring buffer */
uint16_t pktcap = 256; /* truncate frames after 265KB */
const char *output = NULL;
while ((opt = getopt(argc, argv, "i:r:c:o:sfhBD")) != -1)
{
switch (opt)
{
case 'i':
ifname = optarg;
if (!(local.sll_ifindex = if_nametoindex(ifname)))
{
msg("Unknown interface '%s'\n", ifname);
return 2;
}
break;
case 'r':
ringsz = atoi(optarg);
if (ringsz < (3 * pktcap))
{
msg("Ring size of %d bytes is too short, "
"must be at least %d bytes\n", ringsz, 3 * pktcap);
return 3;
}
break;
case 'c':
pktcap = atoi(optarg);
if (pktcap <= (sizeof(radiotap_hdr_t) + LEN_IEEE802_11_HDR))
{
msg("Packet truncate after %d bytes is too short, "
"must be at least %d bytes\n",
pktcap, sizeof(radiotap_hdr_t) + LEN_IEEE802_11_HDR);
return 4;
}
break;
case 's':
streaming = 1;
break;
case 'o':
output = optarg;
break;
case 'B':
filter_beacon = 1;
break;
case 'D':
filter_data = 1;
break;
case 'f':
foreground = 1;
break;
case 'h':
msg(
"Usage:\n"
" %s -i {iface} -s [-b] [-d]\n"
" %s -i {iface} -o {file} [-r len] [-c len] [-B] [-D] [-f]\n"
"\n"
" -i iface\n"
" Specify interface to use, must be in monitor mode and\n"
" produce IEEE 802.11 Radiotap headers.\n\n"
" -s\n"
" Stream to stdout instead of Dumping to file on USR1.\n\n"
" -o file\n"
" Write current ringbuffer contents to given output file\n"
" on receipt of SIGUSR1.\n\n"
" -r len\n"
" Specify the amount of bytes to use for the ringbuffer.\n"
" The default length is %d bytes.\n\n"
" -c len\n"
" Truncate captured packets after given amount of bytes.\n"
" The default size limit is %d bytes.\n\n"
" -B\n"
" Don't store beacon frames in ring, default is keep.\n\n"
" -D\n"
" Don't store data frames in ring, default is keep.\n\n"
" -f\n"
" Do not daemonize but keep running in foreground.\n\n"
" -h\n"
" Display this help.\n\n",
argv[0], argv[0], ringsz, pktcap);
return 1;
}
}
if (!streaming && !output)
{
msg("No output file specified\n");
return 1;
}
if (streaming && output)
{
msg("The -s and -o options are exclusive\n");
return 1;
}
if (streaming && isatty(1))
{
msg("Refusing to stream into a terminal\n");
return 1;
}
if (!local.sll_ifindex)
{
msg("No interface specified\n");
return 2;
}
if (!check_type())
{
msg("Bad interface: not ARPHRD_IEEE80211_RADIOTAP\n");
return 2;
}
if ((capture_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
{
msg("Unable to create raw socket: %s\n",
strerror(errno));
return 6;
}
if (bind(capture_sock, (struct sockaddr *)&local, sizeof(local)) == -1)
{
msg("Unable to bind to interface: %s\n",
strerror(errno));
return 7;
}
if (!streaming)
{
if (!foreground)
{
switch (fork())
{
case -1:
msg("Unable to fork: %s\n", strerror(errno));
return 8;
case 0:
umask(0077);
chdir("/");
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
run_daemon = 1;
break;
default:
msg("Daemon launched ...\n");
return 0;
}
}
msg("Monitoring interface %s ...\n", ifname);
if (!(ring = ringbuf_init(ringsz / pktcap, pktcap)))
{
msg("Unable to allocate ring buffer: %s\n",
strerror(errno));
return 5;
}
msg(" * Using %d bytes ringbuffer with %d slots\n", ringsz, ring->len);
msg(" * Truncating frames at %d bytes\n", pktcap);
msg(" * Dumping data to file %s\n", output);
signal(SIGUSR1, sig_dump);
}
else
{
msg("Monitoring interface %s ...\n", ifname);
msg(" * Streaming data to stdout\n");
}
msg(" * Beacon frames are %sfiltered\n", filter_beacon ? "" : "not ");
msg(" * Data frames are %sfiltered\n", filter_data ? "" : "not ");
signal(SIGINT, sig_teardown);
signal(SIGTERM, sig_teardown);
promisc = set_promisc(1);
/* capture loop */
while (1)
{
if (run_stop)
{
msg("Shutting down ...\n");
if (promisc)
set_promisc(0);
if (ring)
ringbuf_free(ring);
return 0;
}
else if (run_dump)
{
msg("Dumping ring to %s ...\n", output);
if (!(o = fopen(output, "w")))
{
msg("Unable to open %s: %s\n",
output, strerror(errno));
}
else
{
write_pcap_header(o);
/* sig_dump packet buffer */
for (i = 0, n = 0; i < ring->len; i++)
{
if (!(e = ringbuf_get(ring, i)))
continue;
write_pcap_frame(o, &(e->sec), &(e->usec), e->len, e->olen);
fwrite((void *)e + sizeof(*e), 1, e->len, o);
n++;
}
fclose(o);
msg(" * %d frames captured\n", frames_captured);
msg(" * %d frames filtered\n", frames_filtered);
msg(" * %d frames dumped\n", n);
}
run_dump = 0;
}
pktlen = recvfrom(capture_sock, pktbuf, sizeof(pktbuf), 0, NULL, 0);
frames_captured++;
/* check received frametype, if we should filter it, rewind the ring */
rhdr = (radiotap_hdr_t *)pktbuf;
if (pktlen <= sizeof(radiotap_hdr_t) || le16(rhdr->it_len) >= pktlen)
{
frames_filtered++;
continue;
}
frametype = *(uint8_t *)(pktbuf + le16(rhdr->it_len));
if ((filter_data && (frametype & FRAMETYPE_MASK) == FRAMETYPE_DATA) ||
(filter_beacon && (frametype & FRAMETYPE_MASK) == FRAMETYPE_BEACON))
{
frames_filtered++;
continue;
}
if (streaming)
{
if (!header_written)
{
write_pcap_header(stdout);
header_written = 1;
}
write_pcap_frame(stdout, NULL, NULL, pktlen, pktlen);
fwrite(pktbuf, 1, pktlen, stdout);
fflush(stdout);
}
else
{
e = ringbuf_add(ring);
e->olen = pktlen;
e->len = (pktlen > pktcap) ? pktcap : pktlen;
memcpy((void *)e + sizeof(*e), pktbuf, e->len);
}
}
return 0;
}
+118
View File
@@ -0,0 +1,118 @@
#
# Copyright (C) 2010-2012 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:=35
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
PKG_CONFIG_DEPENDS := \
CONFIG_PACKAGE_kmod-brcm-wl \
CONFIG_PACKAGE_kmod-brcm-wl-mini \
CONFIG_PACKAGE_kmod-brcm-wl-mimo \
CONFIG_PACKAGE_kmod-madwifi \
CONFIG_PACKAGE_kmod-mac80211
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
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.
+44
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)
@@ -0,0 +1,190 @@
#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 <sys/mman.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[];
enum iwinfo_opmode {
IWINFO_OPMODE_UNKNOWN = 0,
IWINFO_OPMODE_MASTER = 1,
IWINFO_OPMODE_ADHOC = 2,
IWINFO_OPMODE_CLIENT = 3,
IWINFO_OPMODE_MONITOR = 4,
};
extern const char *IWINFO_OPMODE_NAMES[];
struct iwinfo_rate_entry {
uint32_t rate;
int8_t mcs;
uint8_t is_40mhz:1;
uint8_t is_short_gi:1;
};
struct iwinfo_assoclist_entry {
uint8_t mac[6];
int8_t signal;
int8_t noise;
uint32_t inactive;
uint32_t rx_packets;
uint32_t tx_packets;
struct iwinfo_rate_entry rx_rate;
struct iwinfo_rate_entry tx_rate;
};
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];
enum iwinfo_opmode mode;
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];
};
struct iwinfo_hardware_id {
uint16_t vendor_id;
uint16_t device_id;
uint16_t subsystem_vendor_id;
uint16_t subsystem_device_id;
};
struct iwinfo_hardware_entry {
const char *vendor_name;
const char *device_name;
uint16_t vendor_id;
uint16_t device_id;
uint16_t subsystem_vendor_id;
uint16_t subsystem_device_id;
int16_t txpower_offset;
int16_t frequency_offset;
};
extern const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[];
extern const struct iwinfo_hardware_entry IWINFO_HARDWARE_ENTRIES[];
struct iwinfo_ops {
int (*mode)(const char *, int *);
int (*channel)(const char *, int *);
int (*frequency)(const char *, int *);
int (*frequency_offset)(const char *, int *);
int (*txpower)(const char *, int *);
int (*txpower_offset)(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 (*ssid)(const char *, char *);
int (*bssid)(const char *, char *);
int (*country)(const char *, char *);
int (*hardware_id)(const char *, char *);
int (*hardware_name)(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
@@ -0,0 +1,131 @@
/*
* 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;
#define WL_NUMRATES 255 /* max # of rates in a rateset */
typedef struct wl_rateset {
uint32_t count; /* # rates in this set */
uint8_t rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */
} wl_rateset_t;
typedef struct wl_sta_info {
uint16_t ver; /* version of this struct */
uint16_t len; /* length in bytes of this structure */
uint16_t cap; /* sta's advertised capabilities */
uint32_t flags; /* flags defined below */
uint32_t idle; /* time since data pkt rx'd from sta */
unsigned char ea[6]; /* Station address */
wl_rateset_t rateset; /* rateset in use */
uint32_t in; /* seconds elapsed since associated */
uint32_t listen_interval_inms; /* Min Listen interval in ms for this STA */
uint32_t tx_pkts; /* # of packets transmitted */
uint32_t tx_failures; /* # of packets failed */
uint32_t rx_ucast_pkts; /* # of unicast packets received */
uint32_t rx_mcast_pkts; /* # of multicast packets received */
uint32_t tx_rate; /* Rate of last successful tx frame */
uint32_t rx_rate; /* Rate of last successful rx frame */
} wl_sta_info_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
@@ -0,0 +1,160 @@
/*
* 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
#define IEEE80211_SEQ_SEQ_MASK 0xfff0
#define IEEE80211_SEQ_SEQ_SHIFT 4
/* 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
@@ -0,0 +1,80 @@
/*
* 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_STRUCT(type,op) \
static int iwinfo_L_##type##_##op(lua_State *L) \
{ \
return iwinfo_L_##op(L, type##_get_##op); \
}
#endif
@@ -0,0 +1,83 @@
/*
* 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, int *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_frequency_offset(const char *ifname, int *buf);
int madwifi_get_txpower(const char *ifname, int *buf);
int madwifi_get_txpower_offset(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);
int madwifi_get_hardware_id(const char *ifname, char *buf);
int madwifi_get_hardware_name(const char *ifname, char *buf);
void madwifi_close(void);
static const struct iwinfo_ops madwifi_ops = {
.channel = madwifi_get_channel,
.frequency = madwifi_get_frequency,
.frequency_offset = madwifi_get_frequency_offset,
.txpower = madwifi_get_txpower,
.txpower_offset = madwifi_get_txpower_offset,
.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,
.hardware_id = madwifi_get_hardware_id,
.hardware_name = madwifi_get_hardware_name,
.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
@@ -0,0 +1,125 @@
/*
* 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 genl_family *nlctrl;
};
struct nl80211_msg_conveyor {
struct nl_msg *msg;
struct nl_cb *cb;
};
struct nl80211_event_conveyor {
int wait;
int recv;
};
struct nl80211_group_conveyor {
const char *name;
int id;
};
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, int *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_frequency_offset(const char *ifname, int *buf);
int nl80211_get_txpower(const char *ifname, int *buf);
int nl80211_get_txpower_offset(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);
int nl80211_get_hardware_id(const char *ifname, char *buf);
int nl80211_get_hardware_name(const char *ifname, char *buf);
void nl80211_close(void);
static const struct iwinfo_ops nl80211_ops = {
.channel = nl80211_get_channel,
.frequency = nl80211_get_frequency,
.frequency_offset = nl80211_get_frequency_offset,
.txpower = nl80211_get_txpower,
.txpower_offset = nl80211_get_txpower_offset,
.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,
.hardware_id = nl80211_get_hardware_id,
.hardware_name = nl80211_get_hardware_name,
.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
@@ -0,0 +1,47 @@
/*
* 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);
struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id);
int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id);
void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
uint8_t defcipher, uint8_t defauth);
#endif
@@ -0,0 +1,84 @@
/*
* 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, int *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_frequency_offset(const char *ifname, int *buf);
int wext_get_txpower(const char *ifname, int *buf);
int wext_get_txpower_offset(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);
int wext_get_hardware_id(const char *ifname, char *buf);
int wext_get_hardware_name(const char *ifname, char *buf);
void wext_close(void);
static const struct iwinfo_ops wext_ops = {
.channel = wext_get_channel,
.frequency = wext_get_frequency,
.frequency_offset = wext_get_frequency_offset,
.txpower = wext_get_txpower,
.txpower_offset = wext_get_txpower_offset,
.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,
.hardware_id = wext_get_hardware_id,
.hardware_name = wext_get_hardware_name,
.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
@@ -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
@@ -0,0 +1,84 @@
/*
* 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, int *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_frequency_offset(const char *ifname, int *buf);
int wl_get_txpower(const char *ifname, int *buf);
int wl_get_txpower_offset(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);
int wl_get_hardware_id(const char *ifname, char *buf);
int wl_get_hardware_name(const char *ifname, char *buf);
void wl_close(void);
static const struct iwinfo_ops wl_ops = {
.channel = wl_get_channel,
.frequency = wl_get_frequency,
.frequency_offset = wl_get_frequency_offset,
.txpower = wl_get_txpower,
.txpower_offset = wl_get_txpower_offset,
.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,
.hardware_id = wl_get_hardware_id,
.hardware_name = wl_get_hardware_name,
.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
@@ -0,0 +1,800 @@
/*
* 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), "%d.%d MBit/s",
rate / 1000, (rate % 1000) / 100);
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 char * format_assocrate(struct iwinfo_rate_entry *r)
{
static char buf[40];
char *p = buf;
int l = sizeof(buf);
if (r->rate <= 0)
{
snprintf(buf, sizeof(buf), "unknown");
}
else
{
p += snprintf(p, l, "%s", format_rate(r->rate));
l = sizeof(buf) - (p - buf);
if (r->mcs >= 0)
{
p += snprintf(p, l, ", MCS %d, %dMHz", r->mcs, 20 + r->is_40mhz*20);
l = sizeof(buf) - (p - buf);
if (r->is_short_gi)
p += snprintf(p, l, ", short GI");
}
}
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_hardware_id(const struct iwinfo_ops *iw, const char *ifname)
{
static char buf[20];
struct iwinfo_hardware_id ids;
if (!iw->hardware_id(ifname, (char *)&ids))
{
snprintf(buf, sizeof(buf), "%04X:%04X %04X:%04X",
ids.vendor_id, ids.device_id,
ids.subsystem_vendor_id, ids.subsystem_device_id);
}
else
{
snprintf(buf, sizeof(buf), "unknown");
}
return buf;
}
static char * print_hardware_name(const struct iwinfo_ops *iw, const char *ifname)
{
static char buf[128];
if (iw->hardware_name(ifname, buf))
snprintf(buf, sizeof(buf), "unknown");
return buf;
}
static char * print_txpower_offset(const struct iwinfo_ops *iw, const char *ifname)
{
int off;
static char buf[12];
if (iw->txpower_offset(ifname, &off))
snprintf(buf, sizeof(buf), "unknown");
else if (off != 0)
snprintf(buf, sizeof(buf), "%d dB", off);
else
snprintf(buf, sizeof(buf), "none");
return buf;
}
static char * print_frequency_offset(const struct iwinfo_ops *iw, const char *ifname)
{
int off;
static char buf[12];
if (iw->frequency_offset(ifname, &off))
snprintf(buf, sizeof(buf), "unknown");
else if (off != 0)
snprintf(buf, sizeof(buf), "%.3f GHz", ((float)off / 1000.0));
else
snprintf(buf, sizeof(buf), "none");
return buf;
}
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)
{
int mode;
static char buf[128];
if (iw->mode(ifname, &mode))
mode = IWINFO_OPMODE_UNKNOWN;
snprintf(buf, sizeof(buf), "%s", IWINFO_OPMODE_NAMES[mode]);
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, off;
if (iw->txpower_offset(ifname, &off))
off = 0;
if (iw->txpower(ifname, &pwr))
pwr = -1;
else
pwr += off;
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(" 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(" Type: %s HW Mode(s): %s\n",
print_type(iw, ifname),
print_hwmodes(iw, ifname));
printf(" Hardware: %s [%s]\n",
print_hardware_id(iw, ifname),
print_hardware_name(iw, ifname));
printf(" TX power offset: %s\n",
print_txpower_offset(iw, ifname));
printf(" Frequency offset: %s\n",
print_frequency_offset(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",
IWINFO_OPMODE_NAMES[e->mode],
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, off, 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;
if (iw->txpower_offset(ifname, &off))
off = 0;
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 + off,
iwinfo_dbm2mw(e->dbm + off));
}
}
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) %d ms ago\n",
format_bssid(e->mac),
format_signal(e->signal),
format_noise(e->noise),
(e->signal - e->noise),
e->inactive);
printf(" RX: %-38s %8d Pkts.\n",
format_assocrate(&e->rx_rate),
e->rx_packets
);
printf(" TX: %-38s %8d Pkts.\n\n",
format_assocrate(&e->tx_rate),
e->tx_packets
);
}
}
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;
}
@@ -0,0 +1,453 @@
/*
* 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",
};
const char *IWINFO_OPMODE_NAMES[] = {
"Unknown",
"Master",
"Ad-Hoc",
"Client",
"Monitor",
};
/*
* 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, "" }
};
/*
* hardware database
*/
const char VENDOR_UBNT[] = "Ubiquiti";
const char VENDOR_ATH[] = "Atheros";
const char VENDOR_RALINK[] = "RaLink";
const struct iwinfo_hardware_entry IWINFO_HARDWARE_ENTRIES[] = {
/* { vendor, model, vendorid, deviceid, subsys vendorid, subsys deviceid, poweroff, freqoff } */
#if defined(USE_MADWIFI) || defined(USE_NL80211)
{ VENDOR_UBNT, "PowerStation2 (18V)", 0xffff, 0xffff, 0xffff, 0xb102, 0, 0 },
{ VENDOR_UBNT, "PowerStation2 (16D)", 0xffff, 0xffff, 0xffff, 0xb202, 0, 0 },
{ VENDOR_UBNT, "PowerStation2 (EXT)", 0xffff, 0xffff, 0xffff, 0xb302, 0, 0 },
{ VENDOR_UBNT, "PowerStation5 (22V)", 0xffff, 0xffff, 0xffff, 0xb105, 0, 0 },
{ VENDOR_UBNT, "PowerStation5 (EXT)", 0xffff, 0xffff, 0xffff, 0xb305, 0, 0 },
{ VENDOR_UBNT, "PicoStation2", 0xffff, 0xffff, 0xffff, 0xc302, 0, 0 },
{ VENDOR_UBNT, "PicoStation2 HP", 0xffff, 0xffff, 0xffff, 0xc3a2, 10, 0 },
{ VENDOR_UBNT, "WispStation5", 0xffff, 0xffff, 0xffff, 0xa105, 0, 0 },
{ VENDOR_UBNT, "LiteStation2", 0xffff, 0xffff, 0xffff, 0xa002, 10, 0 },
{ VENDOR_UBNT, "LiteStation5", 0xffff, 0xffff, 0xffff, 0xa005, 5, 0 },
{ VENDOR_UBNT, "NanoStation2", 0xffff, 0xffff, 0xffff, 0xc002, 10, 0 },
{ VENDOR_UBNT, "NanoStation5", 0xffff, 0xffff, 0xffff, 0xc005, 5, 0 },
{ VENDOR_UBNT, "NanoStation Loco2", 0xffff, 0xffff, 0xffff, 0xc102, 10, 0 },
{ VENDOR_UBNT, "NanoStation Loco5", 0xffff, 0xffff, 0xffff, 0xc105, 5, 0 },
{ VENDOR_UBNT, "Bullet2", 0xffff, 0xffff, 0xffff, 0xc202, 10, 0 },
{ VENDOR_UBNT, "Bullet5", 0xffff, 0xffff, 0xffff, 0xc205, 5, 0 },
{ VENDOR_UBNT, "XR2", 0x168c, 0x001b, 0x0777, 0x3002, 10, 0 },
{ VENDOR_UBNT, "XR2", 0x168c, 0x001b, 0x7777, 0x3002, 10, 0 },
{ VENDOR_UBNT, "XR2.3", 0x168c, 0x001b, 0x0777, 0x3b02, 10, 0 },
{ VENDOR_UBNT, "XR2.6", 0x168c, 0x001b, 0x0777, 0x3c02, 10, 0 },
{ VENDOR_UBNT, "XR3-2.8", 0x168c, 0x001b, 0x0777, 0x3b03, 10, 0 },
{ VENDOR_UBNT, "XR3-3.6", 0x168c, 0x001b, 0x0777, 0x3c03, 10, 0 },
{ VENDOR_UBNT, "XR3", 0x168c, 0x001b, 0x0777, 0x3003, 10, 0 },
{ VENDOR_UBNT, "XR4", 0x168c, 0x001b, 0x0777, 0x3004, 10, 0 },
{ VENDOR_UBNT, "XR5", 0x168c, 0x001b, 0x0777, 0x3005, 10, 0 },
{ VENDOR_UBNT, "XR5", 0x168c, 0x001b, 0x7777, 0x3005, 10, 0 },
{ VENDOR_UBNT, "XR7", 0x168c, 0x001b, 0x0777, 0x3007, 10, 0 },
{ VENDOR_UBNT, "XR9", 0x168c, 0x001b, 0x0777, 0x3009, 10, -1520 },
{ VENDOR_ATH, "AR5413", 0x168c, 0x001b, 0x168c, 0x2063, 0, 0 },
{ VENDOR_UBNT, "SRC", 0x168c, 0x0013, 0x168c, 0x1042, 1, 0 },
{ VENDOR_UBNT, "SR2", 0x168c, 0x0013, 0x0777, 0x2041, 10, 0 },
{ VENDOR_UBNT, "SR4", 0x168c, 0x0013, 0x0777, 0x2004, 6, 0 },
{ VENDOR_UBNT, "SR4", 0x168c, 0x0013, 0x7777, 0x2004, 6, 0 },
{ VENDOR_UBNT, "SR4C", 0x168c, 0x0013, 0x0777, 0x1004, 6, 0 },
{ VENDOR_UBNT, "SR4C", 0x168c, 0x0013, 0x7777, 0x1004, 6, 0 },
{ VENDOR_UBNT, "SR5", 0x168c, 0x0013, 0x168c, 0x2042, 7, 0 },
{ VENDOR_UBNT, "SR9", 0x168c, 0x0013, 0x7777, 0x2009, 12, -1500 },
{ VENDOR_UBNT, "SR71A", 0x168c, 0x0027, 0x168c, 0x2082, 10, 0 },
{ VENDOR_UBNT, "SR71", 0x168c, 0x0027, 0x0777, 0x4082, 10, 0 },
#endif
#ifdef USE_NL80211
{ VENDOR_UBNT, "PicoStation M2", 0x168c, 0x002a, 0x0777, 0xe302, 12, 0 }, /* ToDo: confirm offset */
{ VENDOR_UBNT, "NanoStation M2", 0x168c, 0x002a, 0x0777, 0xe012, 12, 0 }, /* ToDo: confirm offset */
{ VENDOR_UBNT, "NanoStation M5", 0x168c, 0x002a, 0x0777, 0xe005, 5, 0 }, /* ToDo: confirm offset */
{ VENDOR_UBNT, "Bullet M2", 0x168c, 0x002a, 0x0777, 0xe202, 12, 0 },
{ VENDOR_UBNT, "Bullet M5", 0x168c, 0x002a, 0x0777, 0xe805, 5, 0 },
{ VENDOR_ATH, "AR9220", 0x168c, 0x0029, 0x168c, 0xa094, 0, 0 },
{ VENDOR_ATH, "AR9223", 0x168c, 0x0029, 0x168c, 0xa095, 0, 0 },
{ VENDOR_ATH, "AR9280", 0x168c, 0x002a, 0x168c, 0xa093, 0, 0 },
{ VENDOR_ATH, "AR9285", 0x168c, 0x002b, 0x168c, 0xa091, 0, 0 },
{ VENDOR_RALINK, "Rt3050", 0x1814, 0x3050, 0x1814, 0x0005, 0, 0 },
{ VENDOR_RALINK, "Rt3052", 0x1814, 0x3052, 0x1814, 0x0008, 0, 0 },
{ VENDOR_RALINK, "Rt3352", 0x1814, 0x3352, 0x1814, 0x000c, 0, 0 },
#endif
{ NULL }
};
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();
}
@@ -0,0 +1,886 @@
/*
* 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 mode */
static int iwinfo_L_mode(lua_State *L, int (*func)(const char *, int *))
{
int mode;
const char *ifname = luaL_checkstring(L, 1);
if ((*func)(ifname, &mode))
mode = IWINFO_OPMODE_UNKNOWN;
lua_pushstring(L, IWINFO_OPMODE_NAMES[mode]);
return 1;
}
/* 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_pushnumber(L, e->inactive);
lua_setfield(L, -2, "inactive");
lua_pushnumber(L, e->rx_packets);
lua_setfield(L, -2, "rx_packets");
lua_pushnumber(L, e->tx_packets);
lua_setfield(L, -2, "tx_packets");
lua_pushnumber(L, e->rx_rate.rate);
lua_setfield(L, -2, "rx_rate");
lua_pushnumber(L, e->tx_rate.rate);
lua_setfield(L, -2, "tx_rate");
if (e->rx_rate.mcs >= 0)
{
lua_pushnumber(L, e->rx_rate.mcs);
lua_setfield(L, -2, "rx_mcs");
lua_pushboolean(L, e->rx_rate.is_40mhz);
lua_setfield(L, -2, "rx_40mhz");
lua_pushboolean(L, e->rx_rate.is_short_gi);
lua_setfield(L, -2, "rx_short_gi");
}
if (e->tx_rate.mcs >= 0)
{
lua_pushnumber(L, e->tx_rate.mcs);
lua_setfield(L, -2, "tx_mcs");
lua_pushboolean(L, e->tx_rate.is_40mhz);
lua_setfield(L, -2, "tx_40mhz");
lua_pushboolean(L, e->tx_rate.is_short_gi);
lua_setfield(L, -2, "tx_short_gi");
}
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;
memset(rv, 0, sizeof(rv));
if (!(*func)(ifname, rv, &len))
{
lua_newtable(L);
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;
}
return 0;
}
/* 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, IWINFO_OPMODE_NAMES[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 mbssid_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 hardware_id */
static int iwinfo_L_hardware_id(lua_State *L, int (*func)(const char *, char *))
{
const char *ifname = luaL_checkstring(L, 1);
struct iwinfo_hardware_id ids;
if (!(*func)(ifname, (char *)&ids))
{
lua_newtable(L);
lua_pushnumber(L, ids.vendor_id);
lua_setfield(L, -2, "vendor_id");
lua_pushnumber(L, ids.device_id);
lua_setfield(L, -2, "device_id");
lua_pushnumber(L, ids.subsystem_vendor_id);
lua_setfield(L, -2, "subsystem_vendor_id");
lua_pushnumber(L, ids.subsystem_device_id);
lua_setfield(L, -2, "subsystem_device_id");
}
else
{
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,frequency_offset)
LUA_WRAP_INT(wl,txpower)
LUA_WRAP_INT(wl,txpower_offset)
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,ssid)
LUA_WRAP_STRING(wl,bssid)
LUA_WRAP_STRING(wl,country)
LUA_WRAP_STRING(wl,hardware_name)
LUA_WRAP_STRUCT(wl,mode)
LUA_WRAP_STRUCT(wl,assoclist)
LUA_WRAP_STRUCT(wl,txpwrlist)
LUA_WRAP_STRUCT(wl,scanlist)
LUA_WRAP_STRUCT(wl,freqlist)
LUA_WRAP_STRUCT(wl,countrylist)
LUA_WRAP_STRUCT(wl,hwmodelist)
LUA_WRAP_STRUCT(wl,encryption)
LUA_WRAP_STRUCT(wl,mbssid_support)
LUA_WRAP_STRUCT(wl,hardware_id)
#endif
#ifdef USE_MADWIFI
/* Madwifi */
LUA_WRAP_INT(madwifi,channel)
LUA_WRAP_INT(madwifi,frequency)
LUA_WRAP_INT(madwifi,frequency_offset)
LUA_WRAP_INT(madwifi,txpower)
LUA_WRAP_INT(madwifi,txpower_offset)
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,ssid)
LUA_WRAP_STRING(madwifi,bssid)
LUA_WRAP_STRING(madwifi,country)
LUA_WRAP_STRING(madwifi,hardware_name)
LUA_WRAP_STRUCT(madwifi,mode)
LUA_WRAP_STRUCT(madwifi,assoclist)
LUA_WRAP_STRUCT(madwifi,txpwrlist)
LUA_WRAP_STRUCT(madwifi,scanlist)
LUA_WRAP_STRUCT(madwifi,freqlist)
LUA_WRAP_STRUCT(madwifi,countrylist)
LUA_WRAP_STRUCT(madwifi,hwmodelist)
LUA_WRAP_STRUCT(madwifi,encryption)
LUA_WRAP_STRUCT(madwifi,mbssid_support)
LUA_WRAP_STRUCT(madwifi,hardware_id)
#endif
#ifdef USE_NL80211
/* NL80211 */
LUA_WRAP_INT(nl80211,channel)
LUA_WRAP_INT(nl80211,frequency)
LUA_WRAP_INT(nl80211,frequency_offset)
LUA_WRAP_INT(nl80211,txpower)
LUA_WRAP_INT(nl80211,txpower_offset)
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,ssid)
LUA_WRAP_STRING(nl80211,bssid)
LUA_WRAP_STRING(nl80211,country)
LUA_WRAP_STRING(nl80211,hardware_name)
LUA_WRAP_STRUCT(nl80211,mode)
LUA_WRAP_STRUCT(nl80211,assoclist)
LUA_WRAP_STRUCT(nl80211,txpwrlist)
LUA_WRAP_STRUCT(nl80211,scanlist)
LUA_WRAP_STRUCT(nl80211,freqlist)
LUA_WRAP_STRUCT(nl80211,countrylist)
LUA_WRAP_STRUCT(nl80211,hwmodelist)
LUA_WRAP_STRUCT(nl80211,encryption)
LUA_WRAP_STRUCT(nl80211,mbssid_support)
LUA_WRAP_STRUCT(nl80211,hardware_id)
#endif
/* Wext */
LUA_WRAP_INT(wext,channel)
LUA_WRAP_INT(wext,frequency)
LUA_WRAP_INT(wext,frequency_offset)
LUA_WRAP_INT(wext,txpower)
LUA_WRAP_INT(wext,txpower_offset)
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,ssid)
LUA_WRAP_STRING(wext,bssid)
LUA_WRAP_STRING(wext,country)
LUA_WRAP_STRING(wext,hardware_name)
LUA_WRAP_STRUCT(wext,mode)
LUA_WRAP_STRUCT(wext,assoclist)
LUA_WRAP_STRUCT(wext,txpwrlist)
LUA_WRAP_STRUCT(wext,scanlist)
LUA_WRAP_STRUCT(wext,freqlist)
LUA_WRAP_STRUCT(wext,countrylist)
LUA_WRAP_STRUCT(wext,hwmodelist)
LUA_WRAP_STRUCT(wext,encryption)
LUA_WRAP_STRUCT(wext,mbssid_support)
LUA_WRAP_STRUCT(wext,hardware_id)
#ifdef USE_WL
/* Broadcom table */
static const luaL_reg R_wl[] = {
LUA_REG(wl,channel),
LUA_REG(wl,frequency),
LUA_REG(wl,frequency_offset),
LUA_REG(wl,txpower),
LUA_REG(wl,txpower_offset),
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),
LUA_REG(wl,hardware_id),
LUA_REG(wl,hardware_name),
{ 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,frequency_offset),
LUA_REG(madwifi,txpower),
LUA_REG(madwifi,txpower_offset),
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),
LUA_REG(madwifi,hardware_id),
LUA_REG(madwifi,hardware_name),
{ 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,frequency_offset),
LUA_REG(nl80211,txpower),
LUA_REG(nl80211,txpower_offset),
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),
LUA_REG(nl80211,hardware_id),
LUA_REG(nl80211,hardware_name),
{ NULL, NULL }
};
#endif
/* Wext table */
static const luaL_reg R_wext[] = {
LUA_REG(wext,channel),
LUA_REG(wext,frequency),
LUA_REG(wext,frequency_offset),
LUA_REG(wext,txpower),
LUA_REG(wext,txpower_offset),
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),
LUA_REG(wext,hardware_id),
LUA_REG(wext,hardware_name),
{ 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;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,347 @@
/*
* 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);
}
struct iwinfo_hardware_entry * iwinfo_hardware(struct iwinfo_hardware_id *id)
{
const struct iwinfo_hardware_entry *e;
for (e = IWINFO_HARDWARE_ENTRIES; e->vendor_name; e++)
{
if ((e->vendor_id != 0xffff) && (e->vendor_id != id->vendor_id))
continue;
if ((e->device_id != 0xffff) && (e->device_id != id->device_id))
continue;
if ((e->subsystem_vendor_id != 0xffff) &&
(e->subsystem_vendor_id != id->subsystem_vendor_id))
continue;
if ((e->subsystem_device_id != 0xffff) &&
(e->subsystem_device_id != id->subsystem_device_id))
continue;
return (struct iwinfo_hardware_entry *)e;
}
return NULL;
}
int iwinfo_hardware_id_from_mtd(struct iwinfo_hardware_id *id)
{
FILE *mtd;
uint16_t *bc;
int fd, len, off;
char buf[128];
if (!(mtd = fopen("/proc/mtd", "r")))
return -1;
while (fgets(buf, sizeof(buf), mtd) > 0)
{
if (fscanf(mtd, "mtd%d: %*x %x %127s", &off, &len, buf) < 3 ||
(strcmp(buf, "\"boardconfig\"") && strcmp(buf, "\"EEPROM\"") &&
strcmp(buf, "\"factory\"")))
{
off = -1;
continue;
}
break;
}
fclose(mtd);
if (off < 0)
return -1;
snprintf(buf, sizeof(buf), "/dev/mtdblock%d", off);
if ((fd = open(buf, O_RDONLY)) < 0)
return -1;
bc = mmap(NULL, len, PROT_READ, MAP_PRIVATE|MAP_LOCKED, fd, 0);
if ((void *)bc != MAP_FAILED)
{
id->vendor_id = 0;
id->device_id = 0;
for (off = len / 2 - 0x800; off >= 0; off -= 0x800)
{
/* AR531X board data magic */
if ((bc[off] == 0x3533) && (bc[off + 1] == 0x3131))
{
id->vendor_id = bc[off + 0x7d];
id->device_id = bc[off + 0x7c];
id->subsystem_vendor_id = bc[off + 0x84];
id->subsystem_device_id = bc[off + 0x83];
break;
}
/* AR5416 EEPROM magic */
else if ((bc[off] == 0xA55A) || (bc[off] == 0x5AA5))
{
id->vendor_id = bc[off + 0x0D];
id->device_id = bc[off + 0x0E];
id->subsystem_vendor_id = bc[off + 0x13];
id->subsystem_device_id = bc[off + 0x14];
break;
}
/* Rt3xxx SoC */
else if ((bc[off] == 0x3352) || (bc[off] == 0x5233) ||
(bc[off] == 0x3350) || (bc[off] == 0x5033) ||
(bc[off] == 0x3050) || (bc[off] == 0x5030) ||
(bc[off] == 0x3052) || (bc[off] == 0x5230))
{
/* vendor: RaLink */
id->vendor_id = 0x1814;
id->subsystem_vendor_id = 0x1814;
/* device */
if (bc[off] & 0xf0 == 0x30)
id->device_id = (bc[off] >> 8) | (bc[off] & 0x00ff) << 8;
else
id->device_id = bc[off];
/* subsystem from EEPROM_NIC_CONF0_RF_TYPE */
id->subsystem_device_id = (bc[off + 0x1a] & 0x0f00) >> 8;
}
}
munmap(bc, len);
}
close(fd);
return (id->vendor_id && id->device_id) ? 0 : -1;
}
void iwinfo_parse_rsn(struct iwinfo_crypto_entry *c, uint8_t *data, uint8_t len,
uint8_t defcipher, uint8_t defauth)
{
uint16_t i, count;
static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
data += 2;
len -= 2;
if (!memcmp(data, ms_oui, 3))
c->wpa_version += 1;
else if (!memcmp(data, ieee80211_oui, 3))
c->wpa_version += 2;
if (len < 4)
{
c->group_ciphers |= defcipher;
c->pair_ciphers |= defcipher;
c->auth_suites |= defauth;
return;
}
if (!memcmp(data, ms_oui, 3) || !memcmp(data, ieee80211_oui, 3))
{
switch (data[3])
{
case 1: c->group_ciphers |= IWINFO_CIPHER_WEP40; break;
case 2: c->group_ciphers |= IWINFO_CIPHER_TKIP; break;
case 4: c->group_ciphers |= IWINFO_CIPHER_CCMP; break;
case 5: c->group_ciphers |= IWINFO_CIPHER_WEP104; break;
case 6: /* AES-128-CMAC */ break;
default: /* proprietary */ break;
}
}
data += 4;
len -= 4;
if (len < 2)
{
c->pair_ciphers |= defcipher;
c->auth_suites |= defauth;
return;
}
count = data[0] | (data[1] << 8);
if (2 + (count * 4) > len)
return;
for (i = 0; i < count; i++)
{
if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
!memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
{
switch (data[2 + (i * 4) + 3])
{
case 1: c->pair_ciphers |= IWINFO_CIPHER_WEP40; break;
case 2: c->pair_ciphers |= IWINFO_CIPHER_TKIP; break;
case 4: c->pair_ciphers |= IWINFO_CIPHER_CCMP; break;
case 5: c->pair_ciphers |= IWINFO_CIPHER_WEP104; break;
case 6: /* AES-128-CMAC */ break;
default: /* proprietary */ break;
}
}
}
data += 2 + (count * 4);
len -= 2 + (count * 4);
if (len < 2)
{
c->auth_suites |= defauth;
return;
}
count = data[0] | (data[1] << 8);
if (2 + (count * 4) > len)
return;
for (i = 0; i < count; i++)
{
if (!memcmp(data + 2 + (i * 4), ms_oui, 3) ||
!memcmp(data + 2 + (i * 4), ieee80211_oui, 3))
{
switch (data[2 + (i * 4) + 3])
{
case 1: c->auth_suites |= IWINFO_KMGMT_8021x; break;
case 2: c->auth_suites |= IWINFO_KMGMT_PSK; break;
case 3: /* FT/IEEE 802.1X */ break;
case 4: /* FT/PSK */ break;
case 5: /* IEEE 802.1X/SHA-256 */ break;
case 6: /* PSK/SHA-256 */ break;
default: /* proprietary */ break;
}
}
}
data += 2 + (count * 4);
len -= 2 + (count * 4);
}
@@ -0,0 +1,520 @@
/*
* 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, int *buf)
{
struct iwreq wrq;
if(wext_ioctl(ifname, SIOCGIWMODE, &wrq) >= 0)
{
switch(wrq.u.mode)
{
case 1:
*buf = IWINFO_OPMODE_ADHOC;
break;
case 2:
*buf = IWINFO_OPMODE_CLIENT;
break;
case 3:
*buf = IWINFO_OPMODE_MASTER;
break;
case 6:
*buf = IWINFO_OPMODE_MONITOR;
break;
default:
*buf = IWINFO_OPMODE_UNKNOWN;
break;
}
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;
*buf = 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;
}
static char * wext_sysfs_ifname_file(const char *ifname, const char *path)
{
FILE *f;
static char buf[128];
char *rv = NULL;
snprintf(buf, sizeof(buf), "/sys/class/net/%s/%s", ifname, path);
if ((f = fopen(buf, "r")) != NULL)
{
memset(buf, 0, sizeof(buf));
if (fread(buf, 1, sizeof(buf), f))
rv = buf;
fclose(f);
}
return rv;
}
int wext_get_hardware_id(const char *ifname, char *buf)
{
char *data;
struct iwinfo_hardware_id *id = (struct iwinfo_hardware_id *)buf;
memset(id, 0, sizeof(struct iwinfo_hardware_id));
data = wext_sysfs_ifname_file(ifname, "device/vendor");
if (data)
id->vendor_id = strtoul(data, NULL, 16);
data = wext_sysfs_ifname_file(ifname, "device/device");
if (data)
id->device_id = strtoul(data, NULL, 16);
data = wext_sysfs_ifname_file(ifname, "device/subsystem_device");
if (data)
id->subsystem_device_id = strtoul(data, NULL, 16);
data = wext_sysfs_ifname_file(ifname, "device/subsystem_vendor");
if (data)
id->subsystem_vendor_id = strtoul(data, NULL, 16);
return (id->vendor_id > 0 && id->device_id > 0) ? 0 : -1;
}
int wext_get_hardware_name(const char *ifname, char *buf)
{
sprintf(buf, "Generic WEXT");
return 0;
}
int wext_get_txpower_offset(const char *ifname, int *buf)
{
/* Stub */
*buf = 0;
return -1;
}
int wext_get_frequency_offset(const char *ifname, int *buf)
{
/* Stub */
*buf = 0;
return -1;
}
@@ -0,0 +1,527 @@
/*
* 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 ielen, struct iwinfo_scanlist_entry *e)
{
static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 };
while (ielen >= 2 && ielen >= iebuf[1])
{
switch (iebuf[0])
{
case 48: /* RSN */
iwinfo_parse_rsn(&e->crypto, iebuf + 2, iebuf[1],
IWINFO_CIPHER_CCMP, IWINFO_KMGMT_8021x);
break;
case 221: /* Vendor */
if (iebuf[1] >= 4 && !memcmp(iebuf + 2, ms_oui, 3) && iebuf[5] == 1)
iwinfo_parse_rsn(&e->crypto, iebuf + 6, iebuf[1] - 4,
IWINFO_CIPHER_TKIP, IWINFO_KMGMT_PSK);
break;
}
ielen -= iebuf[1] + 2;
iebuf += iebuf[1] + 2;
}
}
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:
e->mode = IWINFO_OPMODE_ADHOC;
break;
case 2:
case 3:
e->mode = IWINFO_OPMODE_MASTER;
break;
default:
e->mode = IWINFO_OPMODE_UNKNOWN;
break;
}
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:
wext_fill_wpa(event->u.data.pointer, event->u.data.length, e);
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;
}
@@ -0,0 +1,645 @@
/*
* 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 int wl_iovar(const char *name, const char *cmd, const char *arg,
int arglen, void *buf, int buflen)
{
int cmdlen = strlen(cmd) + 1;
memcpy(buf, cmd, cmdlen);
if (arg && arglen > 0)
memcpy(buf + cmdlen, arg, arglen);
return wl_ioctl(name, WLC_GET_VAR, buf, buflen);
}
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;
return (!wl_ioctl(ifname, WLC_GET_MAGIC, &magic, sizeof(magic)) &&
(magic == WLC_IOCTL_MAGIC));
}
void wl_close(void)
{
/* Nop */
}
int wl_get_mode(const char *ifname, int *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)
*buf = IWINFO_OPMODE_MONITOR;
else if (!infra)
*buf = IWINFO_OPMODE_ADHOC;
else if (ap)
*buf = IWINFO_OPMODE_MASTER;
else
*buf = IWINFO_OPMODE_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)
{
/* WLC_GET_VAR "qtxpower" */
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;
}
static void wl_get_assoclist_cb(const char *ifname,
struct iwinfo_assoclist_entry *e)
{
wl_sta_info_t sta = { 0 };
if (!wl_iovar(ifname, "sta_info", e->mac, 6, &sta, sizeof(sta)) &&
(sta.ver >= 2))
{
e->inactive = sta.idle * 1000;
e->rx_packets = sta.rx_ucast_pkts;
e->tx_packets = sta.tx_pkts;
e->rx_rate.rate = sta.rx_rate;
e->tx_rate.rate = sta.tx_rate;
/* ToDo: 11n */
e->rx_rate.mcs = -1;
e->tx_rate.mcs = -1;
}
}
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))
{
memset(&entry, 0, sizeof(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);
wl_get_assoclist_cb(ifname, &entry);
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[11] = { 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 };
uint8_t mw[11] = { 1, 3, 6, 10, 15, 25, 39, 63, 100, 158, 251 };
int i;
for (i = 0; i < 11; i++)
{
entry.dbm = dbm[i];
entry.mw = mw[i];
memcpy(&buf[i*sizeof(entry)], &entry, sizeof(entry));
}
*len = 11 * 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;
}
int wl_get_hardware_id(const char *ifname, char *buf)
{
wlc_rev_info_t revinfo;
struct iwinfo_hardware_id *ids = (struct iwinfo_hardware_id *)buf;
if (wl_ioctl(ifname, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)))
return -1;
ids->vendor_id = revinfo.vendorid;
ids->device_id = revinfo.deviceid;
ids->subsystem_vendor_id = revinfo.boardvendor;
ids->subsystem_device_id = revinfo.boardid;
return 0;
}
int wl_get_hardware_name(const char *ifname, char *buf)
{
struct iwinfo_hardware_id ids;
if (wl_get_hardware_id(ifname, (char *)&ids))
return -1;
sprintf(buf, "Broadcom BCM%04X", ids.device_id);
return 0;
}
int wl_get_txpower_offset(const char *ifname, int *buf)
{
FILE *p;
char off[8];
*buf = 0;
if ((p = popen("/usr/sbin/nvram get opo", "r")) != NULL)
{
if (fread(off, 1, sizeof(off), p))
*buf = strtoul(off, NULL, 16);
pclose(p);
}
return 0;
}
int wl_get_frequency_offset(const char *ifname, int *buf)
{
/* Stub */
*buf = 0;
return -1;
}
+47
View File
@@ -0,0 +1,47 @@
#
# Copyright (C) 2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=maccalc
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/maccalc
SECTION:=utils
CATEGORY:=Utilities
TITLE:=MAC address calculation
endef
define Package/maccalc/description
This package contains a MAC address manipulation utility.
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CC="$(TARGET_CC)" \
CFLAGS="$(TARGET_CFLAGS) -Wall" \
LDFLAGS="$(TARGET_LDFLAGS)"
endef
define Package/maccalc/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/maccalc $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,maccalc))
@@ -0,0 +1,14 @@
CC = gcc
CFLAGS = -Wall
OBJS = main.o
all: maccalc
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
maccalc: $(OBJS)
$(CC) -o $@ $(OBJS)
clean:
rm -f maccalc *.o
+256
View File
@@ -0,0 +1,256 @@
/*
* MAC address manupulation utility
*
* Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
*
* This program 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.
*
*/
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#define MAC_ADDRESS_LEN 6
#define ERR_INVALID 1
#define ERR_IO 2
static void usage(void);
char *maccalc_name;
static int parse_mac(const char *mac_str, unsigned char *buf)
{
int t;
t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
&buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5]);
if (t != MAC_ADDRESS_LEN)
return ERR_INVALID;
return 0;
}
static void print_mac(unsigned char *buf)
{
printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
}
static int maccalc_do_add(int argc, const char *argv[])
{
unsigned char mac[MAC_ADDRESS_LEN];
uint32_t t;
int err;
int i;
if (argc != 2) {
usage();
return ERR_INVALID;
}
err = parse_mac(argv[0], mac);
if (err)
return err;
i = atoi(argv[1]);
t = (mac[3] << 16) | (mac[4] << 8) | mac[5];
t += i;
mac[3] = (t >> 16) & 0xff;
mac[4] = (t >> 8) & 0xff;
mac[5] = t & 0xff;
print_mac(mac);
return 0;
}
static int maccalc_do_logical(int argc, const char *argv[],
unsigned char (*op)(unsigned char n1,
unsigned char n2))
{
unsigned char mac1[MAC_ADDRESS_LEN];
unsigned char mac2[MAC_ADDRESS_LEN];
int err;
int i;
if (argc != 2) {
usage();
return ERR_INVALID;
}
err = parse_mac(argv[0], mac1);
if (err)
return err;
err = parse_mac(argv[1], mac2);
if (err)
return err;
for (i = 0; i < MAC_ADDRESS_LEN; i++)
mac1[i] = op(mac1[i],mac2[i]);
print_mac(mac1);
return 0;
}
static int maccalc_do_mac2bin(int argc, const char *argv[])
{
unsigned char mac[MAC_ADDRESS_LEN];
ssize_t c;
int err;
if (argc != 1) {
usage();
return ERR_INVALID;
}
err = parse_mac(argv[0], mac);
if (err)
return err;
c = write(STDOUT_FILENO, mac, sizeof(mac));
if (c != sizeof(mac)) {
fprintf(stderr, "failed to write to stdout\n");
return ERR_IO;
}
return 0;
}
static ssize_t read_safe(int fd, void *buf, size_t count)
{
ssize_t total = 0;
ssize_t r;
while(count > 0) {
r = read(fd, buf, count);
if (r == 0)
/* EOF */
break;
if (r < 0) {
if (errno == EINTR)
/* interrupted by a signal, restart */
continue;
/* error */
total = -1;
break;
}
/* ok */
total += r;
count -= r;
buf += r;
}
return total;
}
static int maccalc_do_bin2mac(int argc, const char *argv[])
{
unsigned char mac[MAC_ADDRESS_LEN];
ssize_t c;
if (argc != 0) {
usage();
return ERR_INVALID;
}
c = read_safe(STDIN_FILENO, mac, sizeof(mac));
if (c != sizeof(mac)) {
fprintf(stderr, "failed to read from stdin\n");
return ERR_IO;
}
print_mac(mac);
return 0;
}
static unsigned char op_or(unsigned char n1, unsigned char n2)
{
return n1 | n2;
}
static int maccalc_do_or(int argc, const char *argv[])
{
return maccalc_do_logical(argc, argv, op_or);
}
static unsigned char op_and(unsigned char n1, unsigned char n2)
{
return n1 & n2;
}
static int maccalc_do_and(int argc, const char *argv[])
{
return maccalc_do_logical(argc, argv, op_and);
}
static unsigned char op_xor(unsigned char n1, unsigned char n2)
{
return n1 ^ n2;
}
static int maccalc_do_xor(int argc, const char *argv[])
{
return maccalc_do_logical(argc, argv, op_xor);
}
static void usage(void)
{
fprintf(stderr,
"Usage: %s <command>\n"
"valid commands:\n"
" add <mac> <number>\n"
" and|or|xor <mac1> <mac2>\n"
" mac2bin <mac>\n"
" bin2mac\n",
maccalc_name);
}
int main(int argc, const char *argv[])
{
int (*op)(int argc, const char *argv[]);
int ret;
maccalc_name = (char *) argv[0];
if (argc < 2) {
usage();
return EXIT_FAILURE;
}
if (strcmp(argv[1], "add") == 0) {
op = maccalc_do_add;
} else if (strcmp(argv[1], "and") == 0) {
op = maccalc_do_and;
} else if (strcmp(argv[1], "or") == 0) {
op = maccalc_do_or;
} else if (strcmp(argv[1], "xor") == 0) {
op = maccalc_do_xor;
} else if (strcmp(argv[1], "mac2bin") == 0) {
op = maccalc_do_mac2bin;
} else if (strcmp(argv[1], "bin2mac") == 0) {
op = maccalc_do_bin2mac;
} else {
fprintf(stderr, "unknown command '%s'\n", argv[1]);
usage();
return EXIT_FAILURE;
}
argc -= 2;
argv += 2;
ret = op(argc, argv);
if (ret)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
+49
View File
@@ -0,0 +1,49 @@
#
# Copyright (C) 2012 Jo-Philipp Wich <jow@openwrt.org>
#
# This is free software, licensed under the Apache 2 license.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=owipcalc
PKG_RELEASE:=3
include $(INCLUDE_DIR)/package.mk
define Package/owipcalc
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Simple IPv4/IPv6 address calculator
MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org>
endef
define Package/owipcalc/description
The owipcalc utility supports a number of calculations and tests to work
with ip-address ranges, this is useful for scripts that e.g. need to
partition ipv6-prefixes into small subnets or to calculate address ranges
for dhcp pools.
endef
define Build/Prepare
$(INSTALL_DIR) $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) \
-o $(PKG_BUILD_DIR)/owipcalc $(PKG_BUILD_DIR)/owipcalc.c
endef
define Package/owipcalc/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/owipcalc $(1)/usr/bin/owipcalc
endef
$(eval $(call BuildPackage,owipcalc))
@@ -0,0 +1,951 @@
/*
* owipcalc - OpenWrt IP Calculator
*
* Copyright (C) 2012 Jo-Philipp Wich <jow@openwrt.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
struct cidr {
uint8_t family;
uint32_t prefix;
union {
struct in_addr v4;
struct in6_addr v6;
} addr;
union {
char v4[sizeof("255.255.255.255/255.255.255.255 ")];
char v6[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128 ")];
} buf;
struct cidr *next;
};
struct op {
const char *name;
const char *desc;
struct {
bool (*a1)(struct cidr *a);
bool (*a2)(struct cidr *a, struct cidr *b);
} f4;
struct {
bool (*a1)(struct cidr *a);
bool (*a2)(struct cidr *a, struct cidr *b);
} f6;
};
static bool quiet = false;
static bool printed = false;
static struct cidr *stack = NULL;
#define qprintf(...) \
do { \
if (!quiet) printf(__VA_ARGS__); \
printed = true; \
} while(0)
static void cidr_push(struct cidr *a)
{
if (a)
{
a->next = stack;
stack = a;
}
}
static bool cidr_pop(struct cidr *a)
{
struct cidr *old = stack;
if (old)
{
stack = stack->next;
free(old);
return true;
}
return false;
}
static struct cidr * cidr_clone(struct cidr *a)
{
struct cidr *b = malloc(sizeof(*b));
if (!b)
{
fprintf(stderr, "out of memory\n");
exit(255);
}
memcpy(b, a, sizeof(*b));
cidr_push(b);
return b;
}
static struct cidr * cidr_parse4(const char *s)
{
char *p = NULL, *r;
struct in_addr mask;
struct cidr *addr = malloc(sizeof(struct cidr));
if (!addr || (strlen(s) >= sizeof(addr->buf.v4)))
goto err;
snprintf(addr->buf.v4, sizeof(addr->buf.v4), "%s", s);
addr->family = AF_INET;
if ((p = strchr(addr->buf.v4, '/')) != NULL)
{
*p++ = 0;
if (strchr(p, '.') != NULL)
{
if (inet_pton(AF_INET, p, &mask) != 1)
goto err;
for (addr->prefix = 0; mask.s_addr; mask.s_addr >>= 1)
addr->prefix += (mask.s_addr & 1);
}
else
{
addr->prefix = strtoul(p, &r, 10);
if ((p == r) || (*r != 0) || (addr->prefix > 32))
goto err;
}
}
else
{
addr->prefix = 32;
}
if (p == addr->buf.v4+1)
memset(&addr->addr.v4, 0, sizeof(addr->addr.v4));
else if (inet_pton(AF_INET, addr->buf.v4, &addr->addr.v4) != 1)
goto err;
return addr;
err:
if (addr)
free(addr);
return NULL;
}
static bool cidr_add4(struct cidr *a, struct cidr *b)
{
uint32_t x = ntohl(a->addr.v4.s_addr);
uint32_t y = ntohl(b->addr.v4.s_addr);
struct cidr *n = cidr_clone(a);
if ((n->family != AF_INET) || (b->family != AF_INET))
return false;
if ((uint32_t)(x + y) < x)
{
fprintf(stderr, "overflow during 'add'\n");
return false;
}
n->addr.v4.s_addr = htonl(x + y);
return true;
}
static bool cidr_sub4(struct cidr *a, struct cidr *b)
{
uint32_t x = ntohl(a->addr.v4.s_addr);
uint32_t y = ntohl(b->addr.v4.s_addr);
struct cidr *n = cidr_clone(a);
if ((n->family != AF_INET) || (b->family != AF_INET))
return false;
if ((uint32_t)(x - y) > x)
{
fprintf(stderr, "underflow during 'sub'\n");
return false;
}
n->addr.v4.s_addr = htonl(x - y);
return true;
}
static bool cidr_network4(struct cidr *a)
{
struct cidr *n = cidr_clone(a);
n->addr.v4.s_addr &= htonl(~((1 << (32 - n->prefix)) - 1));
n->prefix = 32;
return true;
}
static bool cidr_broadcast4(struct cidr *a)
{
struct cidr *n = cidr_clone(a);
n->addr.v4.s_addr |= htonl(((1 << (32 - n->prefix)) - 1));
n->prefix = 32;
return true;
}
static bool cidr_contains4(struct cidr *a, struct cidr *b)
{
uint32_t net1 = a->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1));
uint32_t net2 = b->addr.v4.s_addr & htonl(~((1 << (32 - a->prefix)) - 1));
if (printed)
qprintf(" ");
if ((b->prefix >= a->prefix) && (net1 == net2))
{
qprintf("1");
return true;
}
else
{
qprintf("0");
return false;
}
}
static bool cidr_netmask4(struct cidr *a)
{
struct cidr *n = cidr_clone(a);
n->addr.v4.s_addr = htonl(~((1 << (32 - n->prefix)) - 1));
n->prefix = 32;
return true;
}
static bool cidr_private4(struct cidr *a)
{
uint32_t x = ntohl(a->addr.v4.s_addr);
if (printed)
qprintf(" ");
if (((x >= 0x0A000000) && (x <= 0x0AFFFFFF)) ||
((x >= 0xAC100000) && (x <= 0xAC1FFFFF)) ||
((x >= 0xC0A80000) && (x <= 0xC0A8FFFF)))
{
qprintf("1");
return true;
}
else
{
qprintf("0");
return false;
}
}
static bool cidr_linklocal4(struct cidr *a)
{
uint32_t x = ntohl(a->addr.v4.s_addr);
if (printed)
qprintf(" ");
if ((x >= 0xA9FE0000) && (x <= 0xA9FEFFFF))
{
qprintf("1");
return true;
}
else
{
qprintf("0");
return false;
}
}
static bool cidr_prev4(struct cidr *a, struct cidr *b)
{
struct cidr *n = cidr_clone(a);
n->prefix = b->prefix;
n->addr.v4.s_addr -= htonl(1 << (32 - b->prefix));
return true;
}
static bool cidr_next4(struct cidr *a, struct cidr *b)
{
struct cidr *n = cidr_clone(a);
n->prefix = b->prefix;
n->addr.v4.s_addr += htonl(1 << (32 - b->prefix));
return true;
}
static bool cidr_6to4(struct cidr *a)
{
struct cidr *n = cidr_clone(a);
uint32_t x = a->addr.v4.s_addr;
memset(&n->addr.v6.s6_addr, 0, sizeof(n->addr.v6.s6_addr));
n->family = AF_INET6;
n->prefix = 48;
n->addr.v6.s6_addr[0] = 0x20;
n->addr.v6.s6_addr[1] = 0x02;
n->addr.v6.s6_addr[2] = (x >> 24);
n->addr.v6.s6_addr[3] = (x >> 16) & 0xFF;
n->addr.v6.s6_addr[4] = (x >> 8) & 0xFF;
n->addr.v6.s6_addr[5] = x & 0xFF;
return true;
}
static bool cidr_print4(struct cidr *a)
{
char *p;
if (!a || (a->family != AF_INET))
return false;
if (!(p = (char *)inet_ntop(AF_INET, &a->addr.v4, a->buf.v4, sizeof(a->buf.v4))))
return false;
if (printed)
qprintf(" ");
qprintf("%s", p);
if (a->prefix < 32)
qprintf("/%u", a->prefix);
cidr_pop(a);
return true;
}
static struct cidr * cidr_parse6(const char *s)
{
char *p = NULL, *r;
struct cidr *addr = malloc(sizeof(struct cidr));
if (!addr || (strlen(s) >= sizeof(addr->buf.v6)))
goto err;
snprintf(addr->buf.v4, sizeof(addr->buf.v6), "%s", s);
addr->family = AF_INET6;
if ((p = strchr(addr->buf.v4, '/')) != NULL)
{
*p++ = 0;
addr->prefix = strtoul(p, &r, 10);
if ((p == r) || (*r != 0) || (addr->prefix > 128))
goto err;
}
else
{
addr->prefix = 128;
}
if (p == addr->buf.v4+1)
memset(&addr->addr.v6, 0, sizeof(addr->addr.v6));
else if (inet_pton(AF_INET6, addr->buf.v4, &addr->addr.v6) != 1)
goto err;
return addr;
err:
if (addr)
free(addr);
return NULL;
}
static bool cidr_add6(struct cidr *a, struct cidr *b)
{
uint8_t idx = 15, carry = 0, overflow = 0;
struct cidr *n = cidr_clone(a);
struct in6_addr *x = &n->addr.v6;
struct in6_addr *y = &b->addr.v6;
if ((a->family != AF_INET6) || (b->family != AF_INET6))
return false;
do {
overflow = !!((x->s6_addr[idx] + y->s6_addr[idx] + carry) >= 256);
x->s6_addr[idx] += y->s6_addr[idx] + carry;
carry = overflow;
}
while (idx-- > 0);
if (carry)
{
fprintf(stderr, "overflow during 'add'\n");
return false;
}
return true;
}
static bool cidr_sub6(struct cidr *a, struct cidr *b)
{
uint8_t idx = 15, carry = 0, underflow = 0;
struct cidr *n = cidr_clone(a);
struct in6_addr *x = &n->addr.v6;
struct in6_addr *y = &b->addr.v6;
if ((n->family != AF_INET6) || (b->family != AF_INET6))
return false;
do {
underflow = !!((x->s6_addr[idx] - y->s6_addr[idx] - carry) < 0);
x->s6_addr[idx] -= y->s6_addr[idx] + carry;
carry = underflow;
}
while (idx-- > 0);
if (carry)
{
fprintf(stderr, "underflow during 'sub'\n");
return false;
}
return true;
}
static bool cidr_prev6(struct cidr *a, struct cidr *b)
{
uint8_t idx, carry = 1, underflow = 0;
struct cidr *n = cidr_clone(a);
struct in6_addr *x = &n->addr.v6;
if (b->prefix == 0)
{
fprintf(stderr, "underflow during 'prev'\n");
return false;
}
idx = (b->prefix - 1) / 8;
do {
underflow = !!((x->s6_addr[idx] - carry) < 0);
x->s6_addr[idx] -= carry;
carry = underflow;
}
while (idx-- > 0);
if (carry)
{
fprintf(stderr, "underflow during 'prev'\n");
return false;
}
n->prefix = b->prefix;
return true;
}
static bool cidr_next6(struct cidr *a, struct cidr *b)
{
uint8_t idx, carry = 1, overflow = 0;
struct cidr *n = cidr_clone(a);
struct in6_addr *x = &n->addr.v6;
if (b->prefix == 0)
{
fprintf(stderr, "overflow during 'next'\n");
return false;
}
idx = (b->prefix - 1) / 8;
do {
overflow = !!((x->s6_addr[idx] + carry) >= 256);
x->s6_addr[idx] += carry;
carry = overflow;
}
while (idx-- > 0);
if (carry)
{
fprintf(stderr, "overflow during 'next'\n");
return false;
}
n->prefix = b->prefix;
return true;
}
static bool cidr_network6(struct cidr *a)
{
uint8_t i;
struct cidr *n = cidr_clone(a);
for (i = 0; i < (128 - n->prefix) / 8; i++)
n->addr.v6.s6_addr[15-i] = 0;
if ((128 - n->prefix) % 8)
n->addr.v6.s6_addr[15-i] &= ~((1 << ((128 - n->prefix) % 8)) - 1);
return true;
}
static bool cidr_contains6(struct cidr *a, struct cidr *b)
{
struct cidr *n = cidr_clone(a);
struct in6_addr *x = &n->addr.v6;
struct in6_addr *y = &b->addr.v6;
uint8_t i = (128 - n->prefix) / 8;
uint8_t m = ~((1 << ((128 - n->prefix) % 8)) - 1);
uint8_t net1 = x->s6_addr[15-i] & m;
uint8_t net2 = y->s6_addr[15-i] & m;
if (printed)
qprintf(" ");
if ((b->prefix >= n->prefix) && (net1 == net2) &&
((i == 15) || !memcmp(&x->s6_addr, &y->s6_addr, 15-i)))
{
qprintf("1");
return true;
}
else
{
qprintf("0");
return false;
}
}
static bool cidr_linklocal6(struct cidr *a)
{
if (printed)
qprintf(" ");
if ((a->addr.v6.s6_addr[0] == 0xFE) &&
(a->addr.v6.s6_addr[1] >= 0x80) &&
(a->addr.v6.s6_addr[1] <= 0xBF))
{
qprintf("1");
return true;
}
else
{
qprintf("0");
return false;
}
}
static bool cidr_ula6(struct cidr *a)
{
if (printed)
qprintf(" ");
if ((a->addr.v6.s6_addr[0] >= 0xFC) &&
(a->addr.v6.s6_addr[0] <= 0xFD))
{
qprintf("1");
return true;
}
else
{
qprintf("0");
return false;
}
}
static bool cidr_print6(struct cidr *a)
{
char *p;
if (!a || (a->family != AF_INET6))
return NULL;
if (!(p = (char *)inet_ntop(AF_INET6, &a->addr.v6, a->buf.v6, sizeof(a->buf.v6))))
return false;
if (printed)
qprintf(" ");
qprintf("%s", p);
if (a->prefix < 128)
qprintf("/%u", a->prefix);
cidr_pop(a);
return true;
}
static struct cidr * cidr_parse(const char *op, const char *s, int af_hint)
{
char *r;
struct cidr *a;
uint8_t i;
uint32_t sum = strtoul(s, &r, 0);
if ((r > s) && (*r == 0))
{
a = malloc(sizeof(struct cidr));
if (!a)
return NULL;
if (af_hint == AF_INET)
{
a->family = AF_INET;
a->prefix = sum;
a->addr.v4.s_addr = htonl(sum);
}
else
{
a->family = AF_INET6;
a->prefix = sum;
for (i = 0; i <= 15; i++)
{
a->addr.v6.s6_addr[15-i] = sum % 256;
sum >>= 8;
}
}
return a;
}
if (strchr(s, ':'))
a = cidr_parse6(s);
else
a = cidr_parse4(s);
if (!a)
return NULL;
if (a->family != af_hint)
{
fprintf(stderr, "attempt to '%s' %s with %s address\n",
op,
(af_hint == AF_INET) ? "ipv4" : "ipv6",
(af_hint != AF_INET) ? "ipv4" : "ipv6");
exit(4);
}
return a;
}
static bool cidr_howmany(struct cidr *a, struct cidr *b)
{
if (printed)
qprintf(" ");
if (b->prefix < a->prefix)
qprintf("0");
else
qprintf("%u", 1 << (b->prefix - a->prefix));
return true;
}
static bool cidr_prefix(struct cidr *a, struct cidr *b)
{
a->prefix = b->prefix;
return true;
}
static bool cidr_quiet(struct cidr *a)
{
quiet = true;
return true;
}
struct op ops[] = {
{ .name = "add",
.desc = "Add argument to base address",
.f4.a2 = cidr_add4,
.f6.a2 = cidr_add6 },
{ .name = "sub",
.desc = "Substract argument from base address",
.f4.a2 = cidr_sub4,
.f6.a2 = cidr_sub6 },
{ .name = "next",
.desc = "Advance base address to next prefix of given size",
.f4.a2 = cidr_next4,
.f6.a2 = cidr_next6 },
{ .name = "prev",
.desc = "Lower base address to previous prefix of give size",
.f4.a2 = cidr_prev4,
.f6.a2 = cidr_prev6 },
{ .name = "network",
.desc = "Turn base address into network address",
.f4.a1 = cidr_network4,
.f6.a1 = cidr_network6 },
{ .name = "broadcast",
.desc = "Turn base address into broadcast address",
.f4.a1 = cidr_broadcast4 },
{ .name = "prefix",
.desc = "Set the prefix of base address to argument",
.f4.a2 = cidr_prefix,
.f6.a2 = cidr_prefix },
{ .name = "netmask",
.desc = "Calculate netmask of base address",
.f4.a1 = cidr_netmask4 },
{ .name = "6to4",
.desc = "Calculate 6to4 prefix of given ipv4-address",
.f4.a1 = cidr_6to4 },
{ .name = "howmany",
.desc = "Print amount of righ-hand prefixes that fit into base address",
.f4.a2 = cidr_howmany,
.f6.a2 = cidr_howmany },
{ .name = "contains",
.desc = "Print '1' if argument fits into base address or '0' if not",
.f4.a2 = cidr_contains4,
.f6.a2 = cidr_contains6 },
{ .name = "private",
.desc = "Print '1' if base address is in RFC1918 private space or '0' "
"if not",
.f4.a1 = cidr_private4 },
{ .name = "linklocal",
.desc = "Print '1' if base address is in 169.254.0.0/16 or FE80::/10 "
"link local space or '0' if not",
.f4.a1 = cidr_linklocal4,
.f6.a1 = cidr_linklocal6 },
{ .name = "ula",
.desc = "Print '1' if base address is in FC00::/7 unique local address "
"(ULA) space or '0' if not",
.f6.a1 = cidr_ula6 },
{ .name = "quiet",
.desc = "Suppress output, useful for test operation where the result can "
"be inferred from the exit code",
.f4.a1 = cidr_quiet,
.f6.a1 = cidr_quiet },
{ .name = "pop",
.desc = "Pop intermediate result from stack",
.f4.a1 = cidr_pop,
.f6.a1 = cidr_pop },
{ .name = "print",
.desc = "Print intermediate result and pop it from stack, invoked "
"implicitely at the end of calculation if no intermediate prints "
"happened",
.f4.a1 = cidr_print4,
.f6.a1 = cidr_print6 },
};
static void usage(const char *prog)
{
int i;
fprintf(stderr,
"\n"
"Usage:\n\n"
" %s {base address} operation [argument] "
"[operation [argument] ...]\n\n"
"Operations:\n\n",
prog);
for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++)
{
if (ops[i].f4.a2 || ops[i].f6.a2)
{
fprintf(stderr, " %s %s\n",
ops[i].name,
(ops[i].f4.a2 && ops[i].f6.a2) ? "{ipv4/ipv6/amount}" :
(ops[i].f6.a2 ? "{ipv6/amount}" : "{ipv4/amount}"));
}
else
{
fprintf(stderr, " %s\n", ops[i].name);
}
fprintf(stderr, " %s.\n", ops[i].desc);
if ((ops[i].f4.a1 && ops[i].f6.a1) || (ops[i].f4.a2 && ops[i].f6.a2))
fprintf(stderr, " Applicable to ipv4- and ipv6-addresses.\n\n");
else if (ops[i].f6.a2 || ops[i].f6.a1)
fprintf(stderr, " Only applicable to ipv6-addresses.\n\n");
else
fprintf(stderr, " Only applicable to ipv4-addresses.\n\n");
}
fprintf(stderr,
"Examples:\n\n"
" Calculate a DHCP range:\n\n"
" $ %s 192.168.1.1/255.255.255.0 network add 100 print add 150 print\n"
" 192.168.1.100\n"
" 192.168.1.250\n\n"
" Count number of prefixes:\n\n"
" $ %s 2001:0DB8:FDEF::/48 howmany ::/64\n"
" 65536\n\n",
prog, prog);
exit(1);
}
static bool runop(char ***arg, int *status)
{
int i;
char *arg1 = **arg;
char *arg2 = *(*arg+1);
struct cidr *a = stack;
struct cidr *b = NULL;
if (!arg1)
return false;
for (i = 0; i < sizeof(ops) / sizeof(ops[0]); i++)
{
if (!strcmp(ops[i].name, arg1))
{
if (ops[i].f4.a2 || ops[i].f6.a2)
{
if (!arg2)
{
fprintf(stderr, "'%s' requires an argument\n",
ops[i].name);
*status = 2;
return false;
}
b = cidr_parse(ops[i].name, arg2, a->family);
if (!b)
{
fprintf(stderr, "invalid address argument for '%s'\n",
ops[i].name);
*status = 3;
return false;
}
*arg += 2;
if (((a->family == AF_INET) && !ops[i].f4.a2) ||
((a->family == AF_INET6) && !ops[i].f6.a2))
{
fprintf(stderr, "'%s' not supported for %s addresses\n",
ops[i].name,
(a->family == AF_INET) ? "ipv4" : "ipv6");
*status = 5;
return false;
}
*status = !((a->family == AF_INET) ? ops[i].f4.a2(a, b)
: ops[i].f6.a2(a, b));
return true;
}
else
{
*arg += 1;
if (((a->family == AF_INET) && !ops[i].f4.a1) ||
((a->family == AF_INET6) && !ops[i].f6.a1))
{
fprintf(stderr, "'%s' not supported for %s addresses\n",
ops[i].name,
(a->family == AF_INET) ? "ipv4" : "ipv6");
*status = 5;
return false;
}
*status = !((a->family == AF_INET) ? ops[i].f4.a1(a)
: ops[i].f6.a1(a));
return true;
}
}
}
return false;
}
int main(int argc, char **argv)
{
int status = 0;
char **arg = argv+2;
struct cidr *a;
if (argc < 3)
usage(argv[0]);
a = strchr(argv[1], ':') ? cidr_parse6(argv[1]) : cidr_parse4(argv[1]);
if (!a)
usage(argv[0]);
cidr_push(a);
while (runop(&arg, &status));
if (*arg)
{
fprintf(stderr, "unknown operation '%s'\n", *arg);
exit(6);
}
if (!printed && (status < 2))
{
if (stack->family == AF_INET)
cidr_print4(stack);
else
cidr_print6(stack);
}
qprintf("\n");
exit(status);
}
+44
View File
@@ -0,0 +1,44 @@
#
# Copyright (C) 2011 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=resolveip
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/resolveip
SECTION:=utils
CATEGORY:=Base system
TITLE:=Simple DNS resolver with configurable timeout
endef
define Package/resolveip/description
This package contains the small resolveip utility which
can be used by scripts to turn host names into numeric
IP addresses. It supports IPv4 and IPv6 resolving and
has a configurable timeout to guarantee a certain maximum
runtime in case of slow or defunct DNS servers.
endef
define Build/Prepare
$(INSTALL_DIR) $(PKG_BUILD_DIR)
$(INSTALL_DATA) ./src/resolveip.c $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) -Wall \
-o $(PKG_BUILD_DIR)/resolveip $(PKG_BUILD_DIR)/resolveip.c
endef
define Package/resolveip/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/resolveip $(1)/usr/bin/
endef
$(eval $(call BuildPackage,resolveip))
@@ -0,0 +1,98 @@
/*
* Based on code found at https://dev.openwrt.org/ticket/4876 .
* Extended by Jo-Philipp Wich <jow@openwrt.org> for use in OpenWrt.
*
* You may use this program under the terms of the GPLv2 license.
*/
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
static void abort_query(int sig)
{
exit(1);
}
static void show_usage(void)
{
printf("Usage:\n");
printf(" resolveip -h\n");
printf(" resolveip [-t timeout] hostname\n");
printf(" resolveip -4 [-t timeout] hostname\n");
printf(" resolveip -6 [-t timeout] hostname\n");
exit(255);
}
int main(int argc, char **argv)
{
int timeout = 3;
char opt;
char ipaddr[INET6_ADDRSTRLEN];
void *addr;
struct addrinfo *res, *rp;
struct sigaction sa = { .sa_handler = &abort_query };
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
.ai_flags = 0
};
while ((opt = getopt(argc, argv, "46t:h")) > -1)
{
switch (opt)
{
case '4':
hints.ai_family = AF_INET;
break;
case '6':
hints.ai_family = AF_INET6;
break;
case 't':
timeout = atoi(optarg);
if (timeout <= 0)
show_usage();
break;
case 'h':
show_usage();
break;
}
}
if (!argv[optind])
show_usage();
sigaction(SIGALRM, &sa, NULL);
alarm(timeout);
if (getaddrinfo(argv[optind], NULL, &hints, &res))
exit(2);
for (rp = res; rp != NULL; rp = rp->ai_next)
{
addr = (rp->ai_family == AF_INET)
? (void *)&((struct sockaddr_in *)rp->ai_addr)->sin_addr
: (void *)&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr
;
if (!inet_ntop(rp->ai_family, addr, ipaddr, INET6_ADDRSTRLEN - 1))
exit(3);
printf("%s\n", ipaddr);
}
freeaddrinfo(res);
exit(0);
}
+47
View File
@@ -0,0 +1,47 @@
#
# Copyright (C) 2011-2012 Daniel Golle <dgolle@allnet.de>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=rssileds
PKG_VERSION:=0.1
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define Package/rssileds
SECTION:=net
CATEGORY:=Network
TITLE:=RSSI real-time LED indicator
DEPENDS:=+libiwinfo
endef
define Package/rssileds/description
A small process written in C to update the signal-strength indicator LEDs
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure
endef
define Build/Compile
$(TARGET_CC) $(TARGET_CFLAGS) -Wall -liwinfo \
-o $(PKG_BUILD_DIR)/rssileds $(PKG_BUILD_DIR)/rssileds.c
endef
define Package/rssileds/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/rssileds.init $(1)/etc/init.d/rssileds
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/rssileds $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,rssileds))
@@ -0,0 +1,75 @@
#!/bin/sh /etc/rc.common
# (C) 2012 Daniel Golle, Allnet GmbH <dgolle@allnet.de>
START=96
STOP=96
RSSILEDS_BIN="/usr/sbin/rssileds"
SERVICE_DAEMONIZE=1
SERVICE_WRITE_PID=1
start_rssid() {
local name
local dev
local threshold
local refresh
local leds
config_get name $1 name
config_get dev $1 dev
config_get threshold $1 threshold
config_get refresh $1 refresh
leds="$( cur_iface=$1 ; config_foreach get_led led )"
SERVICE_PID_FILE=/var/run/rssileds-$dev.pid
service_start $RSSILEDS_BIN $dev $refresh $threshold $leds
}
stop_rssid() {
local dev
config_get dev $1 dev
SERVICE_PID_FILE=/var/run/rssileds-$dev.pid
service_stop $RSSILEDS_BIN
}
get_led() {
local name
local sysfs
local trigger
local iface
config_get sysfs $1 sysfs
config_get name $1 name "$sysfs"
config_get trigger $1 trigger "none"
config_get iface $1 iface
config_get minq $1 minq
config_get maxq $1 maxq
config_get offset $1 offset
config_get factor $1 factor
[ "$trigger" = "rssi" ] || return
[ "$iface" = "$cur_iface" ] || return
[ ! "$minq" ] || [ ! "$maxq" ] || [ ! "$offset" ] || [ ! "$factor" ] && return
echo "none" > /sys/class/leds/$sysfs/trigger
echo "$sysfs $minq $maxq $offset $factor"
}
off_led() {
local name
local sysfs
local trigger
config_get sysfs $1 sysfs
config_get name $1 name "$sysfs"
config_get trigger $1 trigger "none"
[ "$trigger" = "rssi" ] || return
echo "0" > /sys/class/leds/$sysfs/brightness
}
start() {
[ -e /sys/class/leds/ ] && [ -x "$RSSILEDS_BIN" ] && {
config_load system
config_foreach start_rssid rssid
}
}
stop() {
config_load system
config_foreach stop_rssid rssid
config_foreach off_led led
}
@@ -0,0 +1,280 @@
/*
* configurable RSSI LED control daemon for OpenWrt
* (c) 2012 Allnet GmbH, Daniel Golle <dgolle@allnet.de>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author may be reached as dgolle@allnet.de, or
* ALLNET GmbH
* Maistr. 2
* D-82110 Germering
* Germany
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <syslog.h>
#include "iwinfo.h"
#define RUN_DIR "/var/run"
#define LEDS_BASEPATH "/sys/class/leds/"
#define BACKEND_RETRY_DELAY 500000
char *ifname;
int qual_max;
struct led {
char *sysfspath;
FILE *controlfd;
unsigned char state;
};
typedef struct rule rule_t;
struct rule {
struct led *led;
int minq;
int maxq;
int boffset;
int bfactor;
rule_t *next;
};
void log_rules(rule_t *rules)
{
rule_t *rule = rules;
while (rule)
{
syslog(LOG_INFO, " %s r: %d..%d, o: %d, f: %d\n",
rule->led->sysfspath,
rule->minq, rule->maxq,
rule->boffset, rule->bfactor);
rule = rule->next;
}
}
int init_led(struct led **led, char *ledname)
{
struct led *newled;
struct stat statbuffer;
int status;
char *bp;
FILE *bfp;
bp = calloc(sizeof(char), strlen(ledname) + strlen(LEDS_BASEPATH) + 12);
if ( ! bp )
goto return_error;
sprintf(bp, "%s%s/brightness", LEDS_BASEPATH, ledname);
status = stat(bp, &statbuffer);
if ( status )
goto cleanup_fname;
bfp = fopen( bp, "w" );
if ( !bfp )
goto cleanup_fname;
if ( ferror(bfp) )
goto cleanup_fp;
/* sysfs path exists and, allocate LED struct */
newled = calloc(sizeof(struct led),1);
if ( !newled )
goto cleanup_fp;
newled->sysfspath = bp;
newled->controlfd = bfp;
*led = newled;
return 0;
cleanup_fp:
fclose(bfp);
cleanup_fname:
free(bp);
return_error:
syslog(LOG_CRIT, "can't open LED %s\n", ledname);
*led = NULL;
return -1;
}
void close_led(struct led **led)
{
fclose((*led)->controlfd);
free((*led)->sysfspath);
free((*led));
(*led)=NULL;
}
int set_led(struct led *led, unsigned char value)
{
char buf[8];
if ( ! led )
return -1;
if ( ! led->controlfd )
return -1;
snprintf(buf, 8, "%d", value);
rewind(led->controlfd);
if ( ! fwrite(buf, sizeof(char), strlen(buf), led->controlfd) )
return -2;
fflush(led->controlfd);
led->state=value;
return 0;
}
int quality(const struct iwinfo_ops *iw, const char *ifname)
{
int qual;
if ( ! iw ) return -1;
if (qual_max < 1)
if (iw->quality_max(ifname, &qual_max))
return -1;
if (iw->quality(ifname, &qual))
return -1;
return ( qual * 100 ) / qual_max ;
}
int open_backend(const struct iwinfo_ops **iw, const char *ifname)
{
*iw = iwinfo_backend(ifname);
if (!(*iw))
return 1;
return 0;
}
void update_leds(rule_t *rules, int q)
{
rule_t *rule = rules;
while (rule)
{
int b;
/* offset and factore correction according to rule */
b = ( q + rule->boffset ) * rule->bfactor;
if ( b < 0 )
b=0;
if ( b > 255 )
b=255;
if ( q >= rule->minq && q <= rule->maxq )
set_led(rule->led, (unsigned char)b);
else
set_led(rule->led, 0);
rule = rule->next;
}
}
int main(int argc, char **argv)
{
int i,q,q0,r,s;
const struct iwinfo_ops *iw = NULL;
rule_t *headrule = NULL, *currentrule = NULL;
if (argc < 9 || ( (argc-4) % 5 != 0 ) )
{
printf("syntax: %s (ifname) (refresh) (threshold) (rule) [rule] ...\n", argv[0]);
printf(" rule: (sysfs-name) (minq) (maxq) (offset) (factore)\n");
return 1;
}
ifname = argv[1];
/* refresh interval */
if ( sscanf(argv[2], "%d", &r) != 1 )
return 1;
/* sustain threshold */
if ( sscanf(argv[3], "%d", &s) != 1 )
return 1;
openlog("rssileds", LOG_PID, LOG_DAEMON);
syslog(LOG_INFO, "monitoring %s, refresh rate %d, threshold %d\n", ifname, r, s);
currentrule = headrule;
for (i=4; i<argc; i=i+5) {
if (! currentrule)
{
/* first element in the list */
currentrule = calloc(sizeof(rule_t),1);
headrule = currentrule;
}
else
{
/* follow-up element */
currentrule->next = calloc(sizeof(rule_t),1);
currentrule = currentrule->next;
}
if ( init_led(&(currentrule->led), argv[i]) )
return 1;
if ( sscanf(argv[i+1], "%d", &(currentrule->minq)) != 1 )
return 1;
if ( sscanf(argv[i+2], "%d", &(currentrule->maxq)) != 1 )
return 1;
if ( sscanf(argv[i+3], "%d", &(currentrule->boffset)) != 1 )
return 1;
if ( sscanf(argv[i+4], "%d", &(currentrule->bfactor)) != 1 )
return 1;
}
log_rules(headrule);
q0 = -1;
do {
q = quality(iw, ifname);
if ( q < q0 - s || q > q0 + s ) {
update_leds(headrule, q);
q0=q;
};
// re-open backend...
if ( q == -1 && q0 == -1 ) {
if (iw) {
iwinfo_finish();
iw=NULL;
usleep(BACKEND_RETRY_DELAY);
}
while (open_backend(&iw, ifname))
usleep(BACKEND_RETRY_DELAY);
}
usleep(r);
} while(1);
iwinfo_finish();
return 0;
}
@@ -0,0 +1,89 @@
#
# Copyright (C) 2006-2009 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=wireless-tools
PKG_VERSION:=29
PKG_MINOR:=
PKG_RELEASE:=5
PKG_SOURCE:=wireless_tools.$(PKG_VERSION)$(PKG_MINOR).tar.gz
PKG_SOURCE_URL:=http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux
PKG_MD5SUM:=e06c222e186f7cc013fd272d023710cb
TAR_OPTIONS += || true
PKG_BUILD_DIR:=$(BUILD_DIR)/wireless_tools.$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
define Package/wireless-tools/Default
URL:=http://hplabs.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
endef
define Package/wireless-tools
$(call Package/wireless-tools/Default)
SECTION:=net
CATEGORY:=Base system
TITLE:=Tools for manipulating Linux Wireless Extensions
endef
define Package/wireless-tools/description
This package contains a collection of tools for configuring wireless
adapters implementing the "Linux Wireless Extensions".
endef
define Package/libiw
$(call Package/wireless-tools/Default)
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Library for manipulating Linux Wireless Extensions
endef
define Package/libiw/description
This package contains a library for manipulating
"Linux Wireless Extensions".
endef
define Build/Compile
rm -rf $(PKG_INSTALL_DIR)
mkdir -p $(PKG_INSTALL_DIR)
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) \
CFLAGS="$(TARGET_CFLAGS) -I." \
BUILD_WE_ESSENTIAL=y \
LIBS="-lm -Wl,--gc-sections" \
libiw.so.$(PKG_VERSION) iwmulticall
$(MAKE) -C $(PKG_BUILD_DIR) \
PREFIX="$(PKG_INSTALL_DIR)" \
INSTALL_DIR="$(PKG_INSTALL_DIR)/usr/sbin" \
INSTALL_LIB="$(PKG_INSTALL_DIR)/usr/lib" \
install-iwmulticall
endef
define Build/InstallDev
mkdir -p $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/{iwlib,wireless}.h $(1)/usr/include/
mkdir -p $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/libiw.so* $(1)/usr/lib/
ln -sf libiw.so.$(PKG_VERSION) $(1)/usr/lib/libiw.so
endef
define Package/wireless-tools/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/iwconfig $(1)/usr/sbin/
ln -sf iwconfig $(1)/usr/sbin/iwlist
ln -sf iwconfig $(1)/usr/sbin/iwpriv
endef
define Package/libiw/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/libiw.so.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,wireless-tools))
$(eval $(call BuildPackage,libiw))

Some files were not shown because too many files have changed in this diff Show More