diff options
author | James <> | 2015-11-04 11:49:21 +0000 |
---|---|---|
committer | James <> | 2015-11-04 11:49:21 +0000 |
commit | 716ca530e1c4515d8683c9d5be3d56b301758b66 (patch) | |
tree | 700eb5bcc1a462a5f21dcec15ce7c97ecfefa772 /package/network/utils | |
download | trunk-47381-master.tar.gz trunk-47381-master.tar.bz2 trunk-47381-master.zip |
Diffstat (limited to 'package/network/utils')
475 files changed, 33746 insertions, 0 deletions
diff --git a/package/network/utils/arptables/Makefile b/package/network/utils/arptables/Makefile new file mode 100644 index 0000000..62681dc --- /dev/null +++ b/package/network/utils/arptables/Makefile @@ -0,0 +1,43 @@ +# 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.4 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/ebtables +PKG_MD5SUM:=c2e99c3aa9d78c9dfa30710ca3168182 +PKG_LICENSE:=GPL-2.0 + +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)) diff --git a/package/network/utils/arptables/patches/100-always_optimize.patch b/package/network/utils/arptables/patches/100-always_optimize.patch new file mode 100644 index 0000000..b120eb7 --- /dev/null +++ b/package/network/utils/arptables/patches/100-always_optimize.patch @@ -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; + diff --git a/package/network/utils/arptables/patches/200-musl_fixes.patch b/package/network/utils/arptables/patches/200-musl_fixes.patch new file mode 100644 index 0000000..3a4ba3f --- /dev/null +++ b/package/network/utils/arptables/patches/200-musl_fixes.patch @@ -0,0 +1,31 @@ +--- a/include/arptables.h ++++ b/include/arptables.h +@@ -1,6 +1,7 @@ + #ifndef _ARPTABLES_USER_H + #define _ARPTABLES_USER_H + ++#include <sys/types.h> + #include "arptables_common.h" + #include "libarptc/libarptc.h" + +--- a/arptables.c ++++ b/arptables.c +@@ -43,6 +43,7 @@ + #include <arptables.h> + #include <fcntl.h> + #include <sys/wait.h> ++#include <net/ethernet.h> + + #ifndef TRUE + #define TRUE 1 +--- a/include/libarptc/arpt_kernel_headers.h ++++ b/include/libarptc/arpt_kernel_headers.h +@@ -5,7 +5,7 @@ + + #include <limits.h> + +-#if defined(__GLIBC__) && __GLIBC__ == 2 ++#if 1 + #include <netinet/ip.h> + #include <netinet/in.h> + #include <netinet/ip_icmp.h> diff --git a/package/network/utils/comgt/Makefile b/package/network/utils/comgt/Makefile new file mode 100644 index 0000000..ac19aad --- /dev/null +++ b/package/network/utils/comgt/Makefile @@ -0,0 +1,103 @@ +# +# Copyright (C) 2006-2014 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:=27 + +PKG_SOURCE:=$(PKG_NAME).$(PKG_VERSION).tgz +PKG_SOURCE_URL:=@SF/comgt +PKG_MD5SUM:=db2452680c3d953631299e331daf49ef + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> +PKG_LICENSE:=GPL-2.0+ + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME).$(PKG_VERSION) +PKG_CHECK_FORMAT_SECURITY:=0 + +include $(INCLUDE_DIR)/package.mk + +define Package/comgt/Default + SECTION:=utils + CATEGORY:=Utilities +endef + +define Package/comgt +$(call Package/comgt/Default) + TITLE:=Option/Vodafone 3G/GPRS control tool + DEPENDS:=+chat + URL:=http://www.pharscape.org/comgt.html +endef + +define Package/comgt-directip +$(call Package/comgt/Default) + TITLE:=Sierra Wireless Direct-IP support + DEPENDS:=+comgt +kmod-usb-serial +kmod-usb-serial-sierrawireless +kmod-usb-net +kmod-usb-net-sierrawireless +endef + +define Package/comgt-ncm +$(call Package/comgt/Default) + TITLE+=NCM 3G/4G Support + DEPENDS:=+comgt +wwan +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) 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 + +define Package/comgt-directip/install + $(INSTALL_DIR) $(1)/etc/gcom + $(INSTALL_DATA) ./files/directip.gcom $(1)/etc/gcom/directip.gcom + $(INSTALL_DATA) ./files/directip-stop.gcom $(1)/etc/gcom/directip-stop.gcom + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/directip.sh $(1)/lib/netifd/proto/directip.sh +endef + +define Package/comgt-ncm/install + $(INSTALL_DIR) $(1)/etc/gcom + $(INSTALL_DATA) ./files/ncm.json $(1)/etc/gcom/ncm.json + $(INSTALL_DATA) ./files/runcommand.gcom $(1)/etc/gcom/runcommand.gcom + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/ncm.sh $(1)/lib/netifd/proto/ncm.sh +endef + +$(eval $(call BuildPackage,comgt)) +$(eval $(call BuildPackage,comgt-directip)) +$(eval $(call BuildPackage,comgt-ncm)) diff --git a/package/network/utils/comgt/files/3g.chat b/package/network/utils/comgt/files/3g.chat new file mode 100644 index 0000000..6656240 --- /dev/null +++ b/package/network/utils/comgt/files/3g.chat @@ -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$DIALNUMBER" +CONNECT ' ' diff --git a/package/network/utils/comgt/files/3g.sh b/package/network/utils/comgt/files/3g.sh new file mode 100644 index 0000000..b0cdae2 --- /dev/null +++ b/package/network/utils/comgt/files/3g.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + NOT_INCLUDED=1 + 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:device" + proto_config_add_string "apn" + proto_config_add_string "service" + proto_config_add_string "pincode" + proto_config_add_string "dialnumber" +} + +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 + json_get_var dialnumber dialnumber + + [ -n "$dat_device" ] && device=$dat_device + [ -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 + } + + if [ -z "$dialnumber" ]; then + dialnumber="*99***1#" + fi + + ;; + esac + + connect="${apn:+USE_APN=$apn }DIALNUMBER=$dialnumber /usr/sbin/chat -t5 -v -E -f $chat" + ppp_generic_setup "$interface" \ + noaccomp \ + nopcomp \ + novj \ + nobsdcomp \ + noauth \ + set EXTENDPREFIX=1 \ + lock \ + crtscts \ + 115200 "$device" + return 0 +} + +proto_3g_teardown() { + proto_kill_command "$interface" +} + +[ -z "NOT_INCLUDED" ] || add_protocol 3g diff --git a/package/network/utils/comgt/files/3g.usb b/package/network/utils/comgt/files/3g.usb new file mode 100644 index 0000000..ac8326b --- /dev/null +++ b/package/network/utils/comgt/files/3g.usb @@ -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 ] || [ "$proto" = ncm ] || 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 + diff --git a/package/network/utils/comgt/files/directip-stop.gcom b/package/network/utils/comgt/files/directip-stop.gcom new file mode 100644 index 0000000..1c14863 --- /dev/null +++ b/package/network/utils/comgt/files/directip-stop.gcom @@ -0,0 +1,16 @@ +opengt +set com 115200n81 +set comecho off +set senddelay 0.05 +waitquiet 1 0.2 + +:start + send "AT!SCACT=0,3^m" + waitfor 5 "OK" + if % = 0 goto hangupok + print "WWAN error. Hangup failed.\r\n" + exit 1 + +:hangupok + print "WWAN connection established.\r\n" + exit 0 diff --git a/package/network/utils/comgt/files/directip.gcom b/package/network/utils/comgt/files/directip.gcom new file mode 100644 index 0000000..9a772a9 --- /dev/null +++ b/package/network/utils/comgt/files/directip.gcom @@ -0,0 +1,55 @@ +opengt +set com 115200n81 +set comecho off +set senddelay 0.05 +waitquiet 1 0.2 + +:start + if $env("USE_AUTH") = "0" goto connect + send "AT$QCPDPP=3," + send $env("USE_AUTH") + send ",\"" + if $env("USE_USER") <> "" send $env("USE_USER") + send "\",\"" + if $env("USE_PASS") <> "" send $env("USE_PASS") + send "\"^m" + waitfor 5 "OK" + if % = 0 goto connect + print "WWAN error. Auth failed.\r\n" + exit 1 + +:connect + send "AT+CFUN=1^m" + send "AT+CGDCONT=3,\"IP\",\"" + send $env("USE_APN") + send "\"^m" + waitfor 5 "OK" + if % = 0 goto connok + print "WWAN error. Connection failed.\r\n" + exit 1 + +:connok + let c=1 +:loop + sleep 2 + send "AT+CGATT?^m" + waitfor 5 "+CGATT: 1" + if % = 0 goto carrierok + if c > 10 goto carriererr + inc c + goto loop + +:carriererr + print "WWAN error. No carrier.\r\n" + exit 1 + +:carrierok + send "AT!SCACT=1,3^m" + waitfor 5 "OK" + if % = 0 goto dialok + print "WWAN error. Dialing failed.\r\n" + exit 1 + +:dialok + print "WWAN connection established.\r\n" + exit 0 diff --git a/package/network/utils/comgt/files/directip.sh b/package/network/utils/comgt/files/directip.sh new file mode 100644 index 0000000..d828052 --- /dev/null +++ b/package/network/utils/comgt/files/directip.sh @@ -0,0 +1,111 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_directip_init_config() { + available=1 + no_device=1 + proto_config_add_string "device:device" + proto_config_add_string "apn" + proto_config_add_string "pincode" + proto_config_add_string "auth" + proto_config_add_string "username" + proto_config_add_string "password" +} + +proto_directip_setup() { + local interface="$1" + local chat devpath devname + + local device apn pincode ifname auth username password + json_get_vars device apn pincode auth username password + + [ -n "$ctl_device" ] && device=$ctl_device + + [ -e "$device" ] || { + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + + devname="$(basename "$device")" + devpath="$(readlink -f /sys/class/tty/$devname/device)" + ifname="$( ls "$devpath"/../../*/net )" + + [ -n "$ifname" ] || { + proto_notify_error "$interface" NO_IFNAME + proto_set_available "$interface" 0 + return 1 + } + + cardinfo=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom) + [ -n $(echo "$cardinfo" | grep -q "Sierra Wireless") ] || { + proto_notify_error "$interface" BAD_DEVICE + proto_block_restart "$interface" + return 1 + } + + 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 + # wait for carrier to avoid firmware stability bugs + gcom -d "$device" -s /etc/gcom/getcarrier.gcom || return 1 + + local auth_type=0 + case $auth in + pap) auth_type=1;; + chap) auth_type=2;; + esac + + USE_APN="$apn" USE_USER="$username" USE_PASS="$password" USE_AUTH="$auth_type" \ + gcom -d "$device" -s /etc/gcom/directip.gcom || { + proto_notify_error "$interface" CONNECT_FAILED + proto_block_restart "$interface" + return 1 + } + + logger -p daemon.info -t "directip[$$]" "Connected, starting DHCP" + proto_init_update "$ifname" 1 + proto_send_update "$interface" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@$interface" + json_add_string proto "dhcp" + ubus call network add_dynamic "$(json_dump)" + + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@$interface" + json_add_string proto "dhcpv6" + json_add_string extendprefix 1 + ubus call network add_dynamic "$(json_dump)" + + return 0 +} + +proto_directip_teardown() { + local interface="$1" + + local device + json_get_vars device + + [ -n "$ctl_device" ] && device=$ctl_device + + gcom -d "$device" -s /etc/gcom/directip-stop.gcom || proto_notify_error "$interface" CONNECT_FAILED + + proto_init_update "*" 0 + proto_send_update "$interface" +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol directip +} diff --git a/package/network/utils/comgt/files/evdo.chat b/package/network/utils/comgt/files/evdo.chat new file mode 100644 index 0000000..de49e41 --- /dev/null +++ b/package/network/utils/comgt/files/evdo.chat @@ -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 '' diff --git a/package/network/utils/comgt/files/getcardinfo.gcom b/package/network/utils/comgt/files/getcardinfo.gcom new file mode 100644 index 0000000..5c69a64 --- /dev/null +++ b/package/network/utils/comgt/files/getcardinfo.gcom @@ -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 diff --git a/package/network/utils/comgt/files/getcarrier.gcom b/package/network/utils/comgt/files/getcarrier.gcom new file mode 100644 index 0000000..1e0216d --- /dev/null +++ b/package/network/utils/comgt/files/getcarrier.gcom @@ -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 diff --git a/package/network/utils/comgt/files/getcnum.gcom b/package/network/utils/comgt/files/getcnum.gcom new file mode 100644 index 0000000..450cf8c --- /dev/null +++ b/package/network/utils/comgt/files/getcnum.gcom @@ -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 diff --git a/package/network/utils/comgt/files/getimsi.gcom b/package/network/utils/comgt/files/getimsi.gcom new file mode 100644 index 0000000..0485456 --- /dev/null +++ b/package/network/utils/comgt/files/getimsi.gcom @@ -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 diff --git a/package/network/utils/comgt/files/getstrength.gcom b/package/network/utils/comgt/files/getstrength.gcom new file mode 100644 index 0000000..2886285 --- /dev/null +++ b/package/network/utils/comgt/files/getstrength.gcom @@ -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 diff --git a/package/network/utils/comgt/files/ncm.json b/package/network/utils/comgt/files/ncm.json new file mode 100644 index 0000000..d1f8699 --- /dev/null +++ b/package/network/utils/comgt/files/ncm.json @@ -0,0 +1,67 @@ +{ + "huawei": { + "initialize": [ + "AT", + "ATZ", + "ATQ0", + "ATV1", + "ATE1", + "ATS0=0", + "AT+CGDCONT=1,\\\"${pdptype}\\\",\\\"${apn}\\\"" + ], + "modes": { + "preferlte": "AT^SYSCFGEX=\\\"030201\\\",3fffffff,2,4,7fffffffffffffff,,", + "preferumts": "AT^SYSCFGEX=\\\"0201\\\",3fffffff,2,4,7fffffffffffffff,,", + "lte": "AT^SYSCFGEX=\\\"03\\\",3fffffff,2,4,7fffffffffffffff,,", + "umts": "AT^SYSCFGEX=\\\"02\\\",3fffffff,2,4,7fffffffffffffff,,", + "gsm": "AT^SYSCFGEX=\\\"01\\\",3fffffff,2,4,7fffffffffffffff,,", + "auto": "AT^SYSCFGEX=\\\"00\\\",3fffffff,2,4,7fffffffffffffff,," + }, + "connect": "AT^NDISDUP=1,1,\\\"${apn}\\\"${username:+,\\\"$username\\\"}${password:+,\\\"$password\\\"}${auth:+,$auth}", + "disconnect": "AT^NDISDUP=1,0" + }, + "samsung": { + "initialize": [ + "AT", + "AT+CGREG=2", + "AT+CFUN=5", + "AT+MODESELECT=3", + "AT+CGDCONT=1,\\\"${pdptype}\\\",\\\"${apn}\\\"" + ], + "modes": { + "umts": "AT+CHANGEALLPATH=1" + }, + "connect": "AT+CGATT=1", + "disconnect": "AT+CGATT=0" + }, + "sierra wireless, incorporated": { + "initialize": [ + "AT+CFUN=1", + "AT+CGDCONT=1,\\\"${pdptype}\\\",\\\"${apn}\\\"", + "AT$QCPDPP=1${auth:+,$auth}${password:+,\\\"$password\\\"}${username:+,\\\"$username\\\"}" + ], + "modes": { + "preferlte": "AT!SELRAT=07", + "preferumts": "AT!SELRAT=05", + "lte": "AT!SELRAT=06", + "umts": "AT!SELRAT=01", + "gsm": "AT!SELRAT=02", + "auto": "AT!SELRAT=00" + }, + "connect": "AT!SCACT=1,1", + "disconnect": "AT!SCACT=0,1" + }, + "sony ericsson": { + "initialize": [ + "AT+CFUN=1", + "AT+CGDCONT=1,\\\"${pdptype}\\\",\\\"${apn}\\\"", + "AT*EIAAUW=1,1,\\\"${username}\\\",\\\"${password}\\\",${auth:-00111}" + ], + "modes": { + "umts": "AT+CFUN=6", + "gsm": "AT+CFUN=5" + }, + "connect": "AT*ENAP=1,1", + "disconnect": "AT*ENAP=0" + } +} diff --git a/package/network/utils/comgt/files/ncm.sh b/package/network/utils/comgt/files/ncm.sh new file mode 100644 index 0000000..571cfaa --- /dev/null +++ b/package/network/utils/comgt/files/ncm.sh @@ -0,0 +1,192 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_ncm_init_config() { + no_device=1 + available=1 + proto_config_add_string "device:device" + proto_config_add_string apn + proto_config_add_string auth + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string delay + proto_config_add_string mode + proto_config_add_string pdptype + proto_config_add_boolean ipv6 +} + +proto_ncm_setup() { + local interface="$1" + + local manufacturer initialize setmode connect ifname devname devpath + + local device apn auth username password pincode delay mode pdptype ipv6 + json_get_vars device apn auth username password pincode delay mode pdptype ipv6 + + if [ "$ipv6" = 0 ]; then + ipv6="" + else + ipv6=1 + fi + + [ -z "$pdptype" ] && { + if [ -n "$ipv6" ]; then + pdptype="IPV4V6" + else + pdptype="IP" + fi + } + + [ -n "$ctl_device" ] && device=$ctl_device + + [ -n "$device" ] || { + echo "No control device specified" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + [ -e "$device" ] || { + echo "Control device not valid" + proto_set_available "$interface" 0 + return 1 + } + [ -n "$apn" ] || { + echo "No APN specified" + proto_notify_error "$interface" NO_APN + return 1 + } + + devname="$(basename "$device")" + case "$devname" in + 'tty'*) + devpath="$(readlink -f /sys/class/tty/$devname/device)" + ifname="$( ls "$devpath"/../../*/net )" + ;; + *) + devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" + ifname="$( ls "$devpath"/net )" + ;; + esac + [ -n "$ifname" ] || { + echo "The interface could not be found." + proto_notify_error "$interface" NO_IFACE + proto_set_available "$interface" 0 + return 1 + } + + [ -n "$delay" ] && sleep "$delay" + + manufacturer=`gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk '/Manufacturer/ { print tolower($2) }'` + [ $? -ne 0 ] && { + echo "Failed to get modem information" + proto_notify_error "$interface" GETINFO_FAILED + return 1 + } + + json_load "$(cat /etc/gcom/ncm.json)" + json_select "$manufacturer" + [ $? -ne 0 ] && { + echo "Unsupported modem" + proto_notify_error "$interface" UNSUPPORTED_MODEM + proto_set_available "$interface" 0 + return 1 + } + json_get_values initialize initialize + for i in $initialize; do + eval COMMAND="$i" gcom -d "$device" -s /etc/gcom/runcommand.gcom || { + echo "Failed to initialize modem" + proto_notify_error "$interface" INITIALIZE_FAILED + return 1 + } + done + + [ -n "$pincode" ] && { + PINCODE="$pincode" gcom -d "$device" -s /etc/gcom/setpin.gcom || { + echo "Unable to verify PIN" + proto_notify_error "$interface" PIN_FAILED + proto_block_restart "$interface" + return 1 + } + } + [ -n "$mode" ] && { + json_select modes + json_get_var setmode "$mode" + COMMAND="$setmode" gcom -d "$device" -s /etc/gcom/runcommand.gcom || { + echo "Failed to set operating mode" + proto_notify_error "$interface" SETMODE_FAILED + return 1 + } + json_select .. + } + + json_get_vars connect + eval COMMAND="$connect" gcom -d "$device" -s /etc/gcom/runcommand.gcom || { + echo "Failed to connect" + proto_notify_error "$interface" CONNECT_FAILED + return 1 + } + + echo "Connected, starting DHCP on $ifname" + + proto_init_update "$ifname" 1 + proto_send_update "$interface" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@$interface" + json_add_string proto "dhcp" + ubus call network add_dynamic "$(json_dump)" + + [ -n "$ipv6" ] && { + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@$interface" + json_add_string proto "dhcpv6" + json_add_string extendprefix 1 + ubus call network add_dynamic "$(json_dump)" + } +} + +proto_ncm_teardown() { + local interface="$1" + + local manufacturer disconnect + + local device + json_get_vars device + + echo "Stopping network" + + manufacturer=`gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk '/Manufacturer/ { print tolower($2) }'` + [ $? -ne 0 ] && { + echo "Failed to get modem information" + proto_notify_error "$interface" GETINFO_FAILED + return 1 + } + + json_load "$(cat /etc/gcom/ncm.json)" + json_select "$manufacturer" || { + echo "Unsupported modem" + proto_notify_error "$interface" UNSUPPORTED_MODEM + return 1 + } + + json_get_vars disconnect + COMMAND="$disconnect" gcom -d "$device" -s /etc/gcom/runcommand.gcom || { + echo "Failed to disconnect" + proto_notify_error "$interface" DISCONNECT_FAILED + return 1 + } + + proto_init_update "*" 0 + proto_send_update "$interface" +} +[ -n "$INCLUDE_ONLY" ] || { + add_protocol ncm +} diff --git a/package/network/utils/comgt/files/runcommand.gcom b/package/network/utils/comgt/files/runcommand.gcom new file mode 100644 index 0000000..e99b6f9 --- /dev/null +++ b/package/network/utils/comgt/files/runcommand.gcom @@ -0,0 +1,31 @@ +# run AT-command from environment +opengt + set com 115200n81 + set senddelay 0.02 + waitquiet 1 0.2 + flash 0.1 + +:start + print "sending -> ",$env("COMMAND"),"\n" + send $env("COMMAND") + send "^m" + + waitfor 15 "OK","ERR","ERROR","COMMAND NOT SUPPORT" + if % = 0 goto continue + if % = 1 goto error + if % = 2 goto error + if % = 3 goto notsupported + + print "Timeout running AT-command\n" + exit 1 + +:error + print "Error running AT-command\n" + exit 1 + +:notsupported + print "AT-command not supported\n" + exit 1 + +:continue + exit 0 diff --git a/package/network/utils/comgt/files/setmode.gcom b/package/network/utils/comgt/files/setmode.gcom new file mode 100644 index 0000000..4ce0b5f --- /dev/null +++ b/package/network/utils/comgt/files/setmode.gcom @@ -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 diff --git a/package/network/utils/comgt/files/setpin.gcom b/package/network/utils/comgt/files/setpin.gcom new file mode 100644 index 0000000..66350fe --- /dev/null +++ b/package/network/utils/comgt/files/setpin.gcom @@ -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 diff --git a/package/network/utils/comgt/patches/001-compile_fix.patch b/package/network/utils/comgt/patches/001-compile_fix.patch new file mode 100644 index 0000000..15de850 --- /dev/null +++ b/package/network/utils/comgt/patches/001-compile_fix.patch @@ -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) diff --git a/package/network/utils/comgt/patches/002-termios.patch b/package/network/utils/comgt/patches/002-termios.patch new file mode 100644 index 0000000..08f22d1 --- /dev/null +++ b/package/network/utils/comgt/patches/002-termios.patch @@ -0,0 +1,105 @@ +--- a/comgt.c ++++ b/comgt.c +@@ -30,7 +30,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <signal.h> +-#include <termio.h> ++#include <termios.h> + #include <fcntl.h> + #include <unistd.h> + #include <string.h> +@@ -81,7 +81,7 @@ char token[MAXTOKEN]; /* For gettoken( + char scriptfile[MAXPATH]; /* Script file name */ + char scriptfilepath[MAXPATH]; /* temp storage for full path */ + BOOL verbose=0; /* Log actions */ +-struct termio cons, stbuf, svbuf; /* termios: svbuf=before, stbuf=while */ ++struct termios cons, stbuf, svbuf; /* termios: svbuf=before, stbuf=while */ + int comfd=0; /* Communication file descriptor. Defaults to stdin. */ + char msg[STRINGL]; /* Massage messages here */ + int preturn,returns[MAXGOSUBS]; +@@ -172,7 +172,7 @@ void dotestkey(void) { + + /* Exit after resetting terminal settings */ + void ext(long xtc) { +- ioctl(1, TCSETA, &cons); ++ ioctl(1, TCSETS, &cons); + exit(xtc); + } + +@@ -920,24 +920,24 @@ BOOL getonoroff(void) { + void setcom(void) { + stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB); + stbuf.c_cflag |= (speed | bits | CREAD | clocal | parity | stopbits ); +- if (ioctl(comfd, TCSETA, &stbuf) < 0) { ++ if (ioctl(comfd, TCSETS, &stbuf) < 0) { + serror("Can't ioctl set device",1); + } + } + + void doset(void) { +- struct termio console; ++ struct termios console; + int a,b; + gettoken(); + if(strcmp(token,"echo")==0) { + a=0; + if(getonoroff()) a=ECHO|ECHOE; +- if(ioctl(0, TCGETA, &console)<0) { ++ if(ioctl(0, TCGETS, &console)<0) { + serror("Can't ioctl FD zero!\n",2); + } + console.c_lflag &= ~(ECHO | ECHOE); + console.c_lflag |= a; +- ioctl(0, TCSETA, &console); ++ ioctl(0, TCSETS, &console); + } + else if(strcmp(token,"senddelay")==0) { + senddelay=10000L*getdvalue(); +@@ -1224,7 +1224,7 @@ void doclose(void) { + if(strcmp(token,"hardcom")==0) { + if(comfd== -1) serror("Com device not open",1); + vmsg("Closing device"); +- if (ioctl(comfd, TCSETA, &svbuf) < 0) { ++ if (ioctl(comfd, TCSETS, &svbuf) < 0) { + sprintf(msg,"Can't ioctl set device %s.\n",device); + serror(msg,1); + } +@@ -1266,12 +1266,12 @@ void opengt(void) { + ext(1); + } + } +- if (ioctl (comfd, TCGETA, &svbuf) < 0) { ++ if (ioctl (comfd, TCGETS, &svbuf) < 0) { + sprintf(msg,"Can't control %s, please try again.\n",device); + serror(msg,1); + } + setenv("COMGTDEVICE",device,1); +- ioctl(comfd, TCGETA, &stbuf); ++ ioctl(comfd, TCGETS, &stbuf); + speed=stbuf.c_cflag & CBAUD; + if (high_speed == 0) strcpy(cspeed,"115200"); + else strcpy(cspeed,"57600"); +@@ -1303,11 +1303,11 @@ void opendevice(void) { + } + else comfd=0; + +- if (ioctl (comfd, TCGETA, &svbuf) < 0) { ++ if (ioctl (comfd, TCGETS, &svbuf) < 0) { + sprintf(msg,"Can't ioctl get device %s.\n",device); + serror(msg,1); + } +- ioctl(comfd, TCGETA, &stbuf); ++ ioctl(comfd, TCGETS, &stbuf); + speed=stbuf.c_cflag & CBAUD; + switch(speed) { + case B0: strcpy(cspeed,"0");break; +@@ -1553,7 +1553,7 @@ int main(int argc,char **argv) { + skip_default=0; + filep=NULL; + scriptspace=4096; +- ioctl(1, TCGETA, &cons); ++ ioctl(1, TCGETS, &cons); + if((script=( char *)malloc(scriptspace))==NULL) { + serror("Could not malloc()",3); + } diff --git a/package/network/utils/comgt/patches/003-no_XCASE.patch b/package/network/utils/comgt/patches/003-no_XCASE.patch new file mode 100644 index 0000000..f2060a8 --- /dev/null +++ b/package/network/utils/comgt/patches/003-no_XCASE.patch @@ -0,0 +1,20 @@ +--- a/comgt.c ++++ b/comgt.c +@@ -1281,7 +1281,7 @@ void opengt(void) { + parity=stbuf.c_cflag & (PARENB | PARODD); + stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR ); + stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET); +- stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL); ++ stbuf.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL); + stbuf.c_lflag &= ~(ECHO | ECHOE); + stbuf.c_cc[VMIN] = 1; + stbuf.c_cc[VTIME] = 0; +@@ -1336,7 +1336,7 @@ void opendevice(void) { + parity=stbuf.c_cflag & (PARENB | PARODD); + stbuf.c_iflag &= ~(IGNCR | ICRNL | IUCLC | INPCK | IXON | IXANY | IGNPAR ); + stbuf.c_oflag &= ~(OPOST | OLCUC | OCRNL | ONLCR | ONLRET); +- stbuf.c_lflag &= ~(ICANON | XCASE | ECHO | ECHOE | ECHONL); ++ stbuf.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHONL); + stbuf.c_lflag &= ~(ECHO | ECHOE); + stbuf.c_cc[VMIN] = 1; + stbuf.c_cc[VTIME] = 0; diff --git a/package/network/utils/comgt/patches/004-check_tty.patch b/package/network/utils/comgt/patches/004-check_tty.patch new file mode 100644 index 0000000..fb1d9af --- /dev/null +++ b/package/network/utils/comgt/patches/004-check_tty.patch @@ -0,0 +1,68 @@ +--- a/comgt.c ++++ b/comgt.c +@@ -91,6 +91,7 @@ unsigned long hstart,hset; + char NullString[]={ "" }; + BOOL lastcharnl=1; /* Indicate that last char printed from getonebyte + was a nl, so no new one is needed */ ++BOOL tty=1; + + + //"open com \"/dev/modem\"\nset com 38400n81\nset senddelay 0.05\nsend \"ATi^m\"\nget 2 \" ^m\" $s\nprint \"Response : \",$s,\"\\n\"\nget 2 \" ^m\" $s\nprint \"Response :\",$s,\"\\n\"\nget 2 \" ^m\" $s\nprint \"Response : \",$s,\"\\n\"\n\n"; +@@ -920,7 +921,7 @@ BOOL getonoroff(void) { + void setcom(void) { + stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB); + stbuf.c_cflag |= (speed | bits | CREAD | clocal | parity | stopbits ); +- if (ioctl(comfd, TCSETS, &stbuf) < 0) { ++ if (tty && ioctl(comfd, TCSETS, &stbuf) < 0) { + serror("Can't ioctl set device",1); + } + } +@@ -1224,7 +1225,7 @@ void doclose(void) { + if(strcmp(token,"hardcom")==0) { + if(comfd== -1) serror("Com device not open",1); + vmsg("Closing device"); +- if (ioctl(comfd, TCSETS, &svbuf) < 0) { ++ if (tty && ioctl(comfd, TCSETS, &svbuf) < 0) { + sprintf(msg,"Can't ioctl set device %s.\n",device); + serror(msg,1); + } +@@ -1266,12 +1267,17 @@ void opengt(void) { + ext(1); + } + } +- if (ioctl (comfd, TCGETS, &svbuf) < 0) { ++ if (isatty (comfd)) ++ tty=1; ++ else ++ tty=0; ++ if (tty && ioctl (comfd, TCGETS, &svbuf) < 0) { + sprintf(msg,"Can't control %s, please try again.\n",device); + serror(msg,1); + } + setenv("COMGTDEVICE",device,1); +- ioctl(comfd, TCGETS, &stbuf); ++ if (tty) ++ ioctl(comfd, TCGETS, &stbuf); + speed=stbuf.c_cflag & CBAUD; + if (high_speed == 0) strcpy(cspeed,"115200"); + else strcpy(cspeed,"57600"); +@@ -1302,12 +1308,16 @@ void opendevice(void) { + } + } + else comfd=0; +- +- if (ioctl (comfd, TCGETS, &svbuf) < 0) { ++ if (isatty (comfd)) ++ tty=1; ++ else ++ tty=0; ++ if (tty && ioctl (comfd, TCGETS, &svbuf) < 0) { + sprintf(msg,"Can't ioctl get device %s.\n",device); + serror(msg,1); + } +- ioctl(comfd, TCGETS, &stbuf); ++ if (tty) ++ ioctl(comfd, TCGETS, &stbuf); + speed=stbuf.c_cflag & CBAUD; + switch(speed) { + case B0: strcpy(cspeed,"0");break; diff --git a/package/network/utils/conntrack-tools/Makefile b/package/network/utils/conntrack-tools/Makefile new file mode 100644 index 0000000..978467b --- /dev/null +++ b/package/network/utils/conntrack-tools/Makefile @@ -0,0 +1,70 @@ +# +# Copyright (C) 2009-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:=conntrack-tools +PKG_VERSION:=1.4.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:= \ + http://www.netfilter.org/projects/conntrack-tools/files \ + ftp://ftp.netfilter.org/pub/conntrack-tools \ + http://mirrors.evolva.ro/netfilter.org/conntrack-tools +PKG_MD5SUM:=b1f9d006e7bf000a77395ff7cd3fac16 + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +TAR_OPTIONS += --exclude='*.rej' + +PKG_BUILD_DEPENDS:=librpc + +include $(INCLUDE_DIR)/package.mk + +define Package/conntrack-tools + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libnetfilter-conntrack +libnetfilter-cttimeout +libnetfilter-cthelper +libnetfilter-queue + SUBMENU:=Firewall + TITLE:=Connection tracking userspace tools + URL:=http://conntrack-tools.netfilter.org/ +endef + +define Package/conntrack-tools/description + The conntrack-tools are a set of free software userspace tools for Linux + that allow system administrators interact with the Connection Tracking + System, which is the module that provides stateful packet inspection for + iptables. The conntrack-tools are the userspace daemon conntrackd and the + command line interface conntrack. +endef + +define Package/conntrack-tools/conffiles +/etc/conntrackd/conntrackd.conf +endef + +TARGET_CFLAGS += -D_GNU_SOURCE=1 + +define Package/conntrack-tools/install + $(INSTALL_DIR) $(1)/etc/conntrackd + $(INSTALL_CONF) \ + $(PKG_BUILD_DIR)/doc/stats/conntrackd.conf \ + $(1)/etc/conntrackd/ + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) \ + $(PKG_INSTALL_DIR)/usr/sbin/conntrack \ + $(PKG_INSTALL_DIR)/usr/sbin/conntrackd \ + $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/conntrackd.init $(1)/etc/init.d/conntrackd +endef + +$(eval $(call BuildPackage,conntrack-tools)) diff --git a/package/network/utils/conntrack-tools/files/conntrackd.init b/package/network/utils/conntrack-tools/files/conntrackd.init new file mode 100644 index 0000000..a51eb88 --- /dev/null +++ b/package/network/utils/conntrack-tools/files/conntrackd.init @@ -0,0 +1,17 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2015 OpenWrt.org + +START=21 +STOP=89 + +USE_PROCD=1 +PROG="/usr/sbin/conntrackd" + +start_service() { + procd_open_instance + + procd_set_param command $PROG -C /etc/conntrackd/conntrackd.conf + procd_set_param respawn + + procd_close_instance +} diff --git a/package/network/utils/conntrack-tools/patches/100-missing_include.patch b/package/network/utils/conntrack-tools/patches/100-missing_include.patch new file mode 100644 index 0000000..96941a8 --- /dev/null +++ b/package/network/utils/conntrack-tools/patches/100-missing_include.patch @@ -0,0 +1,40 @@ +--- a/include/mcast.h ++++ b/include/mcast.h +@@ -4,6 +4,7 @@ + #include <stdint.h> + #include <netinet/in.h> + #include <net/if.h> ++#include <sys/select.h> + + struct mcast_conf { + int ipproto; +--- a/include/tcp.h ++++ b/include/tcp.h +@@ -3,6 +3,7 @@ + + #include <stdint.h> + #include <netinet/in.h> ++#include <sys/select.h> + + struct tcp_conf { + int ipproto; +--- a/include/udp.h ++++ b/include/udp.h +@@ -3,6 +3,7 @@ + + #include <stdint.h> + #include <netinet/in.h> ++#include <sys/select.h> + + struct udp_conf { + int ipproto; +--- a/include/bitops.h ++++ b/include/bitops.h +@@ -2,6 +2,7 @@ + #define _BITOPS_H_ + + #include <stdlib.h> ++#include <sys/types.h> + + static inline void set_bit_u32(int nr, u_int32_t *addr) + { diff --git a/package/network/utils/curl/Config.in b/package/network/utils/curl/Config.in new file mode 100644 index 0000000..11cfa39 --- /dev/null +++ b/package/network/utils/curl/Config.in @@ -0,0 +1,154 @@ +if PACKAGE_libcurl + +comment "SSL support" + +choice + prompt "Selected SSL library" + default LIBCURL_POLARSSL + + config LIBCURL_POLARSSL + bool "PolarSSL" + + config LIBCURL_CYASSL + bool "CyaSSL" + + config LIBCURL_AXTLS + bool "axTLS" + + config LIBCURL_OPENSSL + bool "OpenSSL" + + config LIBCURL_GNUTLS + bool "GNUTLS" + + config LIBCURL_NOSSL + bool "No SSL support" + +endchoice + +comment "Supported protocols" + +config LIBCURL_DICT + bool "DICT protocol" + default n + +config LIBCURL_FILE + bool "FILE protocol" + default y + +config LIBCURL_FTP + bool "FTP / FTPS protocol" + default y + +config LIBCURL_GOPHER + bool "Gopher protocol" + default n + +config LIBCURL_HTTP + bool "HTTP / HTTPS protocol" + default y + +config LIBCURL_COOKIES + bool "Enable Cookies support" + depends on LIBCURL_HTTP + default y + +config LIBCURL_IMAP + bool "IMAP / IMAPS protocol" + default n + +config LIBCURL_LDAP + bool "LDAP protocol" + default n + +config LIBCURL_LDAPS + bool "Enable LDAPS support" + depends on LIBCURL_LDAP && !LIBCURL_NOSSL + default y + +config LIBCURL_POP3 + bool "POP3 / POP3S protocol" + default n + +config LIBCURL_RTSP + bool "RTSP protocol" + depends on LIBCURL_HTTP + default n +config LIBCURL_NO_RTSP + string "RTSP require HTTP protocol" + depends on !LIBCURL_HTTP + default "!" + +config LIBCURL_SSH2 + bool "SCP / SFTP protocol" + default n + +config LIBCURL_SMB + bool "SMB protocol (CIFS)" + depends on LIBCURL_CRYPTO_AUTH && (LIBCURL_GNUTLS || LIBCURL_OPENSSL) + default n +config LIBCURL_NO_SMB + string "SMB require 'cryptographic authentication' and either 'GnuTLS' or 'OpenSSL'" + depends on !LIBCURL_CRYPTO_AUTH || (!LIBCURL_GNUTLS && !LIBCURL_OPENSSL) + default "!" + +config LIBCURL_SMTP + bool "SMTP / SMTPS protocol" + default n + +config LIBCURL_TELNET + bool "TELNET protocol" + default n + +config LIBCURL_TFTP + bool "TFTP protocol" + default n + +comment "Miscellaneous" + +config LIBCURL_PROXY + bool "Enable proxy support" + default y + +config LIBCURL_CRYPTO_AUTH + bool "Enable cryptographic authentication" + default n + +config LIBCURL_TLS_SRP + bool "Enable TLS-SRP authentication" + default n + +config LIBCURL_LIBIDN + bool "Enable IDN support" + default n + +config LIBCURL_THREADED_RESOLVER + bool "Enable threaded DNS resolver" + default n + help + Enable POSIX threaded asynchronous DNS resolution + +config LIBCURL_ZLIB + bool "Enable zlib support" + default n + +config LIBCURL_UNIX_SOCKETS + bool "Enable unix domain socket support" + default n + help + Enable HTTP over unix domain sockets. + To use this with the curl command line, you specify the socket path to the new --unix-domain option. + This feature is actually not limited to HTTP, you can do all the TCP-based protocols + except FTP over the unix domain socket, but it is only HTTP that is regularly used this way. + The reason FTP isn't supported is of course its use of two connections + which would be even weirder to do like this. + +config LIBCURL_LIBCURL_OPTION + bool "Enable generation of C code" + default n + +config LIBCURL_VERBOSE + bool "Enable verbose error strings" + default n + +endif diff --git a/package/network/utils/curl/Makefile b/package/network/utils/curl/Makefile new file mode 100644 index 0000000..82574cd --- /dev/null +++ b/package/network/utils/curl/Makefile @@ -0,0 +1,178 @@ +# +# Copyright (C) 2007-2015 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:=curl +PKG_VERSION:=7.43.0 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://curl.haxx.se/download/ \ + http://www.mirrorspace.org/curl/ \ + ftp://ftp.sunet.se/pub/www/utilities/curl/ \ + ftp://ftp.planetmirror.com/pub/curl/ \ + http://www.mirrormonster.com/curl/download/ \ + http://curl.mirrors.cyberservers.net/download/ +PKG_MD5SUM:=11bddbb452a8b766b932f859aaeeed39 + +PKG_LICENSE:=MIT +PKG_LICENSE_FILES:=COPYING + +PKG_FIXUP:=autoreconf +PKG_BUILD_PARALLEL:=1 + +PKG_CONFIG_DEPENDS:= \ + CONFIG_IPV6 \ + \ + CONFIG_LIBCURL_AXTLS \ + CONFIG_LIBCURL_CYASSL \ + CONFIG_LIBCURL_GNUTLS \ + CONFIG_LIBCURL_OPENSSL \ + CONFIG_LIBCURL_POLARSSL \ + CONFIG_LIBCURL_NOSSL \ + \ + CONFIG_LIBCURL_LIBIDN \ + CONFIG_LIBCURL_SSH2 \ + CONFIG_LIBCURL_ZLIB \ + \ + CONFIG_LIBCURL_DICT \ + CONFIG_LIBCURL_FILE \ + CONFIG_LIBCURL_FTP \ + CONFIG_LIBCURL_GOPHER \ + CONFIG_LIBCURL_HTTP \ + CONFIG_LIBCURL_IMAP \ + CONFIG_LIBCURL_LDAP \ + CONFIG_LIBCURL_LDAPS \ + CONFIG_LIBCURL_POP3 \ + CONFIG_LIBCURL_RTSP \ + CONFIG_LIBCURL_NO_RTSP \ + CONFIG_LIBCURL_SMB \ + CONFIG_LIBCURL_NO_SMB \ + CONFIG_LIBCURL_SMTP \ + CONFIG_LIBCURL_TELNET \ + CONFIG_LIBCURL_TFTP \ + \ + CONFIG_LIBCURL_COOKIES \ + CONFIG_LIBCURL_CRYPTO_AUTH \ + CONFIG_LIBCURL_LIBCURL_OPTION \ + CONFIG_LIBCURL_PROXY \ + CONFIG_LIBCURL_THREADED_RESOLVER \ + CONFIG_LIBCURL_TLS_SRP \ + CONFIG_LIBCURL_UNIX_SOCKETS \ + CONFIG_LIBCURL_VERBOSE + +include $(INCLUDE_DIR)/package.mk + +define Package/curl/Default + SECTION:=net + CATEGORY:=Network + URL:=http://curl.haxx.se/ + MAINTAINER:=Imre Kaloz <kaloz@openwrt.org> +endef + +define Package/curl + $(call Package/curl/Default) + SUBMENU:=File Transfer + DEPENDS:=+libcurl + TITLE:=A client-side URL transfer utility +endef + +define Package/libcurl + $(call Package/curl/Default) + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+LIBCURL_POLARSSL:libpolarssl +LIBCURL_CYASSL:libcyassl +LIBCURL_AXTLS:libaxtls +LIBCURL_OPENSSL:libopenssl +LIBCURL_GNUTLS:libgnutls + DEPENDS += +LIBCURL_ZLIB:zlib +LIBCURL_THREADED_RESOLVER:libpthread +LIBCURL_LDAP:libopenldap +LIBCURL_LIBIDN:libidn +LIBCURL_SSH2:libssh2 + TITLE:=A client-side URL transfer library + MENU:=1 +endef + + +define Package/libcurl/config + source "$(SOURCE)/Config.in" +endef + +TARGET_CFLAGS += $(FPIC) + +CONFIGURE_ARGS += \ + --disable-debug \ + --disable-ares \ + --enable-shared \ + --enable-static \ + --disable-manual \ + --without-ca-bundle \ + --without-nss \ + --without-libmetalink \ + --without-librtmp \ + \ + $(call autoconf_bool,CONFIG_IPV6,ipv6) \ + \ + $(if $(CONFIG_LIBCURL_AXTLS),--with-axtls="$(STAGING_DIR)/usr" --without-ca-path,--without-axtls) \ + $(if $(CONFIG_LIBCURL_CYASSL),--with-cyassl="$(STAGING_DIR)/usr" --without-ca-path,--without-cyassl) \ + $(if $(CONFIG_LIBCURL_GNUTLS),--with-gnutls="$(STAGING_DIR)/usr" --without-ca-path,--without-gnutls) \ + $(if $(CONFIG_LIBCURL_OPENSSL),--with-ssl="$(STAGING_DIR)/usr" --with-ca-path=/etc/ssl/certs,--without-ssl) \ + $(if $(CONFIG_LIBCURL_POLARSSL),--with-polarssl="$(STAGING_DIR)/usr" --with-ca-path=/etc/ssl/certs,--without-polarssl) \ + \ + $(if $(CONFIG_LIBCURL_LIBIDN),--with-libidn="$(STAGING_DIR)/usr",--without-libidn) \ + $(if $(CONFIG_LIBCURL_SSH2),--with-libssh2="$(STAGING_DIR)/usr",--without-libssh2) \ + $(if $(CONFIG_LIBCURL_ZLIB),--with-zlib="$(STAGING_DIR)/usr",--without-zlib) \ + \ + $(call autoconf_bool,CONFIG_LIBCURL_DICT,dict) \ + $(call autoconf_bool,CONFIG_LIBCURL_FILE,file) \ + $(call autoconf_bool,CONFIG_LIBCURL_FTP,ftp) \ + $(call autoconf_bool,CONFIG_LIBCURL_GOPHER,gopher) \ + $(call autoconf_bool,CONFIG_LIBCURL_HTTP,http) \ + $(call autoconf_bool,CONFIG_LIBCURL_IMAP,imap) \ + $(call autoconf_bool,CONFIG_LIBCURL_LDAP,ldap) \ + $(call autoconf_bool,CONFIG_LIBCURL_LDAPS,ldaps) \ + $(call autoconf_bool,CONFIG_LIBCURL_POP3,pop3) \ + $(call autoconf_bool,CONFIG_LIBCURL_RTSP,rtsp) \ + $(call autoconf_bool,CONFIG_LIBCURL_SMB,smb) \ + $(call autoconf_bool,CONFIG_LIBCURL_SMTP,smtp) \ + $(call autoconf_bool,CONFIG_LIBCURL_TELNET,telnet) \ + $(call autoconf_bool,CONFIG_LIBCURL_TFTP,tftp) \ + \ + $(call autoconf_bool,CONFIG_LIBCURL_COOKIES,cookies) \ + $(call autoconf_bool,CONFIG_LIBCURL_CRYPTO_AUTH,crypto-auth) \ + $(call autoconf_bool,CONFIG_LIBCURL_LIBCURL_OPTION,libcurl-option) \ + $(call autoconf_bool,CONFIG_LIBCURL_PROXY,proxy) \ + $(call autoconf_bool,CONFIG_LIBCURL_THREADED_RESOLVER,threaded-resolver) \ + $(call autoconf_bool,CONFIG_LIBCURL_TLS_SRP,tls-srp) \ + $(call autoconf_bool,CONFIG_LIBCURL_UNIX_SOCKETS,unix-sockets) \ + $(call autoconf_bool,CONFIG_LIBCURL_VERBOSE,verbose) \ + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + CC="$(TARGET_CC)" \ + install +endef + +define Build/InstallDev + $(INSTALL_DIR) $(2)/bin $(1)/usr/bin $(1)/usr/include $(1)/usr/lib $(1)/usr/lib/pkgconfig + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/curl-config $(1)/usr/bin/ + $(CP) $(PKG_INSTALL_DIR)/usr/include/curl $(1)/usr/include/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcurl.{a,so*} $(1)/usr/lib/ + $(CP) $(PKG_BUILD_DIR)/libcurl.pc $(1)/usr/lib/pkgconfig/ + $(SED) 's,-L$$$${exec_prefix}/lib,,g' $(1)/usr/bin/curl-config + [ -n "$(TARGET_LDFLAGS)" ] && $(SED) 's#$(TARGET_LDFLAGS)##g' $(1)/usr/lib/pkgconfig/libcurl.pc || true + $(LN) $(STAGING_DIR)/usr/bin/curl-config $(2)/bin/ +endef + +define Package/curl/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/curl $(1)/usr/bin/ +endef + +define Package/libcurl/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libcurl.so.* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,curl)) +$(eval $(call BuildPackage,libcurl)) diff --git a/package/network/utils/curl/patches/200-no_docs_tests.patch b/package/network/utils/curl/patches/200-no_docs_tests.patch new file mode 100644 index 0000000..2845577 --- /dev/null +++ b/package/network/utils/curl/patches/200-no_docs_tests.patch @@ -0,0 +1,22 @@ +--- a/Makefile.am ++++ b/Makefile.am +@@ -129,7 +129,7 @@ CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP) + bin_SCRIPTS = curl-config + + SUBDIRS = lib src include +-DIST_SUBDIRS = $(SUBDIRS) tests packages docs ++DIST_SUBDIRS = $(SUBDIRS) packages + + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = libcurl.pc +--- a/Makefile.in ++++ b/Makefile.in +@@ -577,7 +577,7 @@ CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP) + + bin_SCRIPTS = curl-config + SUBDIRS = lib src include +-DIST_SUBDIRS = $(SUBDIRS) tests packages docs ++DIST_SUBDIRS = $(SUBDIRS) packages + pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = libcurl.pc + LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c \ diff --git a/package/network/utils/curl/patches/300-fix-disable-crypto-auth.patch b/package/network/utils/curl/patches/300-fix-disable-crypto-auth.patch new file mode 100644 index 0000000..1cdb820 --- /dev/null +++ b/package/network/utils/curl/patches/300-fix-disable-crypto-auth.patch @@ -0,0 +1,25 @@ +--- a/lib/curl_ntlm_msgs.c ++++ b/lib/curl_ntlm_msgs.c +@@ -569,7 +569,7 @@ CURLcode Curl_sasl_create_ntlm_type3_mes + else + #endif + +-#if USE_NTRESPONSES && USE_NTLM2SESSION ++#if USE_NTRESPONSES && USE_NTLM2SESSION && !defined(CURL_DISABLE_CRYPTO_AUTH) + /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ + if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { + unsigned char ntbuffer[0x18]; +--- a/lib/vtls/vtls.c ++++ b/lib/vtls/vtls.c +@@ -852,9 +852,9 @@ CURLcode Curl_ssl_md5sum(unsigned char * + unsigned char *md5sum, /* output */ + size_t md5len) + { +-#ifdef curlssl_md5sum ++#if defined(curlssl_md5sum) + curlssl_md5sum(tmp, tmplen, md5sum, md5len); +-#else ++#elif !defined(CURL_DISABLE_CRYPTO_AUTH) + MD5_context *MD5pw; + + (void) md5len; diff --git a/package/network/utils/curl/patches/310-polarssl-disable-runtime-version-check.patch b/package/network/utils/curl/patches/310-polarssl-disable-runtime-version-check.patch new file mode 100644 index 0000000..1b5b63a --- /dev/null +++ b/package/network/utils/curl/patches/310-polarssl-disable-runtime-version-check.patch @@ -0,0 +1,11 @@ +--- a/lib/vtls/polarssl.c ++++ b/lib/vtls/polarssl.c +@@ -592,7 +592,7 @@ void Curl_polarssl_session_free(void *pt + + size_t Curl_polarssl_version(char *buffer, size_t size) + { +- unsigned int version = version_get_number(); ++ unsigned int version = POLARSSL_VERSION_NUMBER; + return snprintf(buffer, size, "%s/%d.%d.%d", + version >= 0x01030A00?"mbedTLS":"PolarSSL", + version>>24, (version>>16)&0xff, (version>>8)&0xff); diff --git a/package/network/utils/dante/Makefile b/package/network/utils/dante/Makefile new file mode 100644 index 0000000..f10dd86 --- /dev/null +++ b/package/network/utils/dante/Makefile @@ -0,0 +1,117 @@ +# +# 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:=dante +PKG_VERSION:=1.2.2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.inet.no/dante/files/ +PKG_MD5SUM:=69b9d6234154d7d6a91fcbd98c68e62a + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=BSD-4-Clause + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +TARGET_CFLAGS += -D_GNU_SOURCE +CONFIGURE_ARGS += \ + --without-upnp \ + --without-pam \ + --disable-libwrap + +CONFIGURE_VARS += \ + CC="$(TARGET_CC) $(TARGET_CFLAGS)" + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr/include + $(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/*.{a,so*,la} $(1)/usr/lib/ +endef + + +define Package/dante/default + TITLE:=Dante SOCKS + URL:=http://www.inet.no/dante/ +endef + +define Package/dante/default/description +Dante is a circuit-level firewall/proxy that can be used to provide convenient +and secure network connectivity, requiring only that the server Dante runs on +has external network connectivity. Dante is used daily by Fortune 100 companies +and large international organizations, either as a standard SOCKS server or as +a "reverse proxy". +endef + +define Package/libsocks + $(call Package/dante/default) + SECTION:=libs + CATEGORY:=Libraries + TITLE+= Library +endef + +define Package/libsocks/description +$(call Package/dante/default/description) +This package provides the shared libsocks library. +endef + +define Package/libsocks/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libsocks.so* $(1)/usr/lib/ +endef + + +define Package/sockd + $(call Package/dante/default) + SUBMENU:=Web Servers/Proxies + SECTION:=net + CATEGORY:=Network + TITLE+= Daemon +endef + +define Package/sockd/description +$(call Package/dante/default/description) +This package provides the Dante sockd daemon. +endef + +define Package/sockd/install + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/sockd $(1)/usr/sbin/ +endef + + +define Package/socksify + $(call Package/dante/default) + SECTION:=net + CATEGORY:=Network + SUBMENU:=Web Servers/Proxies + TITLE+= Client +endef + +define Package/socksify/description +$(call Package/dante/default/description) +This package provides the Dante socksify client. +endef + +define Package/socksify/install + $(INSTALL_DIR) $(1)/usr/bin + $(CP) $(PKG_INSTALL_DIR)/usr/bin/socksify $(1)/usr/bin/ + + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libdsocks.so* $(1)/usr/lib/ +endef + + +$(eval $(call BuildPackage,libsocks)) +$(eval $(call BuildPackage,sockd)) +$(eval $(call BuildPackage,socksify)) diff --git a/package/network/utils/dante/patches/001-automake-compat.patch b/package/network/utils/dante/patches/001-automake-compat.patch new file mode 100644 index 0000000..4349a4b --- /dev/null +++ b/package/network/utils/dante/patches/001-automake-compat.patch @@ -0,0 +1,482 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -16,7 +16,7 @@ echo "Configuring Dante ${version}${pren + + AM_INIT_AUTOMAKE(dante, ${version}${prename}) + AC_CONFIG_SRCDIR(include/common.h) +-AM_CONFIG_HEADER(include/autoconf.h) ++AM_CONFIG_HEADER(autoconfig-is-soo-stupid.h include/autoconf.h) + + AC_DEFINE(BAREFOOTD, 0, [we are Dante]) + +@@ -38,17 +38,6 @@ AC_PROG_CPP + + AM_CONDITIONAL(PRERELEASE, test x$prerelease != x) + +-#known keywords for --enable/disable-foo(=yes/no)? +-LTINTERNAL="dlopen|dlopen_self|dlopen_self_static|fast_install|libtool_lock|win32_dll|shared_with_static_runtimes|shared_with_static_runtimes_CXX|shared_with_static_runtimes_F77" +-KNOWN_KEYWORDS="$LTINTERNAL|shared|static|debug|warnings|diagnostic|profiling|linting|libwrap|preload|serverdl|clientdl|internal|pidfile|drt_fallback" +-for keyword in `set | egrep '^enable_' | sed -e 's/^enable_\(.*\)=.*/\1/'`; do +- echo $keyword | egrep "^(${KNOWN_KEYWORDS})$" > /dev/null +- if test $? -ne 0; then +- AC_MSG_WARN([unknown option '$keyword', ignoring ...]) +- sleep 10; +- fi +-done +- + case $host in + *-*-osf*) + AC_MSG_WARN([OSF support might be removed in the near future.]) +@@ -175,31 +164,6 @@ case $host in + #XXX make sure compiling with compiler options works + esac + +-AC_MSG_CHECKING([for support for -pipe compiler flag]) +-oCFLAGS=$CFLAGS +-CFLAGS="$CFLAGS -pipe" +-AC_TRY_RUN([ +-int main() +-{ +- return 0; +-}], [AC_MSG_RESULT([yes]) +- comp_flags="${comp_flags} -pipe"], +- AC_MSG_RESULT([no])) +-CFLAGS="$oCFLAGS" +- +-AC_MSG_CHECKING([for support for -Wbounded compiler flag]) +-oCFLAGS=$CFLAGS +-CFLAGS="$CFLAGS -Wbounded" +-AC_TRY_RUN([ +-int main() +-{ +- return 0; +-}], [AC_MSG_RESULT([yes]) +- comp_flags="${comp_flags} -Wbounded"], +- [AC_MSG_RESULT([no]) +- AC_DEFINE(__bounded__(a,b,c), , [empty __bounded__ macro])]) +-CFLAGS="$oCFLAGS" +- + AC_MSG_CHECKING([for compilation with debugging]) + AC_ARG_ENABLE(debug, + [ --enable-debug compile with debugging support], +@@ -608,43 +572,6 @@ else + fi], [AC_MSG_RESULT(no) + AC_MSG_WARN([performance in the server might be degraded without support for the SO_SNDLOWAT socket option])]) + +-AC_MSG_CHECKING([whether realloc with a NULL pointer calls malloc]) +-AC_TRY_RUN([ +-#include <stdlib.h> +-#ifndef NULL +-#define NULL (char *)0 +-#endif +- +-int main() +-{ +- /* will assume this test doesn\'t fail because of lack of memory */ +- if (realloc(NULL, 1) == NULL) +- return 1; +- else +- return 0; +-}], [AC_MSG_RESULT(yes)], +- [AC_DEFINE(HAVE_NOMALLOC_REALLOC, 1, [realloc never calls malloc]) +- AC_MSG_RESULT(no)]) +- +-AC_MSG_CHECKING([whether free can be called with NULL]) +-AC_TRY_RUN([ +-#include <stdlib.h> +-#ifndef NULL +-#define NULL (char *)0 +-#endif +- +-int main() +-{ +- /* will assume core dump/seg fault if it doesn\'t work */ +- free(NULL); +- return 0; +-}], [AC_MSG_RESULT(yes)], +- [AC_DEFINE(HAVE_NONULL_FREE, 1, [free does not accept NULL parameter]) +- AC_MSG_RESULT(no)]) +- +-#A good time to save the cache (preload code might fail) +-AC_CACHE_SAVE +- + m4_include(preload.m4) + + #construct SUBDIRS variable +@@ -722,31 +649,8 @@ case $host in + ;; + esac + +-AC_MSG_CHECKING([for CMSG_SPACE in sys/socket.h]) +-AC_TRY_RUN([ +-#include <sys/types.h> +-#include <sys/socket.h> +-int main() +-{ +- int d = CMSG_SPACE(4); +- return 0; +-} +-], [AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_CMSG_SPACE, 1, CMSG_SPACE exists)], +- [AC_MSG_RESULT(no)]) +- +-AC_MSG_CHECKING([for CMSG_LEN in sys/socket.h]) +-AC_TRY_RUN([ +-#include <sys/types.h> +-#include <sys/socket.h> +- +-int main() +-{ +- int d = CMSG_LEN(4); +- return 0; +-}], [AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_CMSG_LEN, 1, [CMSG_LEN exists])], +- [AC_MSG_RESULT(no)]) ++AC_DEFINE(HAVE_CMSG_SPACE, 1, [CMSG_SPACE exists]) ++AC_DEFINE(HAVE_CMSG_LEN, 1, [CMSG_LEN exists]) + + AC_MSG_CHECKING([for sa_len in sockaddr]) + AC_TRY_COMPILE([ +@@ -913,10 +817,6 @@ else + AC_MSG_RESULT([yes]) + fi + +-dnl determine GSSAPI support +-no_gssapi=t +-m4_include(gssapi.m4) +- + dnl compatibility library tests + m4_include(libscompat.m4) + +@@ -978,15 +878,6 @@ global: + fi + AC_SUBST(MAPOPT) + +-#expected select behaviour? +-unset nb_select_err +-L_UNCON_SELECT([], +- [nb_select_err=t]) +- +-if test x"${nb_select_err}" = xt; then +- AC_MSG_WARN([operations on nonblocking sockets might fail on this platform]) +-fi +- + AC_MSG_CHECKING([direct route fallback in client enabled]) + with_drtfallback=t + AC_ARG_ENABLE(drt-fallback, +--- a/acinclude.m4 ++++ b/acinclude.m4 +@@ -180,63 +180,7 @@ selectcheck(s) + [AC_MSG_RESULT(no) + [$2]])]) + +-#can it really be this simple? +-#nope, doesn't handle coff files which also have no underscore +-AC_DEFUN([L_SYMBOL_UNDERSCORE], +-[AC_MSG_CHECKING(for object file type) +-AH_TEMPLATE([HAVE_NO_SYMBOL_UNDERSCORE], [platform symbol type]) +-AC_TRY_RUN([ +-/* look for ELF identification header at the start of argv[0] */ +- +-#include <stdio.h> +-#include <fcntl.h> +-#include <string.h> +- +-/* +- * ELF header, from ELF standard (Portable Formats Specification, +- * Version 1.1). +- */ +-char elfheader[] = { 0x7f, 'E', 'L', 'F' }; +- +-int +-main (argc, argv) +- int argc; +- char *argv[]; +-{ +- int fd; +- int len = sizeof(elfheader); +- char header[len]; +- +- if ((fd = open(argv[0], O_RDONLY, 0)) == -1) { +- perror("open"); +- exit(1); +- } +- if (read(fd, header, len) != len) { +- perror("read"); +- exit(1); +- } +- if (memcmp(header, elfheader, len) == 0) +- exit(0); /* pointy ears */ +- else +- exit(1); +-} +-], [AC_MSG_RESULT(elf) +- AC_DEFINE(HAVE_NO_SYMBOL_UNDERSCORE)], +- [ +- #XXX exceptions for coff platforms, should be detected automatically +- case $host in +- alpha*-dec-osf*) +- AC_DEFINE(HAVE_NO_SYMBOL_UNDERSCORE) +- AC_MSG_RESULT(coff) +- ;; +- *-*-hpux*) #XXX apparently does not use underscore +- AC_DEFINE(HAVE_NO_SYMBOL_UNDERSCORE) +- AC_MSG_RESULT(a.out?) +- ;; +- *) +- AC_MSG_RESULT(a.out) +- ;; +- esac])]) ++AC_DEFUN([L_SYMBOL_UNDERSCORE], [AC_DEFINE(HAVE_NO_SYMBOL_UNDERSCORE, [1], [Automake sucks])]) + + + dnl addproto - generate AC_DEFINE statements +--- a/preload.m4 ++++ b/preload.m4 +@@ -517,91 +517,6 @@ AC_DEFINE_UNQUOTED(LIBRARY_LIBC, "${LIBC + + L_SYMBOL_UNDERSCORE() + +-AC_MSG_CHECKING([for working dlsym]) +-AC_TRY_RUN([ +-#include <dlfcn.h> +-#include <stdio.h> +- +-#include "include/symbols.h" +- +-int main() +-{ +- void *lib; +- void *sym; +- +- if ((lib = dlopen(LIBRARY_CONNECT, DL_LAZY)) == NULL) { +- fprintf(stderr, "dlopen: %s", dlerror()); +- return 1; +- } +- (void)dlerror(); +- if ((sym = dlsym(lib, SYMBOL_CONNECT)) == NULL) { +- fprintf(stderr, "dlsym: %s", dlerror()); +- return 1; +- } +- return 0; +-}], [AC_MSG_RESULT(yes)], +- [AC_MSG_RESULT(no) +- no_preload_client=t +- no_preload_server=t +- no_preload=t]) +- +-AC_MSG_CHECKING([for working RTLD_NEXT]) +-AC_TRY_RUN([ +-#define _GNU_SOURCE +-#include <dlfcn.h> +-#include <stdio.h> +- +-#include "include/symbols.h" +- +-int main() +-{ +- void *sym; +- +- if ((sym = dlsym(RTLD_NEXT, SYMBOL_READ)) == NULL) { +- fprintf(stderr, "dlsym: %s", dlerror()); +- return 1; +- } +- return 0; +-}], [AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_RTLD_NEXT, 1, [have working dlsym RTLD_NEXT])], +- [AC_MSG_RESULT(no) +- AC_DEFINE(HAVE_RTLD_NEXT, 0, [no working dlsym RTLD_NEXT])]) +- +-#solaris might block preloading +-AC_MSG_CHECKING([libc preload blocking]) +-AC_TRY_RUN([ +-#include <stdlib.h> +-#include <string.h> +-#include <unistd.h> +-int +-main(int argc, char *argv[]) +-{ +- char buf[1024]; +- +- strcpy(buf, "lari -V "); +- strcat(buf, argv[0]); +- strcat(buf, " | grep read | grep protected > /dev/null"); +- +- /* +- * return error if 'protected' +- * (ignore errors, not indicative of blocking) */ +- if (system(buf) == 0) +- return 1; +- else +- return 0; +-} +- +-ssize_t +-read(d, buf, nbytes) +- int d; +- void *buf; +- size_t nbytes; +-{ +- return 0; +-} +-], [AC_MSG_RESULT(no)], +- [AC_MSG_RESULT(yes) +- AC_MSG_WARN([this platform blocks preloading of libraries]) +- blocked_preload=t]) ++AC_DEFINE(HAVE_RTLD_NEXT, 1, [have working dlsym RTLD_NEXT]) + + AC_CONFIG_FILES(bin/socksify) +--- a/libscompat.m4 ++++ b/libscompat.m4 +@@ -1,70 +1,6 @@ + dnl libscompat.m4 - tests related to replacement code in libscompat directory + +-AC_MSG_CHECKING([for __attribute__ support]) +-AC_TRY_RUN([ +-#include <stdlib.h> +- +-void errfunc(void) __attribute((noreturn)); +- +-void errfunc(void) +-{ +- exit(0); +-} +- +-int main() +-{ +- errfunc(); +-}], [AC_MSG_RESULT([yes])], +- [AC_MSG_RESULT([no]) +- AC_DEFINE(__attribute__(a), , [empty __attribute__ macro])]) +- +-AC_MSG_CHECKING([for __printf__ attribute support]) +-if test x"$have_suncc" = xt; then +- AC_MSG_RESULT([disabled for sun cc]) +- AC_DEFINE(format(a,b,c), , [empty format attribute macro]) +-else +- AC_TRY_RUN([ +-#include <stdlib.h> +- +-void func(const char *fmt, ...) +- __attribute__((format(__printf__, 1, 2))); +- +-void func(const char *fmt, ...) { +- (void)fmt; +- return; +-} +- +-int main() +-{ +- func("foo"); +- return 0; +-}], [AC_MSG_RESULT([yes])], +- [AC_MSG_RESULT([no]) +- AC_DEFINE(format(a,b,c), , [empty format attribute macro])]) +-fi +- +-AC_MSG_CHECKING([for timer macros]) +-AC_TRY_RUN([ +-#include <sys/time.h> +- +-int main() +-{ +- struct timeval tv, tv2, tv3; +- +- tv.tv_sec = 0; +- tv.tv_usec = 0; +- tv2.tv_sec = 0; +- tv2.tv_usec = 0; +- tv3.tv_sec = 0; +- tv3.tv_usec = 0; +- +- timeradd(&tv, &tv2, &tv3); +- timersub(&tv3, &tv2, &tv); +- +- return 0; }], +-[AC_MSG_RESULT(yes) +- AC_DEFINE(HAVE_TIMER_MACROS, 1, [timeradd(), timersub etc. exist in sys/time.h])], +-[AC_MSG_RESULT(no)]) ++AC_DEFINE(HAVE_TIMER_MACROS, 1, [timeradd(), timersub etc. exist in sys/time.h]) + + AC_CHECK_FUNCS(daemon difftime getifaddrs freeifaddrs hstrerror inet_aton) + AC_CHECK_FUNCS(inet_pton issetugid memmove seteuid setegid) +@@ -72,53 +8,7 @@ AC_CHECK_FUNCS(setproctitle sockatmark s + AC_CHECK_FUNCS(bzero) + #inet_ntoa - only checked for incorrect behavior + +-#try to detect gcc bug (irix 64 problem, affects among others inet_ntoa) +-AC_MSG_CHECKING([for incorrect inet_ntoa behaviour]) +-AC_TRY_RUN([ +-#include <sys/types.h> +-#include <netinet/in.h> +-#include <arpa/inet.h> +-#include <sys/socket.h> +-int main(void) +-{ +- struct sockaddr_in addr; +- char *a, *b = "195.195.195.195"; +- addr.sin_addr.s_addr = inet_addr(b); +- a = inet_ntoa(addr.sin_addr); +- if (strcmp(a, b) == 0) +- return 1; +- else +- return 0; +-} +-], [AC_DEFINE(HAVE_BROKEN_INET_NTOA, 1, [platform bug]) +- AC_MSG_RESULT(yes) +- ac_cv_func_inet_ntoa=no], +- AC_MSG_RESULT(no)) +- +-if test x${ac_cv_func_sockatmark} = xyes; then +- AC_MSG_CHECKING([for working sockatmark]) +- AC_TRY_RUN([ +-#include <sys/types.h> +-#include <sys/socket.h> +- +-int +-main() +-{ +- int s; +- int r; +- +- if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) +- return 1; +- if ((r = sockatmark(s)) == -1) +- return 1; +- if (r == 0) +- return 0; +- else +- return 1; /* would likely indicate an error */ +-}], [AC_MSG_RESULT(yes)], +- [AC_MSG_RESULT(no) +- ac_cv_func_sockatmark=no]) +-fi ++ac_cv_func_sockatmark=no + + #only compile files that are needed + unset LIBSCSRC +@@ -139,24 +29,3 @@ AC_SUBST([LIBSCSRC]) + if test x${ac_cv_func_bzero} = xno; then + AC_DEFINE(bzero(b, len), memset((b), 0, (len)), [bzero replacement]) + fi +- +-#causes problems with packaging, allow test to be turned off +-AC_ARG_WITH(glibc-secure, +-[ --without-glibc-secure disable libc_enable_secure check @<:@default=detect@:>@], +-[GLIBCSEC=$withval]) +- +-if test "${GLIBCSEC}" != no; then +- AC_MSG_CHECKING([for __libc_enable_secure]) +- AC_TRY_RUN([ +-extern int __libc_enable_secure; +- +-int main() +-{ +- if (__libc_enable_secure == 0) +- return 0; +- +- return 1; +-}],[AC_MSG_RESULT([yes]) +- AC_DEFINE(HAVE_LIBC_ENABLE_SECURE, 1, [linux version of issetugid()])], +- AC_MSG_RESULT([no])) +-fi diff --git a/package/network/utils/dante/patches/100-do-not-use-defdname.patch b/package/network/utils/dante/patches/100-do-not-use-defdname.patch new file mode 100644 index 0000000..37b91a9 --- /dev/null +++ b/package/network/utils/dante/patches/100-do-not-use-defdname.patch @@ -0,0 +1,42 @@ +--- a/lib/addressmatch.c ++++ b/lib/addressmatch.c +@@ -399,18 +399,6 @@ addrmatch(rule, address, protocol, alias + if (hostareeq(rule->addr.domain, hostent->h_name) + || hostisinlist(rule->addr.domain, (const char **)hostent->h_aliases)) + matched = 1; +-#if !HAVE_NO_RESOLVESTUFF +- else if (strchr(hostent->h_name, '.') == NULL) { +- /* if hostname we got is non-qualified, try to qualify it. */ +- char fqdn[MAXHOSTNAMELEN]; +- +- snprintf(fqdn, sizeof(fqdn), "%s.%s", +- hostent->h_name, _res.defdname); +- +- if (hostareeq(rule->addr.domain, fqdn)) +- matched = 1; +- } +-#endif /* !HAVE_NO_RESOLVESTUFF */ + } + + if (!matched && alias) { +@@ -465,20 +453,6 @@ addrmatch(rule, address, protocol, alias + matched = 1; + break; + } +-#if !HAVE_NO_RESOLVESTUFF +- else if (strchr(ip->h_name, '.') == NULL) { +- /* if hostname we got is non-qualified, try to qualify it. */ +- char fqdn[MAXHOSTNAMELEN]; +- +- snprintf(fqdn, sizeof(fqdn), "%s.%s", +- ip->h_name, _res.defdname); +- +- if (hostareeq(rule->addr.domain, fqdn)) { +- matched = 1; +- break; +- } +- } +-#endif /* !HAVE_NO_RESOLVESTUFF */ + } + + hostentfree(host); diff --git a/package/network/utils/dante/patches/200-fix-RTLD_NEXT.patch b/package/network/utils/dante/patches/200-fix-RTLD_NEXT.patch new file mode 100644 index 0000000..7281ba6 --- /dev/null +++ b/package/network/utils/dante/patches/200-fix-RTLD_NEXT.patch @@ -0,0 +1,36 @@ +--- a/lib/address.c ++++ b/lib/address.c +@@ -45,11 +45,12 @@ + + #include "interposition.h" + +-#ifndef __USE_GNU +-#define __USE_GNU /* XXX for RTLD_NEXT on Linux */ +-#endif /* !__USE_GNU */ + #include <dlfcn.h> + ++#ifndef RTLD_NEXT ++#define RTLD_NEXT ((void *) -1l) ++#endif ++ + static const char rcsid[] = + "$Id: address.c,v 1.177.2.2 2010/05/24 16:38:36 karls Exp $"; + +--- a/dlib/interposition.c ++++ b/dlib/interposition.c +@@ -66,11 +66,12 @@ sendto(HAVE_PROT_SENDTO_1, HAVE_PROT_SEN + HAVE_PROT_SENDTO_4, HAVE_PROT_SENDTO_5, HAVE_PROT_SENDTO_6); + #endif + +-#ifndef __USE_GNU +-#define __USE_GNU /* XXX for RTLD_NEXT on Linux */ +-#endif /* !__USE_GNU */ + #include <dlfcn.h> + ++#ifndef RTLD_NEXT ++#define RTLD_NEXT ((void *) -1l) ++#endif ++ + #undef accept + #undef bind + #undef bindresvport diff --git a/package/network/utils/ebtables/Makefile b/package/network/utils/ebtables/Makefile new file mode 100644 index 0000000..30bf426 --- /dev/null +++ b/package/network/utils/ebtables/Makefile @@ -0,0 +1,72 @@ +# +# Copyright (C) 2006-2015 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:=4 + +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) +PKG_LICENSE:=GPL-2.0 + +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)) diff --git a/package/network/utils/ebtables/patches/100-musl_fix.patch b/package/network/utils/ebtables/patches/100-musl_fix.patch new file mode 100644 index 0000000..84aeb39 --- /dev/null +++ b/package/network/utils/ebtables/patches/100-musl_fix.patch @@ -0,0 +1,180 @@ +--- a/extensions/ebt_among.c ++++ b/extensions/ebt_among.c +@@ -13,7 +13,6 @@ + #include <ctype.h> + #include <unistd.h> + #include "../include/ebtables_u.h" +-#include <netinet/ether.h> + #include "../include/ethernetdb.h" + #include <linux/if_ether.h> + #include <linux/netfilter_bridge/ebt_among.h> +--- a/extensions/ebt_arpreply.c ++++ b/extensions/ebt_arpreply.c +@@ -12,7 +12,6 @@ + #include <string.h> + #include <getopt.h> + #include "../include/ebtables_u.h" +-#include <netinet/ether.h> + #include <linux/netfilter_bridge/ebt_arpreply.h> + + static int mac_supplied; +--- a/extensions/ebt_nat.c ++++ b/extensions/ebt_nat.c +@@ -11,7 +11,6 @@ + #include <string.h> + #include <getopt.h> + #include "../include/ebtables_u.h" +-#include <netinet/ether.h> + #include <linux/netfilter_bridge/ebt_nat.h> + + static int to_source_supplied, to_dest_supplied; +--- a/useful_functions.c ++++ b/useful_functions.c +@@ -25,7 +25,6 @@ + #include "include/ebtables_u.h" + #include "include/ethernetdb.h" + #include <stdio.h> +-#include <netinet/ether.h> + #include <string.h> + #include <stdlib.h> + #include <getopt.h> +--- a/include/ebtables_u.h ++++ b/include/ebtables_u.h +@@ -23,6 +23,8 @@ + + #ifndef EBTABLES_U_H + #define EBTABLES_U_H ++#include <sys/types.h> ++#include <netinet/ether.h> + #include <netinet/in.h> + #include <linux/netfilter_bridge/ebtables.h> + #include <linux/netfilter/x_tables.h> +--- a/include/linux/if_ether.h ++++ /dev/null +@@ -1,126 +0,0 @@ +-/* +- * INET An implementation of the TCP/IP protocol suite for the LINUX +- * operating system. INET is implemented using the BSD Socket +- * interface as the means of communication with the user level. +- * +- * Global definitions for the Ethernet IEEE 802.3 interface. +- * +- * Version: @(#)if_ether.h 1.0.1a 02/08/94 +- * +- * Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> +- * Donald Becker, <becker@super.org> +- * Alan Cox, <alan@lxorguk.ukuu.org.uk> +- * Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk> +- * +- * 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. +- */ +- +-#ifndef _LINUX_IF_ETHER_H +-#define _LINUX_IF_ETHER_H +- +-#include <linux/types.h> +- +-/* +- * IEEE 802.3 Ethernet magic constants. The frame sizes omit the preamble +- * and FCS/CRC (frame check sequence). +- */ +- +-#define ETH_ALEN 6 /* Octets in one ethernet addr */ +-#define ETH_HLEN 14 /* Total octets in header. */ +-#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ +-#define ETH_DATA_LEN 1500 /* Max. octets in payload */ +-#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */ +-#define ETH_FCS_LEN 4 /* Octets in the FCS */ +- +-/* +- * These are the defined Ethernet Protocol ID's. +- */ +- +-#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ +-#define ETH_P_PUP 0x0200 /* Xerox PUP packet */ +-#define ETH_P_PUPAT 0x0201 /* Xerox PUP Addr Trans packet */ +-#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +-#define ETH_P_X25 0x0805 /* CCITT X.25 */ +-#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +-#define ETH_P_BPQ 0x08FF /* G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] */ +-#define ETH_P_IEEEPUP 0x0a00 /* Xerox IEEE802.3 PUP packet */ +-#define ETH_P_IEEEPUPAT 0x0a01 /* Xerox IEEE802.3 PUP Addr Trans packet */ +-#define ETH_P_DEC 0x6000 /* DEC Assigned proto */ +-#define ETH_P_DNA_DL 0x6001 /* DEC DNA Dump/Load */ +-#define ETH_P_DNA_RC 0x6002 /* DEC DNA Remote Console */ +-#define ETH_P_DNA_RT 0x6003 /* DEC DNA Routing */ +-#define ETH_P_LAT 0x6004 /* DEC LAT */ +-#define ETH_P_DIAG 0x6005 /* DEC Diagnostics */ +-#define ETH_P_CUST 0x6006 /* DEC Customer use */ +-#define ETH_P_SCA 0x6007 /* DEC Systems Comms Arch */ +-#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ +-#define ETH_P_RARP 0x8035 /* Reverse Addr Res packet */ +-#define ETH_P_ATALK 0x809B /* Appletalk DDP */ +-#define ETH_P_AARP 0x80F3 /* Appletalk AARP */ +-#define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ +-#define ETH_P_IPX 0x8137 /* IPX over DIX */ +-#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +-#define ETH_P_PAUSE 0x8808 /* IEEE Pause frames. See 802.3 31B */ +-#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ +-#define ETH_P_WCCP 0x883E /* Web-cache coordination protocol +- * defined in draft-wilson-wrec-wccp-v2-00.txt */ +-#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +-#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +-#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */ +-#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */ +-#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */ +-#define ETH_P_LINK_CTL 0x886c /* HPNA, wlan link local tunnel */ +-#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport +- * over Ethernet +- */ +-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +-#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +-#define ETH_P_TIPC 0x88CA /* TIPC */ +-#define ETH_P_1588 0x88F7 /* IEEE 1588 Timesync */ +-#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */ +-#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ +-#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ +- +-/* +- * Non DIX types. Won't clash for 1500 types. +- */ +- +-#define ETH_P_802_3 0x0001 /* Dummy type for 802.3 frames */ +-#define ETH_P_AX25 0x0002 /* Dummy protocol id for AX.25 */ +-#define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ +-#define ETH_P_802_2 0x0004 /* 802.2 frames */ +-#define ETH_P_SNAP 0x0005 /* Internal only */ +-#define ETH_P_DDCMP 0x0006 /* DEC DDCMP: Internal only */ +-#define ETH_P_WAN_PPP 0x0007 /* Dummy type for WAN PPP frames*/ +-#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */ +-#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ +-#define ETH_P_CAN 0x000C /* Controller Area Network */ +-#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ +-#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ +-#define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */ +-#define ETH_P_CONTROL 0x0016 /* Card specific control frames */ +-#define ETH_P_IRDA 0x0017 /* Linux-IrDA */ +-#define ETH_P_ECONET 0x0018 /* Acorn Econet */ +-#define ETH_P_HDLC 0x0019 /* HDLC frames */ +-#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ +-#define ETH_P_DSA 0x001B /* Distributed Switch Arch. */ +-#define ETH_P_TRAILER 0x001C /* Trailer switch tagging */ +-#define ETH_P_PHONET 0x00F5 /* Nokia Phonet frames */ +-#define ETH_P_IEEE802154 0x00F6 /* IEEE802.15.4 frame */ +-#define ETH_P_CAIF 0x00F7 /* ST-Ericsson CAIF protocol */ +- +-/* +- * This is an Ethernet frame header. +- */ +- +-struct ethhdr { +- unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ +- unsigned char h_source[ETH_ALEN]; /* source ether addr */ +- __be16 h_proto; /* packet type ID field */ +-} __attribute__((packed)); +- +- +-#endif /* _LINUX_IF_ETHER_H */ diff --git a/package/network/utils/iftop/Makefile b/package/network/utils/iftop/Makefile new file mode 100644 index 0000000..037fb15 --- /dev/null +++ b/package/network/utils/iftop/Makefile @@ -0,0 +1,43 @@ +# +# 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 + +PKG_NAME:=iftop +PKG_VERSION:=1.0pre2 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.ex-parrot.com/~pdw/iftop/download +PKG_MD5SUM:=fef521a49ec0122458d02c64212af3c5 + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/iftop + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libpcap +libncurses +libpthread + TITLE:=display bandwith usage on an interface + URL:=http://www.ex-parrot.com/~pdw/iftop/ +endef + +define Package/iftop/description + iftop does for network usage what top(1) does for CPU usage. It + listens to network traffic on a named interface and displays a + table of current bandwidth usage by pairs of hosts. Handy for + answering the question 'why is our ADSL link so slow?'. +endef + +define Package/iftop/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/iftop $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,iftop)) diff --git a/package/network/utils/iftop/patches/0001-force-ncurses.patch b/package/network/utils/iftop/patches/0001-force-ncurses.patch new file mode 100644 index 0000000..bf23fb4 --- /dev/null +++ b/package/network/utils/iftop/patches/0001-force-ncurses.patch @@ -0,0 +1,12 @@ +diff -ru iftop-1.0pre2-old/configure iftop-1.0pre2/configure +--- iftop-1.0pre2-old/configure 2011-10-04 13:30:30.000000000 -0700 ++++ iftop-1.0pre2/configure 2012-09-09 22:26:05.000000000 -0700 +@@ -7568,7 +7568,7 @@ + { $as_echo "$as_me:$LINENO: checking for a curses library containing mvchgat" >&5 + $as_echo_n "checking for a curses library containing mvchgat... " >&6; } + oldLIBS=$LIBS +-for curseslib in ncursesw curses ncurses ; do ++for curseslib in ncurses ; do + LIBS="$oldLIBS -l$curseslib" + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ diff --git a/package/network/utils/iperf/Makefile b/package/network/utils/iperf/Makefile new file mode 100644 index 0000000..414342d --- /dev/null +++ b/package/network/utils/iperf/Makefile @@ -0,0 +1,88 @@ +# +# Copyright (C) 2007-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:=iperf +PKG_VERSION:=2.0.5 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/$(PKG_NAME) +PKG_MD5SUM:=44b5536b67719f4250faed632a3cd016 + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> +PKG_LICENSE:=BSD-3-Clause + +PKG_BUILD_PARALLEL:=1 +PKG_CHECK_FORMAT_SECURITY:=0 + +include $(INCLUDE_DIR)/uclibc++.mk +include $(INCLUDE_DIR)/package.mk + +define Package/iperf/Default + SECTION:=net + CATEGORY:=Network + DEPENDS:= $(CXX_DEPENDS) + TITLE:=Internet Protocol bandwidth measuring tool + URL:=http://sourceforge.net/projects/iperf/ +endef + +define Package/iperf/Default/description + Iperf is a modern alternative for measuring TCP and UDP bandwidth + performance, allowing the tuning of various parameters and + characteristics. +endef + +define Package/iperf +$(call Package/iperf/Default) + TITLE+= (with single thread support) + VARIANT:=single +endef + +define Package/iperf/description +$(call Package/iperf/Default/description) + This package is built with single thread support. +endef + +define Package/iperf-mt +$(call Package/iperf/Default) + DEPENDS+= +libpthread + TITLE+= (with multithread support) + VARIANT:=mt +endef + +define Package/iperf-mt/description +$(call Package/iperf/Default/description) + This package is built with multithread support. +endef + +CONFIGURE_ARGS += --disable-multicast +CONFIGURE_VARS += ac_cv_func_malloc_0_nonnull=yes + +ifeq ($(BUILD_VARIANT),single) + CONFIGURE_ARGS += --disable-threads +else + CONFIGURE_ARGS += --enable-threads=posix + CONFIGURE_VARS += ac_cv_func_pthread_cancel=no +endif + +CONFIGURE_VARS += CXXFLAGS="$$$$CXXFLAGS -fno-rtti" + +ifeq ($(BUILD_VARIANT),mt) + CONFIGURE_VARS += LIBS="-lpthread" +endif + +define Package/iperf/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/iperf $(1)/usr/bin/iperf +endef +Package/iperf-mt/install = $(Package/iperf/install) + +$(eval $(call BuildPackage,iperf)) +$(eval $(call BuildPackage,iperf-mt)) diff --git a/package/network/utils/iperf/patches/001-set-report-next-time-in-single-thread-mode.patch b/package/network/utils/iperf/patches/001-set-report-next-time-in-single-thread-mode.patch new file mode 100644 index 0000000..c61c754 --- /dev/null +++ b/package/network/utils/iperf/patches/001-set-report-next-time-in-single-thread-mode.patch @@ -0,0 +1,14 @@ +--- a/src/Reporter.c ++++ b/src/Reporter.c +@@ -308,6 +308,11 @@ ReportHeader* InitReport( thread_Setting + #else + // set start time + gettimeofday( &(reporthdr->report.startTime), NULL ); ++ ++ // set next time ++ reporthdr->report.nextTime = reporthdr->report.startTime; ++ TimeAdd( reporthdr->report.nextTime, reporthdr->report.intervalTime ); ++ + /* + * Process the report in this thread + */ diff --git a/package/network/utils/iperf3/Makefile b/package/network/utils/iperf3/Makefile new file mode 100644 index 0000000..da9c004 --- /dev/null +++ b/package/network/utils/iperf3/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2007-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:=iperf +PKG_VERSION:=3.0.11 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://downloads.es.net/pub/iperf +PKG_MD5SUM:=a3b2bed7961ba184566df3c3d47f96a6 + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> +PKG_LICENSE:=BSD-3-Clause + +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/iperf3 + SECTION:=net + CATEGORY:=Network + TITLE:=Internet Protocol bandwidth measuring tool + URL:=https://github.com/esnet/iperf +endef + +TARGET_CFLAGS += -D_GNU_SOURCE +CONFIGURE_ARGS += --disable-shared + +MAKE_FLAGS += noinst_PROGRAMS= + +define Package/iperf3/description + Iperf is a modern alternative for measuring TCP and UDP bandwidth + performance, allowing the tuning of various parameters and + characteristics. +endef + +define Package/iperf3/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/iperf3 $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,iperf3)) diff --git a/package/network/utils/iproute2/Makefile b/package/network/utils/iproute2/Makefile new file mode 100644 index 0000000..e5015db --- /dev/null +++ b/package/network/utils/iproute2/Makefile @@ -0,0 +1,140 @@ +# +# Copyright (C) 2006-2015 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:=4.0.0 +PKG_RELEASE:=3 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=http://kernel.org/pub/linux/utils/net/iproute2/ +PKG_MD5SUM:=3adc263ade4ee76c35032e8f50b54108 +PKG_BUILD_PARALLEL:=1 +PKG_LICENSE:=GPL-2.0 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + +define Package/iproute2/Default + TITLE:=Routing control utility ($(2)) + SECTION:=net + CATEGORY:=Network + URL:=http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 + SUBMENU:=Routing and Redirection + MAINTAINER:=Russell Senior <russell@personaltelco.net> + DEPENDS:= +libnl-tiny + VARIANT:=$(1) +endef + +define Package/ip +$(call Package/iproute2/Default,tiny,Minimal) + CONFLICTS:=ip-full +endef + +Package/ip-full=$(call Package/iproute2/Default,full,Full) + +define Package/ip-$(BUILD_VARIANT)/conffiles +$(Package/ip/conffiles) +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/ip-bridge +$(call Package/iproute2/Default) + TITLE:=Bridge configuration utility from iproute2 +endef + +define Package/ss +$(call Package/iproute2/Default) + TITLE:=Socket statistics utility +endef + +ifeq ($(BUILD_VARIANT),tiny) + IP_CONFIG_TINY:=y +endif + +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 + +TARGET_CFLAGS += -DHAVE_SETNS +TARGET_CFLAGS += -ffunction-sections -fdata-sections + +MAKE_FLAGS += \ + EXTRA_CCOPTS="$(TARGET_CFLAGS) -I../include -I$(STAGING_DIR)/usr/include/libnl-tiny" \ + KERNEL_INCLUDE="$(LINUX_DIR)/include" \ + SHARED_LIBS="" \ + LDFLAGS="$(TARGET_LDFLAGS) -Wl,--gc-sections" \ + IP_CONFIG_TINY=$(IP_CONFIG_TINY) \ + 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/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/bin/ +endef + +define Package/ip-full/install + $(INSTALL_DIR) $(1)/usr/sbin + $(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/15-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/ip-bridge/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/bridge/bridge $(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,ip-full)) +$(eval $(call BuildPackage,tc)) +$(eval $(call BuildPackage,genl)) +$(eval $(call BuildPackage,ip-bridge)) +$(eval $(call BuildPackage,ss)) diff --git a/package/network/utils/iproute2/files/15-teql b/package/network/utils/iproute2/files/15-teql new file mode 100644 index 0000000..a0c0e50 --- /dev/null +++ b/package/network/utils/iproute2/files/15-teql @@ -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 diff --git a/package/network/utils/iproute2/patches/001-config.patch b/package/network/utils/iproute2/patches/001-config.patch new file mode 100644 index 0000000..ece8652 --- /dev/null +++ b/package/network/utils/iproute2/patches/001-config.patch @@ -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 diff --git a/package/network/utils/iproute2/patches/004-darwin_fixes.patch b/package/network/utils/iproute2/patches/004-darwin_fixes.patch new file mode 100644 index 0000000..e1a5e97 --- /dev/null +++ b/package/network/utils/iproute2/patches/004-darwin_fixes.patch @@ -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 diff --git a/package/network/utils/iproute2/patches/006-no_sctp.patch b/package/network/utils/iproute2/patches/006-no_sctp.patch new file mode 100644 index 0000000..4aa9884 --- /dev/null +++ b/package/network/utils/iproute2/patches/006-no_sctp.patch @@ -0,0 +1,18 @@ +--- a/ip/ipxfrm.c ++++ b/ip/ipxfrm.c +@@ -467,7 +467,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) +@@ -1337,7 +1336,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: diff --git a/package/network/utils/iproute2/patches/007-no_arpd.patch b/package/network/utils/iproute2/patches/007-no_arpd.patch new file mode 100644 index 0000000..6a7e24e --- /dev/null +++ b/package/network/utils/iproute2/patches/007-no_arpd.patch @@ -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 + diff --git a/package/network/utils/iproute2/patches/008-no_netem.patch b/package/network/utils/iproute2/patches/008-no_netem.patch new file mode 100644 index 0000000..165ce0c --- /dev/null +++ b/package/network/utils/iproute2/patches/008-no_netem.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -36,7 +36,7 @@ WFLAGS += -Wmissing-declarations -Wold-s + CFLAGS = $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) + YACCFLAGS = -d -t -v + +-SUBDIRS=lib ip tc bridge misc netem genl man ++SUBDIRS=lib ip tc bridge misc genl man + + LIBNETLINK=../lib/libnetlink.a ../lib/libutil.a + LDLIBS += $(LIBNETLINK) diff --git a/package/network/utils/iproute2/patches/010-type_fixes.patch b/package/network/utils/iproute2/patches/010-type_fixes.patch new file mode 100644 index 0000000..e0055fc --- /dev/null +++ b/package/network/utils/iproute2/patches/010-type_fixes.patch @@ -0,0 +1,396 @@ +--- a/include/iptables_common.h ++++ b/include/iptables_common.h +@@ -2,6 +2,8 @@ + #define _IPTABLES_COMMON_H + /* Shared definitions between ipv4 and ipv6. */ + ++#include <stdint.h> ++ + enum exittype { + OTHER_PROBLEM = 1, + PARAMETER_PROBLEM, +@@ -43,9 +45,9 @@ extern char *lib_dir; + extern void init_extensions(void); + #endif + +-#define __be32 u_int32_t +-#define __le32 u_int32_t +-#define __be16 u_int16_t +-#define __le16 u_int16_t ++#define __be32 uint32_t ++#define __le32 uint32_t ++#define __be16 uint16_t ++#define __le16 uint16_t + + #endif /*_IPTABLES_COMMON_H*/ +--- a/include/netinet/tcp.h ++++ /dev/null +@@ -1,231 +0,0 @@ +-/* +- * Copyright (c) 1982, 1986, 1993 +- * The Regents of the University of California. All rights reserved. +- * +- * 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. +- * 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. +- * 4. Neither the name of the University nor the names of its contributors +- * may be used to endorse or promote products derived from this software +- * without specific prior written permission. +- * +- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. +- * +- * @(#)tcp.h 8.1 (Berkeley) 6/10/93 +- */ +- +-#ifndef _NETINET_TCP_H +-#define _NETINET_TCP_H 1 +- +-#include <features.h> +- +-/* +- * User-settable options (used with setsockopt). +- */ +-#define TCP_NODELAY 1 /* Don't delay send to coalesce packets */ +-#define TCP_MAXSEG 2 /* Set maximum segment size */ +-#define TCP_CORK 3 /* Control sending of partial frames */ +-#define TCP_KEEPIDLE 4 /* Start keeplives after this period */ +-#define TCP_KEEPINTVL 5 /* Interval between keepalives */ +-#define TCP_KEEPCNT 6 /* Number of keepalives before death */ +-#define TCP_SYNCNT 7 /* Number of SYN retransmits */ +-#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ +-#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */ +-#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */ +-#define TCP_INFO 11 /* Information about this connection. */ +-#define TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */ +-#define TCP_CONGESTION 13 /* Congestion control algorithm. */ +- +-#ifdef __USE_MISC +-# include <sys/types.h> +- +-# ifdef __FAVOR_BSD +-typedef u_int32_t tcp_seq; +-/* +- * TCP header. +- * Per RFC 793, September, 1981. +- */ +-struct tcphdr +- { +- u_int16_t th_sport; /* source port */ +- u_int16_t th_dport; /* destination port */ +- tcp_seq th_seq; /* sequence number */ +- tcp_seq th_ack; /* acknowledgement number */ +-# if __BYTE_ORDER == __LITTLE_ENDIAN +- u_int8_t th_x2:4; /* (unused) */ +- u_int8_t th_off:4; /* data offset */ +-# endif +-# if __BYTE_ORDER == __BIG_ENDIAN +- u_int8_t th_off:4; /* data offset */ +- u_int8_t th_x2:4; /* (unused) */ +-# endif +- u_int8_t th_flags; +-# define TH_FIN 0x01 +-# define TH_SYN 0x02 +-# define TH_RST 0x04 +-# define TH_PUSH 0x08 +-# define TH_ACK 0x10 +-# define TH_URG 0x20 +- u_int16_t th_win; /* window */ +- u_int16_t th_sum; /* checksum */ +- u_int16_t th_urp; /* urgent pointer */ +-}; +- +-# else /* !__FAVOR_BSD */ +-struct tcphdr +- { +- u_int16_t source; +- u_int16_t dest; +- u_int32_t seq; +- u_int32_t ack_seq; +-# if __BYTE_ORDER == __LITTLE_ENDIAN +- u_int16_t res1:4; +- u_int16_t doff:4; +- u_int16_t fin:1; +- u_int16_t syn:1; +- u_int16_t rst:1; +- u_int16_t psh:1; +- u_int16_t ack:1; +- u_int16_t urg:1; +- u_int16_t res2:2; +-# elif __BYTE_ORDER == __BIG_ENDIAN +- u_int16_t doff:4; +- u_int16_t res1:4; +- u_int16_t res2:2; +- u_int16_t urg:1; +- u_int16_t ack:1; +- u_int16_t psh:1; +- u_int16_t rst:1; +- u_int16_t syn:1; +- u_int16_t fin:1; +-# else +-# error "Adjust your <bits/endian.h> defines" +-# endif +- u_int16_t window; +- u_int16_t check; +- u_int16_t urg_ptr; +-}; +-# endif /* __FAVOR_BSD */ +- +-enum +-{ +- TCP_ESTABLISHED = 1, +- TCP_SYN_SENT, +- TCP_SYN_RECV, +- TCP_FIN_WAIT1, +- TCP_FIN_WAIT2, +- TCP_TIME_WAIT, +- TCP_CLOSE, +- TCP_CLOSE_WAIT, +- TCP_LAST_ACK, +- TCP_LISTEN, +- TCP_CLOSING /* now a valid state */ +-}; +- +-# define TCPOPT_EOL 0 +-# define TCPOPT_NOP 1 +-# define TCPOPT_MAXSEG 2 +-# define TCPOLEN_MAXSEG 4 +-# define TCPOPT_WINDOW 3 +-# define TCPOLEN_WINDOW 3 +-# define TCPOPT_SACK_PERMITTED 4 /* Experimental */ +-# define TCPOLEN_SACK_PERMITTED 2 +-# define TCPOPT_SACK 5 /* Experimental */ +-# define TCPOPT_TIMESTAMP 8 +-# define TCPOLEN_TIMESTAMP 10 +-# define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ +- +-# define TCPOPT_TSTAMP_HDR \ +- (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) +- +-/* +- * Default maximum segment size for TCP. +- * With an IP MSS of 576, this is 536, +- * but 512 is probably more convenient. +- * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). +- */ +-# define TCP_MSS 512 +- +-# define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ +- +-# define TCP_MAX_WINSHIFT 14 /* maximum window shift */ +- +-# define SOL_TCP 6 /* TCP level */ +- +- +-# define TCPI_OPT_TIMESTAMPS 1 +-# define TCPI_OPT_SACK 2 +-# define TCPI_OPT_WSCALE 4 +-# define TCPI_OPT_ECN 8 +-# define TCPI_OPT_ECN_SEEN 16 +- +-/* Values for tcpi_state. */ +-enum tcp_ca_state +-{ +- TCP_CA_Open = 0, +- TCP_CA_Disorder = 1, +- TCP_CA_CWR = 2, +- TCP_CA_Recovery = 3, +- TCP_CA_Loss = 4 +-}; +- +-struct tcp_info +-{ +- u_int8_t tcpi_state; +- u_int8_t tcpi_ca_state; +- u_int8_t tcpi_retransmits; +- u_int8_t tcpi_probes; +- u_int8_t tcpi_backoff; +- u_int8_t tcpi_options; +- u_int8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; +- +- u_int32_t tcpi_rto; +- u_int32_t tcpi_ato; +- u_int32_t tcpi_snd_mss; +- u_int32_t tcpi_rcv_mss; +- +- u_int32_t tcpi_unacked; +- u_int32_t tcpi_sacked; +- u_int32_t tcpi_lost; +- u_int32_t tcpi_retrans; +- u_int32_t tcpi_fackets; +- +- /* Times. */ +- u_int32_t tcpi_last_data_sent; +- u_int32_t tcpi_last_ack_sent; /* Not remembered, sorry. */ +- u_int32_t tcpi_last_data_recv; +- u_int32_t tcpi_last_ack_recv; +- +- /* Metrics. */ +- u_int32_t tcpi_pmtu; +- u_int32_t tcpi_rcv_ssthresh; +- u_int32_t tcpi_rtt; +- u_int32_t tcpi_rttvar; +- u_int32_t tcpi_snd_ssthresh; +- u_int32_t tcpi_snd_cwnd; +- u_int32_t tcpi_advmss; +- u_int32_t tcpi_reordering; +- u_int32_t tcpi_rcv_rtt; +- u_int32_t tcpi_rcv_space; +- u_int32_t tcpi_total_retrans; +- +-}; +- +-#endif /* Misc. */ +- +-#endif /* netinet/tcp.h */ +--- a/include/iptables.h ++++ b/include/iptables.h +@@ -20,7 +20,7 @@ struct ipt_get_revision + { + char name[IPT_FUNCTION_MAXNAMELEN-1]; + +- u_int8_t revision; ++ uint8_t revision; + }; + #endif /* IPT_SO_GET_REVISION_MATCH Old kernel source */ + +@@ -39,7 +39,7 @@ struct iptables_match + ipt_chainlabel name; + + /* Revision of match (0 by default). */ +- u_int8_t revision; ++ uint8_t revision; + + const char *version; + +@@ -92,7 +92,7 @@ struct iptables_target + ipt_chainlabel name; + + /* Revision of target (0 by default). */ +- u_int8_t revision; ++ uint8_t revision; + + const char *version; + +@@ -153,7 +153,7 @@ extern char *mask_to_dotted(const struct + + extern void parse_hostnetworkmask(const char *name, struct in_addr **addrpp, + struct in_addr *maskp, unsigned int *naddrs); +-extern u_int16_t parse_protocol(const char *s); ++extern uint16_t parse_protocol(const char *s); + + extern int do_command(int argc, char *argv[], char **table, + iptc_handle_t *handle); +--- a/lib/dnet_ntop.c ++++ b/lib/dnet_ntop.c +@@ -1,24 +1,25 @@ + #include <errno.h> + #include <string.h> ++#include <stdint.h> + #include <sys/types.h> + #include <netinet/in.h> + + #include "utils.h" + +-static __inline__ u_int16_t dn_ntohs(u_int16_t addr) ++static __inline__ uint16_t dn_ntohs(uint16_t addr) + { + union { +- u_int8_t byte[2]; +- u_int16_t word; ++ uint8_t byte[2]; ++ uint16_t word; + } u; + + u.word = addr; +- return ((u_int16_t)u.byte[0]) | (((u_int16_t)u.byte[1]) << 8); ++ return ((uint16_t)u.byte[0]) | (((uint16_t)u.byte[1]) << 8); + } + +-static __inline__ int do_digit(char *str, u_int16_t *addr, u_int16_t scale, size_t *pos, size_t len, int *started) ++static __inline__ int do_digit(char *str, uint16_t *addr, uint16_t scale, size_t *pos, size_t len, int *started) + { +- u_int16_t tmp = *addr / scale; ++ uint16_t tmp = *addr / scale; + + if (*pos == len) + return 1; +@@ -36,7 +37,7 @@ static __inline__ int do_digit(char *str + + static const char *dnet_ntop1(const struct dn_naddr *dna, char *str, size_t len) + { +- u_int16_t addr, area; ++ uint16_t addr, area; + size_t pos = 0; + int started = 0; + +--- a/lib/dnet_pton.c ++++ b/lib/dnet_pton.c +@@ -1,23 +1,24 @@ + #include <errno.h> + #include <string.h> ++#include <stdint.h> + #include <sys/types.h> + #include <netinet/in.h> + + #include "utils.h" + +-static __inline__ u_int16_t dn_htons(u_int16_t addr) ++static __inline__ uint16_t dn_htons(uint16_t addr) + { + union { +- u_int8_t byte[2]; +- u_int16_t word; ++ uint8_t byte[2]; ++ uint16_t word; + } u; + + u.word = addr; +- return ((u_int16_t)u.byte[0]) | (((u_int16_t)u.byte[1]) << 8); ++ return ((uint16_t)u.byte[0]) | (((uint16_t)u.byte[1]) << 8); + } + + +-static int dnet_num(const char *src, u_int16_t * dst) ++static int dnet_num(const char *src, uint16_t * dst) + { + int rv = 0; + int tmp; +@@ -38,9 +39,9 @@ static int dnet_num(const char *src, u_i + + static int dnet_pton1(const char *src, struct dn_naddr *dna) + { +- u_int16_t addr; +- u_int16_t area = 0; +- u_int16_t node = 0; ++ uint16_t addr; ++ uint16_t area = 0; ++ uint16_t node = 0; + int pos; + + pos = dnet_num(src, &area); +--- a/include/libiptc/ipt_kernel_headers.h ++++ b/include/libiptc/ipt_kernel_headers.h +@@ -5,7 +5,7 @@ + + #include <limits.h> + +-#if defined(__GLIBC__) && __GLIBC__ == 2 ++#if 1 + #include <netinet/ip.h> + #include <netinet/in.h> + #include <netinet/ip_icmp.h> diff --git a/package/network/utils/iproute2/patches/100-allow_pfifo_fast.patch b/package/network/utils/iproute2/patches/100-allow_pfifo_fast.patch new file mode 100644 index 0000000..ce958a9 --- /dev/null +++ b/package/network/utils/iproute2/patches/100-allow_pfifo_fast.patch @@ -0,0 +1,9 @@ +--- 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, + }; diff --git a/package/network/utils/iproute2/patches/110-extra-ccopts.patch b/package/network/utils/iproute2/patches/110-extra-ccopts.patch new file mode 100644 index 0000000..0e36230 --- /dev/null +++ b/package/network/utils/iproute2/patches/110-extra-ccopts.patch @@ -0,0 +1,11 @@ +--- a/Makefile ++++ b/Makefile +@@ -29,7 +29,7 @@ ADDLIB+=ipx_ntop.o ipx_pton.o + CC = gcc + HOSTCC = gcc + DEFINES += -D_GNU_SOURCE +-CCOPTS = -O2 ++CCOPTS = -O2 $(EXTRA_CCOPTS) + WFLAGS := -Wall -Wstrict-prototypes -Wmissing-prototypes + WFLAGS += -Wmissing-declarations -Wold-style-definition -Wformat=2 + diff --git a/package/network/utils/iproute2/patches/120-libnetlink-pic.patch b/package/network/utils/iproute2/patches/120-libnetlink-pic.patch new file mode 100644 index 0000000..19ccd1a --- /dev/null +++ b/package/network/utils/iproute2/patches/120-libnetlink-pic.patch @@ -0,0 +1,11 @@ +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -4,7 +4,7 @@ ifeq ($(IP_CONFIG_SETNS),y) + CFLAGS += -DHAVE_SETNS + endif + +-CFLAGS += -fPIC ++CFLAGS += $(FPIC) + + UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o namespace.o \ + names.o diff --git a/package/network/utils/iproute2/patches/130-missing_include.patch b/package/network/utils/iproute2/patches/130-missing_include.patch new file mode 100644 index 0000000..8856963 --- /dev/null +++ b/package/network/utils/iproute2/patches/130-missing_include.patch @@ -0,0 +1,10 @@ +--- a/lib/namespace.c ++++ b/lib/namespace.c +@@ -9,6 +9,7 @@ + + #include <fcntl.h> + #include <dirent.h> ++#include <sys/param.h> + + #include "utils.h" + #include "namespace.h" diff --git a/package/network/utils/iproute2/patches/200-add-tc_esfq.patch b/package/network/utils/iproute2/patches/200-add-tc_esfq.patch new file mode 100644 index 0000000..6c148ea --- /dev/null +++ b/package/network/utils/iproute2/patches/200-add-tc_esfq.patch @@ -0,0 +1,249 @@ +--- a/tc/Makefile ++++ b/tc/Makefile +@@ -13,6 +13,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 +--- a/include/linux/pkt_sched.h ++++ b/include/linux/pkt_sched.h +@@ -226,6 +226,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 { +--- /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, ++}; diff --git a/package/network/utils/iproute2/patches/210-add-act_connmark.patch b/package/network/utils/iproute2/patches/210-add-act_connmark.patch new file mode 100644 index 0000000..10167ae --- /dev/null +++ b/package/network/utils/iproute2/patches/210-add-act_connmark.patch @@ -0,0 +1,87 @@ +--- a/tc/Makefile ++++ b/tc/Makefile +@@ -44,6 +44,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 += m_simple.o + TCMODULES += m_vlan.o +--- /dev/null ++++ b/tc/m_connmark.c +@@ -0,0 +1,74 @@ ++/* ++ * 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(); ++ ++ if (matches(*argv, "help") == 0) ++ usage(); ++ ++ *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, ++}; diff --git a/package/network/utils/iproute2/patches/300-ip_tiny.patch b/package/network/utils/iproute2/patches/300-ip_tiny.patch new file mode 100644 index 0000000..14518dc --- /dev/null +++ b/package/network/utils/iproute2/patches/300-ip_tiny.patch @@ -0,0 +1,101 @@ +--- a/ip/Makefile ++++ b/ip/Makefile +@@ -16,6 +16,13 @@ ifeq ($(IP_CONFIG_SETNS),y) + CFLAGS += -DHAVE_SETNS + endif + ++STATIC_SYM_FILTER:= ++ifeq ($(IP_CONFIG_TINY),y) ++ STATIC_SYM_FILTER:=iplink_can.c iplink_ipoib.c iplink_vxlan.c ++ CFLAGS += -DIPROUTE2_TINY ++endif ++STATIC_SYM_SOURCES:=$(filter-out $(STATIC_SYM_FILTER),$(wildcard *.c)) ++ + ALLOBJ=$(IPOBJ) $(RTMONOBJ) + SCRIPTS=ifcfg rtpr routel routef + TARGETS=ip rtmon +@@ -43,7 +50,7 @@ else + + ip: static-syms.o + static-syms.o: static-syms.h +-static-syms.h: $(wildcard *.c) ++static-syms.h: $(STATIC_SYM_SOURCES) + files="$^" ; \ + for s in `grep -B 3 '\<dlsym' $$files | sed -n '/snprintf/{s:.*"\([^"]*\)".*:\1:;s:%s::;p}'` ; do \ + sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \ +--- a/ip/ip.c ++++ b/ip/ip.c +@@ -71,30 +71,42 @@ static const struct cmd { + int (*func)(int argc, char **argv); + } cmds[] = { + { "address", do_ipaddr }, ++#ifndef IPROUTE2_TINY + { "addrlabel", do_ipaddrlabel }, ++#endif + { "maddress", do_multiaddr }, + { "route", do_iproute }, + { "rule", do_iprule }, + { "neighbor", do_ipneigh }, + { "neighbour", do_ipneigh }, ++#ifndef IPROUTE2_TINY + { "ntable", do_ipntable }, + { "ntbl", do_ipntable }, ++#endif + { "link", do_iplink }, ++#ifndef IPROUTE2_TINY + { "l2tp", do_ipl2tp }, + { "fou", do_ipfou }, ++#endif + { "tunnel", do_iptunnel }, + { "tunl", do_iptunnel }, ++#ifndef IPROUTE2_TINY + { "tuntap", do_iptuntap }, + { "tap", do_iptuntap }, + { "token", do_iptoken }, + { "tcpmetrics", do_tcp_metrics }, + { "tcp_metrics",do_tcp_metrics }, ++#endif + { "monitor", do_ipmonitor }, ++#ifndef IPROUTE2_TINY + { "xfrm", do_xfrm }, ++#endif + { "mroute", do_multiroute }, + { "mrule", do_multirule }, + { "netns", do_netns }, ++#ifndef IPROUTE2_TINY + { "netconf", do_ipnetconf }, ++#endif + { "help", do_help }, + { 0 } + }; +--- a/lib/utils.c ++++ b/lib/utils.c +@@ -642,6 +642,7 @@ const char *rt_addr_n2a(int af, const vo + case AF_INET: + case AF_INET6: + return inet_ntop(af, addr, buf, buflen); ++#ifndef IPROUTE2_TINY + case AF_IPX: + return ipx_ntop(af, addr, buf, buflen); + case AF_DECnet: +@@ -650,6 +651,7 @@ const char *rt_addr_n2a(int af, const vo + memcpy(dna.a_addr, addr, 2); + return dnet_ntop(af, &dna, buf, buflen); + } ++#endif + default: + return "???"; + } +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -4,6 +4,10 @@ ifeq ($(IP_CONFIG_SETNS),y) + CFLAGS += -DHAVE_SETNS + endif + ++ifeq ($(IP_CONFIG_TINY),y) ++ CFLAGS += -DIPROUTE2_TINY ++endif ++ + CFLAGS += $(FPIC) + + UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o namespace.o \ diff --git a/package/network/utils/iproute2/patches/900-drop_FAILED_POLICY.patch b/package/network/utils/iproute2/patches/900-drop_FAILED_POLICY.patch new file mode 100644 index 0000000..f5d2dfe --- /dev/null +++ b/package/network/utils/iproute2/patches/900-drop_FAILED_POLICY.patch @@ -0,0 +1,54 @@ +From 4e7dbf76227e8c7be7897dc81def3011f637864d Mon Sep 17 00:00:00 2001 +From: Jonas Gorski <jogo@openwrt.org> +Date: Thu, 30 May 2013 11:54:04 +0200 +Subject: [PATCH] add support for dropping with FAILED_POLICY + +--- + include/linux/fib_rules.h | 4 ++++ + include/linux/rtnetlink.h | 1 + + ip/rtm_map.c | 4 ++++ + 3 files changed, 9 insertions(+) + +--- a/include/linux/fib_rules.h ++++ b/include/linux/fib_rules.h +@@ -64,6 +64,10 @@ enum { + FR_ACT_BLACKHOLE, /* Drop without notification */ + FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ + FR_ACT_PROHIBIT, /* Drop with EACCES */ ++ FR_ACT_RES8, ++ FR_ACT_RES9, ++ FR_ACT_RES10, ++ FR_ACT_FAILED_POLICY, /* Drop with EPERM */ + __FR_ACT_MAX, + }; + +--- a/include/linux/rtnetlink.h ++++ b/include/linux/rtnetlink.h +@@ -208,6 +208,7 @@ enum { + RTN_THROW, /* Not in this table */ + RTN_NAT, /* Translate this address */ + RTN_XRESOLVE, /* Use external resolver */ ++ RTN_FAILED_POLICY, /* Source address failed policy */ + __RTN_MAX + }; + +--- a/ip/rtm_map.c ++++ b/ip/rtm_map.c +@@ -49,6 +49,8 @@ char *rtnl_rtntype_n2a(int id, char *buf + return "nat"; + case RTN_XRESOLVE: + return "xresolve"; ++ case RTN_FAILED_POLICY: ++ return "failed_policy"; + default: + snprintf(buf, len, "%d", id); + return buf; +@@ -84,6 +86,8 @@ int rtnl_rtntype_a2n(int *id, char *arg) + res = RTN_UNICAST; + else if (strcmp(arg, "throw") == 0) + res = RTN_THROW; ++ else if (strcmp(arg, "failed_policy") == 0) ++ res = RTN_FAILED_POLICY; + else { + res = strtoul(arg, &end, 0); + if (!end || end == arg || *end || res > 255) diff --git a/package/network/utils/iproute2/patches/910-sanitize_headers_for_musl.patch b/package/network/utils/iproute2/patches/910-sanitize_headers_for_musl.patch new file mode 100644 index 0000000..ca1125d --- /dev/null +++ b/package/network/utils/iproute2/patches/910-sanitize_headers_for_musl.patch @@ -0,0 +1,10 @@ +--- a/include/linux/if_bridge.h ++++ b/include/linux/if_bridge.h +@@ -15,7 +15,6 @@ + + #include <linux/types.h> + #include <linux/if_ether.h> +-#include <linux/in6.h> + + #define SYSFS_BRIDGE_ATTR "bridge" + #define SYSFS_BRIDGE_FDB "brforward" diff --git a/package/network/utils/ipset/Makefile b/package/network/utils/ipset/Makefile new file mode 100644 index 0000000..f1c50a9 --- /dev/null +++ b/package/network/utils/ipset/Makefile @@ -0,0 +1,53 @@ + +# Copyright (C) 2009-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:=ipset +PKG_VERSION:=6.24 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://ipset.netfilter.org +PKG_MD5SUM:=8831b8f01458bf2abacc222884195a62 + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/ipset + SECTION:=net + CATEGORY:=Network + DEPENDS+= +kmod-ipt-ipset +libmnl + TITLE:=IPset administration utility + URL:=http://ipset.netfilter.org/ +endef + +CONFIGURE_ARGS += \ + --with-kbuild="$(LINUX_DIR)" + +MAKE_FLAGS += \ + ARCH="$(LINUX_KARCH)" \ + SHELL="$(BASH)" + +define Build/Compile + $(call Build/Compile/Default) +endef + +define Package/ipset/install + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/ipset $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libipset*.so* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,ipset)) diff --git a/package/network/utils/iptables/Makefile b/package/network/utils/iptables/Makefile new file mode 100644 index 0000000..626b252 --- /dev/null +++ b/package/network/utils/iptables/Makefile @@ -0,0 +1,548 @@ +# +# Copyright (C) 2006-2013 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.21 +PKG_RELEASE:=1 + +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_MD5SUM:=536d048c8e8eeebcd9757d0863ebb0c0 + +PKG_FIXUP:=autoreconf +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 +PKG_LICENSE:=GPL-2.0 + +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:=IP firewall administration tool + MENU:=1 + DEPENDS+= +kmod-ipt-core +libip4tc +IPV6:libip6tc +libxtables +endef + +define Package/iptables/description +IP firewall administration tool. + + Matches: + - icmp + - tcp + - udp + - comment + - conntrack + - limit + - mac + - mark + - multiport + - set + - state + - time + + Targets: + - ACCEPT + - CT + - DNAT + - DROP + - REJECT + - LOG + - MARK + - MASQUERADE + - REDIRECT + - SET + - SNAT + - TCPMSS + + Tables: + - filter + - mangle + - nat + - raw + +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 + - connlimit + - 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: + - 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 + - statistic + - tcpmss + - unclean + - hl + + Targets: + - DSCP + - CLASSIFY + - ECN + - 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-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 +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-nflog +$(call Package/iptables/Module, +kmod-nfnetlink-log +kmod-ipt-nflog) + TITLE:=Netfilter NFLOG target +endef + +define Package/iptables-mod-nflog/description + iptables extension for user-space logging via NFNETLINK. + + Includes: + - libxt_NFLOG + +endef + +define Package/iptables-mod-nfqueue +$(call Package/iptables/Module, +kmod-nfnetlink-queue +kmod-ipt-nfqueue) + TITLE:=Netfilter NFQUEUE target +endef + +define Package/iptables-mod-nfqueue/description + iptables extension for user-space queuing via NFNETLINK. + + Includes: + - libxt_NFQUEUE + +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-cluster +$(call Package/iptables/Module, +kmod-ipt-cluster) + TITLE:=Match cluster extension +endef + +define Package/iptables-mod-cluster/description +iptables extensions for matching cluster. + + Netfilter (IPv4/IPv6) module for matching cluster + This option allows you to build work-load-sharing clusters of + network servers/stateful firewalls without having a dedicated + load-balancing router/server/switch. Basically, this match returns + true when the packet must be handled by this cluster node. Thus, + all nodes see all packets and this match decides which node handles + what packets. The work-load sharing algorithm is based on source + address hashing. + + This module is usable for ipv4 and ipv6. + + If you select it, it enables kmod-ipt-cluster. + + see `iptables -m cluster --help` for more information. +endef + +define Package/iptables-mod-clusterip +$(call Package/iptables/Module, +kmod-ipt-clusterip) + TITLE:=Clusterip extension +endef + +define Package/iptables-mod-clusterip/description +iptables extensions for CLUSTERIP. + The CLUSTERIP target allows you to build load-balancing clusters of + network servers without having a dedicated load-balancing + router/server/switch. + + If you select it, it enables kmod-ipt-clusterip. + + see `iptables -j CLUSTERIP --help` for more information. +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: + - addrtype + - 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:=@IPV6 +kmod-ip6tables +iptables + CATEGORY:=Network + TITLE:=IPv6 firewall administration tool + MENU:=1 +endef + + +define Package/ip6tables-extra +$(call Package/iptables/Default) + DEPENDS:=ip6tables +kmod-ip6tables-extra + TITLE:=IPv6 header matching modules +endef + +define Package/ip6tables-mod-extra/description +iptables header matching modules for IPv6 +endef + +define Package/ip6tables-mod-nat +$(call Package/iptables/Default) + DEPENDS:=ip6tables +kmod-ipt-nat6 + TITLE:=IPv6 NAT extensions +endef + +define Package/ip6tables-mod-nat/description +iptables extensions for IPv6-NAT targets. +endef + +define Package/libiptc +$(call Package/iptables/Default) + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+libip4tc +libip6tc +libxtables + 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 + DEPENDS:=+libxtables +endef + +define Package/libip6tc +$(call Package/iptables/Default) + SECTION:=libs + CATEGORY:=Libraries + TITLE:=IPv6 firewall - shared libiptc library + DEPENDS:=+libxtables +endef + +define Package/libxtables + $(call Package/iptables/Default) + SECTION:=libs + CATEGORY:=Libraries + TITLE:=IPv4/IPv6 firewall - shared xtables 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 \ + -ffunction-sections -fdata-sections \ + -DNO_LEGACY + +TARGET_LDFLAGS += \ + -Wl,--gc-sections + +CONFIGURE_ARGS += \ + --enable-shared \ + --enable-devel \ + --with-kernel="$(LINUX_DIR)/user_headers" \ + --with-xtlibdir=/usr/lib/iptables \ + --enable-static \ + $(if $(CONFIG_IPV6),,--disable-ipv6) + +MAKE_FLAGS := \ + $(TARGET_CONFIGURE_OPTS) \ + COPT_FLAGS="$(TARGET_CFLAGS)" \ + KERNEL_DIR="$(LINUX_DIR)/user_headers/" PREFIX=/usr \ + KBUILD_OUTPUT="$(LINUX_DIR)" \ + BUILTIN_MODULES="$(patsubst ip6t_%,%,$(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/iptables/*.h $(1)/usr/include/iptables/ + $(CP) $(PKG_BUILD_DIR)/include/iptables.h $(1)/usr/include/ + $(CP) $(PKG_BUILD_DIR)/include/ip6tables.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/ + $(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/libip*tc.pc $(1)/usr/lib/pkgconfig/ + + # XXX: needed by firewall3 + $(CP) $(PKG_BUILD_DIR)/extensions/libiptext*.so $(1)/usr/lib/ +endef + +define Package/iptables/install + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/xtables-multi $(1)/usr/sbin/ + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/iptables{,-restore,-save} $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/usr/lib/iptables +endef + +define Package/ip6tables/install + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/ip6tables{,-restore,-save} $(1)/usr/sbin/ +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/ + $(CP) $(PKG_BUILD_DIR)/extensions/libiptext4.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/ + $(CP) $(PKG_BUILD_DIR)/extensions/libiptext6.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/ + $(CP) $(PKG_BUILD_DIR)/extensions/libiptext.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)) $(patsubst xt_%,ip6t_%,$(2)) $(patsubst ip6t_%,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 + +$(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))) +$(eval $(call BuildPlugin,iptables-mod-ipopt,$(IPT_IPOPT-m))) +$(eval $(call BuildPlugin,iptables-mod-ipsec,$(IPT_IPSEC-m))) +$(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-cluster,$(IPT_CLUSTER-m))) +$(eval $(call BuildPlugin,iptables-mod-clusterip,$(IPT_CLUSTERIP-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 BuildPlugin,iptables-mod-nflog,$(IPT_NFLOG-m))) +$(eval $(call BuildPlugin,iptables-mod-nfqueue,$(IPT_NFQUEUE-m))) +$(eval $(call BuildPackage,ip6tables)) +$(eval $(call BuildPlugin,ip6tables-extra,$(IPT_IPV6_EXTRA-m))) +$(eval $(call BuildPlugin,ip6tables-mod-nat,$(IPT_NAT6-m))) +$(eval $(call BuildPackage,libiptc)) +$(eval $(call BuildPackage,libip4tc)) +$(eval $(call BuildPackage,libip6tc)) +$(eval $(call BuildPackage,libxtables)) diff --git a/package/network/utils/iptables/patches/020-iptables-disable-modprobe.patch b/package/network/utils/iptables/patches/020-iptables-disable-modprobe.patch new file mode 100644 index 0000000..2b6c57e --- /dev/null +++ b/package/network/utils/iptables/patches/020-iptables-disable-modprobe.patch @@ -0,0 +1,18 @@ +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -336,6 +336,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; +@@ -380,6 +381,7 @@ int xtables_insmod(const char *modname, + free(buf); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + return 0; ++#endif + return -1; + } + diff --git a/package/network/utils/iptables/patches/030-no-libnfnetlink.patch b/package/network/utils/iptables/patches/030-no-libnfnetlink.patch new file mode 100644 index 0000000..50542ac --- /dev/null +++ b/package/network/utils/iptables/patches/030-no-libnfnetlink.patch @@ -0,0 +1,94 @@ +--- a/configure ++++ b/configure +@@ -12367,77 +12367,7 @@ 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` +- test "x$?" != "x0" && pkg_failed=yes +-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` +- test "x$?" != "x0" && pkg_failed=yes +-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 --cflags --libs "libnfnetlink >= 1.0" 2>&1` +- else +- libnfnetlink_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "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 +@@ -111,9 +111,7 @@ if test "x$enable_bpfc" = "xyes" || test + AC_CHECK_LIB(pcap, pcap_compile,, AC_MSG_ERROR(missing libpcap library required by bpf compiler or nfsynproxy tool)) + fi + +-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="-Wall -Waggregate-return -Wmissing-declarations \ + -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \ diff --git a/package/network/utils/iptables/patches/050-optional-xml.patch b/package/network/utils/iptables/patches/050-optional-xml.patch new file mode 100644 index 0000000..11311dd --- /dev/null +++ b/package/network/utils/iptables/patches/050-optional-xml.patch @@ -0,0 +1,13 @@ +--- a/iptables/xtables-multi.c ++++ b/iptables/xtables-multi.c +@@ -22,8 +22,10 @@ static const struct subcommand multi_sub + {"iptables-restore", iptables_restore_main}, + {"restore4", iptables_restore_main}, + #endif ++#ifdef ENABLE_XML + {"iptables-xml", iptables_xml_main}, + {"xml", iptables_xml_main}, ++#endif + #ifdef ENABLE_IPV6 + {"ip6tables", ip6tables_main}, + {"main6", ip6tables_main}, diff --git a/package/network/utils/iptables/patches/100-bash-location.patch b/package/network/utils/iptables/patches/100-bash-location.patch new file mode 100644 index 0000000..02ee45b --- /dev/null +++ b/package/network/utils/iptables/patches/100-bash-location.patch @@ -0,0 +1,8 @@ +--- a/iptables/iptables-apply ++++ b/iptables/iptables-apply +@@ -1,4 +1,4 @@ +-#!/bin/bash ++#!/usr/bin/env bash + # + # iptables-apply -- a safer way to update iptables remotely + # diff --git a/package/network/utils/iptables/patches/200-configurable_builtin.patch b/package/network/utils/iptables/patches/200-configurable_builtin.patch new file mode 100644 index 0000000..d35bc5a --- /dev/null +++ b/package/network/utils/iptables/patches/200-configurable_builtin.patch @@ -0,0 +1,60 @@ +--- a/extensions/GNUmakefile.in ++++ b/extensions/GNUmakefile.in +@@ -45,9 +45,24 @@ pfx_symlinks := NOTRACK state + 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} ${pfx_symlinks}) + pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod}) + pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod}) +@@ -58,11 +73,11 @@ pf6_solibs := $(patsubst %,libip6t_%. + # + targets := libext.a libext4.a libext6.a matches.man targets.man + targets_install := +-@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs} +-@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs} +-@ENABLE_STATIC_TRUE@ libext6_objs := ${pf6_objs} +-@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs} +-@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs} ++libext_objs := ${pfx_objs} ++libext4_objs := ${pf4_objs} ++libext6_objs := ${pf6_objs} ++targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs} ++targets_install := $(strip ${targets_install} ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}) + + .SECONDARY: + +@@ -126,9 +141,9 @@ libext4.a: initext4.o ${libext4_objs} + libext6.a: initext6.o ${libext6_objs} + ${AM_VERBOSE_AR} ${AR} crs $@ $^; + +-initext_func := $(addprefix xt_,${pfx_build_mod}) +-initext4_func := $(addprefix ipt_,${pf4_build_mod}) +-initext6_func := $(addprefix ip6t_,${pf6_build_mod}) ++initext_func := $(addprefix xt_,${pfx_build_static}) ++initext4_func := $(addprefix ipt_,${pf4_build_static}) ++initext6_func := $(addprefix ip6t_,${pf6_build_static}) + + .initext.dd: FORCE + @echo "${initext_func}" >$@.tmp; \ diff --git a/package/network/utils/iptables/patches/300-musl_fixes.patch b/package/network/utils/iptables/patches/300-musl_fixes.patch new file mode 100644 index 0000000..a78eda7 --- /dev/null +++ b/package/network/utils/iptables/patches/300-musl_fixes.patch @@ -0,0 +1,127 @@ +--- a/extensions/libip6t_ipv6header.c ++++ b/extensions/libip6t_ipv6header.c +@@ -10,6 +10,9 @@ on whether they contain certain headers + #include <netdb.h> + #include <xtables.h> + #include <linux/netfilter_ipv6/ip6t_ipv6header.h> ++#ifndef IPPROTO_HOPOPTS ++# define IPPROTO_HOPOPTS 0 ++#endif + + enum { + O_HEADER = 0, +--- a/extensions/libxt_TCPOPTSTRIP.c ++++ b/extensions/libxt_TCPOPTSTRIP.c +@@ -12,6 +12,21 @@ + #ifndef TCPOPT_MD5SIG + # define TCPOPT_MD5SIG 19 + #endif ++#ifndef TCPOPT_MAXSEG ++# define TCPOPT_MAXSEG 2 ++#endif ++#ifndef TCPOPT_WINDOW ++# define TCPOPT_WINDOW 3 ++#endif ++#ifndef TCPOPT_SACK_PERMITTED ++# define TCPOPT_SACK_PERMITTED 4 ++#endif ++#ifndef TCPOPT_SACK ++# define TCPOPT_SACK 5 ++#endif ++#ifndef TCPOPT_TIMESTAMP ++# define TCPOPT_TIMESTAMP 8 ++#endif + + enum { + O_STRIP_OPTION = 0, +--- a/include/libiptc/ipt_kernel_headers.h ++++ b/include/libiptc/ipt_kernel_headers.h +@@ -5,7 +5,6 @@ + + #include <limits.h> + +-#if defined(__GLIBC__) && __GLIBC__ == 2 + #include <netinet/ip.h> + #include <netinet/in.h> + #include <netinet/ip_icmp.h> +@@ -13,15 +12,4 @@ + #include <netinet/udp.h> + #include <net/if.h> + #include <sys/types.h> +-#else /* libc5 */ +-#include <sys/socket.h> +-#include <linux/ip.h> +-#include <linux/in.h> +-#include <linux/if.h> +-#include <linux/icmp.h> +-#include <linux/tcp.h> +-#include <linux/udp.h> +-#include <linux/types.h> +-#include <linux/in6.h> +-#endif + #endif +--- a/include/linux/netfilter_ipv4/ip_tables.h ++++ b/include/linux/netfilter_ipv4/ip_tables.h +@@ -16,6 +16,7 @@ + #define _IPTABLES_H + + #include <linux/types.h> ++#include <sys/types.h> + + #include <linux/netfilter_ipv4.h> + +--- a/iptables/ip6tables-restore.c ++++ b/iptables/ip6tables-restore.c +@@ -9,7 +9,7 @@ + */ + + #include <getopt.h> +-#include <sys/errno.h> ++#include <errno.h> + #include <stdbool.h> + #include <string.h> + #include <stdio.h> +--- a/iptables/ip6tables-save.c ++++ b/iptables/ip6tables-save.c +@@ -6,7 +6,7 @@ + * This code is distributed under the terms of GNU GPL v2 + */ + #include <getopt.h> +-#include <sys/errno.h> ++#include <errno.h> + #include <stdio.h> + #include <fcntl.h> + #include <stdlib.h> +--- a/iptables/iptables-restore.c ++++ b/iptables/iptables-restore.c +@@ -6,7 +6,7 @@ + */ + + #include <getopt.h> +-#include <sys/errno.h> ++#include <errno.h> + #include <stdbool.h> + #include <string.h> + #include <stdio.h> +--- a/iptables/iptables-save.c ++++ b/iptables/iptables-save.c +@@ -6,7 +6,7 @@ + * + */ + #include <getopt.h> +-#include <sys/errno.h> ++#include <errno.h> + #include <stdio.h> + #include <fcntl.h> + #include <stdlib.h> +--- a/iptables/iptables-xml.c ++++ b/iptables/iptables-xml.c +@@ -7,7 +7,7 @@ + */ + + #include <getopt.h> +-#include <sys/errno.h> ++#include <errno.h> + #include <string.h> + #include <stdio.h> + #include <stdlib.h> diff --git a/package/network/utils/iptables/patches/500-add-xt_id-match.patch b/package/network/utils/iptables/patches/500-add-xt_id-match.patch new file mode 100644 index 0000000..94762f0 --- /dev/null +++ b/package/network/utils/iptables/patches/500-add-xt_id-match.patch @@ -0,0 +1,59 @@ +--- /dev/null ++++ b/extensions/libxt_id.c +@@ -0,0 +1,45 @@ ++/* Shared library add-on to iptables to add id match support. */ ++ ++#include <stdio.h> ++#include <xtables.h> ++#include <linux/netfilter/xt_id.h> ++ ++enum { ++ O_ID = 0, ++}; ++ ++static const struct xt_option_entry id_opts[] = { ++ { ++ .name = "id", ++ .id = O_ID, ++ .type = XTTYPE_UINT32, ++ .flags = XTOPT_MAND | XTOPT_PUT, ++ XTOPT_POINTER(struct xt_id_info, id) ++ }, ++ XTOPT_TABLEEND, ++}; ++ ++/* Saves the union ipt_matchinfo in parsable form to stdout. */ ++static void ++id_save(const void *ip, const struct xt_entry_match *match) ++{ ++ struct xt_id_info *idinfo = (void *)match->data; ++ ++ printf(" --id %lu", idinfo->id); ++} ++ ++static struct xtables_match id_match = { ++ .family = NFPROTO_UNSPEC, ++ .name = "id", ++ .version = XTABLES_VERSION, ++ .size = XT_ALIGN(sizeof(struct xt_id_info)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_id_info)), ++ .save = id_save, ++ .x6_parse = xtables_option_parse, ++ .x6_options = id_opts, ++}; ++ ++void _init(void) ++{ ++ xtables_register_match(&id_match); ++} +--- /dev/null ++++ b/include/linux/netfilter/xt_id.h +@@ -0,0 +1,8 @@ ++#ifndef _XT_ID_H ++#define _XT_ID_H ++ ++struct xt_id_info { ++ __u32 id; ++}; ++ ++#endif /* XT_ID_H */ diff --git a/package/network/utils/iptables/patches/600-shared-libext.patch b/package/network/utils/iptables/patches/600-shared-libext.patch new file mode 100644 index 0000000..92f5485 --- /dev/null +++ b/package/network/utils/iptables/patches/600-shared-libext.patch @@ -0,0 +1,78 @@ +Index: iptables-1.4.21/extensions/GNUmakefile.in +=================================================================== +--- iptables-1.4.21.orig/extensions/GNUmakefile.in ++++ iptables-1.4.21/extensions/GNUmakefile.in +@@ -71,7 +71,7 @@ pf6_solibs := $(patsubst %,libip6t_%. + # + # Building blocks + # +-targets := libext.a libext4.a libext6.a matches.man targets.man ++targets := libiptext.so libiptext4.so libiptext6.so matches.man targets.man + targets_install := + libext_objs := ${pfx_objs} + libext4_objs := ${pf4_objs} +@@ -96,7 +96,7 @@ clean: + distclean: clean + + init%.o: init%.c +- ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<; ++ ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; + + -include .*.d + +@@ -130,16 +130,16 @@ xt_statistic_LIBADD = -lm + # handling code in the Makefiles. + # + lib%.o: ${srcdir}/lib%.c +- ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<; ++ ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; + +-libext.a: initext.o ${libext_objs} +- ${AM_VERBOSE_AR} ${AR} crs $@ $^; ++libiptext.so: initext.o ${libext_objs} ++ ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $^ -L../libxtables/.libs -lxtables ${$*_LIBADD}; + +-libext4.a: initext4.o ${libext4_objs} +- ${AM_VERBOSE_AR} ${AR} crs $@ $^; ++libiptext4.so: initext4.o ${libext4_objs} ++ ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $^ -L../libxtables/.libs -lxtables ${$*_LIBADD}; + +-libext6.a: initext6.o ${libext6_objs} +- ${AM_VERBOSE_AR} ${AR} crs $@ $^; ++libiptext6.so: initext6.o ${libext6_objs} ++ ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $^ -L../libxtables/.libs -lxtables ${$*_LIBADD}; + + initext_func := $(addprefix xt_,${pfx_build_static}) + initext4_func := $(addprefix ipt_,${pf4_build_static}) +Index: iptables-1.4.21/iptables/Makefile.am +=================================================================== +--- iptables-1.4.21.orig/iptables/Makefile.am ++++ iptables-1.4.21/iptables/Makefile.am +@@ -5,7 +5,8 @@ AM_CPPFLAGS = ${regular_CPPFLAGS} - + + xtables_multi_SOURCES = xtables-multi.c iptables-xml.c + xtables_multi_CFLAGS = ${AM_CFLAGS} +-xtables_multi_LDADD = ../extensions/libext.a ++xtables_multi_LDADD = ++xtables_multi_LDFLAGS = -L../extensions/ -liptext + if ENABLE_STATIC + xtables_multi_CFLAGS += -DALL_INCLUSIVE + endif +@@ -13,13 +14,15 @@ if ENABLE_IPV4 + xtables_multi_SOURCES += iptables-save.c iptables-restore.c \ + iptables-standalone.c iptables.c + xtables_multi_CFLAGS += -DENABLE_IPV4 +-xtables_multi_LDADD += ../libiptc/libip4tc.la ../extensions/libext4.a ++xtables_multi_LDADD += ../libiptc/libip4tc.la ++xtables_multi_LDFLAGS += -liptext4 + endif + if ENABLE_IPV6 + xtables_multi_SOURCES += ip6tables-save.c ip6tables-restore.c \ + ip6tables-standalone.c ip6tables.c + xtables_multi_CFLAGS += -DENABLE_IPV6 +-xtables_multi_LDADD += ../libiptc/libip6tc.la ../extensions/libext6.a ++xtables_multi_LDADD += ../libiptc/libip6tc.la ++xtables_multi_LDFLAGS += -liptext6 + endif + xtables_multi_SOURCES += xshared.c + xtables_multi_LDADD += ../libxtables/libxtables.la -lm diff --git a/package/network/utils/iptables/patches/700-disable-legacy-revisions.patch b/package/network/utils/iptables/patches/700-disable-legacy-revisions.patch new file mode 100644 index 0000000..342c3b0 --- /dev/null +++ b/package/network/utils/iptables/patches/700-disable-legacy-revisions.patch @@ -0,0 +1,108 @@ +Index: iptables-1.4.21/extensions/libxt_conntrack.c +=================================================================== +--- iptables-1.4.21.orig/extensions/libxt_conntrack.c ++++ iptables-1.4.21/extensions/libxt_conntrack.c +@@ -1157,6 +1157,7 @@ static void state_save(const void *ip, c + } + + static struct xtables_match conntrack_mt_reg[] = { ++#ifndef NO_LEGACY + { + .version = XTABLES_VERSION, + .name = "conntrack", +@@ -1232,6 +1233,7 @@ static struct xtables_match conntrack_mt + .alias = conntrack_print_name_alias, + .x6_options = conntrack2_mt_opts, + }, ++#endif + { + .version = XTABLES_VERSION, + .name = "conntrack", +@@ -1262,6 +1264,7 @@ static struct xtables_match conntrack_mt + .alias = conntrack_print_name_alias, + .x6_options = conntrack3_mt_opts, + }, ++#ifndef NO_LEGACY + { + .family = NFPROTO_UNSPEC, + .name = "state", +@@ -1292,6 +1295,7 @@ static struct xtables_match conntrack_mt + .x6_parse = state_ct23_parse, + .x6_options = state_opts, + }, ++#endif + { + .family = NFPROTO_UNSPEC, + .name = "state", +@@ -1307,6 +1311,7 @@ static struct xtables_match conntrack_mt + .x6_parse = state_ct23_parse, + .x6_options = state_opts, + }, ++#ifndef NO_LEGACY + { + .family = NFPROTO_UNSPEC, + .name = "state", +@@ -1320,6 +1325,7 @@ static struct xtables_match conntrack_mt + .x6_parse = state_parse, + .x6_options = state_opts, + }, ++#endif + }; + + void _init(void) +Index: iptables-1.4.21/extensions/libxt_CT.c +=================================================================== +--- iptables-1.4.21.orig/extensions/libxt_CT.c ++++ iptables-1.4.21/extensions/libxt_CT.c +@@ -290,6 +290,7 @@ static void notrack_ct2_tg_init(struct x + } + + static struct xtables_target ct_target_reg[] = { ++#ifndef NO_LEGACY + { + .family = NFPROTO_UNSPEC, + .name = "CT", +@@ -315,6 +316,7 @@ static struct xtables_target ct_target_r + .x6_parse = ct_parse_v1, + .x6_options = ct_opts_v1, + }, ++#endif + { + .family = NFPROTO_UNSPEC, + .name = "CT", +@@ -329,6 +331,7 @@ static struct xtables_target ct_target_r + .x6_parse = ct_parse_v1, + .x6_options = ct_opts_v1, + }, ++#ifndef NO_LEGACY + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", +@@ -366,6 +369,7 @@ static struct xtables_target ct_target_r + .revision = 0, + .version = XTABLES_VERSION, + }, ++#endif + }; + + void _init(void) +Index: iptables-1.4.21/extensions/libxt_multiport.c +=================================================================== +--- iptables-1.4.21.orig/extensions/libxt_multiport.c ++++ iptables-1.4.21/extensions/libxt_multiport.c +@@ -469,6 +469,7 @@ static void multiport_save6_v1(const voi + } + + static struct xtables_match multiport_mt_reg[] = { ++#ifndef NO_LEGACY + { + .family = NFPROTO_IPV4, + .name = "multiport", +@@ -497,6 +498,7 @@ static struct xtables_match multiport_mt + .save = multiport_save6, + .x6_options = multiport_opts, + }, ++#endif + { + .family = NFPROTO_IPV4, + .name = "multiport", diff --git a/package/network/utils/iputils/Makefile b/package/network/utils/iputils/Makefile new file mode 100644 index 0000000..6f75236 --- /dev/null +++ b/package/network/utils/iputils/Makefile @@ -0,0 +1,181 @@ +# +# 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:=iputils +PKG_VERSION:=20101006 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-s$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://www.skbuff.net/iputils +PKG_MD5SUM:=a36c25e9ec17e48be514dc0485e7376c + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=GPL-2.0+ + +PKG_BUILD_DEPENDS:=sysfsutils +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-s$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk + + +define Package/iputils/Default + SECTION:=net + CATEGORY:=Network + URL:=http://www.skbuff.net/iputils +endef + + +define Package/iputils-arping +$(call Package/iputils/Default) + TITLE:=iputils - arping + DEPENDS+= +libsysfs +endef + +define Package/iputils-arping/description + Program arping from iputils. + Sends ARP REQUEST to a neighbour host. +endef + + +define Package/iputils-clockdiff +$(call Package/iputils/Default) + TITLE:=iputils - clockdiff +endef + +define Package/iputils-clockdiff/description + Program clockdiff from iputils. + Measures clock difference between hosts. +endef + + +define Package/iputils-ping +$(call Package/iputils/Default) + TITLE:=iputils - ping +endef + +define Package/iputils-ping/description + Program ping from iputils. + Sends ICMP ECHO_REQUEST to network hosts (IPv4). +endef + + +define Package/iputils-ping6 +$(call Package/iputils/Default) + TITLE:=iputils - ping6 + DEPENDS+= @IPV6 +USE_GLIBC:libopenssl +endef + +define Package/iputils-ping6/description + Program ping6 from iputils. + Sends ICMP ECHO_REQUEST to network hosts (IPv6). +endef + + +define Package/iputils-tftpd +$(call Package/iputils/Default) + TITLE:=iputils - tftpd +endef + +define Package/iputils-tftpd/description + Program tftpd from iputils + Trivial File Transfer Protocol server. +endef + + +define Package/iputils-tracepath +$(call Package/iputils/Default) + TITLE:=iputils - tracepath +endef + +define Package/iputils-tracepath/description + Program tracepath from iputils. + Traces path to a network host discovering MTU along this path (IPv4). +endef + + +define Package/iputils-tracepath6 +$(call Package/iputils/Default) + TITLE:=iputils - tracepath6 + DEPENDS+= @IPV6 +endef + +define Package/iputils-tracepath6/description + Program tracepath6 from iputils. + Traces path to a network host discovering MTU along this path (IPv6). +endef + + +define Package/iputils-traceroute6 +$(call Package/iputils/Default) + TITLE:=iputils - traceroute6 + DEPENDS+= @IPV6 +endef + +define Package/iputils-traceroute6/description + Program traceroute6 from iputils. + Traces path to a network host (IPv6). +endef + +ifdef CONFIG_USE_MUSL + TARGET_CFLAGS += -D__UCLIBC__ +endif + +MAKE_FLAGS += \ + CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS) $(TARGET_LDFLAGS)" \ + CONFIG_IPV6="$(CONFIG_IPV6)" \ + CONFIG_USE_UCLIBC="$(CONFIG_USE_UCLIBC)$(CONFIG_USE_MUSL)" \ + +define Package/iputils-arping/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/arping $(1)/usr/bin/ +endef + +define Package/iputils-clockdiff/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/clockdiff $(1)/usr/bin/ +endef + +define Package/iputils-ping/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ping $(1)/usr/bin/ +endef + +define Package/iputils-ping6/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/ping6 $(1)/usr/bin/ +endef + +define Package/iputils-tftpd/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tftpd $(1)/usr/sbin/ +endef + +define Package/iputils-tracepath/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tracepath $(1)/usr/bin/ +endef + +define Package/iputils-tracepath6/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/tracepath6 $(1)/usr/bin/ +endef + +define Package/iputils-traceroute6/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/traceroute6 $(1)/usr/bin/ +endef + +$(eval $(call BuildPackage,iputils-arping)) +$(eval $(call BuildPackage,iputils-clockdiff)) +$(eval $(call BuildPackage,iputils-ping)) +$(eval $(call BuildPackage,iputils-tftpd)) +$(eval $(call BuildPackage,iputils-tracepath)) +$(eval $(call BuildPackage,iputils-ping6)) +$(eval $(call BuildPackage,iputils-tracepath6)) +$(eval $(call BuildPackage,iputils-traceroute6)) diff --git a/package/network/utils/iputils/patches/001-iputils.patch b/package/network/utils/iputils/patches/001-iputils.patch new file mode 100644 index 0000000..e57db13 --- /dev/null +++ b/package/network/utils/iputils/patches/001-iputils.patch @@ -0,0 +1,14 @@ +diff -ur a/Makefile b/Makefile +--- a/Makefile 2002-09-20 18:23:55.000000000 +0000 ++++ b/Makefile 2007-05-17 13:59:55.000000000 +0000 +@@ -16,8 +16,8 @@ + CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g + CFLAGS=$(CCOPT) $(GLIBCFIX) $(DEFINES) + +-IPV4_TARGETS=tracepath ping clockdiff rdisc arping tftpd rarpd +-IPV6_TARGETS=tracepath6 traceroute6 ping6 ++IPV4_TARGETS=tracepath ping clockdiff arping tftpd ++IPV6_TARGETS=tracepath6 traceroute6 ping6 + TARGETS=$(IPV4_TARGETS) $(IPV6_TARGETS) + + LASTTAG:=`git describe HEAD | sed -e 's/-.*//'` diff --git a/package/network/utils/iputils/patches/002-fix-ipv6.patch b/package/network/utils/iputils/patches/002-fix-ipv6.patch new file mode 100644 index 0000000..4411ca7 --- /dev/null +++ b/package/network/utils/iputils/patches/002-fix-ipv6.patch @@ -0,0 +1,14 @@ +--- a/Makefile ++++ b/Makefile +@@ -18,7 +18,10 @@ CFLAGS=$(CCOPT) $(GLIBCFIX) $(DEFINES) + + IPV4_TARGETS=tracepath ping clockdiff arping tftpd + IPV6_TARGETS=tracepath6 traceroute6 ping6 +-TARGETS=$(IPV4_TARGETS) $(IPV6_TARGETS) ++TARGETS=$(IPV4_TARGETS) ++ifeq ($(CONFIG_IPV6),y) ++ TARGETS=$(IPV4_TARGETS) $(IPV6_TARGETS) ++endif + + LASTTAG:=`git describe HEAD | sed -e 's/-.*//'` + TAG:=`date +s%Y%m%d` diff --git a/package/network/utils/iputils/patches/003-fix-makefile.patch b/package/network/utils/iputils/patches/003-fix-makefile.patch new file mode 100644 index 0000000..926c685 --- /dev/null +++ b/package/network/utils/iputils/patches/003-fix-makefile.patch @@ -0,0 +1,18 @@ +--- a/Makefile ++++ b/Makefile +@@ -30,9 +30,13 @@ all: $(TARGETS) + + + tftpd: tftpd.o tftpsubs.o +-arping: arping.o -lsysfs ++arping: arping.o ++ $(CC) $(CFLAGS) -o $@ arping.o -lsysfs + ping: ping.o ping_common.o +-ping6: ping6.o ping_common.o -lresolv -lcrypto ++ping6: ping6.o ping_common.o ++ifneq ($(CONFIG_USE_UCLIBC),y) ++ $(CC) $(CFLAGS) -o $@ ping6.o ping_common.o -lresolv -lcrypto ++endif + ping.o ping6.o ping_common.o: ping_common.h + tftpd.o tftpsubs.o: tftp.h + diff --git a/package/network/utils/iputils/patches/010-ping6_uclibc_resolv.patch b/package/network/utils/iputils/patches/010-ping6_uclibc_resolv.patch new file mode 100644 index 0000000..6955803 --- /dev/null +++ b/package/network/utils/iputils/patches/010-ping6_uclibc_resolv.patch @@ -0,0 +1,200 @@ +diff --git a/ping6.c b/ping6.c +index c5ff881..ef2243f 100644 +--- a/ping6.c ++++ b/ping6.c +@@ -71,9 +71,11 @@ char copyright[] = + #include <linux/filter.h> + #include <netinet/ip6.h> + #include <netinet/icmp6.h> ++#ifndef __UCLIBC__ + #include <resolv.h> + + #include "ping6_niquery.h" ++#endif /* __UCLIBC__ */ + + #ifndef SOL_IPV6 + #define SOL_IPV6 IPPROTO_IPV6 +@@ -154,6 +156,7 @@ int pmtudisc=-1; + + static int icmp_sock; + ++#ifndef __UCLIBC__ + #include <openssl/md5.h> + + /* Node Information query */ +@@ -165,6 +168,7 @@ int ni_subject_type = 0; + char *ni_group; + + __u8 ni_nonce[8]; ++#endif /* __UCLIBC__ */ + + static struct in6_addr in6_anyaddr; + static __inline__ int ipv6_addr_any(struct in6_addr *addr) +@@ -223,6 +227,7 @@ unsigned int if_name2index(const char *ifname) + return i; + } + ++#ifndef __UCLIBC__ + struct niquery_option { + char *name; + int namelen; +@@ -512,6 +517,7 @@ char *ni_groupaddr(const char *name) + strcat(nigroup_buf, q); + return nigroup_buf; + } ++#endif /* __UCLIBC__ */ + + int main(int argc, char *argv[]) + { +@@ -595,12 +601,14 @@ int main(int argc, char *argv[]) + case 'V': + printf("ping6 utility, iputils-ss%s\n", SNAPSHOT); + exit(0); ++#ifndef __UCLIBC__ + case 'N': + if (niquery_option_handler(optarg) < 0) { + usage(); + break; + } + break; ++#endif /* __UCLIBC__ */ + COMMON_OPTIONS + common_options(ch); + break; +@@ -663,6 +671,7 @@ int main(int argc, char *argv[]) + argc--; + } + ++#ifndef __UCLIBC__ + if (ni_query >= 0) { + int i; + for (i = 0; i < 8; i++) +@@ -674,15 +683,20 @@ int main(int argc, char *argv[]) + ni_subject_type = NI_SUBJ_IPV6; + } + } ++#endif /* __UCLIBC__ */ + + if (argc > 1) + usage(); + else if (argc == 1) { + target = *argv; + } else { ++#ifndef __UCLIBC__ + if (ni_query < 0 && ni_subject_type != NI_SUBJ_NAME) ++#endif /* __UCLIBC__ */ + usage(); ++#ifndef __UCLIBC__ + target = ni_group; ++#endif /* __UCLIBC__ */ + } + + memset(&hints, 0, sizeof(hints)); +@@ -817,7 +831,11 @@ int main(int argc, char *argv[]) + exit(2); + } + ++#ifndef __UCLIBC__ + if (datalen >= sizeof(struct timeval) && (ni_query < 0)) { ++#else ++ if (datalen >= sizeof(struct timeval)) { ++#endif /* __UCLIBC__ */ + /* can we time transfer */ + timing = 1; + } +@@ -866,9 +884,11 @@ int main(int argc, char *argv[]) + ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &filter); + } + ++#ifndef __UCLIBC__ + if (ni_query >= 0) + ICMP6_FILTER_SETPASS(ICMPV6_NI_REPLY, &filter); + else ++#endif /* __UCLIBC__ */ + ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filter); + + err = setsockopt(icmp_sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, +@@ -1100,6 +1120,7 @@ int build_echo(__u8 *_icmph) + return cc; + } + ++#ifndef __UCLIBC__ + int build_niquery(__u8 *_nih) + { + struct ni_hdr *nih; +@@ -1125,6 +1146,7 @@ int build_niquery(__u8 *_nih) + + return cc; + } ++#endif /* __UCLIBC__ */ + + int send_probe(void) + { +@@ -1132,9 +1154,11 @@ int send_probe(void) + + CLR((ntransmitted+1) % mx_dup_ck); + ++#ifndef __UCLIBC__ + if (ni_query >= 0) + len = build_niquery(outpack); + else ++#endif /* __UCLIBC__ */ + len = build_echo(outpack); + + if (cmsglen == 0) { +@@ -1176,6 +1200,7 @@ static void putchar_safe(char c) + printf("\\%03o", c); + } + ++#ifndef __UCLIBC__ + void pr_niquery_reply_name(struct ni_hdr *nih, int len) + { + __u8 *h = (__u8 *)(nih + 1); +@@ -1304,6 +1329,7 @@ void pr_niquery_reply(__u8 *_nih, int len) + } + putchar(';'); + } ++#endif /* __UCLIBC__ */ + + /* + * parse_reply -- +@@ -1353,6 +1379,7 @@ parse_reply(struct msghdr *msg, int cc, void *addr, struct timeval *tv) + hops, 0, tv, pr_addr(&from->sin6_addr), + pr_echo_reply)) + return 0; ++#ifndef __UCLIBC__ + } else if (icmph->icmp6_type == ICMPV6_NI_REPLY) { + struct ni_hdr *nih = (struct ni_hdr *)icmph; + __u16 seq = ntohs(*(__u16 *)nih->ni_nonce); +@@ -1363,6 +1390,7 @@ parse_reply(struct msghdr *msg, int cc, void *addr, struct timeval *tv) + hops, 0, tv, pr_addr(&from->sin6_addr), + pr_niquery_reply)) + return 0; ++#endif /* __UCLIBC__ */ + } else { + int nexthdr; + struct ip6_hdr *iph1 = (struct ip6_hdr*)(icmph+1); +@@ -1557,7 +1585,9 @@ void usage(void) + "Usage: ping6 [-LUdfnqrvVaAD] [-c count] [-i interval] [-w deadline]\n" + " [-p pattern] [-s packetsize] [-t ttl] [-I interface]\n" + " [-M pmtudisc-hint] [-S sndbuf] [-F flowlabel] [-Q tclass]\n" ++#ifndef __UCLIBC__ + " [[-N nodeinfo-option] ...]\n" ++#endif /* __UCLIBC__ */ + " [hop1 ...] destination\n"); + exit(2); + } +diff --git a/ping6_niquery.h b/ping6_niquery.h +index 61a5cfa..34c31f8 100644 +--- a/ping6_niquery.h ++++ b/ping6_niquery.h +@@ -1,3 +1,4 @@ ++#ifndef __UCLIBC__ + #include <asm/byteorder.h> + + /* Node Information Query */ +@@ -45,3 +46,4 @@ struct ni_hdr { + #define NI_IPV4ADDR_F_TRUNCATE NI_IPV6ADDR_F_TRUNCATE + #define NI_IPV4ADDR_F_ALL NI_IPV6ADDR_F_ALL + ++#endif /* __UCLIBC__ */ diff --git a/package/network/utils/iputils/patches/011-ping6_use_gnu_source.patch b/package/network/utils/iputils/patches/011-ping6_use_gnu_source.patch new file mode 100644 index 0000000..dc61b8c --- /dev/null +++ b/package/network/utils/iputils/patches/011-ping6_use_gnu_source.patch @@ -0,0 +1,11 @@ +--- a/ping6.c ++++ b/ping6.c +@@ -66,6 +66,8 @@ char copyright[] = + * More statistics could always be gathered. + * This program has to run SUID to ROOT to access the ICMP socket. + */ ++ ++#define _GNU_SOURCE + #include "ping_common.h" + + #include <linux/filter.h> diff --git a/package/network/utils/iputils/patches/020-include_fixes.patch b/package/network/utils/iputils/patches/020-include_fixes.patch new file mode 100644 index 0000000..e982dab --- /dev/null +++ b/package/network/utils/iputils/patches/020-include_fixes.patch @@ -0,0 +1,71 @@ +--- a/ping_common.h ++++ b/ping_common.h +@@ -2,6 +2,7 @@ + #include <stdlib.h> + #include <unistd.h> + #include <time.h> ++#include <sys/types.h> + #include <sys/param.h> + #include <sys/socket.h> + #include <linux/sockios.h> +@@ -11,7 +12,7 @@ + #include <sys/ioctl.h> + #include <net/if.h> + #include <sys/uio.h> +-#include <sys/poll.h> ++#include <poll.h> + #include <ctype.h> + #include <errno.h> + #include <string.h> +@@ -24,6 +25,10 @@ + + #include "SNAPSHOT.h" + ++#ifndef HZ ++#define HZ 100 ++#endif ++ + #define DEFDATALEN (64 - 8) /* default data length */ + + #define MAXWAIT 10 /* max seconds to wait for response */ +--- a/clockdiff.c ++++ b/clockdiff.c +@@ -13,8 +13,6 @@ + #include <netinet/in.h> + #include <netinet/ip.h> + #include <netinet/ip_icmp.h> +-#define TSPTYPES +-#include <protocols/timed.h> + #include <fcntl.h> + #include <netdb.h> + #include <arpa/inet.h> +--- a/tracepath.c ++++ b/tracepath.c +@@ -13,6 +13,7 @@ + #include <stdlib.h> + #include <unistd.h> + #include <sys/socket.h> ++#include <sys/time.h> + #include <linux/types.h> + #include <linux/errqueue.h> + #include <errno.h> +--- a/ping.c ++++ b/ping.c +@@ -661,8 +661,15 @@ int send_probe() + + do { + static struct iovec iov = {outpack, 0}; +- static struct msghdr m = { &whereto, sizeof(whereto), +- &iov, 1, &cmsg, 0, 0 }; ++ static struct msghdr m = { ++ .msg_name = &whereto, ++ .msg_namelen = sizeof(whereto), ++ .msg_iov = &iov, ++ .msg_iovlen = 1, ++ .msg_control = &cmsg, ++ .msg_controllen = 0, ++ .msg_flags = 0 ++ }; + m.msg_controllen = cmsg_len; + iov.iov_len = cc; + diff --git a/package/network/utils/iw/Makefile b/package/network/utils/iw/Makefile new file mode 100644 index 0000000..53cfee3 --- /dev/null +++ b/package/network/utils/iw/Makefile @@ -0,0 +1,57 @@ +# +# 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:=4.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=https://www.kernel.org/pub/software/network/iw +PKG_MD5SUM:=3a292dd342bb88e30e74015ae6fe1e54 + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +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 +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) -ffunction-sections -fdata-sections" \ + LDFLAGS="$(TARGET_LDFLAGS) -Wl,--gc-sections" \ + 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)) diff --git a/package/network/utils/iw/patches/001-nl80211_h_sync.patch b/package/network/utils/iw/patches/001-nl80211_h_sync.patch new file mode 100644 index 0000000..afa5506 --- /dev/null +++ b/package/network/utils/iw/patches/001-nl80211_h_sync.patch @@ -0,0 +1,100 @@ +--- a/nl80211.h ++++ b/nl80211.h +@@ -1761,6 +1761,9 @@ enum nl80211_commands { + * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device + * is operating in an indoor environment. + * ++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce ++ * transmit power to stay within regulatory limits. u32, dBi. ++ * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +@@ -2130,6 +2133,8 @@ enum nl80211_attrs { + + NL80211_ATTR_REG_INDOOR, + ++ NL80211_ATTR_WIPHY_ANTENNA_GAIN, ++ + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, +@@ -2620,16 +2625,17 @@ enum nl80211_band_attr { + * an indoor surroundings, i.e., it is connected to AC power (and not + * through portable DC inverters) or is under the control of a master + * that is acting as an AP and is connected to AC power. +- * @NL80211_FREQUENCY_ATTR_GO_CONCURRENT: GO operation is allowed on this ++ * @NL80211_FREQUENCY_ATTR_IR_CONCURRENT: IR operation is allowed on this + * channel if it's connected concurrently to a BSS on the same channel on + * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz +- * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO on a +- * channel that has the GO_CONCURRENT attribute set can be done when there +- * is a clear assessment that the device is operating under the guidance of +- * an authorized master, i.e., setting up a GO while the device is also +- * connected to an AP with DFS and radar detection on the UNII band (it is +- * up to user-space, i.e., wpa_supplicant to perform the required +- * verifications) ++ * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO or TDLS ++ * off-channel on a channel that has the IR_CONCURRENT attribute set can be ++ * done when there is a clear assessment that the device is operating under ++ * the guidance of an authorized master, i.e., setting up a GO or TDLS ++ * off-channel while the device is also connected to an AP with DFS and ++ * radar detection on the UNII band (it is up to user-space, i.e., ++ * wpa_supplicant to perform the required verifications). Using this ++ * attribute for IR is disallowed for master interfaces (IBSS, AP). + * @NL80211_FREQUENCY_ATTR_NO_20MHZ: 20 MHz operation is not allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_10MHZ: 10 MHz operation is not allowed +@@ -2641,7 +2647,7 @@ enum nl80211_band_attr { + * See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122 + * for more information on the FCC description of the relaxations allowed + * by NL80211_FREQUENCY_ATTR_INDOOR_ONLY and +- * NL80211_FREQUENCY_ATTR_GO_CONCURRENT. ++ * NL80211_FREQUENCY_ATTR_IR_CONCURRENT. + */ + enum nl80211_frequency_attr { + __NL80211_FREQUENCY_ATTR_INVALID, +@@ -2659,7 +2665,7 @@ enum nl80211_frequency_attr { + NL80211_FREQUENCY_ATTR_NO_160MHZ, + NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, + NL80211_FREQUENCY_ATTR_INDOOR_ONLY, +- NL80211_FREQUENCY_ATTR_GO_CONCURRENT, ++ NL80211_FREQUENCY_ATTR_IR_CONCURRENT, + NL80211_FREQUENCY_ATTR_NO_20MHZ, + NL80211_FREQUENCY_ATTR_NO_10MHZ, + +@@ -2672,6 +2678,8 @@ enum nl80211_frequency_attr { + #define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR + #define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR + #define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR ++#define NL80211_FREQUENCY_ATTR_GO_CONCURRENT \ ++ NL80211_FREQUENCY_ATTR_IR_CONCURRENT + + /** + * enum nl80211_bitrate_attr - bitrate attributes +@@ -2830,7 +2838,7 @@ enum nl80211_sched_scan_match_attr { + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. +- * @NL80211_RRF_GO_CONCURRENT: See &NL80211_FREQUENCY_ATTR_GO_CONCURRENT ++ * @NL80211_RRF_IR_CONCURRENT: See &NL80211_FREQUENCY_ATTR_IR_CONCURRENT + * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation + * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation + * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed +@@ -2847,7 +2855,7 @@ enum nl80211_reg_rule_flags { + NL80211_RRF_NO_IR = 1<<7, + __NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, +- NL80211_RRF_GO_CONCURRENT = 1<<12, ++ NL80211_RRF_IR_CONCURRENT = 1<<12, + NL80211_RRF_NO_HT40MINUS = 1<<13, + NL80211_RRF_NO_HT40PLUS = 1<<14, + NL80211_RRF_NO_80MHZ = 1<<15, +@@ -2859,6 +2867,7 @@ enum nl80211_reg_rule_flags { + #define NL80211_RRF_NO_IR NL80211_RRF_NO_IR + #define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\ + NL80211_RRF_NO_HT40PLUS) ++#define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT + + /* For backport compatibility with older userspace */ + #define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) diff --git a/package/network/utils/iw/patches/120-antenna_gain.patch b/package/network/utils/iw/patches/120-antenna_gain.patch new file mode 100644 index 0000000..8de3df2 --- /dev/null +++ b/package/network/utils/iw/patches/120-antenna_gain.patch @@ -0,0 +1,34 @@ +--- a/phy.c ++++ b/phy.c +@@ -532,3 +532,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."); diff --git a/package/network/utils/iw/patches/200-reduce_size.patch b/package/network/utils/iw/patches/200-reduce_size.patch new file mode 100644 index 0000000..3ba4730 --- /dev/null +++ b/package/network/utils/iw/patches/200-reduce_size.patch @@ -0,0 +1,255 @@ +--- a/Makefile ++++ b/Makefile +@@ -15,8 +15,8 @@ CFLAGS += -Wall -Wundef -Wstrict-prototy + OBJS = iw.o genl.o event.o info.o phy.o \ + interface.o ibss.o station.o survey.o util.o ocb.o \ + mesh.o mpath.o mpp.o scan.o reg.o version.o \ +- reason.o status.o connect.o link.o offch.o ps.o cqm.o \ +- bitrate.o wowlan.o coalesce.o roc.o p2p.o vendor.o ++ reason.o status.o link.o offch.o ps.o cqm.o \ ++ bitrate.o vendor.o + OBJS += sections.o + + OBJS-$(HWSIM) += hwsim.o +--- a/info.c ++++ b/info.c +@@ -219,6 +219,7 @@ next: + } + } + ++#if 0 + if (tb_band[NL80211_BAND_ATTR_RATES]) { + printf("\t\tBitrates (non-HT):\n"); + nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { +@@ -235,6 +236,7 @@ next: + printf("\n"); + } + } ++#endif + } + } + +@@ -291,6 +293,7 @@ next: + printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); + } + ++#if 0 + if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) { + int num = nla_len(tb_msg[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32); + int i; +@@ -302,6 +305,7 @@ next: + cipher_name(ciphers[i])); + } + } ++#endif + + if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] && + tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]) +@@ -321,11 +325,13 @@ next: + printf("\t\t * %s\n", iftype_name(nla_type(nl_mode))); + } + ++#if 0 + if (tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]) { + printf("\tsoftware interface modes (can always be added):\n"); + nla_for_each_nested(nl_mode, tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES], rem_mode) + printf("\t\t * %s\n", iftype_name(nla_type(nl_mode))); + } ++#endif + + if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) { + struct nlattr *nl_combi; +@@ -422,6 +428,7 @@ broken_combination: + printf("\tinterface combinations are not supported\n"); + } + ++#if 0 + if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) { + printf("\tSupported commands:\n"); + nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], rem_cmd) +@@ -518,6 +525,7 @@ broken_combination: + printf("\t\t * wake up on TCP connection\n"); + } + } ++#endif + + if (tb_msg[NL80211_ATTR_ROAM_SUPPORT]) + printf("\tDevice supports roaming.\n"); +@@ -554,6 +562,7 @@ broken_combination: + } + } + ++#if 0 + if (tb_msg[NL80211_ATTR_FEATURE_FLAGS]) { + unsigned int features = nla_get_u32(tb_msg[NL80211_ATTR_FEATURE_FLAGS]); + +@@ -612,6 +621,7 @@ broken_combination: + if (features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) + printf("\tDevice supports TDLS channel switching\n"); + } ++#endif + + if (tb_msg[NL80211_ATTR_EXT_FEATURES]) { + struct nlattr *tb = tb_msg[NL80211_ATTR_EXT_FEATURES]; +@@ -669,6 +679,7 @@ TOPLEVEL(list, NULL, NL80211_CMD_GET_WIP + "List all wireless devices and their capabilities."); + TOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, NULL); + ++#if 0 + static int handle_commands(struct nl80211_state *state, + struct nl_cb *cb, struct nl_msg *msg, + int argc, char **argv, enum id_input id) +@@ -681,6 +692,7 @@ static int handle_commands(struct nl8021 + } + TOPLEVEL(commands, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_NONE, handle_commands, + "list all known commands and their decimal & hex value"); ++#endif + + static int print_feature_handler(struct nl_msg *msg, void *arg) + { +--- a/scan.c ++++ b/scan.c +@@ -1080,6 +1080,7 @@ static void print_ht_op(const uint8_t ty + printf("\t\t * secondary channel offset: %s\n", + ht_secondary_offset[data[1] & 0x3]); + printf("\t\t * STA channel width: %s\n", sta_chan_width[(data[1] & 0x4)>>2]); ++ return; + printf("\t\t * RIFS: %d\n", (data[1] & 0x8)>>3); + printf("\t\t * HT protection: %s\n", protection[data[2] & 0x3]); + printf("\t\t * non-GF present: %d\n", (data[2] & 0x4) >> 2); +@@ -1311,6 +1312,13 @@ static void print_ie(const struct ie_pri + + static const struct ie_print ieprinters[] = { + [0] = { "SSID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, ++ [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, ++ [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, ++ [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, ++ [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, ++ [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, ++ [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, ++#if 0 + [1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, + [3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, + [5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, +@@ -1320,14 +1328,8 @@ static const struct ie_print ieprinters[ + [32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), }, + [35] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, + [42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, + [47] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, + [74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, +- [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, +- [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, +- [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, +- [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +- [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, + [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, + [113] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, + [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, +@@ -1335,6 +1337,7 @@ static const struct ie_print ieprinters[ + [107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), }, + [108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), }, + [111] = { "802.11u Roaming Consortium", print_11u_rcon, 0, 255, BIT(PRINT_SCAN), }, ++#endif + }; + + static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data) +@@ -1766,6 +1769,7 @@ void print_ies(unsigned char *ie, int ie + ieprinters[ie[0]].name && + ieprinters[ie[0]].flags & BIT(ptype)) { + print_ie(&ieprinters[ie[0]], ie[0], ie[1], ie + 2); ++#if 0 + } else if (ie[0] == 221 /* vendor */) { + print_vendor(ie[1], ie + 2, unknown, ptype); + } else if (unknown) { +@@ -1775,6 +1779,7 @@ void print_ies(unsigned char *ie, int ie + for (i=0; i<ie[1]; i++) + printf(" %.2x", ie[2+i]); + printf("\n"); ++#endif + } + ielen -= ie[1] + 2; + ie += ie[1] + 2; +@@ -1815,6 +1820,7 @@ static void print_capa_non_dmg(__u16 cap + printf(" ESS"); + if (capa & WLAN_CAPABILITY_IBSS) + printf(" IBSS"); ++#if 0 + if (capa & WLAN_CAPABILITY_CF_POLLABLE) + printf(" CfPollable"); + if (capa & WLAN_CAPABILITY_CF_POLL_REQUEST) +@@ -1843,6 +1849,7 @@ static void print_capa_non_dmg(__u16 cap + printf(" DelayedBACK"); + if (capa & WLAN_CAPABILITY_IMM_BACK) + printf(" ImmediateBACK"); ++#endif + } + + static int print_bss_handler(struct nl_msg *msg, void *arg) +@@ -1921,8 +1928,10 @@ static int print_bss_handler(struct nl_m + if (bss[NL80211_BSS_FREQUENCY]) { + int freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); + printf("\tfreq: %d\n", freq); ++#if 0 + if (freq > 45000) + is_dmg = true; ++#endif + } + if (bss[NL80211_BSS_BEACON_INTERVAL]) + printf("\tbeacon interval: %d TUs\n", +--- a/util.c ++++ b/util.c +@@ -264,6 +264,7 @@ static const char *commands[NL80211_CMD_ + + static char cmdbuf[100]; + ++#if 0 + const char *command_name(enum nl80211_commands cmd) + { + if (cmd <= NL80211_CMD_MAX && commands[cmd]) +@@ -271,6 +272,7 @@ const char *command_name(enum nl80211_co + sprintf(cmdbuf, "Unknown command (%d)", cmd); + return cmdbuf; + } ++#endif + + int ieee80211_channel_to_frequency(int chan, enum nl80211_band band) + { +--- a/event.c ++++ b/event.c +@@ -334,6 +334,7 @@ static int print_event(struct nl_msg *ms + } + + switch (gnlh->cmd) { ++#if 0 + case NL80211_CMD_NEW_WIPHY: + printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME])); + break; +@@ -368,6 +369,7 @@ static int print_event(struct nl_msg *ms + case NL80211_CMD_SCHED_SCAN_RESULTS: + printf("got scheduled scan results\n"); + break; ++#endif + case NL80211_CMD_REG_CHANGE: + printf("regulatory domain change: "); + +@@ -446,6 +448,7 @@ static int print_event(struct nl_msg *ms + mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); + printf("del station %s\n", macbuf); + break; ++#if 0 + case NL80211_CMD_JOIN_IBSS: + mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); + printf("IBSS %s joined\n", macbuf); +@@ -599,9 +602,9 @@ static int print_event(struct nl_msg *ms + } + printf("\n"); + break; ++#endif + default: +- printf("unknown event %d (%s)\n", +- gnlh->cmd, command_name(gnlh->cmd)); ++ printf("unknown event %d\n", gnlh->cmd); + break; + } + diff --git a/package/network/utils/iwcap/Makefile b/package/network/utils/iwcap/Makefile new file mode 100644 index 0000000..d3f8847 --- /dev/null +++ b/package/network/utils/iwcap/Makefile @@ -0,0 +1,51 @@ +# +# 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 +PKG_LICENSE:=Apache-2.0 + +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)) diff --git a/package/network/utils/iwcap/src/iwcap.c b/package/network/utils/iwcap/src/iwcap.c new file mode 100644 index 0000000..d335e50 --- /dev/null +++ b/package/network/utils/iwcap/src/iwcap.c @@ -0,0 +1,583 @@ +/* + * 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 <byteswap.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; +} diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile new file mode 100644 index 0000000..6de47e8 --- /dev/null +++ b/package/network/utils/iwinfo/Makefile @@ -0,0 +1,121 @@ +# +# Copyright (C) 2010-2015 Jo-Philipp Wich <jow@openwrt.org> +# +# This is free software, licensed under the GPL 2 license. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libiwinfo +PKG_VERSION:=2015-10-05 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=http://git.openwrt.org/project/iwinfo.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=813f61e48b9b1a76cb55f3b4a229bf98d3cd53a9 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +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-cfg80211 + +include $(INCLUDE_DIR)/package.mk + + +define Package/libiwinfo + SECTION:=libs + CATEGORY:=Libraries + TITLE:=Generalized Wireless Information Library (iwinfo) + DEPENDS:=+PACKAGE_kmod-cfg80211:libnl-tiny +libuci + ABI_VERSION:=$(PKG_RELEASE) +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 +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 +endef + +define Package/iwinfo/description + Command line frontend for the wireless information library. +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-cfg80211),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 + $(INSTALL_DIR) $(1)/usr/share/libiwinfo + $(INSTALL_DATA) $(PKG_BUILD_DIR)/hardware.txt $(1)/usr/share/libiwinfo/hardware.txt +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)) diff --git a/package/network/utils/linux-atm/Makefile b/package/network/utils/linux-atm/Makefile new file mode 100644 index 0000000..d9402c3 --- /dev/null +++ b/package/network/utils/linux-atm/Makefile @@ -0,0 +1,193 @@ +# +# 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:=linux-atm +PKG_VERSION:=2.5.2 +PKG_RELEASE:=5 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@SF/$(PKG_NAME) +PKG_MD5SUM:=d49499368c3cf15f73a05d9bce8824a8 + +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 +PKG_CHECK_FORMAT_SECURITY:=0 +PKG_LICENSE:=GPL-2.0+ +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +ATM_DEBUG_BINS:=aread awrite atmdiag atmdump atmswitch saaldump \ + sonetdiag svc_recv svc_send ttcp_atm +ATM_DEBUG_SBINS:=atmaddr atmloop atmtcp esi atmsigd bus \ + ilmid ilmidiag lecs les mpcd zeppelin +ATM_DEBUG_TOOLS:=$(ATM_DEBUG_BINS) $(ATM_DEBUG_SBINS) + +define Package/linux-atm + SECTION:=libs + CATEGORY:=Libraries + TITLE:=Linux ATM library + URL:=http://linux-atm.sourceforge.net/ +endef + +define Package/linux-atm/description + This package contains a library for accessing the Linux ATM subsystem. +endef + +define Package/linux-atm/Default + SECTION:=net + CATEGORY:=Network + DEPENDS:=+linux-atm + URL:=http://linux-atm.sourceforge.net/ + SUBMENU:=Linux ATM tools +endef + +define Package/atm-tools + $(call Package/linux-atm/Default) + TITLE:=Linux ATM tools +endef + +define Package/atm-tools/description + This package contains the Linux ATM tools. +endef + +define Package/atm-diagnostics + $(call Package/linux-atm/Default) + TITLE:=Linux ATM Diagnostics +endef + +define Package/atm-diagnostics/description + This package contains the Linux ATM diagnostics. +endef + +define Package/atm-debug-tools + $(call Package/linux-atm/Default) + TITLE:=Linux ATM debugging tools +endef + +define Package/atm-debug-tools/description + This package contains the Linux ATM debugging tools. +endef + +define Package/br2684ctl + $(call Package/linux-atm/Default) + TITLE:=ATM Ethernet bridging configuration utility +endef + +define Package/br2684ctl/description + Support for AAL5 encapsulation (RFC-1483/RFC-2684) over ATM. +endef + +define GenAtmPlugin + define Package/$(1) + $(call Package/linux-atm/Default) + TITLE:=Linux ATM tool $(2) + endef + + define Package/$(1)/description + Linux ATM tool $(2). + endef +endef + +$(foreach t,$(ATM_DEBUG_TOOLS),$(eval $(call GenAtmPlugin,atm-$(t),$(t)))) + +define Build/Configure + $(call Build/Configure/Default) + # prevent autoheader invocation + touch $(PKG_BUILD_DIR)/stamp-h.in +endef + +unexport PREFIX + +define Build/Compile + # src/qgen is built with HOSTCC, which does not really like our LDFLAGS + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/src/qgen \ + LDFLAGS="" \ + all + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) OBJCOPY=$(TARGET_CROSS)objcopy all +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1)/usr + $(CP) \ + $(PKG_INSTALL_DIR)/usr/include \ + $(PKG_INSTALL_DIR)/usr/lib \ + $(1)/usr/ +endef + +define Package/linux-atm/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libatm.so* $(1)/usr/lib/ +endef + +define Package/atm-tools/install + $(INSTALL_DIR) $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmarp{,d} $(1)/usr/sbin/ +endef + + +define BuildAtmPlugin + define Package/$(1)/install + $(INSTALL_DIR) $$(1)/usr/$(3) + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/$(3)/$(2) $$(1)/usr/$(3) + endef + + $$(eval $$(call BuildPackage,$(1))) +endef + +define Package/atm-debug-tools/install + $(INSTALL_DIR) $(1)/usr/bin/ + $(INSTALL_DIR) $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmaddr $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmloop $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmtcp $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/esi $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/aread $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/awrite $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdiag $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdump $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/atmsigd $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/bus $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ilmid $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/ilmidiag $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/lecs $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/les $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/mpcd $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/zeppelin $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmswitch $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/saaldump $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/sonetdiag $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/svc_recv $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/svc_send $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ttcp_atm $(1)/usr/bin/ +endef + +define Package/atm-diagnostics/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/aread $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/awrite $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdiag $(1)/usr/bin/ + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/atmdump $(1)/usr/bin/ +endef + +define Package/br2684ctl/install + $(INSTALL_DIR) $(1)/etc/init.d/ + $(INSTALL_BIN) ./files/br2684ctl $(1)/etc/init.d/ + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/br2684ctl $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,linux-atm)) +$(eval $(call BuildPackage,atm-tools)) +$(eval $(call BuildPackage,atm-debug-tools)) +$(eval $(call BuildPackage,atm-diagnostics)) +$(eval $(call BuildPackage,br2684ctl)) +$(foreach t,$(ATM_DEBUG_BINS),$(eval $(call BuildAtmPlugin,atm-$(t),$(t),bin))) +$(foreach t,$(ATM_DEBUG_SBINS),$(eval $(call BuildAtmPlugin,atm-$(t),$(t),sbin))) diff --git a/package/network/utils/linux-atm/files/br2684ctl b/package/network/utils/linux-atm/files/br2684ctl new file mode 100755 index 0000000..30b1a44 --- /dev/null +++ b/package/network/utils/linux-atm/files/br2684ctl @@ -0,0 +1,89 @@ +#!/bin/sh /etc/rc.common + +START=50 + +SERVICE_DAEMONIZE=1 +SERVICE_WRITE_PID=1 + +start_daemon() { + . /lib/functions/network.sh + + local cfg="$1" + + local atmdev + config_get atmdev "$cfg" atmdev 0 + + local unit + config_get unit "$cfg" unit 0 + + local vpi + config_get vpi "$cfg" vpi 8 + + local vci + config_get vci "$cfg" vci 35 + + local encaps + config_get encaps "$cfg" encaps + + case "$encaps" in + 1|vc) encaps=1;; + *) encaps=0;; + esac + + local payload + config_get payload "$cfg" payload + + case "$payload" in + 0|routed) payload=0;; + *) payload=1;; + esac + + local qos + config_get qos "$cfg" qos + + local sendsize + config_get sendsize "$cfg" sendsize + + local circuit="$atmdev.$vpi.$vci" + + network_defer_device "nas$unit" + + SERVICE_PID_FILE="/var/run/br2684ctl-$circuit.pid" \ + service_start /usr/sbin/br2684ctl \ + -c "$unit" -e "$encaps" -p "$payload" \ + -a "$circuit" ${qos:+-q "$qos"} ${sendsize:+-s "$sendsize"} + sleep 1 + + network_ready_device "nas$unit" +} + +stop_daemon() { + local cfg="$1" + + local atmdev + config_get atmdev "$cfg" atmdev 0 + + local unit + config_get unit "$cfg" unit 0 + + local vpi + config_get vpi "$cfg" vpi 8 + + local vci + config_get vci "$cfg" vci 35 + + local circuit="$atmdev.$vpi.$vci" + + SERVICE_PID_FILE="/var/run/br2684ctl-$circuit.pid" \ + service_stop /usr/sbin/br2684ctl +} + +start() { + config_load network + config_foreach start_daemon atm-bridge +} + +stop() { + config_load network + config_foreach stop_daemon atm-bridge +} diff --git a/package/network/utils/linux-atm/patches/000-debian_16.patch b/package/network/utils/linux-atm/patches/000-debian_16.patch new file mode 100644 index 0000000..4abaac0 --- /dev/null +++ b/package/network/utils/linux-atm/patches/000-debian_16.patch @@ -0,0 +1,270 @@ +--- a/src/arpd/io.c ++++ b/src/arpd/io.c +@@ -277,7 +277,8 @@ static void accept_new(void) + struct atm_qos qos; + ENTRY *entry; + VCC *vcc; +- int fd,len,size,error; ++ int fd,error; ++ socklen_t len,size; + + len = sizeof(addr); + if ((fd = accept(incoming,(struct sockaddr *) &addr,&len)) < 0) { +@@ -614,7 +615,8 @@ int ip_itf_info(int number,uint32_t *ip, + + int get_local(int fd,struct sockaddr_atmsvc *addr) + { +- int length,result; ++ int result; ++ size_t length; + + length = sizeof(struct sockaddr_atmsvc); + result = getsockname(fd,(struct sockaddr *) addr,&length); +--- a/src/arpd/table.c ++++ b/src/arpd/table.c +@@ -101,7 +101,8 @@ static void dump_vcc(VCC *vcc) + char addr_buf[MAX_ATM_ADDR_LEN+1]; + char qos_buf[MAX_ATM_QOS_LEN+1]; + struct atm_qos qos; +- int size,sndbuf; ++ int sndbuf; ++ socklen_t size; + + size = sizeof(addr); + if (getpeername(vcc->fd,(struct sockaddr *) &addr,&size) < 0) { +--- a/src/ilmid/asn1/asn_int.c ++++ b/src/ilmid/asn1/asn_int.c +@@ -185,7 +185,7 @@ FILE* f _AND_ + AsnInt* v _AND_ + unsigned short int indent) + { +- fprintf(f,"%d", *v); ++ fprintf(f,"%ld", *v); + } + + +@@ -370,5 +370,5 @@ FILE* f _AND_ + UAsnInt* v _AND_ + unsigned short int indent) + { +- fprintf(f,"%u", *v); ++ fprintf(f,"%lu", *v); + } +--- a/src/ilmid/asn1/asn_oid.c ++++ b/src/ilmid/asn1/asn_oid.c +@@ -127,7 +127,7 @@ unsigned short int indent) + if (firstArcNum > 2) + firstArcNum = 2; + +- fprintf(f,"%u %u", firstArcNum, arcNum - (firstArcNum * 40)); ++ fprintf(f,"%d %lu", firstArcNum, arcNum - (firstArcNum * 40)); + + for (; i < v->octetLen ; ) + { +@@ -136,7 +136,7 @@ unsigned short int indent) + + arcNum = (arcNum << 7) + (v->octs[i] & 0x7f); + i++; +- fprintf(f," %u", arcNum); ++ fprintf(f," %lu", arcNum); + } + fprintf(f,"}"); + +--- a/src/lane/connect.c ++++ b/src/lane/connect.c +@@ -258,7 +258,8 @@ static int + data_handler(const Event_t *event, void *funcdata) + { + Conn_t *tmp, *newconn; +- int fd, nbytes; ++ int fd; ++ socklen_t nbytes; + static char buffer[BUFSIZE]; + LaneControl_t *ctmp; + struct sockaddr_atmsvc addr; +--- a/src/lane/connect_bus.c ++++ b/src/lane/connect_bus.c +@@ -170,7 +170,8 @@ static int + data_handler(const Event_t *event, void *funcdata) + { + Conn_t *tmp, *newconn; +- int fd, nbytes; ++ int fd; ++ socklen_t nbytes; + static char buffer[BUFSIZE]; + struct sockaddr_atmsvc addr; + +--- a/src/lane/lane_atm.c ++++ b/src/lane/lane_atm.c +@@ -138,7 +138,7 @@ atm_connect_back(const AtmAddr_t *our_ad + struct atm_blli blli; + struct atm_qos qos; + int fd, ret; +- int len = sizeof(address); ++ socklen_t len = sizeof(address); + + fd = socket(PF_ATMSVC, SOCK_DGRAM, 0); + if (fd <0) { +--- a/src/lane/lecs.c ++++ b/src/lane/lecs.c +@@ -119,7 +119,7 @@ int main(int argc, char **argv) + int just_dump=0; + fd_set fds; + struct sockaddr_atmsvc client; +- int len; ++ socklen_t len; + unsigned char buffer[P_SIZE]; + + while(i!=-1) { +--- a/src/lib/ans.c ++++ b/src/lib/ans.c +@@ -41,7 +41,7 @@ + static int ans(const char *text,int wanted,void *result,int res_len) + { + unsigned char answer[MAX_ANSWER]; +- unsigned char name[MAX_NAME]; ++ char name[MAX_NAME]; + unsigned char *pos,*data,*found; + int answer_len,name_len,data_len,found_len; + int questions,answers; +--- a/src/lib/sdu2cell.c ++++ b/src/lib/sdu2cell.c +@@ -15,7 +15,8 @@ int sdu2cell(int s,int sizes,const int * + { + struct atm_qos qos; + int trailer,total,cells; +- int size,i; ++ int i; ++ socklen_t size; + + size = sizeof(qos); + if (getsockopt(s,SOL_AAL,SO_ATMQOS,&qos,&size) < 0) return -1; +--- a/src/lib/unix.c ++++ b/src/lib/unix.c +@@ -63,8 +63,8 @@ int un_attach(const char *path) + int un_recv_connect(int s,void *buf,int size) + { + struct sockaddr_un addr; +- int addr_size; + int len; ++ socklen_t addr_size; + + addr_size = sizeof(addr); + len = recvfrom(s,buf,size,0,(struct sockaddr *) &addr,&addr_size); +--- a/src/maint/atmtcp.c ++++ b/src/maint/atmtcp.c +@@ -817,7 +817,8 @@ int main(int argc,char **argv) + } + else if (!strcmp(ARG,"listen") || + (do_background = !strcmp(ARG,"listen-bg"))) { +- int fd,port,addr_len; ++ int fd,port; ++ socklen_t addr_len; + int *fd2 = alloc_t(int); + + if ((fd = socket(PF_INET,SOCK_STREAM,0)) < 0) { +--- a/src/maint/hediag.c ++++ b/src/maint/hediag.c +@@ -1,6 +1,7 @@ + #include <stdio.h> + #include <stdlib.h> + #include <unistd.h> ++#include <string.h> + #include <sys/ioctl.h> + #include <sys/types.h> + #include <sys/socket.h> +--- a/src/mpoad/io.c ++++ b/src/mpoad/io.c +@@ -521,7 +521,8 @@ static int msg_from_mps(int slot) + static int accept_conn(int slot) + { + struct sockaddr_atmsvc sa; +- int i, new_fd, sa_len; ++ int i, new_fd; ++ socklen_t sa_len; + + sa_len = sizeof(sa); + new_fd = accept(fds[slot].fd, (struct sockaddr *)&sa, &sa_len); +--- a/src/sigd/io.c ++++ b/src/sigd/io.c +@@ -355,7 +355,7 @@ int get_pvc(int itf,int *vci) + error = 0; + if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) error = errno; + else { +- int size; ++ socklen_t size; + + size = sizeof(addr); + if (getsockname(s,(struct sockaddr *) &addr,&size) < 0) +--- a/src/test/ttcp.c ++++ b/src/test/ttcp.c +@@ -92,7 +92,8 @@ struct sockaddr_in frominet; + struct sockaddr_atmsvc satm; + struct atm_qos qos; + +-int domain, fromlen; ++int domain; ++socklen_t fromlen; + int fd; /* fd of network socket */ + + int buflen = 8 * 1024; /* length of buffer */ +@@ -466,7 +467,7 @@ int no_check = 0; + + { + struct sockaddr_atmsvc peer; +- int peerlen = sizeof(peer); ++ socklen_t peerlen = sizeof(peer); + if (getpeername(fd, (struct sockaddr *) &peer, + &peerlen) < 0) { + err("getpeername"); +@@ -498,7 +499,7 @@ int no_check = 0; + /* set socket buffer size */ + #if defined(SO_SNDBUF) || defined(SO_RCVBUF) + if (sockbufsize) { +- int len; ++ socklen_t len; + + if (trans) { + /* set send socket buffer if we are transmitting */ +--- a/src/mpoad/mpcd.8 ++++ b/src/mpoad/mpcd.8 +@@ -28,7 +28,7 @@ mpcd \- ATM MPOA (Multi\-Protocol Over A + .B ]] + .SH DESCRIPTION + MPOA client +-.SM(MPC) is responsible for creating and receiving ++.SM (MPC) is responsible for creating and receiving + internetwork layer shortcuts. Using these shortcuts MPCs forward + unicast internetwork layer packets effectively over ATM without need + for routing protocols. +@@ -43,7 +43,7 @@ accepts shortcuts and packets arriving o + shortcuts is done with the help of + .SM MPOA + server +-.SM(MPS). ++.SM (MPS). + .PP + Just as the Linux + .SM LAN +--- a/src/led/zeppelin.8 ++++ b/src/led/zeppelin.8 +@@ -99,7 +99,7 @@ Ring and ATM parts of the ELAN, so using + recommended. Token Ring support has received less testing than its + Ethernet counterpart. + .SH FILES +-.IP \fI/var/run/lec[interface number].pid\fP ++.IP \fI/var/run/lec[interface\ number].pid\fP + The file containing the process id of zeppelin. + .SH BUGS + John Bonham died 1980 and Led Zeppelin broke. +--- a/src/sigd/atmsigd.conf.4 ++++ b/src/sigd/atmsigd.conf.4 +@@ -125,7 +125,7 @@ a comment. The `#' character cannot be e + .P + If an option is specified in \fBatmsigd.conf\fP and on the command + line, the command line has priority. +-.COMPATIBILITY ++.SH COMPATIBILITY + Certain options used by past versions of \fBatmsigd\fP but no longer documented + on the man page are still recognized and supported, but they also yield a + warning message. Future versions of \fBatmsigd\fP will not recognize those diff --git a/package/network/utils/linux-atm/patches/200-no_libfl.patch b/package/network/utils/linux-atm/patches/200-no_libfl.patch new file mode 100644 index 0000000..6db8779 --- /dev/null +++ b/package/network/utils/linux-atm/patches/200-no_libfl.patch @@ -0,0 +1,179 @@ +--- a/src/qgen/Makefile.am ++++ b/src/qgen/Makefile.am +@@ -2,7 +2,7 @@ noinst_PROGRAMS = qgen + + qgen_SOURCES = common.c common.h file.c file.h first.c ql_y.y ql_l.l qgen.c \ + qgen.h second.c third.c +-qgen_LDADD = -lfl ++qgen_LDADD = + + COMPILE = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@ + LINK = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@ -o $@ +--- a/src/qgen/Makefile.in ++++ b/src/qgen/Makefile.in +@@ -204,7 +204,7 @@ top_srcdir = @top_srcdir@ + qgen_SOURCES = common.c common.h file.c file.h first.c ql_y.y ql_l.l qgen.c \ + qgen.h second.c third.c + +-qgen_LDADD = -lfl ++qgen_LDADD = + COMPILE = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@ + LINK = @CC_FOR_BUILD@ @CFLAGS_FOR_BUILD@ -o $@ + +--- a/src/sigd/Makefile.am ++++ b/src/sigd/Makefile.am +@@ -8,7 +8,7 @@ atmsigd_XTRAS = mess.o $(top_builddir)/s + $(top_builddir)/src/q2931/qd.dump.o \ + $(top_builddir)/src/lib/libatm.la \ + $(top_builddir)/src/saal/libsaal.a +-atmsigd_LDADD = $(atmsigd_XTRAS) -lfl ++atmsigd_LDADD = $(atmsigd_XTRAS) + atmsigd_DEPENDENCIES = mess.c $(atmsigd_XTRAS) + + CLEANFILES = mess.c +--- a/src/sigd/Makefile.in ++++ b/src/sigd/Makefile.in +@@ -245,7 +245,7 @@ atmsigd_XTRAS = mess.o $(top_builddir)/s + $(top_builddir)/src/lib/libatm.la \ + $(top_builddir)/src/saal/libsaal.a + +-atmsigd_LDADD = $(atmsigd_XTRAS) -lfl ++atmsigd_LDADD = $(atmsigd_XTRAS) + atmsigd_DEPENDENCIES = mess.c $(atmsigd_XTRAS) + CLEANFILES = mess.c + sysconf_DATA = atmsigd.conf +--- a/src/switch/debug/debug.c ++++ b/src/switch/debug/debug.c +@@ -20,6 +20,11 @@ + + #define PRV(call) ((FAB *) (call)->fab) + ++int yywrap(void) ++{ ++ return 1; ++} ++ + + typedef struct _fab { + CALL *next; /* relay.c may not keep track of calls, but WE are */ +--- a/src/switch/debug/Makefile.am ++++ b/src/switch/debug/Makefile.am +@@ -5,7 +5,7 @@ INCLUDES = -I$(srcdir)/../../q2931 + sw_debug_SOURCES = debug.c + sw_debug_XTRAS = $(top_builddir)/src/switch/libsw.a \ + $(top_builddir)/src/lib/libatm.la +-sw_debug_LDADD = $(sw_debug_XTRAS) -lfl ++sw_debug_LDADD = $(sw_debug_XTRAS) + + sw_debug_DEPENDENCIES = $(sw_debug_XTRAS) + +--- a/src/switch/debug/Makefile.in ++++ b/src/switch/debug/Makefile.in +@@ -200,7 +200,8 @@ sw_debug_SOURCES = debug.c + sw_debug_XTRAS = $(top_builddir)/src/switch/libsw.a \ + $(top_builddir)/src/lib/libatm.la + +-sw_debug_LDADD = $(sw_debug_XTRAS) -lfl ++sw_debug_LDADD = $(sw_debug_XTRAS) ++ + sw_debug_DEPENDENCIES = $(sw_debug_XTRAS) + EXTRA_DIST = demo README + all: all-am +--- a/src/switch/tcp/Makefile.am ++++ b/src/switch/tcp/Makefile.am +@@ -5,7 +5,7 @@ INCLUDES = -I$(srcdir)/../../q2931 + sw_tcp_SOURCES = tcpsw.c + sw_tcp_XTRAS = $(top_builddir)/src/switch/libsw.a \ + $(top_builddir)/src/lib/libatm.la +-sw_tcp_LDADD = $(sw_tcp_XTRAS) -lfl ++sw_tcp_LDADD = $(sw_tcp_XTRAS) + sw_tcp_DEPENDENCIES = $(sw_tcp_XTRAS) + + EXTRA_DIST = mkfiles README +--- a/src/switch/tcp/Makefile.in ++++ b/src/switch/tcp/Makefile.in +@@ -200,7 +200,7 @@ sw_tcp_SOURCES = tcpsw.c + sw_tcp_XTRAS = $(top_builddir)/src/switch/libsw.a \ + $(top_builddir)/src/lib/libatm.la + +-sw_tcp_LDADD = $(sw_tcp_XTRAS) -lfl ++sw_tcp_LDADD = $(sw_tcp_XTRAS) + sw_tcp_DEPENDENCIES = $(sw_tcp_XTRAS) + EXTRA_DIST = mkfiles README + all: all-am +--- a/src/switch/tcp/tcpsw.c ++++ b/src/switch/tcp/tcpsw.c +@@ -35,6 +35,10 @@ + #define MAX_PACKET (ATM_MAX_AAL5_PDU+sizeof(struct atmtcp_hdr)) + #define BUFFER_SIZE (MAX_PACKET*2) + ++int yywrap(void) ++{ ++ return 1; ++} + + typedef struct _table { + struct _link *out; /* output port */ +--- a/src/test/Makefile.am ++++ b/src/test/Makefile.am +@@ -20,7 +20,7 @@ br_SOURCES = br.c + bw_SOURCES = bw.c + isp_SOURCES = isp.c isp.h ispl_y.y ispl_l.l + isp_XTRAS = $(LDADD) +-isp_LDADD = $(isp_XTRAS) -lfl ++isp_LDADD = $(isp_XTRAS) + isp_DEPENDENCIES = $(isp_XTRAS) + window_SOURCES = window.c + +--- a/src/test/Makefile.in ++++ b/src/test/Makefile.in +@@ -283,7 +283,7 @@ br_SOURCES = br.c + bw_SOURCES = bw.c + isp_SOURCES = isp.c isp.h ispl_y.y ispl_l.l + isp_XTRAS = $(LDADD) +-isp_LDADD = $(isp_XTRAS) -lfl ++isp_LDADD = $(isp_XTRAS) + isp_DEPENDENCIES = $(isp_XTRAS) + window_SOURCES = window.c + CLEANFILES = errnos.inc +--- a/src/test/ispl_l.l ++++ b/src/test/ispl_l.l +@@ -18,6 +18,11 @@ + #include "ispl_y.h" + + ++int yywrap(void) ++{ ++ return 1; ++} ++ + static int lineno = 1; + + %} +--- a/src/qgen/ql_l.l ++++ b/src/qgen/ql_l.l +@@ -11,6 +11,11 @@ + #include "ql_y.h" + + ++int yywrap(void) ++{ ++ return 1; ++} ++ + typedef struct _tree { + struct _tree *left,*right; + const char str[0]; +--- a/src/sigd/cfg_l.l ++++ b/src/sigd/cfg_l.l +@@ -16,6 +16,10 @@ + + #include "cfg_y.h" + ++int yywrap(void) ++{ ++ return 1; ++} + + static int lineno = 1; + static int token; /* f@#%ing flex doesn't grok return after BEGIN */ diff --git a/package/network/utils/linux-atm/patches/300-objcopy_path.patch b/package/network/utils/linux-atm/patches/300-objcopy_path.patch new file mode 100644 index 0000000..4f11516 --- /dev/null +++ b/package/network/utils/linux-atm/patches/300-objcopy_path.patch @@ -0,0 +1,40 @@ +--- a/src/extra/Makefile.am ++++ b/src/extra/Makefile.am +@@ -7,6 +7,8 @@ EXTRA_DIST = linux-atm.spec.in \ + BUILT_SOURCES = pca200e.bin pca200e_ecd.bin2 sba200e_ecd.bin2 + CLEANFILES = pca200e.bin pca200e_ecd.bin2 sba200e_ecd.bin2 + ++OBJCOPY = objcopy ++ + install-exec-hook: + $(MKDIR_P) $(DESTDIR)/lib/firmware + $(INSTALL_DATA) $(srcdir)/pca200e.bin $(DESTDIR)/lib/firmware +@@ -14,7 +16,7 @@ install-exec-hook: + $(INSTALL_DATA) $(srcdir)/sba200e_ecd.bin2 $(DESTDIR)/lib/firmware + + %.bin %.bin2: %.data +- objcopy -Iihex $< -Obinary $@.gz ++ $(OBJCOPY) -Iihex $< -Obinary $@.gz + gzip -n -df $@.gz + + +--- a/src/extra/Makefile.in ++++ b/src/extra/Makefile.in +@@ -187,6 +187,8 @@ CLEANFILES = pca200e.bin pca200e_ecd.bin + all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + ++OBJCOPY = objcopy ++ + .SUFFIXES: + $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ +@@ -385,7 +387,7 @@ install-exec-hook: + $(INSTALL_DATA) $(srcdir)/sba200e_ecd.bin2 $(DESTDIR)/lib/firmware + + %.bin %.bin2: %.data +- objcopy -Iihex $< -Obinary $@.gz ++ $(OBJCOPY) -Iihex $< -Obinary $@.gz + gzip -n -df $@.gz + + # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/package/network/utils/linux-atm/patches/400-portability_fixes.patch b/package/network/utils/linux-atm/patches/400-portability_fixes.patch new file mode 100644 index 0000000..462f57c --- /dev/null +++ b/package/network/utils/linux-atm/patches/400-portability_fixes.patch @@ -0,0 +1,60 @@ +diff -urN linux-atm-2.5.2/src/ilmid/io.c linux-atm-2.5.2.new/src/ilmid/io.c +--- linux-atm-2.5.2/src/ilmid/io.c 2008-01-01 01:14:50.000000000 +0100 ++++ linux-atm-2.5.2.new/src/ilmid/io.c 2012-11-23 17:32:18.149268039 +0100 +@@ -48,6 +48,14 @@ + be manually configured (after ilmid has + registered the "official" address) - HACK */ + ++#ifndef SUN_LEN ++# include <string.h> /* For prototype of `strlen'. */ ++ ++/* Evaluate to actual length of the `sockaddr_un' structure. */ ++# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ ++ + strlen ((ptr)->sun_path)) ++#endif ++ + extern SysGroup *remsys; + extern State ilmi_state; + static short atm_itf = -1; /* bad value */ +diff -urN linux-atm-2.5.2/src/mpoad/io.c linux-atm-2.5.2.new/src/mpoad/io.c +--- linux-atm-2.5.2/src/mpoad/io.c 2008-01-01 01:14:51.000000000 +0100 ++++ linux-atm-2.5.2.new/src/mpoad/io.c 2012-11-23 17:34:17.745271101 +0100 +@@ -10,14 +10,7 @@ + #include <errno.h> + #include <sys/ioctl.h> + #include <sys/param.h> /* for OPEN_MAX */ +-#if __GLIBC__ >= 2 + #include <sys/poll.h> +-#else /* ugly hack to make it compile on RH 4.2 - WA */ +-#include <syscall.h> +-#include <linux/poll.h> +-#define SYS_poll 168 +-_syscall3(int,poll,struct pollfd *,ufds,unsigned int,nfds,int,timeout); +-#endif + #include <atm.h> + #include <linux/types.h> + #include <linux/atmioc.h> +diff -urN linux-atm-2.5.2/src/sigd/atmsigd.c linux-atm-2.5.2.new/src/sigd/atmsigd.c +--- linux-atm-2.5.2/src/sigd/atmsigd.c 2008-01-01 01:14:52.000000000 +0100 ++++ linux-atm-2.5.2.new/src/sigd/atmsigd.c 2012-11-23 17:30:38.689265492 +0100 +@@ -517,7 +517,7 @@ + exit(0); + } + } +- (void) on_exit(trace_on_exit,NULL); ++ (void) atexit(trace_on_exit); + poll_loop(); + close_all(); + for (sig = entities; sig; sig = sig->next) stop_saal(&sig->saal); +diff -urN linux-atm-2.5.2/src/test/align.c linux-atm-2.5.2.new/src/test/align.c +--- linux-atm-2.5.2/src/test/align.c 2001-10-10 00:33:08.000000000 +0200 ++++ linux-atm-2.5.2.new/src/test/align.c 2012-11-23 17:25:15.077257206 +0100 +@@ -24,7 +24,7 @@ + #include <signal.h> + #include <sys/types.h> + #include <sys/socket.h> +-#include <sys/errno.h> ++#include <errno.h> + #include <atm.h> + + diff --git a/package/network/utils/maccalc/Makefile b/package/network/utils/maccalc/Makefile new file mode 100644 index 0000000..b4800d0 --- /dev/null +++ b/package/network/utils/maccalc/Makefile @@ -0,0 +1,48 @@ +# +# 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_LICENSE:=GPL-2.0 + +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)) diff --git a/package/network/utils/maccalc/src/Makefile b/package/network/utils/maccalc/src/Makefile new file mode 100644 index 0000000..486badb --- /dev/null +++ b/package/network/utils/maccalc/src/Makefile @@ -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 diff --git a/package/network/utils/maccalc/src/main.c b/package/network/utils/maccalc/src/main.c new file mode 100644 index 0000000..dcb5f55 --- /dev/null +++ b/package/network/utils/maccalc/src/main.c @@ -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; +} diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile new file mode 100644 index 0000000..96db6ff --- /dev/null +++ b/package/network/utils/nftables/Makefile @@ -0,0 +1,43 @@ +# Copyright (C) 2015 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:=nftables +PKG_VERSION:=0.4+2015-04-09 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_URL:=git://git.netfilter.org/nftables +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=3ed296118a065caff5600e60d4f7ef18e137f9a0 +PKG_MAINTAINER:=Steven Barth <steven@midlink.org> +PKG_LICENSE:=GPL-2.0 + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +CONFIGURE_ARGS += \ + --with-mini-gmp \ + --without-cli \ + +define Package/nftables + SECTION:=net + CATEGORY:=Network + SUBMENU:=Firewall + TITLE:=nftables packet filtering userspace utility + DEPENDS:=+kmod-nft-core +kmod-nft-nat +libnftnl + URL:=http://netfilter.org/projects/nftables/ +endef + +define Package/nftables/install + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) $(PKG_BUILD_DIR)/src/nft $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,nftables)) diff --git a/package/network/utils/nftables/patches/100-disable-doc-generation.patch b/package/network/utils/nftables/patches/100-disable-doc-generation.patch new file mode 100644 index 0000000..bcbffe2 --- /dev/null +++ b/package/network/utils/nftables/patches/100-disable-doc-generation.patch @@ -0,0 +1,8 @@ +--- a/Makefile.am ++++ b/Makefile.am +@@ -2,5 +2,4 @@ ACLOCAL_AMFLAGS = -I m4 + + SUBDIRS = src \ + include \ +- doc \ + files diff --git a/package/network/utils/owipcalc/Makefile b/package/network/utils/owipcalc/Makefile new file mode 100644 index 0000000..9d6b397 --- /dev/null +++ b/package/network/utils/owipcalc/Makefile @@ -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:=owipcalc +PKG_RELEASE:=3 +PKG_LICENSE:=Apache-2.0 + +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)) diff --git a/package/network/utils/owipcalc/src/owipcalc.c b/package/network/utils/owipcalc/src/owipcalc.c new file mode 100644 index 0000000..d22594b --- /dev/null +++ b/package/network/utils/owipcalc/src/owipcalc.c @@ -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); +} diff --git a/package/network/utils/resolveip/Makefile b/package/network/utils/resolveip/Makefile new file mode 100644 index 0000000..3243a80 --- /dev/null +++ b/package/network/utils/resolveip/Makefile @@ -0,0 +1,46 @@ +# +# Copyright (C) 2011-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:=resolveip +PKG_RELEASE:=2 +PKG_LICENSE:=GPL-2.0 + +include $(INCLUDE_DIR)/package.mk + +define Package/resolveip + SECTION:=utils + CATEGORY:=Base system + TITLE:=Simple DNS resolver with configurable timeout + MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +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)) diff --git a/package/network/utils/resolveip/src/resolveip.c b/package/network/utils/resolveip/src/resolveip.c new file mode 100644 index 0000000..43c5ae7 --- /dev/null +++ b/package/network/utils/resolveip/src/resolveip.c @@ -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; + int 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 ((char)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); +} diff --git a/package/network/utils/rssileds/Makefile b/package/network/utils/rssileds/Makefile new file mode 100644 index 0000000..6ca4e32 --- /dev/null +++ b/package/network/utils/rssileds/Makefile @@ -0,0 +1,49 @@ +# +# 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.2 +PKG_RELEASE:=1 +PKG_LICNESE:=GPL-2.0+ + +include $(INCLUDE_DIR)/package.mk + +define Package/rssileds + SECTION:=net + CATEGORY:=Network + TITLE:=RSSI real-time LED indicator + DEPENDS:=+libiwinfo + MAINTAINER:=Daniel Golle <dgolle@allnet.de> +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)) diff --git a/package/network/utils/rssileds/files/rssileds.init b/package/network/utils/rssileds/files/rssileds.init new file mode 100644 index 0000000..b0d2627 --- /dev/null +++ b/package/network/utils/rssileds/files/rssileds.init @@ -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 +} diff --git a/package/network/utils/rssileds/src/rssileds.c b/package/network/utils/rssileds/src/rssileds.c new file mode 100644 index 0000000..60d30f1 --- /dev/null +++ b/package/network/utils/rssileds/src/rssileds.c @@ -0,0 +1,290 @@ +/* + * 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 set_led(struct led *led, unsigned char value) +{ + char buf[8]; + + if ( ! led ) + return -1; + + if ( ! led->controlfd ) + return -1; + + if ( led->state == value ) + return 0; + + 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 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; + + if ( set_led(newled, 255) ) + goto cleanup_fp; + + if ( set_led(newled, 0) ) + goto cleanup_fp; + + 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 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; +} diff --git a/package/network/utils/tcpdump/Makefile b/package/network/utils/tcpdump/Makefile new file mode 100644 index 0000000..8e33a2b --- /dev/null +++ b/package/network/utils/tcpdump/Makefile @@ -0,0 +1,90 @@ +# +# 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:=tcpdump +PKG_VERSION:=4.5.1 +PKG_RELEASE:=4 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=http://www.tcpdump.org/release/ \ + http://ftp.gwdg.de/pub/misc/tcpdump/ \ + http://www.at.tcpdump.org/ \ + http://www.br.tcpdump.org/ +PKG_MD5SUM:=973a2513d0076e34aa9da7e15ed98e1b + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION) +PKG_BUILD_PARALLEL:=1 + +PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> +PKG_LICENSE:=BSD-3-Clause + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/tcpdump/default + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libpcap + TITLE:=Network monitoring and data acquisition tool + URL:=http://www.tcpdump.org/ +endef + +define Package/tcpdump + $(Package/tcpdump/default) + VARIANT:=full +endef + +define Package/tcpdump-mini + $(Package/tcpdump/default) + TITLE+= (minimal version) + VARIANT:=mini +endef + +CONFIGURE_ARGS += \ + --without-crypto + +ifeq ($(CONFIG_IPV6),y) +CONFIGURE_ARGS += \ + --enable-ipv6 +endif + +TARGET_CFLAGS += -ffunction-sections -fdata-sections +TARGET_LDFLAGS += -Wl,--gc-sections + +CONFIGURE_VARS += \ + BUILD_CC="$(TARGET_CC)" \ + HOSTCC="$(HOSTCC)" \ + td_cv_buggygetaddrinfo="no" \ + ac_cv_linux_vers=$(LINUX_VERSION) \ + ac_cv_header_rpc_rpcent_h=no \ + ac_cv_lib_rpc_main=no \ + ac_cv_path_PCAP_CONFIG="" + +MAKE_FLAGS := + +ifeq ($(BUILD_VARIANT),mini) + TARGET_CFLAGS += -DTCPDUMP_MINI + CONFIGURE_ARGS += --disable-smb + MAKE_FLAGS += TCPDUMP_MINI=1 +endif + +MAKE_FLAGS += \ + CCOPT="$(TARGET_CFLAGS)" INCLS="-I. $(TARGET_CPPFLAGS)" + + +define Package/tcpdump/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tcpdump $(1)/usr/sbin/ +endef + +Package/tcpdump-mini/install = $(Package/tcpdump/install) + +$(eval $(call BuildPackage,tcpdump)) +$(eval $(call BuildPackage,tcpdump-mini)) diff --git a/package/network/utils/tcpdump/patches/001-remove_pcap_debug.patch b/package/network/utils/tcpdump/patches/001-remove_pcap_debug.patch new file mode 100644 index 0000000..d2c724d --- /dev/null +++ b/package/network/utils/tcpdump/patches/001-remove_pcap_debug.patch @@ -0,0 +1,23 @@ +--- a/tcpdump.c ++++ b/tcpdump.c +@@ -1095,20 +1095,6 @@ main(int argc, char **argv) + error("invalid data link type %s", gndo->ndo_dltname); + break; + +-#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) +- case 'Y': +- { +- /* Undocumented flag */ +-#ifdef HAVE_PCAP_DEBUG +- extern int pcap_debug; +- pcap_debug = 1; +-#else +- extern int yydebug; +- yydebug = 1; +-#endif +- } +- break; +-#endif + case 'z': + if (optarg) { + zflag = strdup(optarg); diff --git a/package/network/utils/tcpdump/patches/002-remove_static_libpcap_check.patch b/package/network/utils/tcpdump/patches/002-remove_static_libpcap_check.patch new file mode 100644 index 0000000..c8bdf14 --- /dev/null +++ b/package/network/utils/tcpdump/patches/002-remove_static_libpcap_check.patch @@ -0,0 +1,73 @@ +--- a/configure ++++ b/configure +@@ -5813,28 +5813,6 @@ $as_echo "Using $pfopen" >&6; } + LIBS="$LIBS $pfopen" + fi + fi +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for local pcap library" >&5 +-$as_echo_n "checking for local pcap library... " >&6; } +- libpcap=FAIL +- lastdir=FAIL +- places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \ +- egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT)?$'` +- for dir in $places $srcdir/../libpcap $srcdir/libpcap ; do +- basedir=`echo $dir | sed -e 's/[ab][0-9]*$//' | \ +- sed -e 's/-PRE-GIT$//' ` +- if test $lastdir = $basedir ; then +- continue; +- fi +- lastdir=$dir +- if test -r $dir/libpcap.a ; then +- libpcap=$dir/libpcap.a +- d=$dir +- fi +- done +- if test $libpcap = FAIL ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +-$as_echo "not found" >&6; } +- + # + # Look for pcap-config. + # +@@ -5989,41 +5967,6 @@ if test "x$ac_cv_lib_pcap_main" = xyes; + libpcap="-lpcap" + fi + +- if test $libpcap = FAIL ; then +- as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5 +- fi +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extraneous pcap header directories" >&5 +-$as_echo_n "checking for extraneous pcap header directories... " >&6; } +- if test \( ! -r /usr/local/include/pcap.h \) -a \ +- \( ! -r /usr/include/pcap.h \); then +- if test -r /usr/local/include/pcap/pcap.h; then +- d="/usr/local/include/pcap" +- elif test -r /usr/include/pcap/pcap.h; then +- d="/usr/include/pcap" +- fi +- fi +- if test -z "$d" ; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +-$as_echo "not found" >&6; } +- else +- V_INCLS="-I$d $V_INCLS" +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: found -- -I$d added" >&5 +-$as_echo "found -- -I$d added" >&6; } +- fi +- fi +- else +- V_PCAPDEP=$libpcap +- places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \ +- egrep '/libpcap-[0-9]*.[0-9]*(.[0-9]*)?([ab][0-9]*)?$'` +- if test -r $d/pcap.h; then +- V_INCLS="-I$d $V_INCLS" +- elif test -r $places/pcap.h; then +- V_INCLS="-I$places $V_INCLS" +- else +- as_fn_error see INSTALL "cannot find pcap.h" "$LINENO" 5 +- fi +- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libpcap" >&5 +-$as_echo "$libpcap" >&6; } + # Extract the first word of "pcap-config", so it can be a program name with args. + set dummy pcap-config; ac_word=$2 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 diff --git a/package/network/utils/tcpdump/patches/100-tcpdump_mini.patch b/package/network/utils/tcpdump/patches/100-tcpdump_mini.patch new file mode 100644 index 0000000..8d07be6 --- /dev/null +++ b/package/network/utils/tcpdump/patches/100-tcpdump_mini.patch @@ -0,0 +1,844 @@ +--- a/Makefile.in ++++ b/Makefile.in +@@ -71,6 +71,22 @@ DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@ + @rm -f $@ + $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c + ++ifdef TCPDUMP_MINI ++ ++CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \ ++ nlpid.c l2vpn.c machdep.c parsenfsfh.c in_cksum.c \ ++ print-802_11.c print-aodv.c print-arp.c print-ascii.c \ ++ print-bgp.c print-bootp.c print-cdp.c print-domain.c print-eap.c print-ether.c \ ++ print-gre.c print-icmp.c print-igmp.c print-ip.c \ ++ print-l2tp.c print-lldp.c print-llc.c \ ++ print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \ ++ print-ppp.c print-pppoe.c print-pptp.c print-radius.c print-raw.c print-rsvp.c \ ++ print-sctp.c print-sip.c print-sll.c print-snmp.c print-stp.c print-sunrpc.c \ ++ print-syslog.c print-tcp.c print-telnet.c print-tftp.c print-udp.c \ ++ setsignal.c tcpdump.c util.c signature.c print-ipnet.c print-forces.c ++ ++else ++ + CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \ + nlpid.c l2vpn.c machdep.c parsenfsfh.c in_cksum.c \ + print-802_11.c print-802_15_4.c print-ap1394.c print-ah.c \ +@@ -103,6 +119,8 @@ LIBNETDISSECT_SRC=print-isakmp.c + LIBNETDISSECT_OBJ=$(LIBNETDISSECT_SRC:.c=.o) + LIBNETDISSECT=libnetdissect.a + ++endif ++ + LOCALSRC = @LOCALSRC@ + GENSRC = version.c + LIBOBJS = @LIBOBJS@ +@@ -286,10 +304,12 @@ $(PROG): $(OBJ) @V_PCAPDEP@ + @rm -f $@ + $(CC) $(FULL_CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) + ++ifndef TCPDUMP_MINI + $(LIBNETDISSECT): $(LIBNETDISSECT_OBJ) + @rm -f $@ + $(AR) cr $@ $(LIBNETDISSECT_OBJ) + $(RANLIB) $@ ++endif + + datalinks.o: $(srcdir)/missing/datalinks.c + $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/datalinks.c +--- a/addrtoname.c ++++ b/addrtoname.c +@@ -556,10 +556,10 @@ linkaddr_string(const u_char *ep, const + + if (type == LINKADDR_ETHER && len == ETHER_ADDR_LEN) + return (etheraddr_string(ep)); +- ++#ifndef TCPDUMP_MINI + if (type == LINKADDR_FRELAY) + return (q922_string(ep)); +- ++#endif + tp = lookup_bytestring(ep, len); + if (tp->e_name) + return (tp->e_name); +@@ -1159,6 +1159,7 @@ init_addrtoname(u_int32_t localnet, u_in + init_ipxsaparray(); + } + ++#ifndef TCPDUMP_MINI + const char * + dnaddr_string(u_short dnaddr) + { +@@ -1178,6 +1179,7 @@ dnaddr_string(u_short dnaddr) + + return(tp->name); + } ++#endif + + /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ + struct hnamemem * +--- a/print-ether.c ++++ b/print-ether.c +@@ -342,6 +342,7 @@ ethertype_print(netdissect_options *ndo, + arp_print(ndo, p, length, caplen); + return (1); + ++#ifndef TCPDUMP_MINI + case ETHERTYPE_DN: + decnet_print(/*ndo,*/p, length, caplen); + return (1); +@@ -360,10 +361,13 @@ ethertype_print(netdissect_options *ndo, + ND_PRINT((ndo, "(NOV-ETHII) ")); + ipx_print(/*ndo,*/p, length); + return (1); ++#endif + ++#ifndef TCPDUMP_MINI + case ETHERTYPE_ISO: + isoclns_print(/*ndo,*/p+1, length-1, length-1); + return(1); ++#endif + + case ETHERTYPE_PPPOED: + case ETHERTYPE_PPPOES: +@@ -376,9 +380,11 @@ ethertype_print(netdissect_options *ndo, + eap_print(ndo, p, length); + return (1); + ++#ifndef TCPDUMP_MINI + case ETHERTYPE_RRCP: + rrcp_print(ndo, p - 14 , length + 14); + return (1); ++#endif + + case ETHERTYPE_PPP: + if (length) { +@@ -387,6 +393,7 @@ ethertype_print(netdissect_options *ndo, + } + return (1); + ++#ifndef TCPDUMP_MINI + case ETHERTYPE_MPCP: + mpcp_print(/*ndo,*/p, length); + return (1); +@@ -399,7 +406,7 @@ ethertype_print(netdissect_options *ndo, + case ETHERTYPE_CFM_OLD: + cfm_print(/*ndo,*/p, length); + return (1); +- ++#endif + case ETHERTYPE_LLDP: + lldp_print(/*ndo,*/p, length); + return (1); +@@ -407,6 +414,7 @@ ethertype_print(netdissect_options *ndo, + case ETHERTYPE_LOOPBACK: + return (1); + ++#ifndef TCPDUMP_MINI + case ETHERTYPE_MPLS: + case ETHERTYPE_MPLS_MULTI: + mpls_print(/*ndo,*/p, length); +@@ -428,6 +436,7 @@ ethertype_print(netdissect_options *ndo, + case ETHERTYPE_CALM_FAST: + calm_fast_print(ndo, p-14, p, length); + return (1); ++#endif + + case ETHERTYPE_LAT: + case ETHERTYPE_SCA: +--- a/print-gre.c ++++ b/print-gre.c +@@ -213,6 +213,7 @@ gre_print_0(const u_char *bp, u_int leng + ip6_print(gndo, bp, len); + break; + #endif ++#ifndef TCPDUMP_MINI + case ETHERTYPE_MPLS: + mpls_print(bp, len); + break; +@@ -228,6 +229,7 @@ gre_print_0(const u_char *bp, u_int leng + case ETHERTYPE_TEB: + ether_print(gndo, bp, len, len, NULL, NULL); + break; ++#endif + default: + printf("gre-proto-0x%x", prot); + } +--- a/print-igmp.c ++++ b/print-igmp.c +@@ -309,6 +309,7 @@ igmp_print(register const u_char *bp, re + TCHECK2(bp[4], 4); + (void)printf("igmp leave %s", ipaddr_string(&bp[4])); + break; ++#ifndef TCPDUMP_MINI + case 0x13: + (void)printf("igmp dvmrp"); + if (len < 8) +@@ -320,6 +321,7 @@ igmp_print(register const u_char *bp, re + (void)printf("igmp pimv1"); + pimv1_print(bp, len); + break; ++#endif + case 0x1e: + print_mresp(bp, len); + break; +--- a/print-ip.c ++++ b/print-ip.c +@@ -328,6 +328,7 @@ ip_print_demux(netdissect_options *ndo, + again: + switch (ipds->nh) { + ++#ifndef TCPDUMP_MINI + case IPPROTO_AH: + ipds->nh = *ipds->cp; + ipds->advance = ah_print(ipds->cp); +@@ -362,15 +363,15 @@ again: + ipds->nh = enh & 0xff; + goto again; + } +- ++#endif + case IPPROTO_SCTP: + sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len); + break; +- ++#ifndef TCPDUMP_MINI + case IPPROTO_DCCP: + dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len); + break; +- ++#endif + case IPPROTO_TCP: + /* pass on the MF bit plus the offset to detect fragments */ + tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, +@@ -388,7 +389,7 @@ again: + icmp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip, + ipds->off & (IP_MF|IP_OFFMASK)); + break; +- ++#ifndef TCPDUMP_MINI + case IPPROTO_PIGP: + /* + * XXX - the current IANA protocol number assignments +@@ -409,15 +410,15 @@ again: + case IPPROTO_EIGRP: + eigrp_print(ipds->cp, ipds->len); + break; +- ++#endif + case IPPROTO_ND: + ND_PRINT((ndo, " nd %d", ipds->len)); + break; +- ++#ifndef TCPDUMP_MINI + case IPPROTO_EGP: + egp_print(ipds->cp, ipds->len); + break; +- ++#endif + case IPPROTO_OSPF: + ospf_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); + break; +@@ -451,10 +452,10 @@ again: + gre_print(ipds->cp, ipds->len); + break; + ++#ifndef TCPDUMP_MINI + case IPPROTO_MOBILE: + mobile_print(ipds->cp, ipds->len); + break; +- + case IPPROTO_PIM: + vec[0].ptr = ipds->cp; + vec[0].len = ipds->len; +@@ -480,7 +481,7 @@ again: + case IPPROTO_PGM: + pgm_print(ipds->cp, ipds->len, (const u_char *)ipds->ip); + break; +- ++#endif + default: + if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) + ND_PRINT((ndo, " %s", proto->p_name)); +--- a/print-ip6.c ++++ b/print-ip6.c +@@ -192,9 +192,11 @@ ip6_print(netdissect_options *ndo, const + case IPPROTO_SCTP: + sctp_print(cp, (const u_char *)ip6, len); + return; ++#ifndef TCPDUMP_MINI + case IPPROTO_DCCP: + dccp_print(cp, (const u_char *)ip6, len); + return; ++#endif + case IPPROTO_TCP: + tcp_print(cp, len, (const u_char *)ip6, fragmented); + return; +@@ -204,6 +206,7 @@ ip6_print(netdissect_options *ndo, const + case IPPROTO_ICMPV6: + icmp6_print(ndo, cp, len, (const u_char *)ip6, fragmented); + return; ++#ifndef TCPDUMP_MINI + case IPPROTO_AH: + advance = ah_print(cp); + nh = *cp; +@@ -228,7 +231,7 @@ ip6_print(netdissect_options *ndo, const + pim_print(cp, len, nextproto6_cksum(ip6, cp, len, + IPPROTO_PIM)); + return; +- ++#endif + case IPPROTO_OSPF: + ospf6_print(cp, len); + return; +@@ -240,11 +243,11 @@ ip6_print(netdissect_options *ndo, const + case IPPROTO_IPV4: + ip_print(ndo, cp, len); + return; +- ++#ifndef TCPDUMP_MINI + case IPPROTO_PGM: + pgm_print(cp, len, (const u_char *)ip6); + return; +- ++#endif + case IPPROTO_GRE: + gre_print(cp, len); + return; +--- a/print-llc.c ++++ b/print-llc.c +@@ -196,7 +196,7 @@ llc_print(const u_char *p, u_int length, + control = EXTRACT_LE_16BITS(p + 2); + is_u = 0; + } +- ++#ifndef TCPDUMP_MINI + if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) { + /* + * This is an Ethernet_802.3 IPX frame; it has an +@@ -219,6 +219,7 @@ llc_print(const u_char *p, u_int length, + ipx_print(p, length); + return (1); + } ++#endif + + dsap = dsap_field & ~LLC_IG; + ssap = ssap_field & ~LLC_GSAP; +@@ -251,6 +252,7 @@ llc_print(const u_char *p, u_int length, + return (1); + } + ++#ifndef TCPDUMP_MINI + if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX && + control == LLC_UI) { + /* +@@ -266,6 +268,7 @@ llc_print(const u_char *p, u_int length, + ipx_print(p+3, length-3); + return (1); + } ++#endif + + #ifdef TCPDUMP_DO_SMB + if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI +@@ -297,11 +300,13 @@ llc_print(const u_char *p, u_int length, + return (1); + } + #endif ++#ifndef TCPDUMP_MINI + if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS + && control == LLC_UI) { + isoclns_print(p + 3, length - 3, caplen - 3); + return (1); + } ++#endif + + if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP + && control == LLC_UI) { +@@ -444,6 +449,7 @@ snap_print(const u_char *p, u_int length + case PID_CISCO_CDP: + cdp_print(p, length, caplen); + return (1); ++#ifndef TCPDUMP_MINI + case PID_CISCO_DTP: + dtp_print(p, length); + return (1); +@@ -453,6 +459,7 @@ snap_print(const u_char *p, u_int length + case PID_CISCO_VTP: + vtp_print(p, length); + return (1); ++#endif + case PID_CISCO_PVST: + case PID_CISCO_VLANBRIDGE: + stp_print(p, length); +@@ -484,6 +491,7 @@ snap_print(const u_char *p, u_int length + ether_print(gndo, p, length, caplen, NULL, NULL); + return (1); + ++#ifndef TCPDUMP_MINI + case PID_RFC2684_802_5_FCS: + case PID_RFC2684_802_5_NOFCS: + /* +@@ -525,6 +533,7 @@ snap_print(const u_char *p, u_int length + */ + fddi_print(p, length, caplen); + return (1); ++#endif + + case PID_RFC2684_BPDU: + stp_print(p, length); +--- a/print-null.c ++++ b/print-null.c +@@ -128,7 +128,7 @@ null_if_print(const struct pcap_pkthdr * + ip6_print(gndo, p, length); + break; + #endif +- ++#ifndef TCPDUMP_MINI + case BSD_AFNUM_ISO: + isoclns_print(p, length, caplen); + break; +@@ -140,7 +140,7 @@ null_if_print(const struct pcap_pkthdr * + case BSD_AFNUM_IPX: + ipx_print(p, length); + break; +- ++#endif + default: + /* unknown AF_ value */ + if (!eflag) +--- a/print-ppp.c ++++ b/print-ppp.c +@@ -1262,7 +1262,7 @@ trunc: + return 0; + } + +- ++#ifndef TCPDUMP_MINI + static void + ppp_hdlc(const u_char *p, int length) + { +@@ -1327,17 +1327,19 @@ cleanup: + free(b); + return; + } ++#endif + + + /* PPP */ + static void + handle_ppp(u_int proto, const u_char *p, int length) + { ++#ifndef TCPDUMP_MINI + if ((proto & 0xff00) == 0x7e00) {/* is this an escape code ? */ + ppp_hdlc(p-1, length); + return; + } +- ++#endif + switch (proto) { + case PPP_LCP: /* fall through */ + case PPP_IPCP: +@@ -1371,6 +1373,7 @@ handle_ppp(u_int proto, const u_char *p, + ip6_print(gndo, p, length); + break; + #endif ++#ifndef TCPDUMP_MINI + case ETHERTYPE_IPX: /*XXX*/ + case PPP_IPX: + ipx_print(p, length); +@@ -1382,6 +1385,7 @@ handle_ppp(u_int proto, const u_char *p, + case PPP_MPLS_MCAST: + mpls_print(p, length); + break; ++#endif + case PPP_COMP: + printf("compressed PPP data"); + break; +@@ -1520,6 +1524,7 @@ ppp_if_print(const struct pcap_pkthdr *h + return (0); + } + ++#ifndef TCPDUMP_MINI + /* + * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like + * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547, +@@ -1747,7 +1752,7 @@ printx: + #endif /* __bsdi__ */ + return (hdrlength); + } +- ++#endif + + /* + * Local Variables: +--- a/print-tcp.c ++++ b/print-tcp.c +@@ -573,14 +573,14 @@ tcp_print(register const u_char *bp, reg + utoval >>= 1; + (void)printf(" %u", utoval); + break; +- ++#ifndef TCPDUMP_MINI + case TCPOPT_MPTCP: + datalen = len - 2; + LENCHECK(datalen); + if (!mptcp_print(cp-2, len, flags)) + goto bad; + break; +- ++#endif + case TCPOPT_EXPERIMENT2: + datalen = len - 2; + LENCHECK(datalen); +@@ -659,8 +659,8 @@ tcp_print(register const u_char *bp, reg + if ((flags & TH_RST) && vflag) { + print_tcp_rst_data(bp, length); + return; +- } +- ++ } ++#ifndef TCPDUMP_MINI + if (packettype) { + switch (packettype) { + case PT_ZMTP1: +@@ -669,7 +669,7 @@ tcp_print(register const u_char *bp, reg + } + return; + } +- ++#endif + if (sport == TELNET_PORT || dport == TELNET_PORT) { + if (!qflag && vflag) + telnet_print(bp, length); +@@ -683,10 +683,12 @@ tcp_print(register const u_char *bp, reg + else if (sport == SMB_PORT || dport == SMB_PORT) + smb_tcp_print(bp, length); + #endif ++#ifndef TCPDUMP_MINI + else if (sport == BEEP_PORT || dport == BEEP_PORT) + beep_print(bp, length); + else if (sport == OPENFLOW_PORT || dport == OPENFLOW_PORT) + openflow_print(bp, length); ++#endif + else if (length > 2 && + (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT || + sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) { +@@ -695,6 +697,7 @@ tcp_print(register const u_char *bp, reg + * XXX packet could be unaligned, it can go strange + */ + ns_print(bp + 2, length - 2, 0); ++#ifndef TCPDUMP_MINI + } else if (sport == MSDP_PORT || dport == MSDP_PORT) { + msdp_print(bp, length); + } else if (sport == RPKI_RTR_PORT || dport == RPKI_RTR_PORT) { +@@ -702,6 +705,7 @@ tcp_print(register const u_char *bp, reg + } + else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) { + ldp_print(bp, length); ++#endif + } + else if ((sport == NFS_PORT || dport == NFS_PORT) && + length >= 4 && TTEST2(*bp, 4)) { +--- a/print-udp.c ++++ b/print-udp.c +@@ -418,11 +418,12 @@ udp_print(register const u_char *bp, u_i + vat_print((void *)(up + 1), up); + break; + ++#ifndef TCPDUMP_MINI + case PT_WB: + udpipaddr_print(ip, sport, dport); + wb_print((void *)(up + 1), length); + break; +- ++#endif + case PT_RPC: + rp = (struct sunrpc_msg *)(up + 1); + direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); +@@ -450,11 +451,12 @@ udp_print(register const u_char *bp, u_i + snmp_print((const u_char *)(up + 1), length); + break; + ++#ifndef TCPDUMP_MINI + case PT_CNFP: + udpipaddr_print(ip, sport, dport); + cnfp_print(cp, (const u_char *)ip); + break; +- ++#endif + case PT_TFTP: + udpipaddr_print(ip, sport, dport); + tftp_print(cp, length); +@@ -475,6 +477,7 @@ udp_print(register const u_char *bp, u_i + radius_print(cp, length); + break; + ++#ifndef TCPDUMP_MINI + case PT_VXLAN: + udpipaddr_print(ip, sport, dport); + vxlan_print((const u_char *)(up + 1), length); +@@ -489,6 +492,7 @@ udp_print(register const u_char *bp, u_i + udpipaddr_print(ip, sport, dport); + lmp_print(cp, length); + break; ++#endif + } + return; + } +@@ -517,6 +521,7 @@ udp_print(register const u_char *bp, u_i + } + #endif + } ++#ifndef TCPDUMP_MINI + if (TTEST(((struct LAP *)cp)->type) && + ((struct LAP *)cp)->type == lapDDP && + (atalk_port(sport) || atalk_port(dport))) { +@@ -525,6 +530,7 @@ udp_print(register const u_char *bp, u_i + llap_print(cp, length); + return; + } ++#endif + } + udpipaddr_print(ip, sport, dport); + +@@ -575,14 +581,18 @@ udp_print(register const u_char *bp, u_i + ns_print((const u_char *)(up + 1), length, 0); + else if (ISPORT(MULTICASTDNS_PORT)) + ns_print((const u_char *)(up + 1), length, 1); ++#ifndef TCPDUMP_MINI + else if (ISPORT(TIMED_PORT)) + timed_print((const u_char *)(up + 1)); ++#endif + else if (ISPORT(TFTP_PORT)) + tftp_print((const u_char *)(up + 1), length); + else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS)) + bootp_print((const u_char *)(up + 1), length); ++#ifndef TCPDUMP_MINI + else if (ISPORT(RIP_PORT)) + rip_print((const u_char *)(up + 1), length); ++#endif + else if (ISPORT(AODV_PORT)) + aodv_print((const u_char *)(up + 1), length, + #ifdef INET6 +@@ -590,6 +600,7 @@ udp_print(register const u_char *bp, u_i + #else + 0); + #endif ++#ifndef TCPDUMP_MINI + else if (ISPORT(ISAKMP_PORT)) + isakmp_print(gndo, (const u_char *)(up + 1), length, bp2); + else if (ISPORT(ISAKMP_PORT_NATT)) +@@ -598,12 +609,15 @@ udp_print(register const u_char *bp, u_i + else if (ISPORT(ISAKMP_PORT_USER1) || ISPORT(ISAKMP_PORT_USER2)) + isakmp_print(gndo, (const u_char *)(up + 1), length, bp2); + #endif ++#endif + else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT)) + snmp_print((const u_char *)(up + 1), length); + else if (ISPORT(NTP_PORT)) + ntp_print((const u_char *)(up + 1), length); ++#ifndef TCPDUMP_MINI + else if (ISPORT(KERBEROS_PORT) || ISPORT(KERBEROS_SEC_PORT)) + krb_print((const void *)(up + 1)); ++#endif + else if (ISPORT(L2TP_PORT)) + l2tp_print((const u_char *)(up + 1), length); + #ifdef TCPDUMP_DO_SMB +@@ -614,6 +628,7 @@ udp_print(register const u_char *bp, u_i + #endif + else if (dport == VAT_PORT) + vat_print((const void *)(up + 1), up); ++#ifndef TCPDUMP_MINI + else if (ISPORT(ZEPHYR_SRV_PORT) || ISPORT(ZEPHYR_CLT_PORT)) + zephyr_print((const void *)(up + 1), length); + /* +@@ -624,6 +639,7 @@ udp_print(register const u_char *bp, u_i + (dport >= RX_PORT_LOW && dport <= RX_PORT_HIGH)) + rx_print((const void *)(up + 1), length, sport, dport, + (u_char *) ip); ++#endif + #ifdef INET6 + else if (ISPORT(RIPNG_PORT)) + ripng_print((const u_char *)(up + 1), length); +@@ -635,21 +651,25 @@ udp_print(register const u_char *bp, u_i + /* + * Kludge in test for whiteboard packets. + */ ++#ifndef TCPDUMP_MINI + else if (dport == WB_PORT) + wb_print((const void *)(up + 1), length); + else if (ISPORT(CISCO_AUTORP_PORT)) + cisco_autorp_print((const void *)(up + 1), length); ++#endif + else if (ISPORT(RADIUS_PORT) || + ISPORT(RADIUS_NEW_PORT) || + ISPORT(RADIUS_ACCOUNTING_PORT) || + ISPORT(RADIUS_NEW_ACCOUNTING_PORT) ) + radius_print((const u_char *)(up+1), length); ++#ifndef TCPDUMP_MINI + else if (dport == HSRP_PORT) + hsrp_print((const u_char *)(up + 1), length); + else if (ISPORT(LWRES_PORT)) + lwres_print((const u_char *)(up + 1), length); + else if (ISPORT(LDP_PORT)) + ldp_print((const u_char *)(up + 1), length); ++#endif + else if (ISPORT(OLSR_PORT)) + olsr_print((const u_char *)(up + 1), length, + #if INET6 +@@ -657,6 +677,7 @@ udp_print(register const u_char *bp, u_i + #else + 0); + #endif ++#ifndef TCPDUMP_MINI + else if (ISPORT(MPLS_LSP_PING_PORT)) + lspping_print((const u_char *)(up + 1), length); + else if (dport == BFD_CONTROL_PORT || +@@ -674,14 +695,17 @@ udp_print(register const u_char *bp, u_i + lwapp_control_print((const u_char *)(up + 1), length, 0); + else if (ISPORT(LWAPP_DATA_PORT)) + lwapp_data_print((const u_char *)(up + 1), length); ++#endif + else if (ISPORT(SIP_PORT)) + sip_print((const u_char *)(up + 1), length); + else if (ISPORT(SYSLOG_PORT)) + syslog_print((const u_char *)(up + 1), length); ++#ifndef TCPDUMP_MINI + else if (ISPORT(OTV_PORT)) + otv_print((const u_char *)(up + 1), length); + else if (ISPORT(VXLAN_PORT)) + vxlan_print((const u_char *)(up + 1), length); ++#endif + else + (void)printf("UDP, length %u", + (u_int32_t)(ulen - sizeof(*up))); +--- a/tcpdump.c ++++ b/tcpdump.c +@@ -161,6 +161,7 @@ struct ndo_printer { + + + static struct printer printers[] = { ++#ifndef TCPDUMP_MINI + { arcnet_if_print, DLT_ARCNET }, + #ifdef DLT_ARCNET_LINUX + { arcnet_linux_if_print, DLT_ARCNET_LINUX }, +@@ -179,19 +180,23 @@ static struct printer printers[] = { + #ifdef DLT_SLIP_BSDOS + { sl_bsdos_if_print, DLT_SLIP_BSDOS }, + #endif ++#endif + { ppp_if_print, DLT_PPP }, + #ifdef DLT_PPP_WITHDIRECTION + { ppp_if_print, DLT_PPP_WITHDIRECTION }, + #endif ++#ifndef TCPDUMP_MINI + #ifdef DLT_PPP_BSDOS + { ppp_bsdos_if_print, DLT_PPP_BSDOS }, + #endif + { fddi_if_print, DLT_FDDI }, ++#endif + { null_if_print, DLT_NULL }, + #ifdef DLT_LOOP + { null_if_print, DLT_LOOP }, + #endif + { raw_if_print, DLT_RAW }, ++#ifndef TCPDUMP_MINI + { atm_if_print, DLT_ATM_RFC1483 }, + #ifdef DLT_C_HDLC + { chdlc_if_print, DLT_C_HDLC }, +@@ -202,6 +207,7 @@ static struct printer printers[] = { + #ifdef DLT_PPP_SERIAL + { ppp_hdlc_if_print, DLT_PPP_SERIAL }, + #endif ++#endif + #ifdef DLT_PPP_ETHER + { pppoe_if_print, DLT_PPP_ETHER }, + #endif +@@ -211,6 +217,7 @@ static struct printer printers[] = { + #ifdef DLT_IEEE802_11 + { ieee802_11_if_print, DLT_IEEE802_11}, + #endif ++#ifndef TCPDUMP_MINI + #ifdef DLT_LTALK + { ltalk_if_print, DLT_LTALK }, + #endif +@@ -229,12 +236,14 @@ static struct printer printers[] = { + #ifdef DLT_IP_OVER_FC + { ipfc_if_print, DLT_IP_OVER_FC }, + #endif ++#endif + #ifdef DLT_PRISM_HEADER + { prism_if_print, DLT_PRISM_HEADER }, + #endif + #ifdef DLT_IEEE802_11_RADIO + { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, + #endif ++#ifndef TCPDUMP_MINI + #ifdef DLT_ENC + { enc_if_print, DLT_ENC }, + #endif +@@ -244,9 +253,11 @@ static struct printer printers[] = { + #ifdef DLT_APPLE_IP_OVER_IEEE1394 + { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, + #endif ++#endif + #ifdef DLT_IEEE802_11_RADIO_AVS + { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, + #endif ++#ifndef TCPDUMP_MINI + #ifdef DLT_JUNIPER_ATM1 + { juniper_atm1_print, DLT_JUNIPER_ATM1 }, + #endif +@@ -312,6 +323,7 @@ static struct printer printers[] = { + #ifdef DLT_IPV6 + { raw_if_print, DLT_IPV6 }, + #endif ++#endif + { NULL, 0 }, + }; + +@@ -320,6 +332,7 @@ static struct ndo_printer ndo_printers[] + #ifdef DLT_IPNET + { ipnet_if_print, DLT_IPNET }, + #endif ++#ifndef TCPDUMP_MINI + #ifdef DLT_IEEE802_15_4 + { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, + #endif +@@ -329,15 +342,18 @@ static struct ndo_printer ndo_printers[] + #ifdef DLT_PPI + { ppi_if_print, DLT_PPI }, + #endif ++#endif + #ifdef DLT_NETANALYZER + { netanalyzer_if_print, DLT_NETANALYZER }, + #endif + #ifdef DLT_NETANALYZER_TRANSPARENT + { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, + #endif ++#ifndef TCPDUMP_MINI + #ifdef DLT_NFLOG + { nflog_if_print, DLT_NFLOG}, + #endif ++#endif + { NULL, 0 }, + }; + +--- a/print-sll.c ++++ b/print-sll.c +@@ -154,14 +154,14 @@ recurse: + * Yes - what type is it? + */ + switch (ether_type) { +- ++#ifndef TCPDUMP_MINI + case LINUX_SLL_P_802_3: + /* + * Ethernet_802.3 IPX frame. + */ + ipx_print(p, length); + break; +- ++#endif + case LINUX_SLL_P_802_2: + /* + * 802.2. diff --git a/package/network/utils/umbim/Makefile b/package/network/utils/umbim/Makefile new file mode 100644 index 0000000..2ba6991 --- /dev/null +++ b/package/network/utils/umbim/Makefile @@ -0,0 +1,45 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=umbim +PKG_VERSION:=2015-04-09 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://git.openwrt.org/project/umbim.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=af9c293c1f1d8a97fbd8adf9c6070ead4920ca84 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/umbim + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libubox +kmod-usb-net +kmod-usb-net-cdc-mbim +wwan + TITLE:=Control utility for mobile broadband modems +endef + +define Package/umbim/description + umbim is a command line tool for controlling mobile broadband modems using + the MBIM-protocol. +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections + +TARGET_LDFLAGS += -Wl,--gc-sections + +define Package/umbim/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/umbim $(1)/sbin/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,umbim)) diff --git a/package/network/utils/umbim/files/lib/netifd/proto/mbim.sh b/package/network/utils/umbim/files/lib/netifd/proto/mbim.sh new file mode 100755 index 0000000..f8b2c06 --- /dev/null +++ b/package/network/utils/umbim/files/lib/netifd/proto/mbim.sh @@ -0,0 +1,177 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} +#DBG=-v + +proto_mbim_init_config() { + available=1 + no_device=1 + proto_config_add_string "device:device" + proto_config_add_string apn + proto_config_add_string pincode + proto_config_add_string delay + proto_config_add_string auth + proto_config_add_string username + proto_config_add_string password +} + +_proto_mbim_setup() { + local interface="$1" + local tid=2 + local ret + + local device apn pincode delay + json_get_vars device apn pincode delay auth username password + + [ -n "$ctl_device" ] && device=$ctl_device + + [ -n "$device" ] || { + echo "mbim[$$]" "No control device specified" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + [ -c "$device" ] || { + echo "mbim[$$]" "The specified control device does not exist" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + + devname="$(basename "$device")" + devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" + ifname="$( ls "$devpath"/net )" + + [ -n "$ifname" ] || { + echo "mbim[$$]" "Failed to find matching interface" + proto_notify_error "$interface" NO_IFNAME + proto_set_available "$interface" 0 + return 1 + } + + [ -n "$apn" ] || { + echo "mbim[$$]" "No APN specified" + proto_notify_error "$interface" NO_APN + return 1 + } + + [ -n "$delay" ] && sleep "$delay" + + echo "mbim[$$]" "Reading capabilities" + umbim $DBG -n -d $device caps || { + echo "mbim[$$]" "Failed to read modem caps" + proto_notify_error "$interface" PIN_FAILED + return 1 + } + tid=$((tid + 1)) + + [ "$pincode" ] && { + echo "mbim[$$]" "Sending pin" + umbim $DBG -n -t $tid -d $device unlock "$pincode" || { + echo "mbim[$$]" "Unable to verify PIN" + proto_notify_error "$interface" PIN_FAILED + proto_block_restart "$interface" + return 1 + } + } + tid=$((tid + 1)) + + echo "mbim[$$]" "Checking pin" + umbim $DBG -n -t $tid -d $device pinstate || { + echo "mbim[$$]" "PIN required" + proto_notify_error "$interface" PIN_FAILED + proto_block_restart "$interface" + return 1 + } + tid=$((tid + 1)) + + echo "mbim[$$]" "Checking subscriber" + umbim $DBG -n -t $tid -d $device subscriber || { + echo "mbim[$$]" "Subscriber init failed" + proto_notify_error "$interface" NO_SUBSCRIBER + return 1 + } + tid=$((tid + 1)) + + echo "mbim[$$]" "Register with network" + umbim $DBG -n -t $tid -d $device registration || { + echo "mbim[$$]" "Subscriber registration failed" + proto_notify_error "$interface" NO_REGISTRATION + return 1 + } + tid=$((tid + 1)) + + echo "mbim[$$]" "Attach to network" + umbim $DBG -n -t $tid -d $device attach || { + echo "mbim[$$]" "Failed to attach to network" + proto_notify_error "$interface" ATTACH_FAILED + return 1 + } + tid=$((tid + 1)) + + echo "mbim[$$]" "Connect to network" + while ! umbim $DBG -n -t $tid -d $device connect "$apn" "$auth" "$username" "$password"; do + tid=$((tid + 1)) + sleep 1; + done + tid=$((tid + 1)) + + uci_set_state network $interface tid "$tid" + + echo "mbim[$$]" "Connected, starting DHCP" + proto_init_update "$ifname" 1 + proto_send_update "$interface" + + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@$interface" + json_add_string proto "dhcp" + json_close_object + ubus call network add_dynamic "$(json_dump)" + + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@$interface" + json_add_string proto "dhcpv6" + json_add_string extendprefix 1 + ubus call network add_dynamic "$(json_dump)" +} + +proto_mbim_setup() { + local ret + + _proto_mbim_setup $@ + ret=$? + + [ "$ret" = 0 ] || { + logger "mbim bringup failed, retry in 15s" + sleep 15 + } + + return $rt +} + +proto_mbim_teardown() { + local interface="$1" + + local device + json_get_vars device + local tid=$(uci_get_state network $interface tid) + + [ -n "$ctl_device" ] && device=$ctl_device + + echo "mbim[$$]" "Stopping network" + [ -n "$tid" ] && { + umbim $DBG -t$tid -d "$device" disconnect + uci_revert_state network $interface tid + } + + proto_init_update "*" 0 + proto_send_update "$interface" +} + +[ -n "$INCLUDE_ONLY" ] || add_protocol mbim diff --git a/package/network/utils/uqmi/Makefile b/package/network/utils/uqmi/Makefile new file mode 100644 index 0000000..7ccf549 --- /dev/null +++ b/package/network/utils/uqmi/Makefile @@ -0,0 +1,50 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=uqmi +PKG_VERSION:=2015-09-17 +PKG_RELEASE=$(PKG_SOURCE_VERSION) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://nbd.name/uqmi.git +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE_VERSION:=8a97586e9445a60e355dea13aa87885ab3dcb277 +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz +PKG_MAINTAINER:=Matti Laakso <malaakso@elisanet.fi> +# PKG_MIRROR_MD5SUM:= +# CMAKE_INSTALL:=1 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_BUILD_PARALLEL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/uqmi + SECTION:=net + CATEGORY:=Network + DEPENDS:=+libubox +libblobmsg-json +kmod-usb-net +kmod-usb-net-qmi-wwan +wwan + TITLE:=Control utility for mobile broadband modems +endef + +define Package/uqmi/description + uqmi is a command line tool for controlling mobile broadband modems using + the QMI-protocol. +endef + +TARGET_CFLAGS += \ + -I$(STAGING_DIR)/usr/include -ffunction-sections -fdata-sections + +TARGET_LDFLAGS += -Wl,--gc-sections + +CMAKE_OPTIONS += \ + -DDEBUG=1 + +define Package/uqmi/install + $(INSTALL_DIR) $(1)/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/uqmi $(1)/sbin/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,uqmi)) diff --git a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh new file mode 100755 index 0000000..48864be --- /dev/null +++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh @@ -0,0 +1,257 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_qmi_init_config() { + available=1 + no_device=1 + proto_config_add_string "device:device" + proto_config_add_string apn + proto_config_add_string auth + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string delay + proto_config_add_string modes + proto_config_add_boolean ipv6 + proto_config_add_boolean dhcp +} + +proto_qmi_setup() { + local interface="$1" + + local device apn auth username password pincode delay modes ipv6 dhcp + local cid_4 pdh_4 cid_6 pdh_6 ipv4 + local ip subnet gateway dns1 dns2 ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6 + json_get_vars device apn auth username password pincode delay modes ipv6 dhcp + + ipv4=1 + + if [ "$ipv6" = 0 ]; then + ipv6="" + else + ipv6=1 + fi + + [ -n "$ctl_device" ] && device=$ctl_device + + [ -n "$device" ] || { + echo "No control device specified" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + [ -c "$device" ] || { + echo "The specified control device does not exist" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + + devname="$(basename "$device")" + devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)" + ifname="$( ls "$devpath"/net )" + [ -n "$ifname" ] || { + echo "The interface could not be found." + proto_notify_error "$interface" NO_IFACE + proto_set_available "$interface" 0 + return 1 + } + + [ -n "$delay" ] && sleep "$delay" + + while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do + sleep 1; + done + + [ -n "$pincode" ] && { + uqmi -s -d "$device" --verify-pin1 "$pincode" || { + echo "Unable to verify PIN" + proto_notify_error "$interface" PIN_FAILED + proto_block_restart "$interface" + return 1 + } + } + + [ -n "$apn" ] || { + echo "No APN specified" + proto_notify_error "$interface" NO_APN + return 1 + } + + uqmi -s -d "$device" --set-data-format 802.3 + uqmi -s -d "$device" --wda-set-data-format 802.3 + + echo "Waiting for network registration" + while uqmi -s -d "$device" --get-serving-system | grep '"searching"' > /dev/null; do + sleep 5; + done + + [ -n "$modes" ] && uqmi -s -d "$device" --set-network-modes "$modes" + + echo "Starting network $apn" + + cid_4=`uqmi -s -d "$device" --get-client-id wds` + [ $? -ne 0 ] && { + echo "Unable to obtain client ID" + proto_notify_error "$interface" NO_CID + return 1 + } + + pdh_4=`uqmi -s -d "$device" --set-client-id wds,"$cid_4" \ + --start-network "$apn" \ + ${auth:+--auth-type $auth} \ + ${username:+--username $username} \ + ${password:+--password $password} \ + --ip-family ipv4` + [ $? -ne 0 ] && { + echo "Unable to connect IPv4" + uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds + ipv4="" + } + + [ -n "$ipv6" ] && { + cid_6=`uqmi -s -d "$device" --get-client-id wds` + if [ $? = 0 ]; then + pdh_6=`uqmi -s -d "$device" --set-client-id wds,"$cid_6" \ + --start-network "$apn" \ + ${auth:+--auth-type $auth} \ + ${username:+--username $username} \ + ${password:+--password $password} \ + --ip-family ipv6` + [ $? -ne 0 ] && { + echo "Unable to connect IPv6" + uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds + ipv6="" + } + else + echo "Unable to connect IPv6" + ipv6="" + fi + } + + [ -z "$ipv4" -a -z "$ipv6" ] && { + echo "Unable to connect" + proto_notify_error "$interface" CALL_FAILED + return 1 + } + + if [ -z "$dhcp" -o "$dhcp" = 0 ]; then + echo "Setting up $ifname" + [ -n "$ipv4" ] && { + json_load "$(uqmi -s -d $device --set-client-id wds,$cid_4 --get-current-settings)" + json_select ipv4 + json_get_vars ip subnet gateway dns1 dns2 + + proto_init_update "$ifname" 1 + proto_set_keep 1 + proto_add_ipv4_address "$ip" "$subnet" + proto_add_dns_server "$dns1" + proto_add_dns_server "$dns2" + proto_add_ipv4_route "0.0.0.0" 0 "$gateway" + proto_add_data + json_add_string "cid_4" "$cid_4" + json_add_string "pdh_4" "$pdh_4" + proto_close_data + proto_send_update "$interface" + } + + [ -n "$ipv6" ] && { + json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)" + json_select ipv6 + json_get_var ip_6 ip + json_get_var gateway_6 gateway + json_get_var dns1_6 dns1 + json_get_var dns2_6 dns2 + json_get_var ip_prefix_length ip-prefix-length + + proto_init_update "$ifname" 1 + proto_set_keep 1 + # RFC 7278: Extend an IPv6 /64 Prefix to LAN + proto_add_ipv6_address "$ip_6" "128" + proto_add_ipv6_prefix "${ip_6}/${ip_prefix_length}" + proto_add_ipv6_route "$gateway_6" "128" + proto_add_ipv6_route "::0" 0 "$gateway_6" "" "" "${ip_6}/${ip_prefix_length}" + proto_add_dns_server "$dns1_6" + proto_add_dns_server "$dns2_6" + proto_add_data + json_add_string "cid_6" "$cid_6" + json_add_string "pdh_6" "$pdh_6" + proto_close_data + proto_send_update "$interface" + } + else + echo "Starting DHCP on $ifname" + proto_init_update "$ifname" 1 + proto_add_data + [ -n "$ipv4" ] && { + json_add_string "cid_4" "$cid_4" + json_add_string "pdh_4" "$pdh_4" + } + [ -n "$ipv6" ] && { + json_add_string "cid_6" "$cid_6" + json_add_string "pdh_6" "$pdh_6" + } + proto_close_data + proto_send_update "$interface" + + [ -n "$ipv4" ] && { + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@$interface" + json_add_string proto "dhcp" + json_close_object + ubus call network add_dynamic "$(json_dump)" + } + + [ -n "$ipv6" ] && { + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@$interface" + json_add_string proto "dhcpv6" + # RFC 7278: Extend an IPv6 /64 Prefix to LAN + json_add_string extendprefix 1 + json_close_object + ubus call network add_dynamic "$(json_dump)" + } + fi +} + +proto_qmi_teardown() { + local interface="$1" + + local device cid_4 pdh_4 cid_6 pdh_6 + json_get_vars device + + [ -n "$ctl_device" ] && device=$ctl_device + + echo "Stopping network" + + json_load "$(ubus call network.interface.$interface status)" + json_select data + json_get_vars cid_4 pdh_4 cid_6 pdh_6 + + [ -n "$cid_4" ] && { + [ -n "$pdh_4" ] && { + uqmi -s -d "$device" --set-client-id wds,"$cid_4" --stop-network "$pdh_4" + uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds + } + } + [ -n "$cid_6" ] && { + [ -n "$pdh_6" ] && { + uqmi -s -d "$device" --set-client-id wds,"$cid_6" --stop-network "$pdh_6" + uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds + } + } + + proto_init_update "*" 0 + proto_send_update "$interface" +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol qmi +} diff --git a/package/network/utils/wireless-tools/Makefile b/package/network/utils/wireless-tools/Makefile new file mode 100644 index 0000000..67986ba --- /dev/null +++ b/package/network/utils/wireless-tools/Makefile @@ -0,0 +1,92 @@ +# +# Copyright (C) 2006-2014 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_MAINTAINER:=Felix Fietkau <nbd@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +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) 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) iwconfig $(1)/usr/sbin/iwlist + $(LN) 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)) diff --git a/package/network/utils/wireless-tools/patches/001-debian.patch b/package/network/utils/wireless-tools/patches/001-debian.patch new file mode 100644 index 0000000..e00bad2 --- /dev/null +++ b/package/network/utils/wireless-tools/patches/001-debian.patch @@ -0,0 +1,35 @@ +--- a/iwlib.c ++++ b/iwlib.c +@@ -667,6 +667,7 @@ iw_get_basic_config(int skfd, + { + struct iwreq wrq; + ++ memset((char *) &wrq, 0, sizeof(struct iwreq)); + memset((char *) info, 0, sizeof(struct wireless_config)); + + /* Get wireless name */ +--- a/Makefile ++++ b/Makefile +@@ -73,8 +73,8 @@ DYNAMIC_LINK= libiw.so + # Install directories + INSTALL_DIR= $(PREFIX)/sbin/ + INSTALL_LIB= $(PREFIX)/lib/ +-INSTALL_INC= $(PREFIX)/include/ +-INSTALL_MAN= $(PREFIX)/man/ ++INSTALL_INC= $(PREFIX)/usr/include/ ++INSTALL_MAN= $(PREFIX)/usr/share/man/ + + # Various commands + RM = rm -f +@@ -102,9 +102,9 @@ ifdef BUILD_WE_ESSENTIAL + endif + + # Other flags +-CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \ ++#CFLAGS=-Os -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow \ + -Wpointer-arith -Wcast-qual -Winline -I. +-#CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I. ++CFLAGS=-O2 -W -Wall -Wstrict-prototypes -I. + DEPFLAGS=-MMD + XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) $(WELIB_FLAG) $(WEDEF_FLAG) + PICFLAG=-fPIC diff --git a/package/network/utils/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch b/package/network/utils/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch new file mode 100644 index 0000000..2b61ef2 --- /dev/null +++ b/package/network/utils/wireless-tools/patches/002-fix-iwconfig-power-argument-parsing.patch @@ -0,0 +1,13 @@ +--- a/iwconfig.c ++++ b/iwconfig.c +@@ -1034,8 +1034,8 @@ set_power_info(int skfd, + wrq.u.power.disabled = 0; + + /* Is there any value to grab ? */ +- value = strtod(args[0], &unit); +- if(unit != args[0]) ++ value = strtod(args[i], &unit); ++ if(unit != args[i]) + { + struct iw_range range; + int flags; diff --git a/package/network/utils/wireless-tools/patches/003-we_essential_def.patch b/package/network/utils/wireless-tools/patches/003-we_essential_def.patch new file mode 100644 index 0000000..8666f3e --- /dev/null +++ b/package/network/utils/wireless-tools/patches/003-we_essential_def.patch @@ -0,0 +1,359 @@ +--- a/iwlist.c ++++ b/iwlist.c +@@ -58,7 +58,6 @@ typedef struct iw_auth_descr + * Maybe this should go in iwlib.c ? + */ + +-#ifndef WE_ESSENTIAL + #define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0])) + + //static const struct iwmask_name iw_enc_mode_name[] = { +@@ -161,11 +160,8 @@ static const char * iw_ie_key_mgmt_name[ + }; + #define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name) + +-#endif /* WE_ESSENTIAL */ +- + /************************* WPA SUBROUTINES *************************/ + +-#ifndef WE_ESSENTIAL + /*------------------------------------------------------------------*/ + /* + * Print all names corresponding to a mask. +@@ -431,7 +427,6 @@ iw_print_gen_ie(unsigned char * buffer, + offset += buffer[offset+1] + 2; + } + } +-#endif /* WE_ESSENTIAL */ + + /***************************** SCANNING *****************************/ + /* +@@ -585,12 +580,10 @@ print_scanning_token(struct stream_descr + &event->u.qual, iw_range, has_range); + printf(" %s\n", buffer); + break; +-#ifndef WE_ESSENTIAL + case IWEVGENIE: + /* Informations Elements are complex, let's do only some of them */ + iw_print_gen_ie(event->u.data.pointer, event->u.data.length); + break; +-#endif /* WE_ESSENTIAL */ + case IWEVCUSTOM: + { + char custom[IW_CUSTOM_MAX+1]; +@@ -1302,7 +1295,6 @@ print_pm_info(int skfd, + return(0); + } + +-#ifndef WE_ESSENTIAL + /************************** TRANSMIT POWER **************************/ + + /*------------------------------------------------------------------*/ +@@ -1405,6 +1397,7 @@ print_txpower_info(int skfd, + return(0); + } + ++#ifndef WE_ESSENTIAL + /*********************** RETRY LIMIT/LIFETIME ***********************/ + + /*------------------------------------------------------------------*/ +@@ -2060,8 +2053,8 @@ static const struct iwlist_entry iwlist_ + { "encryption", print_keys_info, 0, NULL }, + { "keys", print_keys_info, 0, NULL }, + { "power", print_pm_info, 0, NULL }, +-#ifndef WE_ESSENTIAL + { "txpower", print_txpower_info, 0, NULL }, ++#ifndef WE_ESSENTIAL + { "retry", print_retry_info, 0, NULL }, + { "ap", print_ap_info, 0, NULL }, + { "accesspoints", print_ap_info, 0, NULL }, +--- a/iwconfig.c ++++ b/iwconfig.c +@@ -106,16 +106,6 @@ get_info(int skfd, + if(wrq.u.data.length > 1) + info->has_nickname = 1; + +- if((info->has_range) && (info->range.we_version_compiled > 9)) +- { +- /* Get Transmit Power */ +- if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) +- { +- info->has_txpower = 1; +- memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); +- } +- } +- + /* Get sensitivity */ + if(iw_get_ext(skfd, ifname, SIOCGIWSENS, &wrq) >= 0) + { +@@ -132,6 +122,17 @@ get_info(int skfd, + memcpy(&(info->retry), &(wrq.u.retry), sizeof(iwparam)); + } + } ++#endif /* WE_ESSENTIAL */ ++ ++ if((info->has_range) && (info->range.we_version_compiled > 9)) ++ { ++ /* Get Transmit Power */ ++ if(iw_get_ext(skfd, ifname, SIOCGIWTXPOW, &wrq) >= 0) ++ { ++ info->has_txpower = 1; ++ memcpy(&(info->txpower), &(wrq.u.txpower), sizeof(iwparam)); ++ } ++ } + + /* Get RTS threshold */ + if(iw_get_ext(skfd, ifname, SIOCGIWRTS, &wrq) >= 0) +@@ -146,7 +147,6 @@ get_info(int skfd, + info->has_frag = 1; + memcpy(&(info->frag), &(wrq.u.frag), sizeof(iwparam)); + } +-#endif /* WE_ESSENTIAL */ + + return(0); + } +@@ -269,7 +269,6 @@ display_info(struct wireless_info * info + printf("Bit Rate%c%s ", (info->bitrate.fixed ? '=' : ':'), buffer); + } + +-#ifndef WE_ESSENTIAL + /* Display the Transmit Power */ + if(info->has_txpower) + { +@@ -286,6 +285,7 @@ display_info(struct wireless_info * info + printf("Tx-Power%c%s ", (info->txpower.fixed ? '=' : ':'), buffer); + } + ++#ifndef WE_ESSENTIAL + /* Display sensitivity */ + if(info->has_sens) + { +@@ -340,6 +340,7 @@ display_info(struct wireless_info * info + printf(" "); + tokens += 5; /* Between 3 and 5, depend on flags */ + } ++#endif /* WE_ESSENTIAL */ + + /* Display the RTS threshold */ + if(info->has_rts) +@@ -383,7 +384,6 @@ display_info(struct wireless_info * info + /* Formating */ + if(tokens > 0) + printf("\n "); +-#endif /* WE_ESSENTIAL */ + + /* Display encryption information */ + /* Note : we display only the "current" key, use iwlist to list all keys */ +@@ -1196,6 +1196,7 @@ set_nwid_info(int skfd, + /* 1 arg */ + return(1); + } ++#endif /* WE_ESSENTIAL */ + + /*------------------------------------------------------------------*/ + /* +@@ -1362,6 +1363,7 @@ set_txpower_info(int skfd, + return(i); + } + ++#ifndef WE_ESSENTIAL + /*------------------------------------------------------------------*/ + /* + * Set Sensitivity +@@ -1459,6 +1461,7 @@ set_retry_info(int skfd, + /* Var args */ + return(i); + } ++#endif /* WE_ESSENTIAL */ + + /*------------------------------------------------------------------*/ + /* +@@ -1565,6 +1568,7 @@ set_frag_info(int skfd, + return(1); + } + ++#ifndef WE_ESSENTIAL + /*------------------------------------------------------------------*/ + /* + * Set Modulation +@@ -1719,21 +1723,21 @@ static const struct iwconfig_entry iwcon + "Set Nickname", "NNN" }, + { "nwid", set_nwid_info, 1, SIOCSIWNWID, + "Set NWID", "{NN|on|off}" }, +- { "ap", set_apaddr_info, 1, SIOCSIWAP, +- "Set AP Address", "{N|off|auto}" }, +- { "txpower", set_txpower_info, 1, SIOCSIWTXPOW, +- "Set Tx Power", "{NmW|NdBm|off|auto}" }, + { "sens", set_sens_info, 1, SIOCSIWSENS, + "Set Sensitivity", "N" }, ++ { "modulation", set_modulation_info, 1, SIOCGIWMODUL, ++ "Set Modulation", "{11g|11a|CCK|OFDMg|...}" }, + { "retry", set_retry_info, 1, SIOCSIWRETRY, + "Set Retry Limit", "{limit N|lifetime N}" }, ++#endif /* WE_ESSENTIAL */ ++ { "ap", set_apaddr_info, 1, SIOCSIWAP, ++ "Set AP Address", "{N|off|auto}" }, ++ { "txpower", set_txpower_info, 1, SIOCSIWTXPOW, ++ "Set Tx Power", "{NmW|NdBm|off|auto}" }, + { "rts", set_rts_info, 1, SIOCSIWRTS, + "Set RTS Threshold", "{N|auto|fixed|off}" }, + { "frag", set_frag_info, 1, SIOCSIWFRAG, + "Set Fragmentation Threshold", "{N|auto|fixed|off}" }, +- { "modulation", set_modulation_info, 1, SIOCGIWMODUL, +- "Set Modulation", "{11g|11a|CCK|OFDMg|...}" }, +-#endif /* WE_ESSENTIAL */ + { "commit", set_commit_info, 0, SIOCSIWCOMMIT, + "Commit changes", "" }, + { NULL, NULL, 0, 0, NULL, NULL }, +--- a/iwmulticall.c ++++ b/iwmulticall.c +@@ -81,7 +81,7 @@ extern int + #define main(args...) main_iwspy(args) + #include "iwspy.c" + #undef main +-#endif /* WE_ESSENTIAL */ ++#endif + + /* Get iwpriv in there. Mandatory for HostAP and some other drivers. */ + #define main(args...) main_iwpriv(args) +@@ -90,12 +90,14 @@ extern int + #undef iw_usage + #undef main + ++#ifndef WE_ESSENTIAL + /* Do we really need iwgetid ? Well, it's not like it's a big one */ + #define main(args...) main_iwgetid(args) + #define iw_usage(args...) iwgetid_usage(args) + #include "iwgetid.c" + #undef iw_usage + #undef main ++#endif + + /* iwevent is useless for most people, don't grab it ? */ + +@@ -131,11 +133,13 @@ main(int argc, + #ifndef WE_ESSENTIAL + if(!strcmp(call_name, "iwspy")) + return(main_iwspy(argc, argv)); +-#endif /* WE_ESSENTIAL */ ++#endif + if(!strcmp(call_name, "iwpriv")) + return(main_iwpriv(argc, argv)); ++#ifndef WE_ESSENTIAL + if(!strcmp(call_name, "iwgetid")) + return(main_iwgetid(argc, argv)); ++#endif + + /* Uh oh... Not supposed to come here. */ + printf("iwmulticall : you are not supposed to call me this way...\n"); +--- a/iwlib.c ++++ b/iwlib.c +@@ -113,6 +113,7 @@ const struct iw_modul_descr iw_modul_lis + { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" }, + { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" }, + ++#ifndef WE_ESSENTIAL + /* Proprietary aggregates */ + { IW_MODUL_TURBO | IW_MODUL_11A, "turboa", + "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" }, +@@ -120,6 +121,7 @@ const struct iw_modul_descr iw_modul_lis + "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" }, + { IW_MODUL_PBCC | IW_MODUL_11B, "11+", + "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" }, ++#endif + + /* Individual modulations */ + { IW_MODUL_OFDM_G, "OFDMg", +@@ -129,6 +131,7 @@ const struct iw_modul_descr iw_modul_lis + { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" }, + { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" }, + ++#ifndef WE_ESSENTIAL + /* Proprietary modulations */ + { IW_MODUL_TURBO, "turbo", + "Atheros turbo mode, channel bonding (up to 108 Mb/s)" }, +@@ -136,6 +139,7 @@ const struct iw_modul_descr iw_modul_lis + "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" }, + { IW_MODUL_CUSTOM, "custom", + "Driver specific modulation (check driver documentation)" }, ++#endif + }; + + /* Disable runtime version warning in iw_get_range_info() */ +@@ -440,6 +444,7 @@ iw_print_version_info(const char * tooln + return -1; + } + ++#ifndef WE_ESSENTIAL + /* Information about the tools themselves */ + if(toolname != NULL) + printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION); +@@ -452,6 +457,7 @@ iw_print_version_info(const char * tooln + if(we_kernel_version > 15) + printf("Kernel Currently compiled with Wireless Extension v%d.\n\n", + we_kernel_version); ++#endif + + /* Version for each device */ + iw_enum_devices(skfd, &print_iface_version_info, NULL, 0); +@@ -501,6 +507,7 @@ iw_get_range_info(int skfd, + /* Copy stuff at the right place, ignore extra */ + memcpy((char *) range, buffer, sizeof(iwrange)); + } ++#ifndef WE_ESSENTIAL + else + { + /* Zero unknown fields */ +@@ -574,6 +581,7 @@ iw_get_range_info(int skfd, + * If the driver source has not been updated to the latest, it doesn't + * matter because the new fields are set to zero */ + } ++#endif + + /* Don't complain twice. + * In theory, the test apply to each individual driver, but usually +@@ -1542,6 +1550,7 @@ iw_print_key(char * buffer, + } + } + ++#ifndef WE_ESSENTIAL + /*------------------------------------------------------------------*/ + /* + * Convert a passphrase into a key +@@ -1556,6 +1565,7 @@ iw_pass_key(const char * input, + fprintf(stderr, "Error: Passphrase not implemented\n"); + return(-1); + } ++#endif + + /*------------------------------------------------------------------*/ + /* +@@ -1578,12 +1588,14 @@ iw_in_key(const char * input, + keylen = IW_ENCODING_TOKEN_MAX; + memcpy(key, input + 2, keylen); + } ++#ifndef WE_ESSENTIAL + else + if(!strncmp(input, "p:", 2)) + { + /* Second case : as a passphrase (PrismII cards) */ + return(iw_pass_key(input + 2, key)); /* skip "p:" */ + } ++#endif + else + { + const char * p; +--- a/Makefile ++++ b/Makefile +@@ -195,9 +195,9 @@ install-iwmulticall:: iwmulticall + install -m 755 $< $(INSTALL_DIR)/iwconfig + ( cd $(INSTALL_DIR) ; \ + ln -f -s iwconfig iwlist ; \ +- ln -f -s iwconfig iwspy ; \ ++ $(if $(BUILD_WE_ESSENTIAL),,ln -f -s iwconfig iwspy ;) \ + ln -f -s iwconfig iwpriv ; \ +- ln -f -s iwconfig iwgetid ) ++ $(if $(BUILD_WE_ESSENTIAL),,ln -f -s iwconfig iwgetid ) ) + + clean:: + $(RM_CMD) diff --git a/package/network/utils/wireless-tools/patches/004-increase_iwlist_buffer.patch b/package/network/utils/wireless-tools/patches/004-increase_iwlist_buffer.patch new file mode 100644 index 0000000..f2fdb12 --- /dev/null +++ b/package/network/utils/wireless-tools/patches/004-increase_iwlist_buffer.patch @@ -0,0 +1,46 @@ +--- a/iwlist.c ++++ b/iwlist.c +@@ -792,7 +792,8 @@ print_scanning_info(int skfd, + if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) + { + /* Check if buffer was too small (WE-17 only) */ +- if((errno == E2BIG) && (range.we_version_compiled > 16)) ++ if((errno == E2BIG) && (range.we_version_compiled > 16) ++ && (buflen < 0xFFFF)) + { + /* Some driver may return very large scan results, either + * because there are many cells, or because they have many +@@ -808,6 +809,10 @@ print_scanning_info(int skfd, + else + buflen *= 2; + ++ /* wrq.u.data.length is 16 bits so max size is 65535 */ ++ if(buflen > 0xFFFF) ++ buflen = 0xFFFF; ++ + /* Try again */ + goto realloc; + } +@@ -2152,6 +2157,7 @@ main(int argc, + char **args; /* Command arguments */ + int count; /* Number of arguments */ + const iwlist_cmd *iwcmd; ++ int goterr = 0; + + if(argc < 2) + iw_usage(1); +@@ -2199,12 +2205,12 @@ main(int argc, + + /* do the actual work */ + if (dev) +- (*iwcmd->fn)(skfd, dev, args, count); ++ goterr = (*iwcmd->fn)(skfd, dev, args, count); + else + iw_enum_devices(skfd, iwcmd->fn, args, count); + + /* Close the socket. */ + iw_sockets_close(skfd); + +- return 0; ++ return goterr; + } diff --git a/package/network/utils/wpan-tools/Makefile b/package/network/utils/wpan-tools/Makefile new file mode 100644 index 0000000..6c2559d --- /dev/null +++ b/package/network/utils/wpan-tools/Makefile @@ -0,0 +1,36 @@ +# +# Copyright (C) 2015 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:=wpan-tools +PKG_VERSION:=0.5 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://wpan.cakelab.org/releases/ +PKG_MD5SUM:=6226df405a98c13ec41bf4d1f0777d6b + +include $(INCLUDE_DIR)/package.mk + +define Package/wpan-tools + SECTION:=net + CATEGORY:=Network + TITLE:=cfg802154 interface configuration utility + URL:=http://wpan.cakelab.org/ + DEPENDS:= +libnl +endef + +define Build/Configure + $(call Build/Configure/Default) +endef + +define Package/wpan-tools/install + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/iwpan $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackage,wpan-tools)) diff --git a/package/network/utils/wwan/Makefile b/package/network/utils/wwan/Makefile new file mode 100644 index 0000000..8d388dc --- /dev/null +++ b/package/network/utils/wwan/Makefile @@ -0,0 +1,35 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=wwan +PKG_VERSION:=2014-07-17 +PKG_RELEASE=1 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:= + +PKG_MAINTAINER:=John Crispin <blogic@openwrt.org> + +include $(INCLUDE_DIR)/package.mk + +define Package/wwan + SECTION:=net + CATEGORY:=Network + TITLE:=Generic OpenWrt 3G/4G proto handler +endef + +define Build/Compile + true +endef + +define Package/wwan/install + $(INSTALL_DIR) $(1)/lib/netifd/proto/ + $(CP) ./files/wwan.sh $(1)/lib/netifd/proto/ + $(INSTALL_DIR) $(1)/etc/hotplug.d/usb + $(INSTALL_BIN) ./files/wwan.usb $(1)/etc/hotplug.d/usb/00_wwan.sh + $(INSTALL_DIR) $(1)/etc/hotplug.d/usbmisc + $(INSTALL_BIN) ./files/wwan.usbmisc $(1)/etc/hotplug.d/usbmisc/00_wwan.sh + $(INSTALL_DIR) $(1)/lib/network/wwan/ + $(INSTALL_DATA) ./files/data/* $(1)/lib/network/wwan/ +endef + +$(eval $(call BuildPackage,wwan)) diff --git a/package/network/utils/wwan/files/data/0421:03a7 b/package/network/utils/wwan/files/data/0421:03a7 new file mode 100644 index 0000000..1313401 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:03a7 @@ -0,0 +1,6 @@ +{ + "desc": "Nokia C5-00 Mobile phone", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:060d b/package/network/utils/wwan/files/data/0421:060d new file mode 100644 index 0000000..a9ad650 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:060d @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-10", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:060e b/package/network/utils/wwan/files/data/0421:060e new file mode 100644 index 0000000..a9ad650 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:060e @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-10", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:0612 b/package/network/utils/wwan/files/data/0421:0612 new file mode 100644 index 0000000..bc3e780 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:0612 @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-15/CS-18", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:0619 b/package/network/utils/wwan/files/data/0421:0619 new file mode 100644 index 0000000..52fbf58 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:0619 @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-12", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:061e b/package/network/utils/wwan/files/data/0421:061e new file mode 100644 index 0000000..c1cb9f4 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:061e @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-11", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:0623 b/package/network/utils/wwan/files/data/0421:0623 new file mode 100644 index 0000000..f6674ba --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:0623 @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-17", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:0629 b/package/network/utils/wwan/files/data/0421:0629 new file mode 100644 index 0000000..b637c34 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:0629 @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-18", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:062d b/package/network/utils/wwan/files/data/0421:062d new file mode 100644 index 0000000..a95192b --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:062d @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-19", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:062f b/package/network/utils/wwan/files/data/0421:062f new file mode 100644 index 0000000..a95192b --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:062f @@ -0,0 +1,6 @@ +{ + "desc": "Nokia CS-19", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0421:0638 b/package/network/utils/wwan/files/data/0421:0638 new file mode 100644 index 0000000..5fa7d49 --- /dev/null +++ b/package/network/utils/wwan/files/data/0421:0638 @@ -0,0 +1,6 @@ +{ + "desc": "Nokia 21M-02", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/05c6:0016 b/package/network/utils/wwan/files/data/05c6:0016 new file mode 100644 index 0000000..1a4a796 --- /dev/null +++ b/package/network/utils/wwan/files/data/05c6:0016 @@ -0,0 +1,6 @@ +{ + "desc": "iBall 3.5G Connect", + "control": 2, + "data": 2 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/05c6:0023 b/package/network/utils/wwan/files/data/05c6:0023 new file mode 100644 index 0000000..ce288ed --- /dev/null +++ b/package/network/utils/wwan/files/data/05c6:0023 @@ -0,0 +1,5 @@ +{ + "desc": "Leoxsys LN-72V", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/05c6:00a0 b/package/network/utils/wwan/files/data/05c6:00a0 new file mode 100644 index 0000000..0b96160 --- /dev/null +++ b/package/network/utils/wwan/files/data/05c6:00a0 @@ -0,0 +1,6 @@ +{ + "desc": "Axesstel MV241", + "control": 2, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/05c6:6000 b/package/network/utils/wwan/files/data/05c6:6000 new file mode 100644 index 0000000..e8863b9 --- /dev/null +++ b/package/network/utils/wwan/files/data/05c6:6000 @@ -0,0 +1,5 @@ +{ + "desc": "Siemens SG75", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/05c6:9000 b/package/network/utils/wwan/files/data/05c6:9000 new file mode 100644 index 0000000..6a72f4f --- /dev/null +++ b/package/network/utils/wwan/files/data/05c6:9000 @@ -0,0 +1,5 @@ +{ + "desc": "Generic Qualcomm", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/07d1:3e01 b/package/network/utils/wwan/files/data/07d1:3e01 new file mode 100644 index 0000000..b1da177 --- /dev/null +++ b/package/network/utils/wwan/files/data/07d1:3e01 @@ -0,0 +1,5 @@ +{ + "desc": "D-Link DWM-152", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/07d1:3e02 b/package/network/utils/wwan/files/data/07d1:3e02 new file mode 100644 index 0000000..cd1ecee --- /dev/null +++ b/package/network/utils/wwan/files/data/07d1:3e02 @@ -0,0 +1,5 @@ +{ + "desc": "D-Link DWM-156", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/07d1:7e11 b/package/network/utils/wwan/files/data/07d1:7e11 new file mode 100644 index 0000000..84705b7 --- /dev/null +++ b/package/network/utils/wwan/files/data/07d1:7e11 @@ -0,0 +1,6 @@ +{ + "desc": "D-Link DWM-156", + "control": 1, + "data": 2 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/0af0:4005 b/package/network/utils/wwan/files/data/0af0:4005 new file mode 100644 index 0000000..5ab6c12 --- /dev/null +++ b/package/network/utils/wwan/files/data/0af0:4005 @@ -0,0 +1,4 @@ +{ + "desc": "Option GIO711", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0af0:6901 b/package/network/utils/wwan/files/data/0af0:6901 new file mode 100644 index 0000000..06b2664 --- /dev/null +++ b/package/network/utils/wwan/files/data/0af0:6901 @@ -0,0 +1,5 @@ +{ + "desc": "Option GI0201", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/0af0:7201 b/package/network/utils/wwan/files/data/0af0:7201 new file mode 100644 index 0000000..20b18b7 --- /dev/null +++ b/package/network/utils/wwan/files/data/0af0:7201 @@ -0,0 +1,5 @@ +{ + "desc": "Option GTM380", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/0af0:8120 b/package/network/utils/wwan/files/data/0af0:8120 new file mode 100644 index 0000000..c378e7f --- /dev/null +++ b/package/network/utils/wwan/files/data/0af0:8120 @@ -0,0 +1,4 @@ +{ + "desc": "Option GTM681W", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0af0:9200 b/package/network/utils/wwan/files/data/0af0:9200 new file mode 100644 index 0000000..7e55a36 --- /dev/null +++ b/package/network/utils/wwan/files/data/0af0:9200 @@ -0,0 +1,5 @@ +{ + "desc": "Option GTM671WFS", + "control": 2, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/0b3c:c000 b/package/network/utils/wwan/files/data/0b3c:c000 new file mode 100644 index 0000000..b45bbf4 --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c000 @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 100", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0b3c:c001 b/package/network/utils/wwan/files/data/0b3c:c001 new file mode 100644 index 0000000..74a0334 --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c001 @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 120", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0b3c:c002 b/package/network/utils/wwan/files/data/0b3c:c002 new file mode 100644 index 0000000..ed4f2fd --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c002 @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 140", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0b3c:c003 b/package/network/utils/wwan/files/data/0b3c:c003 new file mode 100644 index 0000000..5b4ea48 --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c003 @@ -0,0 +1,5 @@ +{ + "desc": "Olivetti Olicard 145", + "control": 0, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/0b3c:c004 b/package/network/utils/wwan/files/data/0b3c:c004 new file mode 100644 index 0000000..d819379 --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c004 @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 155", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0b3c:c005 b/package/network/utils/wwan/files/data/0b3c:c005 new file mode 100644 index 0000000..f3768c6 --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c005 @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 200", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0b3c:c00a b/package/network/utils/wwan/files/data/0b3c:c00a new file mode 100644 index 0000000..a2ba14a --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c00a @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 160", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0b3c:c00b b/package/network/utils/wwan/files/data/0b3c:c00b new file mode 100644 index 0000000..1c6edb1 --- /dev/null +++ b/package/network/utils/wwan/files/data/0b3c:c00b @@ -0,0 +1,4 @@ +{ + "desc": "Olivetti Olicard 500", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0bdb:1900 b/package/network/utils/wwan/files/data/0bdb:1900 new file mode 100644 index 0000000..84a9a9b --- /dev/null +++ b/package/network/utils/wwan/files/data/0bdb:1900 @@ -0,0 +1,6 @@ +{ + "desc": "Ericsson F3507g", + "control": 4, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0bdb:1902 b/package/network/utils/wwan/files/data/0bdb:1902 new file mode 100644 index 0000000..84a9a9b --- /dev/null +++ b/package/network/utils/wwan/files/data/0bdb:1902 @@ -0,0 +1,6 @@ +{ + "desc": "Ericsson F3507g", + "control": 4, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0bdb:190a b/package/network/utils/wwan/files/data/0bdb:190a new file mode 100644 index 0000000..2e82613 --- /dev/null +++ b/package/network/utils/wwan/files/data/0bdb:190a @@ -0,0 +1,6 @@ +{ + "desc": "Ericsson F3307", + "control": 4, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0bdb:190d b/package/network/utils/wwan/files/data/0bdb:190d new file mode 100644 index 0000000..2f725eb --- /dev/null +++ b/package/network/utils/wwan/files/data/0bdb:190d @@ -0,0 +1,6 @@ +{ + "desc": "Ericsson F5521gw", + "control": 4, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0bdb:1910 b/package/network/utils/wwan/files/data/0bdb:1910 new file mode 100644 index 0000000..2f725eb --- /dev/null +++ b/package/network/utils/wwan/files/data/0bdb:1910 @@ -0,0 +1,6 @@ +{ + "desc": "Ericsson F5521gw", + "control": 4, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/0c88:17da b/package/network/utils/wwan/files/data/0c88:17da new file mode 100644 index 0000000..d5ca787 --- /dev/null +++ b/package/network/utils/wwan/files/data/0c88:17da @@ -0,0 +1,5 @@ +{ + "desc": "Kyocera KPC650", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/0c88:180a b/package/network/utils/wwan/files/data/0c88:180a new file mode 100644 index 0000000..a2bee34 --- /dev/null +++ b/package/network/utils/wwan/files/data/0c88:180a @@ -0,0 +1,5 @@ +{ + "desc": "Kyocera KPC680", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/0f3d:68a2 b/package/network/utils/wwan/files/data/0f3d:68a2 new file mode 100644 index 0000000..f85a049 --- /dev/null +++ b/package/network/utils/wwan/files/data/0f3d:68a2 @@ -0,0 +1,4 @@ +{ + "desc": "Sierra MC7700", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/0f3d:68aa b/package/network/utils/wwan/files/data/0f3d:68aa new file mode 100644 index 0000000..3a68c20 --- /dev/null +++ b/package/network/utils/wwan/files/data/0f3d:68aa @@ -0,0 +1,5 @@ +{ + "desc": "Sierra Wireless AC313U/320U/330U Direct IP", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1004:6124 b/package/network/utils/wwan/files/data/1004:6124 new file mode 100644 index 0000000..471d8a5 --- /dev/null +++ b/package/network/utils/wwan/files/data/1004:6124 @@ -0,0 +1,6 @@ +{ + "desc": "LG L-05A", + "control": 0, + "data": 2 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/1004:6141 b/package/network/utils/wwan/files/data/1004:6141 new file mode 100644 index 0000000..840dc64 --- /dev/null +++ b/package/network/utils/wwan/files/data/1004:6141 @@ -0,0 +1,6 @@ +{ + "desc": "LG LUU-2100TI", + "control": 0, + "data": 2 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/1004:6157 b/package/network/utils/wwan/files/data/1004:6157 new file mode 100644 index 0000000..ec94956 --- /dev/null +++ b/package/network/utils/wwan/files/data/1004:6157 @@ -0,0 +1,6 @@ +{ + "desc": "LG LUU-2110TI", + "control": 0, + "data": 2 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/1004:618f b/package/network/utils/wwan/files/data/1004:618f new file mode 100644 index 0000000..df98b66 --- /dev/null +++ b/package/network/utils/wwan/files/data/1004:618f @@ -0,0 +1,5 @@ +{ + "desc": "LG L-02C", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/106c:3711 b/package/network/utils/wwan/files/data/106c:3711 new file mode 100644 index 0000000..4d22d4d --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3711 @@ -0,0 +1,6 @@ +{ + "desc": "PANTECH UM-150", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/106c:3714 b/package/network/utils/wwan/files/data/106c:3714 new file mode 100644 index 0000000..5fa2a3a --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3714 @@ -0,0 +1,6 @@ +{ + "desc": "PANTECH UM-175", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/106c:3715 b/package/network/utils/wwan/files/data/106c:3715 new file mode 100644 index 0000000..8cbe23d --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3715 @@ -0,0 +1,6 @@ +{ + "desc": "PANTECH UM-175AL", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/106c:3716 b/package/network/utils/wwan/files/data/106c:3716 new file mode 100644 index 0000000..18bd074 --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3716 @@ -0,0 +1,6 @@ +{ + "desc": "PANTECH UM-190", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/106c:3717 b/package/network/utils/wwan/files/data/106c:3717 new file mode 100644 index 0000000..e028a4b --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3717 @@ -0,0 +1,6 @@ +{ + "desc": "PANTECH UM-185C/UM185E", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/106c:3718 b/package/network/utils/wwan/files/data/106c:3718 new file mode 100644 index 0000000..362f482 --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3718 @@ -0,0 +1,4 @@ +{ + "desc": "PANTECH UML-290 4G Modem", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/106c:3721 b/package/network/utils/wwan/files/data/106c:3721 new file mode 100644 index 0000000..ac61a08 --- /dev/null +++ b/package/network/utils/wwan/files/data/106c:3721 @@ -0,0 +1,4 @@ +{ + "desc": "PANTECH P4200 4G Modem", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/1199:0017 b/package/network/utils/wwan/files/data/1199:0017 new file mode 100644 index 0000000..a50654d --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0017 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra EM5625", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0018 b/package/network/utils/wwan/files/data/1199:0018 new file mode 100644 index 0000000..02d7494 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0018 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5720", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0019 b/package/network/utils/wwan/files/data/1199:0019 new file mode 100644 index 0000000..4d6d4a9 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0019 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC595U", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0020 b/package/network/utils/wwan/files/data/1199:0020 new file mode 100644 index 0000000..3482db4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0020 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5725", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0021 b/package/network/utils/wwan/files/data/1199:0021 new file mode 100644 index 0000000..226c1b4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0021 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC597E", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0022 b/package/network/utils/wwan/files/data/1199:0022 new file mode 100644 index 0000000..dd089a3 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0022 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra EM5725", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0023 b/package/network/utils/wwan/files/data/1199:0023 new file mode 100644 index 0000000..9c7e72b --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0023 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC597", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0024 b/package/network/utils/wwan/files/data/1199:0024 new file mode 100644 index 0000000..425d4cc --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0024 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5727 CDMA", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0025 b/package/network/utils/wwan/files/data/1199:0025 new file mode 100644 index 0000000..002d6fb --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0025 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC598", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0026 b/package/network/utils/wwan/files/data/1199:0026 new file mode 100644 index 0000000..13998de --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0026 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra T11", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0027 b/package/network/utils/wwan/files/data/1199:0027 new file mode 100644 index 0000000..af4824c --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0027 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC402", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0028 b/package/network/utils/wwan/files/data/1199:0028 new file mode 100644 index 0000000..34c896e --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0028 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5728", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0112 b/package/network/utils/wwan/files/data/1199:0112 new file mode 100644 index 0000000..083baee --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0112 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra CDMA 1xEVDO PC Card, AC580", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0120 b/package/network/utils/wwan/files/data/1199:0120 new file mode 100644 index 0000000..4d6d4a9 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0120 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC595U", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0218 b/package/network/utils/wwan/files/data/1199:0218 new file mode 100644 index 0000000..02d7494 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0218 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5720", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0220 b/package/network/utils/wwan/files/data/1199:0220 new file mode 100644 index 0000000..3482db4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0220 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5725", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0224 b/package/network/utils/wwan/files/data/1199:0224 new file mode 100644 index 0000000..a57e54a --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0224 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC5727", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:0301 b/package/network/utils/wwan/files/data/1199:0301 new file mode 100644 index 0000000..13fd7da --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:0301 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC250U", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6802 b/package/network/utils/wwan/files/data/1199:6802 new file mode 100644 index 0000000..d9bd29f --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6802 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8755", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6803 b/package/network/utils/wwan/files/data/1199:6803 new file mode 100644 index 0000000..c694fa3 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6803 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8765", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6804 b/package/network/utils/wwan/files/data/1199:6804 new file mode 100644 index 0000000..d9bd29f --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6804 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8755", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6805 b/package/network/utils/wwan/files/data/1199:6805 new file mode 100644 index 0000000..c694fa3 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6805 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8765", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6808 b/package/network/utils/wwan/files/data/1199:6808 new file mode 100644 index 0000000..d9bd29f --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6808 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8755", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6809 b/package/network/utils/wwan/files/data/1199:6809 new file mode 100644 index 0000000..d9bd29f --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6809 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8755", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6813 b/package/network/utils/wwan/files/data/1199:6813 new file mode 100644 index 0000000..f10c104 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6813 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8775", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6815 b/package/network/utils/wwan/files/data/1199:6815 new file mode 100644 index 0000000..f10c104 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6815 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8775", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6816 b/package/network/utils/wwan/files/data/1199:6816 new file mode 100644 index 0000000..f10c104 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6816 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8775", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6820 b/package/network/utils/wwan/files/data/1199:6820 new file mode 100644 index 0000000..ce52c8f --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6820 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC875", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1199:6821 b/package/network/utils/wwan/files/data/1199:6821 new file mode 100644 index 0000000..3ebd0be --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6821 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC875U", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6822 b/package/network/utils/wwan/files/data/1199:6822 new file mode 100644 index 0000000..35ee919 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6822 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC875E", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6833 b/package/network/utils/wwan/files/data/1199:6833 new file mode 100644 index 0000000..0fcd10e --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6833 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8781", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6834 b/package/network/utils/wwan/files/data/1199:6834 new file mode 100644 index 0000000..0b9eadf --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6834 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8780", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6835 b/package/network/utils/wwan/files/data/1199:6835 new file mode 100644 index 0000000..0fcd10e --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6835 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8781", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6838 b/package/network/utils/wwan/files/data/1199:6838 new file mode 100644 index 0000000..0b9eadf --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6838 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8780", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6839 b/package/network/utils/wwan/files/data/1199:6839 new file mode 100644 index 0000000..0fcd10e --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6839 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8781", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:683a b/package/network/utils/wwan/files/data/1199:683a new file mode 100644 index 0000000..02da610 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:683a @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8785", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:683b b/package/network/utils/wwan/files/data/1199:683b new file mode 100644 index 0000000..0f2a133 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:683b @@ -0,0 +1,5 @@ +{ + "desc": "Sierra MC8785 Composite", + "control": 3, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1199:6850 b/package/network/utils/wwan/files/data/1199:6850 new file mode 100644 index 0000000..1989d0a --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6850 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC880", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6851 b/package/network/utils/wwan/files/data/1199:6851 new file mode 100644 index 0000000..16d8ab4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6851 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC 881", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6852 b/package/network/utils/wwan/files/data/1199:6852 new file mode 100644 index 0000000..65be37b --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6852 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC880E", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6853 b/package/network/utils/wwan/files/data/1199:6853 new file mode 100644 index 0000000..a8aee6d --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6853 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC881E", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6855 b/package/network/utils/wwan/files/data/1199:6855 new file mode 100644 index 0000000..24eddc6 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6855 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC880U", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6856 b/package/network/utils/wwan/files/data/1199:6856 new file mode 100644 index 0000000..415a80a --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6856 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra ATT USB Connect 881", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6859 b/package/network/utils/wwan/files/data/1199:6859 new file mode 100644 index 0000000..075cc6b --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6859 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC885E", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:685a b/package/network/utils/wwan/files/data/1199:685a new file mode 100644 index 0000000..075cc6b --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:685a @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC885E", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1199:6880 b/package/network/utils/wwan/files/data/1199:6880 new file mode 100644 index 0000000..e188c03 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6880 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra C885", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1199:6890 b/package/network/utils/wwan/files/data/1199:6890 new file mode 100644 index 0000000..6d2f892 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6890 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra C888", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1199:6891 b/package/network/utils/wwan/files/data/1199:6891 new file mode 100644 index 0000000..fa866e2 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6891 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra C22 and C33", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1199:6892 b/package/network/utils/wwan/files/data/1199:6892 new file mode 100644 index 0000000..99a2bd2 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6892 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra Compass HSPA", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1199:6893 b/package/network/utils/wwan/files/data/1199:6893 new file mode 100644 index 0000000..16f4dfd --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:6893 @@ -0,0 +1,5 @@ +{ + "desc": "Sierra C889", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1199:68a2 b/package/network/utils/wwan/files/data/1199:68a2 new file mode 100644 index 0000000..ac1b184 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:68a2 @@ -0,0 +1,4 @@ +{ + "desc": "Sierra MC7710", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/1199:68aa b/package/network/utils/wwan/files/data/1199:68aa new file mode 100644 index 0000000..7c5a9f2 --- /dev/null +++ b/package/network/utils/wwan/files/data/1199:68aa @@ -0,0 +1,5 @@ +{ + "desc": "Sierra AC320U/AC330U Direct IP", + "control": 3, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1035 b/package/network/utils/wwan/files/data/12d1:1035 new file mode 100644 index 0000000..ad7025a --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1035 @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI U8110", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1404 b/package/network/utils/wwan/files/data/12d1:1404 new file mode 100644 index 0000000..b186ad5 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1404 @@ -0,0 +1,4 @@ +{ + "desc": "HUAWEI UMG1831", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:1406 b/package/network/utils/wwan/files/data/12d1:1406 new file mode 100644 index 0000000..b1aa317 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1406 @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option newer modems", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:140b b/package/network/utils/wwan/files/data/12d1:140b new file mode 100644 index 0000000..cc99898 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:140b @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option EC1260 Wireless Data Modem HSD USB Card", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:140c b/package/network/utils/wwan/files/data/12d1:140c new file mode 100644 index 0000000..148d1d1 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:140c @@ -0,0 +1,4 @@ +{ + "desc": "HUAWEI/Option newer modems", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:1412 b/package/network/utils/wwan/files/data/12d1:1412 new file mode 100644 index 0000000..e6fb6cc --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1412 @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option EC168", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:141b b/package/network/utils/wwan/files/data/12d1:141b new file mode 100644 index 0000000..b1aa317 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:141b @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option newer modems", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1433 b/package/network/utils/wwan/files/data/12d1:1433 new file mode 100644 index 0000000..c5d86cb --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1433 @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option E1756C", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1436 b/package/network/utils/wwan/files/data/12d1:1436 new file mode 100644 index 0000000..7db8644 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1436 @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option E1800", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1444 b/package/network/utils/wwan/files/data/12d1:1444 new file mode 100644 index 0000000..500d775 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1444 @@ -0,0 +1,5 @@ +{ + "desc": "HUAWEI/Option E352-R1", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:144e b/package/network/utils/wwan/files/data/12d1:144e new file mode 100644 index 0000000..a704946 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:144e @@ -0,0 +1,5 @@ +{ + "desc": "Huawei K3806", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1464 b/package/network/utils/wwan/files/data/12d1:1464 new file mode 100644 index 0000000..1b5397c --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1464 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei K4505", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1465 b/package/network/utils/wwan/files/data/12d1:1465 new file mode 100644 index 0000000..dbb20f7 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1465 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei K3765", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1491 b/package/network/utils/wwan/files/data/12d1:1491 new file mode 100644 index 0000000..c1ae9a5 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1491 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei R201", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:14a5 b/package/network/utils/wwan/files/data/12d1:14a5 new file mode 100644 index 0000000..50ea079 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14a5 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:14a8 b/package/network/utils/wwan/files/data/12d1:14a8 new file mode 100644 index 0000000..50ea079 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14a8 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:14ac b/package/network/utils/wwan/files/data/12d1:14ac new file mode 100644 index 0000000..148d1d1 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14ac @@ -0,0 +1,4 @@ +{ + "desc": "HUAWEI/Option newer modems", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:14ae b/package/network/utils/wwan/files/data/12d1:14ae new file mode 100644 index 0000000..e27a798 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14ae @@ -0,0 +1,5 @@ +{ + "desc": "Huawei K3806", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/12d1:14c6 b/package/network/utils/wwan/files/data/12d1:14c6 new file mode 100644 index 0000000..0cb4d8c --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14c6 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K4605", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:14c8 b/package/network/utils/wwan/files/data/12d1:14c8 new file mode 100644 index 0000000..958b118 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14c8 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K5005", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:14c9 b/package/network/utils/wwan/files/data/12d1:14c9 new file mode 100644 index 0000000..bc75791 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14c9 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K3770", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:14ca b/package/network/utils/wwan/files/data/12d1:14ca new file mode 100644 index 0000000..8155b4b --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14ca @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K3771", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:14cb b/package/network/utils/wwan/files/data/12d1:14cb new file mode 100644 index 0000000..b496a60 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14cb @@ -0,0 +1,5 @@ +{ + "desc": "Huawei K4510", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:14cc b/package/network/utils/wwan/files/data/12d1:14cc new file mode 100644 index 0000000..98488bd --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14cc @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K4511", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:14cf b/package/network/utils/wwan/files/data/12d1:14cf new file mode 100644 index 0000000..18e1e1e --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14cf @@ -0,0 +1,5 @@ +{ + "desc": "Huawei K3772", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:14d2 b/package/network/utils/wwan/files/data/12d1:14d2 new file mode 100644 index 0000000..414b846 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:14d2 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E173/E177", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:1506 b/package/network/utils/wwan/files/data/12d1:1506 new file mode 100644 index 0000000..65760e8 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1506 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E367/E398", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:150a b/package/network/utils/wwan/files/data/12d1:150a new file mode 100644 index 0000000..45f191a --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:150a @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E398", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:150c b/package/network/utils/wwan/files/data/12d1:150c new file mode 100644 index 0000000..7ab4c49 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:150c @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E367", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:150f b/package/network/utils/wwan/files/data/12d1:150f new file mode 100644 index 0000000..7ab4c49 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:150f @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E367", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:151b b/package/network/utils/wwan/files/data/12d1:151b new file mode 100644 index 0000000..28e561c --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:151b @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E392u-12", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/12d1:151d b/package/network/utils/wwan/files/data/12d1:151d new file mode 100644 index 0000000..e5eae2a --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:151d @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E3131", + "control": 3, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:156c b/package/network/utils/wwan/files/data/12d1:156c new file mode 100644 index 0000000..3fc6b1b --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:156c @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E3276", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1576 b/package/network/utils/wwan/files/data/12d1:1576 new file mode 100644 index 0000000..1aeb021 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1576 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K4201 composite", + "type": "mbim" +} diff --git a/package/network/utils/wwan/files/data/12d1:1577 b/package/network/utils/wwan/files/data/12d1:1577 new file mode 100644 index 0000000..46a12da --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1577 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K4202 composite", + "type": "mbim" +} diff --git a/package/network/utils/wwan/files/data/12d1:1578 b/package/network/utils/wwan/files/data/12d1:1578 new file mode 100644 index 0000000..6710d15 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1578 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K4606 composite", + "type": "mbim" +} diff --git a/package/network/utils/wwan/files/data/12d1:1589 b/package/network/utils/wwan/files/data/12d1:1589 new file mode 100644 index 0000000..e2d3527 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1589 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E8278", + "type": "ncm" +} diff --git a/package/network/utils/wwan/files/data/12d1:1c05 b/package/network/utils/wwan/files/data/12d1:1c05 new file mode 100644 index 0000000..c561224 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c05 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173s", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1c07 b/package/network/utils/wwan/files/data/12d1:1c07 new file mode 100644 index 0000000..cee7276 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c07 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E188", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1c08 b/package/network/utils/wwan/files/data/12d1:1c08 new file mode 100644 index 0000000..4f6fb21 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c08 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173s", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1c10 b/package/network/utils/wwan/files/data/12d1:1c10 new file mode 100644 index 0000000..50ea079 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c10 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1c12 b/package/network/utils/wwan/files/data/12d1:1c12 new file mode 100644 index 0000000..50ea079 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c12 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1c1e b/package/network/utils/wwan/files/data/12d1:1c1e new file mode 100644 index 0000000..4622965 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c1e @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E586", + "type": "ncm" +} diff --git a/package/network/utils/wwan/files/data/12d1:1c1f b/package/network/utils/wwan/files/data/12d1:1c1f new file mode 100644 index 0000000..13cb40f --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c1f @@ -0,0 +1,4 @@ +{ + "desc": "Huawei E587", + "type": "ncm" +} diff --git a/package/network/utils/wwan/files/data/12d1:1c23 b/package/network/utils/wwan/files/data/12d1:1c23 new file mode 100644 index 0000000..d104347 --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1c23 @@ -0,0 +1,5 @@ +{ + "desc": "Huawei E173", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/12d1:1f16 b/package/network/utils/wwan/files/data/12d1:1f16 new file mode 100644 index 0000000..10d27cf --- /dev/null +++ b/package/network/utils/wwan/files/data/12d1:1f16 @@ -0,0 +1,4 @@ +{ + "desc": "Huawei K5150 composite", + "mode": "mbim" +} diff --git a/package/network/utils/wwan/files/data/1410:1400 b/package/network/utils/wwan/files/data/1410:1400 new file mode 100644 index 0000000..e2bda96 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:1400 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel U730", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:1410 b/package/network/utils/wwan/files/data/1410:1410 new file mode 100644 index 0000000..ba48aea --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:1410 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel U740", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:1420 b/package/network/utils/wwan/files/data/1410:1420 new file mode 100644 index 0000000..5cc96b6 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:1420 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel U870", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:1430 b/package/network/utils/wwan/files/data/1410:1430 new file mode 100644 index 0000000..012f3ad --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:1430 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel XU870", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:1450 b/package/network/utils/wwan/files/data/1410:1450 new file mode 100644 index 0000000..d101677 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:1450 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel X950D", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2100 b/package/network/utils/wwan/files/data/1410:2100 new file mode 100644 index 0000000..a0328cf --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2100 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel EV620", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2110 b/package/network/utils/wwan/files/data/1410:2110 new file mode 100644 index 0000000..701bf42 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2110 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel ES720", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2120 b/package/network/utils/wwan/files/data/1410:2120 new file mode 100644 index 0000000..7ab3c9d --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2120 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel E725", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2130 b/package/network/utils/wwan/files/data/1410:2130 new file mode 100644 index 0000000..98006e2 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2130 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel ES620", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2400 b/package/network/utils/wwan/files/data/1410:2400 new file mode 100644 index 0000000..cd9f290 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2400 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel EU730", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2410 b/package/network/utils/wwan/files/data/1410:2410 new file mode 100644 index 0000000..4635063 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2410 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel EU740", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:2420 b/package/network/utils/wwan/files/data/1410:2420 new file mode 100644 index 0000000..340666c --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:2420 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel EU870D", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:4100 b/package/network/utils/wwan/files/data/1410:4100 new file mode 100644 index 0000000..260a289 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:4100 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel MC727/U727", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:4400 b/package/network/utils/wwan/files/data/1410:4400 new file mode 100644 index 0000000..838a7fb --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:4400 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel Ovation MC930D/MC950D", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:6000 b/package/network/utils/wwan/files/data/1410:6000 new file mode 100644 index 0000000..a12716e --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:6000 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel USB760", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:6001 b/package/network/utils/wwan/files/data/1410:6001 new file mode 100644 index 0000000..a12716e --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:6001 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel USB760", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:6002 b/package/network/utils/wwan/files/data/1410:6002 new file mode 100644 index 0000000..fce8e9b --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:6002 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel USB760 3G", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:6010 b/package/network/utils/wwan/files/data/1410:6010 new file mode 100644 index 0000000..d08c399 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:6010 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel MC780", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:7001 b/package/network/utils/wwan/files/data/1410:7001 new file mode 100644 index 0000000..079c7d5 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:7001 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel MiFi 2372", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:7003 b/package/network/utils/wwan/files/data/1410:7003 new file mode 100644 index 0000000..079c7d5 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:7003 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel MiFi 2372", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:7030 b/package/network/utils/wwan/files/data/1410:7030 new file mode 100644 index 0000000..0fc4029 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:7030 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel USB998", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:7031 b/package/network/utils/wwan/files/data/1410:7031 new file mode 100644 index 0000000..e1ba049 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:7031 @@ -0,0 +1,6 @@ +{ + "desc": "Novatel USB679", + "control": 0, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1410:7041 b/package/network/utils/wwan/files/data/1410:7041 new file mode 100644 index 0000000..03e8fcd --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:7041 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel MF3470", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:7042 b/package/network/utils/wwan/files/data/1410:7042 new file mode 100644 index 0000000..0bb9cdb --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:7042 @@ -0,0 +1,5 @@ +{ + "desc": "Novatel Ovation MC545/MC547", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1410:9011 b/package/network/utils/wwan/files/data/1410:9011 new file mode 100644 index 0000000..8247a97 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:9011 @@ -0,0 +1,4 @@ +{ + "desc": "Novatel E371", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/1410:b001 b/package/network/utils/wwan/files/data/1410:b001 new file mode 100644 index 0000000..3c13539 --- /dev/null +++ b/package/network/utils/wwan/files/data/1410:b001 @@ -0,0 +1,4 @@ +{ + "desc": "Novatel MC551/USB551L", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/1529:3100 b/package/network/utils/wwan/files/data/1529:3100 new file mode 100644 index 0000000..5e4fe34 --- /dev/null +++ b/package/network/utils/wwan/files/data/1529:3100 @@ -0,0 +1,6 @@ +{ + "desc": "UBIQUAM U-100/105/200/300/520", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d5:6202 b/package/network/utils/wwan/files/data/16d5:6202 new file mode 100644 index 0000000..1ba8a50 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d5:6202 @@ -0,0 +1,5 @@ +{ + "desc": "AnyData ADU-620UW", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/16d5:6501 b/package/network/utils/wwan/files/data/16d5:6501 new file mode 100644 index 0000000..09207df --- /dev/null +++ b/package/network/utils/wwan/files/data/16d5:6501 @@ -0,0 +1,5 @@ +{ + "desc": "AnyData ADU-300A", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/16d5:6502 b/package/network/utils/wwan/files/data/16d5:6502 new file mode 100644 index 0000000..4bdbf89 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d5:6502 @@ -0,0 +1,5 @@ +{ + "desc": "AnyData ADU-500A", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/16d5:6603 b/package/network/utils/wwan/files/data/16d5:6603 new file mode 100644 index 0000000..5c108a2 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d5:6603 @@ -0,0 +1,6 @@ +{ + "desc": "AnyData ADU-890WH", + "control": 0, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/16d5:900d b/package/network/utils/wwan/files/data/16d5:900d new file mode 100644 index 0000000..b1c4869 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d5:900d @@ -0,0 +1,6 @@ +{ + "desc": "AnyData ADU-890WH", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:5141 b/package/network/utils/wwan/files/data/16d8:5141 new file mode 100644 index 0000000..bda356f --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:5141 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CNU-510", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:5533 b/package/network/utils/wwan/files/data/16d8:5533 new file mode 100644 index 0000000..185d257 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:5533 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CNU-550", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:5543 b/package/network/utils/wwan/files/data/16d8:5543 new file mode 100644 index 0000000..185d257 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:5543 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CNU-550", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:5553 b/package/network/utils/wwan/files/data/16d8:5553 new file mode 100644 index 0000000..2403381 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:5553 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CDU-550", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:6002 b/package/network/utils/wwan/files/data/16d8:6002 new file mode 100644 index 0000000..715878c --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6002 @@ -0,0 +1,5 @@ +{ + "desc": "Franklin U300", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/16d8:6006 b/package/network/utils/wwan/files/data/16d8:6006 new file mode 100644 index 0000000..bb8f87e --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6006 @@ -0,0 +1,5 @@ +{ + "desc": "Cmotech CGU-628", + "control": 0, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/16d8:6007 b/package/network/utils/wwan/files/data/16d8:6007 new file mode 100644 index 0000000..a0ed8bc --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6007 @@ -0,0 +1,4 @@ +{ + "desc": "Cmotech CHE-628S", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/16d8:6008 b/package/network/utils/wwan/files/data/16d8:6008 new file mode 100644 index 0000000..1afeb99 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6008 @@ -0,0 +1,4 @@ +{ + "desc": "Franklin U301", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/16d8:6522 b/package/network/utils/wwan/files/data/16d8:6522 new file mode 100644 index 0000000..44343d0 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6522 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CDU-650", + "control": 2, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:6523 b/package/network/utils/wwan/files/data/16d8:6523 new file mode 100644 index 0000000..406566b --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6523 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CCU-650U", + "control": 2, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:6532 b/package/network/utils/wwan/files/data/16d8:6532 new file mode 100644 index 0000000..5b6a147 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6532 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CCU-650", + "control": 2, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:6533 b/package/network/utils/wwan/files/data/16d8:6533 new file mode 100644 index 0000000..07175f3 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6533 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CNM-650", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:6543 b/package/network/utils/wwan/files/data/16d8:6543 new file mode 100644 index 0000000..c518ca7 --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:6543 @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CNU-650", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/16d8:680a b/package/network/utils/wwan/files/data/16d8:680a new file mode 100644 index 0000000..9b1c85f --- /dev/null +++ b/package/network/utils/wwan/files/data/16d8:680a @@ -0,0 +1,6 @@ +{ + "desc": "Cmotech CDU-680", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:0001 b/package/network/utils/wwan/files/data/19d2:0001 new file mode 100644 index 0000000..31ee3fd --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0001 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0002 b/package/network/utils/wwan/files/data/19d2:0002 new file mode 100644 index 0000000..ee80af5 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0002 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE ET502HS/MT505UP/MF632", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0015 b/package/network/utils/wwan/files/data/19d2:0015 new file mode 100644 index 0000000..31ee3fd --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0015 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0016 b/package/network/utils/wwan/files/data/19d2:0016 new file mode 100644 index 0000000..48c5fef --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0016 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MF110/ZTE", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0017 b/package/network/utils/wwan/files/data/19d2:0017 new file mode 100644 index 0000000..87178fb --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0017 @@ -0,0 +1,4 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0018 b/package/network/utils/wwan/files/data/19d2:0018 new file mode 100644 index 0000000..76120d4 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0018 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MSA110UP/ZTE", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0019 b/package/network/utils/wwan/files/data/19d2:0019 new file mode 100644 index 0000000..8d31ed7 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0019 @@ -0,0 +1,4 @@ +{ + "desc": "ONDA MT689DC/ZTE", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0022 b/package/network/utils/wwan/files/data/19d2:0022 new file mode 100644 index 0000000..7ed8ed1 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0022 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE K2525", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0024 b/package/network/utils/wwan/files/data/19d2:0024 new file mode 100644 index 0000000..5ae34af --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0024 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MT503HSA", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0025 b/package/network/utils/wwan/files/data/19d2:0025 new file mode 100644 index 0000000..68baeb7 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0025 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF628", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0031 b/package/network/utils/wwan/files/data/19d2:0031 new file mode 100644 index 0000000..7aa8aa4 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0031 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF110/MF112/MF626", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0033 b/package/network/utils/wwan/files/data/19d2:0033 new file mode 100644 index 0000000..e99314e --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0033 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF636", + "control": 1, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0037 b/package/network/utils/wwan/files/data/19d2:0037 new file mode 100644 index 0000000..8ee565d --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0037 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "control": 2, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0039 b/package/network/utils/wwan/files/data/19d2:0039 new file mode 100644 index 0000000..c80a51a --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0039 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF100", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0042 b/package/network/utils/wwan/files/data/19d2:0042 new file mode 100644 index 0000000..c08014c --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0042 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF190", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0052 b/package/network/utils/wwan/files/data/19d2:0052 new file mode 100644 index 0000000..87178fb --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0052 @@ -0,0 +1,4 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0055 b/package/network/utils/wwan/files/data/19d2:0055 new file mode 100644 index 0000000..87178fb --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0055 @@ -0,0 +1,4 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0057 b/package/network/utils/wwan/files/data/19d2:0057 new file mode 100644 index 0000000..7800746 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0057 @@ -0,0 +1,5 @@ +{ + "desc": "AIKO 83D", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0063 b/package/network/utils/wwan/files/data/19d2:0063 new file mode 100644 index 0000000..f45825d --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0063 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K3565-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0064 b/package/network/utils/wwan/files/data/19d2:0064 new file mode 100644 index 0000000..edb0efe --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0064 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF627", + "control": 0, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0066 b/package/network/utils/wwan/files/data/19d2:0066 new file mode 100644 index 0000000..c57d7ae --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0066 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF626", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0073 b/package/network/utils/wwan/files/data/19d2:0073 new file mode 100644 index 0000000..0f9502f --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0073 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE A580", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0079 b/package/network/utils/wwan/files/data/19d2:0079 new file mode 100644 index 0000000..569a999 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0079 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE A353", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0082 b/package/network/utils/wwan/files/data/19d2:0082 new file mode 100644 index 0000000..ea4fcd9 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0082 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF668/MF190", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0086 b/package/network/utils/wwan/files/data/19d2:0086 new file mode 100644 index 0000000..f25d77a --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0086 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF645", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0091 b/package/network/utils/wwan/files/data/19d2:0091 new file mode 100644 index 0000000..4e429a6 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0091 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF636", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0094 b/package/network/utils/wwan/files/data/19d2:0094 new file mode 100644 index 0000000..34a976e --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0094 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE AC581", + "control": 3, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0104 b/package/network/utils/wwan/files/data/19d2:0104 new file mode 100644 index 0000000..0646b8d --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0104 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K4505-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0108 b/package/network/utils/wwan/files/data/19d2:0108 new file mode 100644 index 0000000..369d70f --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0108 @@ -0,0 +1,5 @@ +{ + "desc": "ONDA MT505UP/ZTE", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0116 b/package/network/utils/wwan/files/data/19d2:0116 new file mode 100644 index 0000000..bfe9b5d --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0116 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF651", + "control": 1, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:0117 b/package/network/utils/wwan/files/data/19d2:0117 new file mode 100644 index 0000000..8610bbf --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0117 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF112", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0121 b/package/network/utils/wwan/files/data/19d2:0121 new file mode 100644 index 0000000..da5b96c --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0121 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF637", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0124 b/package/network/utils/wwan/files/data/19d2:0124 new file mode 100644 index 0000000..74b4f6f --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0124 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF110", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0128 b/package/network/utils/wwan/files/data/19d2:0128 new file mode 100644 index 0000000..620eb90 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0128 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF651", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0142 b/package/network/utils/wwan/files/data/19d2:0142 new file mode 100644 index 0000000..6d19e3e --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0142 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF665C", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:0143 b/package/network/utils/wwan/files/data/19d2:0143 new file mode 100644 index 0000000..6885a9b --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0143 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF190B", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:0152 b/package/network/utils/wwan/files/data/19d2:0152 new file mode 100644 index 0000000..20047be --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0152 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE AC583", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:0157 b/package/network/utils/wwan/files/data/19d2:0157 new file mode 100644 index 0000000..d7be7c4 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0157 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF683", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0167 b/package/network/utils/wwan/files/data/19d2:0167 new file mode 100644 index 0000000..0eefdc1 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0167 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF820D", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0170 b/package/network/utils/wwan/files/data/19d2:0170 new file mode 100644 index 0000000..d7d6f97 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0170 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE A371", + "control": 0, + "data": 1 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:0199 b/package/network/utils/wwan/files/data/19d2:0199 new file mode 100644 index 0000000..565afcf --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0199 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF820S", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0257 b/package/network/utils/wwan/files/data/19d2:0257 new file mode 100644 index 0000000..6e94316 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0257 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF821", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0265 b/package/network/utils/wwan/files/data/19d2:0265 new file mode 100644 index 0000000..284c6ed --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0265 @@ -0,0 +1,4 @@ +{ + "desc": "Onda MT8205/ZTE", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0284 b/package/network/utils/wwan/files/data/19d2:0284 new file mode 100644 index 0000000..4fc3bbb --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0284 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF880", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:0326 b/package/network/utils/wwan/files/data/19d2:0326 new file mode 100644 index 0000000..c854f2a --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:0326 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF821D", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1003 b/package/network/utils/wwan/files/data/19d2:1003 new file mode 100644 index 0000000..a7d0eb5 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1003 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE K3805-Z", + "control": 1, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1008 b/package/network/utils/wwan/files/data/19d2:1008 new file mode 100644 index 0000000..d0b329c --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1008 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K3570-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1010 b/package/network/utils/wwan/files/data/19d2:1010 new file mode 100644 index 0000000..fe294f0 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1010 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K3571-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1015 b/package/network/utils/wwan/files/data/19d2:1015 new file mode 100644 index 0000000..a5eab00 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1015 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE K3806-Z", + "control": 1, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1018 b/package/network/utils/wwan/files/data/19d2:1018 new file mode 100644 index 0000000..48add8f --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1018 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K5006-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1172 b/package/network/utils/wwan/files/data/19d2:1172 new file mode 100644 index 0000000..1b4c728 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1172 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE K4510-Z", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1173 b/package/network/utils/wwan/files/data/19d2:1173 new file mode 100644 index 0000000..1b4c728 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1173 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE K4510-Z", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1176 b/package/network/utils/wwan/files/data/19d2:1176 new file mode 100644 index 0000000..4bbd5b7 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1176 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K3770-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1177 b/package/network/utils/wwan/files/data/19d2:1177 new file mode 100644 index 0000000..3d196af --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1177 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE K3770-Z", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1181 b/package/network/utils/wwan/files/data/19d2:1181 new file mode 100644 index 0000000..5ee7b2f --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1181 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE K3772-Z", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1203 b/package/network/utils/wwan/files/data/19d2:1203 new file mode 100644 index 0000000..4502531 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1203 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF691", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1208 b/package/network/utils/wwan/files/data/19d2:1208 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1208 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1211 b/package/network/utils/wwan/files/data/19d2:1211 new file mode 100644 index 0000000..0df58f0 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1211 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF195", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1212 b/package/network/utils/wwan/files/data/19d2:1212 new file mode 100644 index 0000000..0df58f0 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1212 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF195", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1217 b/package/network/utils/wwan/files/data/19d2:1217 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1217 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1218 b/package/network/utils/wwan/files/data/19d2:1218 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1218 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1220 b/package/network/utils/wwan/files/data/19d2:1220 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1220 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1222 b/package/network/utils/wwan/files/data/19d2:1222 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1222 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1245 b/package/network/utils/wwan/files/data/19d2:1245 new file mode 100644 index 0000000..c08014c --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1245 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF190", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1252 b/package/network/utils/wwan/files/data/19d2:1252 new file mode 100644 index 0000000..768a433 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1252 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF669", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1254 b/package/network/utils/wwan/files/data/19d2:1254 new file mode 100644 index 0000000..c08014c --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1254 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF190", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1256 b/package/network/utils/wwan/files/data/19d2:1256 new file mode 100644 index 0000000..c08014c --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1256 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF190", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1270 b/package/network/utils/wwan/files/data/19d2:1270 new file mode 100644 index 0000000..7ad57f0 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1270 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF667", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1401 b/package/network/utils/wwan/files/data/19d2:1401 new file mode 100644 index 0000000..730b634 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1401 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF60", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1402 b/package/network/utils/wwan/files/data/19d2:1402 new file mode 100644 index 0000000..730b634 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1402 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF60", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1426 b/package/network/utils/wwan/files/data/19d2:1426 new file mode 100644 index 0000000..cb9337b --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1426 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE MF91D", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:1512 b/package/network/utils/wwan/files/data/19d2:1512 new file mode 100644 index 0000000..7e4bbf7 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1512 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MFxxx", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1515 b/package/network/utils/wwan/files/data/19d2:1515 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1515 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1518 b/package/network/utils/wwan/files/data/19d2:1518 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1518 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1519 b/package/network/utils/wwan/files/data/19d2:1519 new file mode 100644 index 0000000..d8bc573 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1519 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF192", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1522 b/package/network/utils/wwan/files/data/19d2:1522 new file mode 100644 index 0000000..4c926f0 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1522 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF652", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1525 b/package/network/utils/wwan/files/data/19d2:1525 new file mode 100644 index 0000000..7a37c43 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1525 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF591", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1527 b/package/network/utils/wwan/files/data/19d2:1527 new file mode 100644 index 0000000..6b46c73 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1527 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF196", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1537 b/package/network/utils/wwan/files/data/19d2:1537 new file mode 100644 index 0000000..a625164 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1537 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF190J", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1538 b/package/network/utils/wwan/files/data/19d2:1538 new file mode 100644 index 0000000..a625164 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1538 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF190J", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:1544 b/package/network/utils/wwan/files/data/19d2:1544 new file mode 100644 index 0000000..a625164 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:1544 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE MF190J", + "control": 0, + "data": 0 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:2002 b/package/network/utils/wwan/files/data/19d2:2002 new file mode 100644 index 0000000..a049f19 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:2002 @@ -0,0 +1,4 @@ +{ + "desc": "ZTE K3765-Z", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/19d2:2003 b/package/network/utils/wwan/files/data/19d2:2003 new file mode 100644 index 0000000..a2a0880 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:2003 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MF180", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/19d2:ffdd b/package/network/utils/wwan/files/data/19d2:ffdd new file mode 100644 index 0000000..71d1050 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:ffdd @@ -0,0 +1,5 @@ +{ + "desc": "ZTE AC682", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:ffe4 b/package/network/utils/wwan/files/data/19d2:ffe4 new file mode 100644 index 0000000..03a16bf --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:ffe4 @@ -0,0 +1,6 @@ +{ + "desc": "ZTE AC3781", + "control": 1, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/19d2:ffe9 b/package/network/utils/wwan/files/data/19d2:ffe9 new file mode 100644 index 0000000..57531e2 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:ffe9 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE AC2738", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:fff1 b/package/network/utils/wwan/files/data/19d2:fff1 new file mode 100644 index 0000000..4347f28 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:fff1 @@ -0,0 +1,5 @@ +{ + "desc": "ZTE generic", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:fffb b/package/network/utils/wwan/files/data/19d2:fffb new file mode 100644 index 0000000..4ff616a --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:fffb @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MG880", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:fffc b/package/network/utils/wwan/files/data/19d2:fffc new file mode 100644 index 0000000..4ff616a --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:fffc @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MG880", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:fffd b/package/network/utils/wwan/files/data/19d2:fffd new file mode 100644 index 0000000..4ff616a --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:fffd @@ -0,0 +1,5 @@ +{ + "desc": "ZTE MG880", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:fffe b/package/network/utils/wwan/files/data/19d2:fffe new file mode 100644 index 0000000..4e60049 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:fffe @@ -0,0 +1,5 @@ +{ + "desc": "ZTE AC8700", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/19d2:ffff b/package/network/utils/wwan/files/data/19d2:ffff new file mode 100644 index 0000000..747fa23 --- /dev/null +++ b/package/network/utils/wwan/files/data/19d2:ffff @@ -0,0 +1,5 @@ +{ + "desc": "ZTE AC8710", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:1002 b/package/network/utils/wwan/files/data/1a8d:1002 new file mode 100644 index 0000000..93388be --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:1002 @@ -0,0 +1,5 @@ +{ + "desc": "Bandrich C-100/C-120", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:1003 b/package/network/utils/wwan/files/data/1a8d:1003 new file mode 100644 index 0000000..93388be --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:1003 @@ -0,0 +1,5 @@ +{ + "desc": "Bandrich C-100/C-120", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:1007 b/package/network/utils/wwan/files/data/1a8d:1007 new file mode 100644 index 0000000..f013968 --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:1007 @@ -0,0 +1,5 @@ +{ + "desc": "Bandrich C-270", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:1009 b/package/network/utils/wwan/files/data/1a8d:1009 new file mode 100644 index 0000000..82e4bf0 --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:1009 @@ -0,0 +1,5 @@ +{ + "desc": "Bandrich C-170/C-180", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:100c b/package/network/utils/wwan/files/data/1a8d:100c new file mode 100644 index 0000000..1acb9ee --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:100c @@ -0,0 +1,5 @@ +{ + "desc": "Bandrich C-320", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:100d b/package/network/utils/wwan/files/data/1a8d:100d new file mode 100644 index 0000000..67db2b4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:100d @@ -0,0 +1,5 @@ +{ + "desc": "Bandrich C-508", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1a8d:2006 b/package/network/utils/wwan/files/data/1a8d:2006 new file mode 100644 index 0000000..78f36ce --- /dev/null +++ b/package/network/utils/wwan/files/data/1a8d:2006 @@ -0,0 +1,6 @@ +{ + "desc": "Bandrich C-33x", + "control": 0, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/1bbb:0000 b/package/network/utils/wwan/files/data/1bbb:0000 new file mode 100644 index 0000000..0be73af --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:0000 @@ -0,0 +1,5 @@ +{ + "desc": "Alcatel X060S/X070S/X080S/X200", + "control": 2, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1bbb:0012 b/package/network/utils/wwan/files/data/1bbb:0012 new file mode 100644 index 0000000..3eecac0 --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:0012 @@ -0,0 +1,6 @@ +{ + "desc": "Alcatel X085C", + "control": 2, + "data": 2 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1bbb:0017 b/package/network/utils/wwan/files/data/1bbb:0017 new file mode 100644 index 0000000..853c05c --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:0017 @@ -0,0 +1,5 @@ +{ + "desc": "Alcatel X220L", + "control": 4, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1bbb:0052 b/package/network/utils/wwan/files/data/1bbb:0052 new file mode 100644 index 0000000..853c05c --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:0052 @@ -0,0 +1,5 @@ +{ + "desc": "Alcatel X220L", + "control": 4, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1bbb:00b7 b/package/network/utils/wwan/files/data/1bbb:00b7 new file mode 100644 index 0000000..9eaffe6 --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:00b7 @@ -0,0 +1,5 @@ +{ + "desc": "Alcatel X600", + "control": 0, + "data": 4 +}} diff --git a/package/network/utils/wwan/files/data/1bbb:00ca b/package/network/utils/wwan/files/data/1bbb:00ca new file mode 100644 index 0000000..80d71fa --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:00ca @@ -0,0 +1,6 @@ +{ + "desc": "Alcatel X080C", + "control": 0, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1bbb:011e b/package/network/utils/wwan/files/data/1bbb:011e new file mode 100644 index 0000000..160221d --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:011e @@ -0,0 +1,4 @@ +{ + "desc": "Alcatel L100V,", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/1bbb:0203 b/package/network/utils/wwan/files/data/1bbb:0203 new file mode 100644 index 0000000..2632a63 --- /dev/null +++ b/package/network/utils/wwan/files/data/1bbb:0203 @@ -0,0 +1,4 @@ +{ + "desc": "Alcatel L800Z,", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/1c9e:6060 b/package/network/utils/wwan/files/data/1c9e:6060 new file mode 100644 index 0000000..6f77bb4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:6060 @@ -0,0 +1,6 @@ +{ + "desc": "Alcatel X020 & X030", + "control": 2, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1c9e:6061 b/package/network/utils/wwan/files/data/1c9e:6061 new file mode 100644 index 0000000..6f77bb4 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:6061 @@ -0,0 +1,6 @@ +{ + "desc": "Alcatel X020 & X030", + "control": 2, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1c9e:9000 b/package/network/utils/wwan/files/data/1c9e:9000 new file mode 100644 index 0000000..39dcd77 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:9000 @@ -0,0 +1,6 @@ +{ + "desc": "4G Systems XS Stick W14", + "control": 0, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1c9e:9603 b/package/network/utils/wwan/files/data/1c9e:9603 new file mode 100644 index 0000000..fd3f099 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:9603 @@ -0,0 +1,5 @@ +{ + "desc": "4G Systems XS Stick W14", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1c9e:9605 b/package/network/utils/wwan/files/data/1c9e:9605 new file mode 100644 index 0000000..c2992c1 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:9605 @@ -0,0 +1,5 @@ +{ + "desc": "4G Systems XS Stick W14", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1c9e:9607 b/package/network/utils/wwan/files/data/1c9e:9607 new file mode 100644 index 0000000..c2992c1 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:9607 @@ -0,0 +1,5 @@ +{ + "desc": "4G Systems XS Stick W14", + "control": 1, + "data": 3 +}} diff --git a/package/network/utils/wwan/files/data/1c9e:9801 b/package/network/utils/wwan/files/data/1c9e:9801 new file mode 100644 index 0000000..40dcc76 --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:9801 @@ -0,0 +1,6 @@ +{ + "desc": "4G Systems XS Stick W21", + "control": 2, + "data": 1 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1c9e:9900 b/package/network/utils/wwan/files/data/1c9e:9900 new file mode 100644 index 0000000..42da3ab --- /dev/null +++ b/package/network/utils/wwan/files/data/1c9e:9900 @@ -0,0 +1,6 @@ +{ + "desc": "Softbank C02LC", + "control": 1, + "data": 2 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/1e0e:9000 b/package/network/utils/wwan/files/data/1e0e:9000 new file mode 100644 index 0000000..bdb159d --- /dev/null +++ b/package/network/utils/wwan/files/data/1e0e:9000 @@ -0,0 +1,5 @@ +{ + "desc": "PROLink PHS100, Hyundai MB-810, A-Link 3GU", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1e0e:9100 b/package/network/utils/wwan/files/data/1e0e:9100 new file mode 100644 index 0000000..d1b2dda --- /dev/null +++ b/package/network/utils/wwan/files/data/1e0e:9100 @@ -0,0 +1,5 @@ +{ + "desc": "PROLink PHS300, A-Link 3GU", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1e0e:9200 b/package/network/utils/wwan/files/data/1e0e:9200 new file mode 100644 index 0000000..bdb159d --- /dev/null +++ b/package/network/utils/wwan/files/data/1e0e:9200 @@ -0,0 +1,5 @@ +{ + "desc": "PROLink PHS100, Hyundai MB-810, A-Link 3GU", + "control": 1, + "data": 2 +}} diff --git a/package/network/utils/wwan/files/data/1e0e:ce16 b/package/network/utils/wwan/files/data/1e0e:ce16 new file mode 100644 index 0000000..93e0c3f --- /dev/null +++ b/package/network/utils/wwan/files/data/1e0e:ce16 @@ -0,0 +1,5 @@ +{ + "desc": "D-Link DWM-162-U5, Micromax MMX 300c", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/1e0e:cefe b/package/network/utils/wwan/files/data/1e0e:cefe new file mode 100644 index 0000000..ebc941d --- /dev/null +++ b/package/network/utils/wwan/files/data/1e0e:cefe @@ -0,0 +1,6 @@ +{ + "desc": "D-Link DWM-162-U5, Micromax MMX 300c", + "control": 1, + "data": 2 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/2001:7d00 b/package/network/utils/wwan/files/data/2001:7d00 new file mode 100644 index 0000000..b0cc479 --- /dev/null +++ b/package/network/utils/wwan/files/data/2001:7d00 @@ -0,0 +1,6 @@ +{ + "desc": "D-Link DWM-156 A6", + "control": 1, + "data": 0 +} "generic": 1 +} diff --git a/package/network/utils/wwan/files/data/2001:7d01 b/package/network/utils/wwan/files/data/2001:7d01 new file mode 100644 index 0000000..ab8fd9d --- /dev/null +++ b/package/network/utils/wwan/files/data/2001:7d01 @@ -0,0 +1,5 @@ +{ + "desc": "D-Link DWM-156 A7", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/2001:7d02 b/package/network/utils/wwan/files/data/2001:7d02 new file mode 100644 index 0000000..ab8fd9d --- /dev/null +++ b/package/network/utils/wwan/files/data/2001:7d02 @@ -0,0 +1,5 @@ +{ + "desc": "D-Link DWM-156 A7", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/2001:7d03 b/package/network/utils/wwan/files/data/2001:7d03 new file mode 100644 index 0000000..ab8fd9d --- /dev/null +++ b/package/network/utils/wwan/files/data/2001:7d03 @@ -0,0 +1,5 @@ +{ + "desc": "D-Link DWM-156 A7", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/211f:6801 b/package/network/utils/wwan/files/data/211f:6801 new file mode 100644 index 0000000..06cdddc --- /dev/null +++ b/package/network/utils/wwan/files/data/211f:6801 @@ -0,0 +1,5 @@ +{ + "desc": "Celot K-3000/CT-650/CT-680", + "control": 2, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/2357:0201 b/package/network/utils/wwan/files/data/2357:0201 new file mode 100644 index 0000000..7ad8690 --- /dev/null +++ b/package/network/utils/wwan/files/data/2357:0201 @@ -0,0 +1,4 @@ +{ + "desc": "TP-Link MA180", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/2357:0202 b/package/network/utils/wwan/files/data/2357:0202 new file mode 100644 index 0000000..7ad8690 --- /dev/null +++ b/package/network/utils/wwan/files/data/2357:0202 @@ -0,0 +1,4 @@ +{ + "desc": "TP-Link MA180", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/2357:0203 b/package/network/utils/wwan/files/data/2357:0203 new file mode 100644 index 0000000..7ad8690 --- /dev/null +++ b/package/network/utils/wwan/files/data/2357:0203 @@ -0,0 +1,4 @@ +{ + "desc": "TP-Link MA180", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/2357:9000 b/package/network/utils/wwan/files/data/2357:9000 new file mode 100644 index 0000000..0ddb804 --- /dev/null +++ b/package/network/utils/wwan/files/data/2357:9000 @@ -0,0 +1,4 @@ +{ + "desc": "TP-Link MA260", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/413c:8114 b/package/network/utils/wwan/files/data/413c:8114 new file mode 100644 index 0000000..a3cb2cd --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8114 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5700", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8115 b/package/network/utils/wwan/files/data/413c:8115 new file mode 100644 index 0000000..af27cbe --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8115 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5500", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8116 b/package/network/utils/wwan/files/data/413c:8116 new file mode 100644 index 0000000..31b79bf --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8116 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5505", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8117 b/package/network/utils/wwan/files/data/413c:8117 new file mode 100644 index 0000000..a3cb2cd --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8117 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5700", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8118 b/package/network/utils/wwan/files/data/413c:8118 new file mode 100644 index 0000000..b92d415 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8118 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5510", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8128 b/package/network/utils/wwan/files/data/413c:8128 new file mode 100644 index 0000000..a3cb2cd --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8128 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5700", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8129 b/package/network/utils/wwan/files/data/413c:8129 new file mode 100644 index 0000000..a3cb2cd --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8129 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5700", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8133 b/package/network/utils/wwan/files/data/413c:8133 new file mode 100644 index 0000000..4ae8402 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8133 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5720", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8134 b/package/network/utils/wwan/files/data/413c:8134 new file mode 100644 index 0000000..4ae8402 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8134 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5720", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8135 b/package/network/utils/wwan/files/data/413c:8135 new file mode 100644 index 0000000..4ae8402 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8135 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5720", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8136 b/package/network/utils/wwan/files/data/413c:8136 new file mode 100644 index 0000000..d2bf508 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8136 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5520", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8137 b/package/network/utils/wwan/files/data/413c:8137 new file mode 100644 index 0000000..d2bf508 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8137 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5520", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8138 b/package/network/utils/wwan/files/data/413c:8138 new file mode 100644 index 0000000..d2bf508 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8138 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5520", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8147 b/package/network/utils/wwan/files/data/413c:8147 new file mode 100644 index 0000000..f0b0638 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8147 @@ -0,0 +1,6 @@ +{ + "desc": "Dell 5530", + "control": 0, + "data": 1 +} "acm": 1 +} diff --git a/package/network/utils/wwan/files/data/413c:8180 b/package/network/utils/wwan/files/data/413c:8180 new file mode 100644 index 0000000..1ae4405 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8180 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5730", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8181 b/package/network/utils/wwan/files/data/413c:8181 new file mode 100644 index 0000000..1ae4405 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8181 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5730", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8182 b/package/network/utils/wwan/files/data/413c:8182 new file mode 100644 index 0000000..1ae4405 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8182 @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5730", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/data/413c:8186 b/package/network/utils/wwan/files/data/413c:8186 new file mode 100644 index 0000000..fa24099 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8186 @@ -0,0 +1,4 @@ +{ + "desc": "Dell 5620", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/413c:8194 b/package/network/utils/wwan/files/data/413c:8194 new file mode 100644 index 0000000..b361f54 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8194 @@ -0,0 +1,4 @@ +{ + "desc": "Dell 5630", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/413c:8195 b/package/network/utils/wwan/files/data/413c:8195 new file mode 100644 index 0000000..45b7876 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8195 @@ -0,0 +1,4 @@ +{ + "desc": "Dell 5800", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/413c:8196 b/package/network/utils/wwan/files/data/413c:8196 new file mode 100644 index 0000000..cd24730 --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:8196 @@ -0,0 +1,4 @@ +{ + "desc": "Dell 5800v2", + "type": "qmi" +} diff --git a/package/network/utils/wwan/files/data/413c:819b b/package/network/utils/wwan/files/data/413c:819b new file mode 100644 index 0000000..e66c3fc --- /dev/null +++ b/package/network/utils/wwan/files/data/413c:819b @@ -0,0 +1,5 @@ +{ + "desc": "Dell 5804", + "control": 1, + "data": 0 +}} diff --git a/package/network/utils/wwan/files/wwan.sh b/package/network/utils/wwan/files/wwan.sh new file mode 100755 index 0000000..6b33600 --- /dev/null +++ b/package/network/utils/wwan/files/wwan.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +INCLUDE_ONLY=1 + +ctl_device="" +dat_device="" + +proto_mbim_setup() { echo "wwan[$$] mbim proto is missing"; } +proto_qmi_setup() { echo "wwan[$$] qmi proto is missing"; } +proto_ncm_setup() { echo "wwan[$$] ncm proto is missing"; } +proto_3g_setup() { echo "wwan[$$] 3g proto is missing"; } +proto_directip_setup() { echo "wwan[$$] directip proto is missing"; } + +[ -f ./mbim.sh ] && . ./mbim.sh +[ -f ./ncm.sh ] && . ./ncm.sh +[ -f ./qmi.sh ] && . ./qmi.sh +[ -f ./3g.sh ] && { . ./ppp.sh; . ./3g.sh; } +[ -f ./directip.sh ] && . ./directip.sh + +proto_wwan_init_config() { + available=1 + no_device=1 + + proto_config_add_string apn + proto_config_add_string auth + proto_config_add_string username + proto_config_add_string password + proto_config_add_string pincode + proto_config_add_string delay + proto_config_add_string modes +} + +proto_wwan_setup() { + local driver usb devicename desc + + for a in `ls /sys/bus/usb/devices`; do + local vendor product + [ -z "$usb" -a -f /sys/bus/usb/devices/$a/idVendor -a -f /sys/bus/usb/devices/$a/idProduct ] || continue + vendor=$(cat /sys/bus/usb/devices/$a/idVendor) + product=$(cat /sys/bus/usb/devices/$a/idProduct) + [ -f /lib/network/wwan/$vendor:$product ] && { + usb=/lib/network/wwan/$vendor:$product + devicename=$a + } + done + + [ -n "$usb" ] && { + local old_cb control data + + json_set_namespace wwan old_cb + json_init + json_load "$(cat $usb)" + json_select + json_get_vars desc control data + json_set_namespace $old_cb + + [ -n "$control" -a -n "$data" ] && { + ttys=$(ls -d /sys/bus/usb/devices/$devicename/${devicename}*/tty* | sed "s/.*\///g" | tr "\n" " ") + ctl_device=/dev/$(echo $ttys | cut -d" " -f $((control + 1))) + dat_device=/dev/$(echo $ttys | cut -d" " -f $((data + 1))) + driver=comgt + } + } + + [ -z "$ctl_device" ] && for net in $(ls /sys/class/net/ | grep wwan); do + [ -z "$ctl_device" ] || continue + driver=$(grep DRIVER /sys/class/net/$net/device/uevent | cut -d= -f2) + case "$driver" in + qmi_wwan|cdc_mbim) + ctl_device=/dev/$(ls /sys/class/net/$net/device/usbmisc) + ;; + sierra_net|*cdc_ncm) + ctl_device=/dev/$(cd /sys/class/net/$net/; find ../../../ -name ttyUSB* |xargs basename | head -n1) + ;; + *) continue;; + esac + echo "wwan[$$]" "Using proto:$proto device:$ctl_device iface:$net desc:$desc" + done + + [ -n "$ctl_device" ] || { + echo "wwan[$$]" "No valid device was found" + proto_notify_error "$interface" NO_DEVICE + proto_block_restart "$interface" + return 1 + } + + uci_set_state network $interface driver "$driver" + uci_set_state network $interface ctl_device "$ctl_device" + uci_set_state network $interface dat_device "$dat_device" + + case $driver in + qmi_wwan) proto_qmi_setup $@ ;; + cdc_mbim) proto_mbim_setup $@ ;; + sierra_net) proto_directip_setup $@ ;; + comgt) proto_3g_setup $@ ;; + *cdc_ncm) proto_ncm_setup $@ ;; + esac +} + +proto_wwan_teardown() { + local interface=$1 + local driver=$(uci_get_state network $interface driver) + ctl_device=$(uci_get_state network $interface ctl_device) + dat_device=$(uci_get_state network $interface dat_device) + + case $driver in + qmi_wwan) proto_qmi_teardown $@ ;; + cdc_mbim) proto_mbim_teardown $@ ;; + sierra_net) proto_mbim_teardown $@ ;; + comgt) proto_3g_teardown $@ ;; + *cdc_ncm) proto_ncm_teardown $@ ;; + esac +} + +add_protocol wwan diff --git a/package/network/utils/wwan/files/wwan.usb b/package/network/utils/wwan/files/wwan.usb new file mode 100644 index 0000000..507b002 --- /dev/null +++ b/package/network/utils/wwan/files/wwan.usb @@ -0,0 +1,18 @@ +[ "$ACTION" = add -a "$DEVTYPE" = usb_device ] || exit 0 + +vid=$(cat /sys$DEVPATH/idVendor) +pid=$(cat /sys$DEVPATH/idProduct) +[ -f "/lib/network/wwan/$vid:$pid" ] || exit 0 + +find_wwan_iface() { + local cfg="$1" + local proto + config_get proto "$cfg" proto + [ "$proto" = wwan ] || return 0 + proto_set_available "$cfg" 1 + ifup $cfg + exit 0 +} + +config_load network +config_foreach find_wwan_iface interface diff --git a/package/network/utils/wwan/files/wwan.usbmisc b/package/network/utils/wwan/files/wwan.usbmisc new file mode 100644 index 0000000..4079a7f --- /dev/null +++ b/package/network/utils/wwan/files/wwan.usbmisc @@ -0,0 +1,27 @@ +#!/bin/sh + +[ "$ACTION" = add ] || [ "$ACTION" = remove ] || exit 0 +[ "${DEVNAME/[0-9]/}" = cdc-wdm ] || exit 0 + +. /lib/functions.sh +. /lib/netifd/netifd-proto.sh + +find_wwan_iface() { + local cfg="$1" + + local proto device + config_get proto "$cfg" proto + config_get device "$cfg" device + + [ "$proto" = wwan ] || [ "$proto" = mbim ] || [ "$proto" = qmi ] || [ "$proto" = ncm ] || return 0 + [ -z "$device" -a "$proto" = wwan ] || [ "$device" = "/dev/$DEVNAME" ] || return 0 + if [ "$ACTION" = add ]; then + proto_set_available "$cfg" 1 + else + proto_set_available "$cfg" 0 + fi + exit 0 +} + +config_load network +config_foreach find_wwan_iface interface diff --git a/package/network/utils/xtables-addons/Makefile b/package/network/utils/xtables-addons/Makefile new file mode 100644 index 0000000..ff6466f --- /dev/null +++ b/package/network/utils/xtables-addons/Makefile @@ -0,0 +1,152 @@ +# +# Copyright (C) 2009-2013 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:=xtables-addons +PKG_VERSION:=2.7 +PKG_RELEASE:=1 +PKG_MD5SUM:=81bd7ba82e5f7bfd1458fc97ddf72e1d + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz +PKG_SOURCE_URL:=@SF/xtables-addons +PKG_BUILD_DEPENDS:=iptables +PKG_INSTALL:=1 +PKG_BUILD_PARALLEL:=1 +PKG_CHECK_FORMAT_SECURITY:=0 + +PKG_MAINTAINER:=Jo-Philipp Wich <jow@openwrt.org> +PKG_LICENSE:=GPL-2.0 + +PKG_FIXUP:=autoreconf + +include $(INCLUDE_DIR)/package.mk + +define Package/xtables-addons + SECTION:=net + CATEGORY:=Network + SUBMENU:=Firewall + TITLE:=Extensions not distributed in the main Xtables + URL:=http://xtables-addons.sourceforge.net/ +endef + +# uses GNU configure + +CONFIGURE_ARGS+= \ + --with-kbuild="$(LINUX_DIR)" \ + --with-xtables="$(STAGING_DIR)/usr" \ + --with-xtlibdir="/usr/lib/iptables" \ + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + DEPMOD="/bin/true" \ + all +endef + +define Build/Install + $(MAKE) -C $(PKG_BUILD_DIR) \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + DESTDIR="$(PKG_INSTALL_DIR)" \ + DEPMOD="/bin/true" \ + install +endef + +# 1: extension/module suffix used in package name +# 2: extension/module display name used in package title/description +# 3: list of extensions to package +# 4: list of modules to package +# 5: module load priority +# 6: module depends +define BuildTemplate + + ifneq ($(3),) + define Package/iptables-mod-$(1) + $$(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=$(2) iptables extension + DEPENDS:=iptables $(if $(4),+kmod-ipt-$(1)) + endef + + define Package/iptables-mod-$(1)/install + $(INSTALL_DIR) $$(1)/usr/lib/iptables + for m in $(3); do \ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so \ + $$(1)/usr/lib/iptables/ ; \ + done + endef + + $$(eval $$(call BuildPackage,iptables-mod-$(1))) + endif + + ifneq ($(4),) + define KernelPackage/ipt-$(1) + SUBMENU:=Netfilter Extensions + TITLE:=$(2) netfilter module + DEPENDS:=+kmod-ipt-core $(5) + KCONFIG:=$(6) + FILES:=$(foreach mod,$(4),$(PKG_BUILD_DIR)/extensions/$(mod).$(LINUX_KMOD_SUFFIX)) + AUTOLOAD:=$(call AutoProbe,$(notdir $(4))) + endef + + $$(eval $$(call KernelPackage,ipt-$(1))) + endif + +endef + + +define Package/iptaccount + $(call Package/xtables-addons) + CATEGORY:=Network + TITLE:=iptables-mod-account control utility + DEPENDS:=iptables +iptables-mod-account +endef + +define Package/iptaccount/install + $(INSTALL_DIR) $(1)/usr/lib + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) \ + $(PKG_INSTALL_DIR)/usr/lib/libxt_ACCOUNT_cl.so* \ + $(1)/usr/lib/ + $(CP) \ + $(PKG_INSTALL_DIR)/usr/sbin/iptaccount \ + $(1)/usr/sbin/ +endef + + +#$(eval $(call BuildTemplate,SUFFIX,DESCRIPTION,EXTENSION,MODULE,PRIORITY,DEPENDS)) + +$(eval $(call BuildTemplate,compat-xtables,API compatibilty layer,,compat_xtables,+IPV6:kmod-ip6tables,CONFIG_NF_CONNTRACK_MARK=y)) +$(eval $(call BuildTemplate,nathelper-rtsp,RTSP Conntrack and NAT,,rtsp/nf_conntrack_rtsp rtsp/nf_nat_rtsp,+kmod-ipt-conntrack-extra +kmod-ipt-nat)) + +$(eval $(call BuildTemplate,account,ACCOUNT,xt_ACCOUNT,ACCOUNT/xt_ACCOUNT,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,chaos,CHAOS,xt_CHAOS,xt_CHAOS,+kmod-ipt-compat-xtables +kmod-ipt-delude +kmod-ipt-tarpit)) +$(eval $(call BuildTemplate,condition,Condition,xt_condition,xt_condition,)) +$(eval $(call BuildTemplate,delude,DELUDE,xt_DELUDE,xt_DELUDE,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,dhcpmac,DHCPMAC,xt_DHCPMAC,xt_DHCPMAC,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,dnetmap,DNETMAP,xt_DNETMAP,xt_DNETMAP,+kmod-ipt-compat-xtables +kmod-ipt-nat)) +$(eval $(call BuildTemplate,fuzzy,fuzzy,xt_fuzzy,xt_fuzzy,)) +$(eval $(call BuildTemplate,geoip,geoip,xt_geoip,xt_geoip,)) +$(eval $(call BuildTemplate,iface,iface,xt_iface,xt_iface,)) +$(eval $(call BuildTemplate,ipmark,IPMARK,xt_IPMARK,xt_IPMARK,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,ipp2p,IPP2P,xt_ipp2p,xt_ipp2p,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,ipv4options,ipv4options,xt_ipv4options,xt_ipv4options,)) +$(eval $(call BuildTemplate,length2,length2,xt_length2,xt_length2,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,logmark,LOGMARK,xt_LOGMARK,xt_LOGMARK,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,lscan,lscan,xt_lscan,xt_lscan,)) +$(eval $(call BuildTemplate,lua,Lua PacketScript,xt_LUA,LUA/xt_LUA,+kmod-ipt-conntrack-extra)) +$(eval $(call BuildTemplate,psd,psd,xt_psd,xt_psd,)) +$(eval $(call BuildTemplate,quota2,quota2,xt_quota2,xt_quota2,)) +$(eval $(call BuildTemplate,sysrq,SYSRQ,xt_SYSRQ,xt_SYSRQ,+kmod-ipt-compat-xtables)) +$(eval $(call BuildTemplate,tarpit,TARPIT,xt_TARPIT,xt_TARPIT,+kmod-ipt-compat-xtables)) + +$(eval $(call BuildPackage,iptaccount)) diff --git a/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch b/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch new file mode 100644 index 0000000..e4101ad --- /dev/null +++ b/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch @@ -0,0 +1,11 @@ +--- a/configure.ac ++++ b/configure.ac +@@ -44,7 +44,7 @@ regular_CFLAGS="-Wall -Waggregate-return + + if test -n "$kbuilddir"; then + AC_MSG_CHECKING([kernel version that we will build against]) +- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease)"; ++ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion)"; + kmajor="${krel%%[[^0-9]]*}"; + kmajor="$(($kmajor+0))"; + krel="${krel:${#kmajor}}"; diff --git a/package/network/utils/xtables-addons/patches/100-add-rtsp-conntrack.patch b/package/network/utils/xtables-addons/patches/100-add-rtsp-conntrack.patch new file mode 100644 index 0000000..6c169ee --- /dev/null +++ b/package/network/utils/xtables-addons/patches/100-add-rtsp-conntrack.patch @@ -0,0 +1,1526 @@ +--- /dev/null ++++ b/extensions/rtsp/Kbuild +@@ -0,0 +1,4 @@ ++# -*- Makefile -*- ++ ++obj-m += nf_nat_rtsp.o ++obj-m += nf_conntrack_rtsp.o +--- /dev/null ++++ b/extensions/rtsp/netfilter_helpers.h +@@ -0,0 +1,133 @@ ++/* ++ * Helpers for netfiler modules. This file provides implementations for basic ++ * functions such as strncasecmp(), etc. ++ * ++ * gcc will warn for defined but unused functions, so we only include the ++ * functions requested. The following macros are used: ++ * NF_NEED_STRNCASECMP nf_strncasecmp() ++ * NF_NEED_STRTOU16 nf_strtou16() ++ * NF_NEED_STRTOU32 nf_strtou32() ++ */ ++#ifndef _NETFILTER_HELPERS_H ++#define _NETFILTER_HELPERS_H ++ ++/* Only include these functions for kernel code. */ ++#ifdef __KERNEL__ ++ ++#include <linux/ctype.h> ++#define iseol(c) ( (c) == '\r' || (c) == '\n' ) ++ ++/* ++ * The standard strncasecmp() ++ */ ++#ifdef NF_NEED_STRNCASECMP ++static int ++nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) ++{ ++ if (s1 == NULL || s2 == NULL) ++ { ++ if (s1 == NULL && s2 == NULL) ++ { ++ return 0; ++ } ++ return (s1 == NULL) ? -1 : 1; ++ } ++ while (len > 0 && tolower(*s1) == tolower(*s2)) ++ { ++ len--; ++ s1++; ++ s2++; ++ } ++ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); ++} ++#endif /* NF_NEED_STRNCASECMP */ ++ ++/* ++ * Parse a string containing a 16-bit unsigned integer. ++ * Returns the number of chars used, or zero if no number is found. ++ */ ++#ifdef NF_NEED_STRTOU16 ++static int ++nf_strtou16(const char* pbuf, u_int16_t* pval) ++{ ++ int n = 0; ++ ++ *pval = 0; ++ while (isdigit(pbuf[n])) ++ { ++ *pval = (*pval * 10) + (pbuf[n] - '0'); ++ n++; ++ } ++ ++ return n; ++} ++#endif /* NF_NEED_STRTOU16 */ ++ ++/* ++ * Parse a string containing a 32-bit unsigned integer. ++ * Returns the number of chars used, or zero if no number is found. ++ */ ++#ifdef NF_NEED_STRTOU32 ++static int ++nf_strtou32(const char* pbuf, u_int32_t* pval) ++{ ++ int n = 0; ++ ++ *pval = 0; ++ while (pbuf[n] >= '0' && pbuf[n] <= '9') ++ { ++ *pval = (*pval * 10) + (pbuf[n] - '0'); ++ n++; ++ } ++ ++ return n; ++} ++#endif /* NF_NEED_STRTOU32 */ ++ ++/* ++ * Given a buffer and length, advance to the next line and mark the current ++ * line. ++ */ ++#ifdef NF_NEED_NEXTLINE ++static int ++nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) ++{ ++ uint off = *poff; ++ uint physlen = 0; ++ ++ if (off >= len) ++ { ++ return 0; ++ } ++ ++ while (p[off] != '\n') ++ { ++ if (len-off <= 1) ++ { ++ return 0; ++ } ++ ++ physlen++; ++ off++; ++ } ++ ++ /* if we saw a crlf, physlen needs adjusted */ ++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') ++ { ++ physlen--; ++ } ++ ++ /* advance past the newline */ ++ off++; ++ ++ *plineoff = *poff; ++ *plinelen = physlen; ++ *poff = off; ++ ++ return 1; ++} ++#endif /* NF_NEED_NEXTLINE */ ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _NETFILTER_HELPERS_H */ +--- /dev/null ++++ b/extensions/rtsp/netfilter_mime.h +@@ -0,0 +1,89 @@ ++/* ++ * MIME functions for netfilter modules. This file provides implementations ++ * for basic MIME parsing. MIME headers are used in many protocols, such as ++ * HTTP, RTSP, SIP, etc. ++ * ++ * gcc will warn for defined but unused functions, so we only include the ++ * functions requested. The following macros are used: ++ * NF_NEED_MIME_NEXTLINE nf_mime_nextline() ++ */ ++#ifndef _NETFILTER_MIME_H ++#define _NETFILTER_MIME_H ++ ++/* Only include these functions for kernel code. */ ++#ifdef __KERNEL__ ++ ++#include <linux/ctype.h> ++ ++/* ++ * Given a buffer and length, advance to the next line and mark the current ++ * line. If the current line is empty, *plinelen will be set to zero. If ++ * not, it will be set to the actual line length (including CRLF). ++ * ++ * 'line' in this context means logical line (includes LWS continuations). ++ * Returns 1 on success, 0 on failure. ++ */ ++#ifdef NF_NEED_MIME_NEXTLINE ++static int ++nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) ++{ ++ uint off = *poff; ++ uint physlen = 0; ++ int is_first_line = 1; ++ ++ if (off >= len) ++ { ++ return 0; ++ } ++ ++ do ++ { ++ while (p[off] != '\n') ++ { ++ if (len-off <= 1) ++ { ++ return 0; ++ } ++ ++ physlen++; ++ off++; ++ } ++ ++ /* if we saw a crlf, physlen needs adjusted */ ++ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') ++ { ++ physlen--; ++ } ++ ++ /* advance past the newline */ ++ off++; ++ ++ /* check for an empty line */ ++ if (physlen == 0) ++ { ++ break; ++ } ++ ++ /* check for colon on the first physical line */ ++ if (is_first_line) ++ { ++ is_first_line = 0; ++ if (memchr(p+(*poff), ':', physlen) == NULL) ++ { ++ return 0; ++ } ++ } ++ } ++ while (p[off] == ' ' || p[off] == '\t'); ++ ++ *plineoff = *poff; ++ *plinelen = (physlen == 0) ? 0 : (off - *poff); ++ *poff = off; ++ ++ return 1; ++} ++#endif /* NF_NEED_MIME_NEXTLINE */ ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _NETFILTER_MIME_H */ +--- /dev/null ++++ b/extensions/rtsp/nf_conntrack_rtsp.c +@@ -0,0 +1,576 @@ ++/* ++ * RTSP extension for IP connection tracking ++ * (C) 2003 by Tom Marshall <tmarshall at real.com> ++ * ++ * 2005-02-13: Harald Welte <laforge at netfilter.org> ++ * - port to 2.6 ++ * - update to recent post-2.6.11 api changes ++ * 2006-09-14: Steven Van Acker <deepstar at singularity.be> ++ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack ++ * 2007-04-18: Michael Guntsche <mike at it-loops.com> ++ * - Port to new NF API ++ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd ++ * - fixed rtcp nat mapping and other port mapping fixes ++ * - simple TEARDOWN request handling ++ * - codestyle fixes and other less significant bug fixes ++ * ++ * based on ip_conntrack_irc.c ++ * ++ * 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. ++ * ++ * Module load syntax: ++ * insmod nf_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS> ++ * max_outstanding=n setup_timeout=secs ++ * ++ * If no ports are specified, the default will be port 554. ++ * ++ * With max_outstanding you can define the maximum number of not yet ++ * answered SETUP requests per RTSP session (default 8). ++ * With setup_timeout you can specify how long the system waits for ++ * an expected data channel (default 300 seconds). ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/netfilter.h> ++#include <linux/ip.h> ++#include <linux/inet.h> ++#include <net/tcp.h> ++ ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_expect.h> ++#include <net/netfilter/nf_conntrack_helper.h> ++#include "nf_conntrack_rtsp.h" ++ ++#define NF_NEED_STRNCASECMP ++#define NF_NEED_STRTOU16 ++#define NF_NEED_STRTOU32 ++#define NF_NEED_NEXTLINE ++#include "netfilter_helpers.h" ++#define NF_NEED_MIME_NEXTLINE ++#include "netfilter_mime.h" ++ ++#include <linux/ctype.h> ++ ++#define MAX_PORTS 8 ++static int ports[MAX_PORTS]; ++static int num_ports = 0; ++static int max_outstanding = 8; ++static unsigned int setup_timeout = 300; ++ ++MODULE_AUTHOR("Tom Marshall <tmarshall at real.com>"); ++MODULE_DESCRIPTION("RTSP connection tracking module"); ++MODULE_LICENSE("GPL"); ++module_param_array(ports, int, &num_ports, 0400); ++MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); ++module_param(max_outstanding, int, 0400); ++MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); ++module_param(setup_timeout, int, 0400); ++MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); ++ ++static char *rtsp_buffer; ++static DEFINE_SPINLOCK(rtsp_buffer_lock); ++ ++static struct nf_conntrack_expect_policy rtsp_exp_policy; ++ ++unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, ++ enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect *rtp_exp, ++ struct nf_conntrack_expect *rtcp_exp); ++ ++EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); ++ ++/* ++ * Max mappings we will allow for one RTSP connection (for RTP, the number ++ * of allocated ports is twice this value). Note that SMIL burns a lot of ++ * ports so keep this reasonably high. If this is too low, you will see a ++ * lot of "no free client map entries" messages. ++ */ ++#define MAX_PORT_MAPS 16 ++ ++/*** default port list was here in the masq code: 554, 3030, 4040 ***/ ++ ++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } ++ ++/* ++ * Parse an RTSP packet. ++ * ++ * Returns zero if parsing failed. ++ * ++ * Parameters: ++ * IN ptcp tcp data pointer ++ * IN tcplen tcp data len ++ * IN/OUT ptcpoff points to current tcp offset ++ * OUT phdrsoff set to offset of rtsp headers ++ * OUT phdrslen set to length of rtsp headers ++ * OUT pcseqoff set to offset of CSeq header ++ * OUT pcseqlen set to length of CSeq header ++ */ ++static int ++rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, ++ uint* phdrsoff, uint* phdrslen, ++ uint* pcseqoff, uint* pcseqlen, ++ uint* transoff, uint* translen) ++{ ++ uint entitylen = 0; ++ uint lineoff; ++ uint linelen; ++ ++ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) ++ return 0; ++ ++ *phdrsoff = *ptcpoff; ++ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { ++ if (linelen == 0) { ++ if (entitylen > 0) ++ *ptcpoff += min(entitylen, tcplen - *ptcpoff); ++ break; ++ } ++ if (lineoff+linelen > tcplen) { ++ pr_info("!! overrun !!\n"); ++ break; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { ++ *pcseqoff = lineoff; ++ *pcseqlen = linelen; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { ++ *transoff = lineoff; ++ *translen = linelen; ++ } ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { ++ uint off = lineoff+15; ++ SKIP_WSPACE(ptcp+lineoff, linelen, off); ++ nf_strtou32(ptcp+off, &entitylen); ++ } ++ } ++ *phdrslen = (*ptcpoff) - (*phdrsoff); ++ ++ return 1; ++} ++ ++/* ++ * Find lo/hi client ports (if any) in transport header ++ * In: ++ * ptcp, tcplen = packet ++ * tranoff, tranlen = buffer to search ++ * ++ * Out: ++ * pport_lo, pport_hi = lo/hi ports (host endian) ++ * ++ * Returns nonzero if any client ports found ++ * ++ * Note: it is valid (and expected) for the client to request multiple ++ * transports, so we need to parse the entire line. ++ */ ++static int ++rtsp_parse_transport(char* ptran, uint tranlen, ++ struct ip_ct_rtsp_expect* prtspexp) ++{ ++ int rc = 0; ++ uint off = 0; ++ ++ if (tranlen < 10 || !iseol(ptran[tranlen-1]) || ++ nf_strncasecmp(ptran, "Transport:", 10) != 0) { ++ pr_info("sanity check failed\n"); ++ return 0; ++ } ++ ++ pr_debug("tran='%.*s'\n", (int)tranlen, ptran); ++ off += 10; ++ SKIP_WSPACE(ptran, tranlen, off); ++ ++ /* Transport: tran;field;field=val,tran;field;field=val,... */ ++ while (off < tranlen) { ++ const char* pparamend; ++ uint nextparamoff; ++ ++ pparamend = memchr(ptran+off, ',', tranlen-off); ++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; ++ nextparamoff = pparamend-ptran; ++ ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (strncmp(ptran+off, "client_port=", 12) == 0) { ++ u_int16_t port; ++ uint numlen; ++ ++ off += 12; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ if (prtspexp->loport != 0 && prtspexp->loport != port) ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ else { ++ pr_debug("lo port found : %hu\n", port); ++ prtspexp->loport = prtspexp->hiport = port; ++ if (ptran[off] == '-') { ++ off++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ prtspexp->pbtype = pb_range; ++ prtspexp->hiport = port; ++ ++ // If we have a range, assume rtp: ++ // loport must be even, hiport must be loport+1 ++ if ((prtspexp->loport & 0x0001) != 0 || ++ prtspexp->hiport != prtspexp->loport+1) { ++ pr_debug("incorrect range: %hu-%hu, correcting\n", ++ prtspexp->loport, prtspexp->hiport); ++ prtspexp->loport &= 0xfffe; ++ prtspexp->hiport = prtspexp->loport+1; ++ } ++ } else if (ptran[off] == '/') { ++ off++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ prtspexp->pbtype = pb_discon; ++ prtspexp->hiport = port; ++ } ++ rc = 1; ++ } ++ } ++ ++ /* ++ * Note we don't look for the destination parameter here. ++ * If we are using NAT, the NAT module will handle it. If not, ++ * and the client is sending packets elsewhere, the expectation ++ * will quietly time out. ++ */ ++ ++ off = nextfieldoff; ++ } ++ ++ off = nextparamoff; ++ } ++ ++ return rc; ++} ++ ++ ++/*** conntrack functions ***/ ++ ++/* outbound packet: client->server */ ++ ++static inline int ++help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo, ++ unsigned int protoff) ++#else ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++#endif ++{ ++ struct ip_ct_rtsp_expect expinfo; ++ ++ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ ++ //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; ++ //uint tcplen = pktlen - iph->ihl * 4; ++ char* pdata = rb_ptr; ++ //uint datalen = tcplen - tcph->doff * 4; ++ uint dataoff = 0; ++ int ret = NF_ACCEPT; ++ ++ struct nf_conntrack_expect *rtp_exp; ++ struct nf_conntrack_expect *rtcp_exp = NULL; ++ ++ __be16 be_loport; ++ __be16 be_hiport; ++ ++ typeof(nf_nat_rtsp_hook) nf_nat_rtsp; ++ ++ memset(&expinfo, 0, sizeof(expinfo)); ++ ++ while (dataoff < datalen) { ++ uint cmdoff = dataoff; ++ uint hdrsoff = 0; ++ uint hdrslen = 0; ++ uint cseqoff = 0; ++ uint cseqlen = 0; ++ uint transoff = 0; ++ uint translen = 0; ++ uint off; ++ ++ if (!rtsp_parse_message(pdata, datalen, &dataoff, ++ &hdrsoff, &hdrslen, ++ &cseqoff, &cseqlen, ++ &transoff, &translen)) ++ break; /* not a valid message */ ++ ++ if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) { ++ pr_debug("teardown handled\n"); ++ nf_ct_remove_expectations(ct); /* FIXME must be session id aware */ ++ break; ++ } ++ ++ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) ++ continue; /* not a SETUP message */ ++ ++ pr_debug("found a setup message\n"); ++ ++ off = 0; ++ if(translen) ++ rtsp_parse_transport(pdata+transoff, translen, &expinfo); ++ ++ if (expinfo.loport == 0) { ++ pr_debug("no udp transports found\n"); ++ continue; /* no udp transports found */ ++ } ++ ++ pr_debug("udp transport found, ports=(%d,%hu,%hu)\n", ++ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); ++ ++ ++ be_loport = htons(expinfo.loport); ++ ++ rtp_exp = nf_ct_expect_alloc(ct); ++ if (rtp_exp == NULL) { ++ ret = NF_DROP; ++ goto out; ++ } ++ ++ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, ++ nf_ct_l3num(ct), ++ NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */ ++ &ct->tuplehash[!dir].tuple.dst.u3, ++ IPPROTO_UDP, NULL, &be_loport); ++ ++ rtp_exp->flags = 0; ++ ++ if (expinfo.pbtype == pb_range) { ++ pr_debug("setup expectation for rtcp\n"); ++ ++ be_hiport = htons(expinfo.hiport); ++ rtcp_exp = nf_ct_expect_alloc(ct); ++ if (rtcp_exp == NULL) { ++ ret = NF_DROP; ++ goto out1; ++ } ++ ++ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, ++ nf_ct_l3num(ct), ++ NULL, /* &ct->tuplehash[!dir].tuple.src.u3, */ ++ &ct->tuplehash[!dir].tuple.dst.u3, ++ IPPROTO_UDP, NULL, &be_hiport); ++ ++ rtcp_exp->flags = 0; ++ ++ pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ ntohs(rtcp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port), ++ ntohs(rtcp_exp->tuple.dst.u.udp.port)); ++ } else { ++ pr_debug("expect_related %pI4:%u-%pI4:%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port)); ++ } ++ ++ nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook); ++ if (nf_nat_rtsp && ct->status & IPS_NAT_MASK) ++ /* pass the request off to the nat helper */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, ++ &expinfo, rtp_exp, rtcp_exp); ++#else ++ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, ++ &expinfo, rtp_exp, rtcp_exp); ++#endif ++ else { ++ if (nf_ct_expect_related(rtp_exp) == 0) { ++ if (rtcp_exp && nf_ct_expect_related(rtcp_exp) != 0) { ++ nf_ct_unexpect_related(rtp_exp); ++ pr_info("nf_conntrack_expect_related failed for rtcp\n"); ++ ret = NF_DROP; ++ } ++ } else { ++ pr_info("nf_conntrack_expect_related failed for rtp\n"); ++ ret = NF_DROP; ++ } ++ } ++ if (rtcp_exp) { ++ nf_ct_expect_put(rtcp_exp); ++ } ++out1: ++ nf_ct_expect_put(rtp_exp); ++ goto out; ++ } ++out: ++ ++ return ret; ++} ++ ++ ++static inline int ++help_in(struct sk_buff *skb, size_t pktlen, ++ struct nf_conn* ct, enum ip_conntrack_info ctinfo) ++{ ++ return NF_ACCEPT; ++} ++ ++static int help(struct sk_buff *skb, unsigned int protoff, ++ struct nf_conn *ct, enum ip_conntrack_info ctinfo) ++{ ++ struct tcphdr _tcph, *th; ++ unsigned int dataoff, datalen; ++ char *rb_ptr; ++ int ret = NF_DROP; ++ ++ /* Until there's been traffic both ways, don't look in packets. */ ++ if (ctinfo != IP_CT_ESTABLISHED && ++ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { ++ pr_debug("conntrackinfo = %u\n", ctinfo); ++ return NF_ACCEPT; ++ } ++ ++ /* Not whole TCP header? */ ++ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); ++ ++ if (!th) ++ return NF_ACCEPT; ++ ++ /* No data ? */ ++ dataoff = protoff + th->doff*4; ++ datalen = skb->len - dataoff; ++ if (dataoff >= skb->len) ++ return NF_ACCEPT; ++ ++ spin_lock_bh(&rtsp_buffer_lock); ++ rb_ptr = skb_header_pointer(skb, dataoff, ++ skb->len - dataoff, rtsp_buffer); ++ BUG_ON(rb_ptr == NULL); ++ ++#if 0 ++ /* Checksum invalid? Ignore. */ ++ /* FIXME: Source route IP option packets --RR */ ++ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, ++ csum_partial((char*)tcph, tcplen, 0))) ++ { ++ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", ++ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); ++ return NF_ACCEPT; ++ } ++#endif ++ ++ switch (CTINFO2DIR(ctinfo)) { ++ case IP_CT_DIR_ORIGINAL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); ++#else ++ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); ++#endif ++ break; ++ case IP_CT_DIR_REPLY: ++ pr_debug("IP_CT_DIR_REPLY\n"); ++ /* inbound packet: server->client */ ++ ret = NF_ACCEPT; ++ break; ++ } ++ ++ spin_unlock_bh(&rtsp_buffer_lock); ++ ++ return ret; ++} ++ ++static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; ++static char rtsp_names[MAX_PORTS][10]; ++ ++/* This function is intentionally _NOT_ defined as __exit */ ++static void ++fini(void) ++{ ++ int i; ++ for (i = 0; i < num_ports; i++) { ++ pr_debug("unregistering port %d\n", ports[i]); ++ nf_conntrack_helper_unregister(&rtsp_helpers[i]); ++ } ++ kfree(rtsp_buffer); ++} ++ ++static int __init ++init(void) ++{ ++ int i, ret; ++ struct nf_conntrack_helper *hlpr; ++ char *tmpname; ++ ++ printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); ++ ++ if (max_outstanding < 1) { ++ printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); ++ return -EBUSY; ++ } ++ if (setup_timeout < 0) { ++ printk("nf_conntrack_rtsp: setup_timeout must be a positive integer\n"); ++ return -EBUSY; ++ } ++ ++ rtsp_exp_policy.max_expected = max_outstanding; ++ rtsp_exp_policy.timeout = setup_timeout; ++ ++ rtsp_buffer = kmalloc(65536, GFP_KERNEL); ++ if (!rtsp_buffer) ++ return -ENOMEM; ++ ++ /* If no port given, default to standard rtsp port */ ++ if (ports[0] == 0) { ++ ports[0] = RTSP_PORT; ++ num_ports = 1; ++ } ++ ++ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { ++ hlpr = &rtsp_helpers[i]; ++ memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); ++ hlpr->tuple.src.l3num = AF_INET; ++ hlpr->tuple.src.u.tcp.port = htons(ports[i]); ++ hlpr->tuple.dst.protonum = IPPROTO_TCP; ++ hlpr->expect_policy = &rtsp_exp_policy; ++ hlpr->me = THIS_MODULE; ++ hlpr->help = help; ++ ++ tmpname = &rtsp_names[i][0]; ++ if (ports[i] == RTSP_PORT) { ++ sprintf(tmpname, "rtsp"); ++ } else { ++ sprintf(tmpname, "rtsp-%d", i); ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) ++ strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); ++#else ++ hlpr->name = tmpname; ++#endif ++ pr_debug("port #%d: %d\n", i, ports[i]); ++ ++ ret = nf_conntrack_helper_register(hlpr); ++ ++ if (ret) { ++ printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); ++ fini(); ++ return -EBUSY; ++ } ++ } ++ return 0; ++} ++ ++module_init(init); ++module_exit(fini); +--- /dev/null ++++ b/extensions/rtsp/nf_conntrack_rtsp.h +@@ -0,0 +1,72 @@ ++/* ++ * RTSP extension for IP connection tracking. ++ * (C) 2003 by Tom Marshall <tmarshall at real.com> ++ * based on ip_conntrack_irc.h ++ * ++ * 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. ++ * ++ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd ++ * - conditional compilation for kernel 3.7 ++ * - port mapping improvements ++*/ ++#ifndef _IP_CONNTRACK_RTSP_H ++#define _IP_CONNTRACK_RTSP_H ++ ++#include <linux/version.h> ++ ++//#define IP_NF_RTSP_DEBUG 1 ++#define IP_NF_RTSP_VERSION "0.7" ++ ++#ifdef __KERNEL__ ++/* port block types */ ++typedef enum { ++ pb_single, /* client_port=x */ ++ pb_range, /* client_port=x-y */ ++ pb_discon /* client_port=x/y (rtspbis) */ ++} portblock_t; ++ ++/* We record seq number and length of rtsp headers here, all in host order. */ ++ ++/* ++ * This structure is per expected connection. It is a member of struct ++ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored ++ * there and we are expected to only store the length of the data which ++ * needs replaced. If a packet contains multiple RTSP messages, we create ++ * one expected connection per message. ++ * ++ * We use these variables to mark the entire header block. This may seem ++ * like overkill, but the nature of RTSP requires it. A header may appear ++ * multiple times in a message. We must treat two Transport headers the ++ * same as one Transport header with two entries. ++ */ ++struct ip_ct_rtsp_expect ++{ ++ u_int32_t len; /* length of header block */ ++ portblock_t pbtype; /* Type of port block that was requested */ ++ u_int16_t loport; /* Port that was requested, low or first */ ++ u_int16_t hiport; /* Port that was requested, high or second */ ++#if 0 ++ uint method; /* RTSP method */ ++ uint cseq; /* CSeq from request */ ++#endif ++}; ++ ++extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, ++ enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, ++ unsigned int matchlen, ++ struct ip_ct_rtsp_expect *prtspexp, ++ struct nf_conntrack_expect *rtp_exp, ++ struct nf_conntrack_expect *rtcp_exp); ++ ++#define RTSP_PORT 554 ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* _IP_CONNTRACK_RTSP_H */ +--- /dev/null ++++ b/extensions/rtsp/nf_nat_rtsp.c +@@ -0,0 +1,617 @@ ++/* ++ * RTSP extension for TCP NAT alteration ++ * (C) 2003 by Tom Marshall <tmarshall at real.com> ++ * ++ * 2013-03-04: Il'inykh Sergey <sergeyi at inango-sw.com>. Inango Systems Ltd ++ * - fixed rtcp nat mapping and other port mapping fixes ++ * - fixed system hard lock because of bug in the parser ++ * - codestyle fixes and less significant fixes ++ * ++ * based on ip_nat_irc.c ++ * ++ * 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. ++ * ++ * Module load syntax: ++ * insmod nf_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS> ++ * stunaddr=<address> ++ * destaction=[auto|strip|none] ++ * ++ * If no ports are specified, the default will be port 554 only. ++ * ++ * stunaddr specifies the address used to detect that a client is using STUN. ++ * If this address is seen in the destination parameter, it is assumed that ++ * the client has already punched a UDP hole in the firewall, so we don't ++ * mangle the client_port. If none is specified, it is autodetected. It ++ * only needs to be set if you have multiple levels of NAT. It should be ++ * set to the external address that the STUN clients detect. Note that in ++ * this case, it will not be possible for clients to use UDP with servers ++ * between the NATs. ++ * ++ * If no destaction is specified, auto is used. ++ * destaction=auto: strip destination parameter if it is not stunaddr. ++ * destaction=strip: always strip destination parameter (not recommended). ++ * destaction=none: do not touch destination parameter (not recommended). ++ */ ++ ++#include <linux/module.h> ++#include <linux/version.h> ++#include <net/tcp.h> ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++# include <net/netfilter/nf_nat.h> ++#else ++# include <net/netfilter/nf_nat_rule.h> ++#endif ++#include <net/netfilter/nf_nat_helper.h> ++#include "nf_conntrack_rtsp.h" ++#include <net/netfilter/nf_conntrack_expect.h> ++ ++#include <linux/inet.h> ++#include <linux/ctype.h> ++#define NF_NEED_STRNCASECMP ++#define NF_NEED_STRTOU16 ++#include "netfilter_helpers.h" ++#define NF_NEED_MIME_NEXTLINE ++#include "netfilter_mime.h" ++ ++#define MAX_PORTS 8 ++#define DSTACT_AUTO 0 ++#define DSTACT_STRIP 1 ++#define DSTACT_NONE 2 ++ ++static char* stunaddr = NULL; ++static char* destaction = NULL; ++ ++static u_int32_t extip = 0; ++static int dstact = 0; ++ ++static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp); ++ ++MODULE_AUTHOR("Tom Marshall <tmarshall at real.com>"); ++MODULE_DESCRIPTION("RTSP network address translation module"); ++MODULE_LICENSE("GPL"); ++module_param(stunaddr, charp, 0644); ++MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); ++module_param(destaction, charp, 0644); ++MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); ++ ++#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } ++ ++/*** helper functions ***/ ++ ++static void ++get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) ++{ ++ struct iphdr* iph = ip_hdr(skb); ++ struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); ++ ++ *pptcpdata = (char*)tcph + tcph->doff*4; ++ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++/* copy of sip_sprintf_addr */ ++static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer, ++ const union nf_inet_addr *addr, bool delim) ++{ ++ if (nf_ct_l3num(ct) == NFPROTO_IPV4) { ++ return sprintf(buffer, "%pI4", &addr->ip); ++ } else { ++ if (delim) ++ return sprintf(buffer, "[%pI6c]", &addr->ip6); ++ else ++ return sprintf(buffer, "%pI6c", &addr->ip6); ++ } ++} ++#endif ++ ++/*** nat functions ***/ ++ ++/* ++ * Mangle the "Transport:" header: ++ * - Replace all occurences of "client_port=<spec>" ++ * - Handle destination parameter ++ * ++ * In: ++ * ct, ctinfo = conntrack context ++ * skb = packet ++ * tranoff = Transport header offset from TCP data ++ * tranlen = Transport header length (incl. CRLF) ++ * rport_lo = replacement low port (host endian) ++ * rport_hi = replacement high port (host endian) ++ * ++ * Returns packet size difference. ++ * ++ * Assumes that a complete transport header is present, ending with CR or LF ++ */ ++static int ++rtsp_mangle_tran(enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct sk_buff* skb, uint tranoff, uint tranlen) ++{ ++ char* ptcp; ++ uint tcplen; ++ char* ptran; ++ char rbuf1[16]; /* Replacement buffer (one port) */ ++ uint rbuf1len; /* Replacement len (one port) */ ++ char rbufa[16]; /* Replacement buffer (all ports) */ ++ uint rbufalen; /* Replacement len (all ports) */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ union nf_inet_addr newip; ++#else ++ u_int32_t newip; ++#endif ++ u_int16_t loport, hiport; ++ uint off = 0; ++ uint diff; /* Number of bytes we removed */ ++ ++ struct nf_conn *ct = rtp_exp->master; ++ /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ ++ struct nf_conntrack_tuple *rtp_t; ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ char szextaddr[INET6_ADDRSTRLEN]; ++#else ++ char szextaddr[INET_ADDRSTRLEN]; ++#endif ++ uint extaddrlen; ++ int is_stun; ++ ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ ++ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || ++ tranlen < 10 || !iseol(ptran[tranlen-1]) || ++ nf_strncasecmp(ptran, "Transport:", 10) != 0) { ++ pr_info("sanity check failed\n"); ++ return 0; ++ } ++ off += 10; ++ SKIP_WSPACE(ptcp+tranoff, tranlen, off); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; ++ rtp_t = &rtp_exp->tuple; ++ rtp_t->dst.u3 = newip; ++ if (rtcp_exp) { ++ rtcp_exp->tuple.dst.u3 = newip; ++ } ++ extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip ++ pr_debug("stunaddr=%s (auto)\n", szextaddr); ++#else ++ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; ++ rtp_t = &rtp_exp->tuple; ++ rtp_t->dst.u3.ip = newip; ++ if (rtcp_exp) { ++ rtcp_exp->tuple.dst.u3.ip = newip; ++ } ++ extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) ++ : sprintf(szextaddr, "%pI4", &newip); ++ pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); ++#endif ++ hiport = 0; ++ rbuf1len = rbufalen = 0; ++ switch (prtspexp->pbtype) { ++ case pb_single: ++ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu\n", loport); ++ break; ++ } ++ } ++ if (loport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, "%hu", loport); ++ } ++ break; ++ case pb_range: ++ for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (nf_ct_expect_related(rtp_exp) != 0) { ++ continue; ++ } ++ hiport = loport + 1; ++ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); ++ if (nf_ct_expect_related(rtcp_exp) != 0) { ++ nf_ct_unexpect_related(rtp_exp); ++ continue; ++ } ++ ++ /* FIXME: invalid print in case of ipv6 */ ++ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", ++ &rtp_exp->tuple.src.u3.ip, ++ ntohs(rtp_exp->tuple.src.u.udp.port), ++ ntohs(rtcp_exp->tuple.src.u.udp.port), ++ &rtp_exp->tuple.dst.u3.ip, ++ ntohs(rtp_exp->tuple.dst.u.udp.port), ++ ntohs(rtcp_exp->tuple.dst.u.udp.port)); ++ break; ++ } ++ if (loport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); ++ } ++ break; ++ case pb_discon: ++ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(loport); ++ if (nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu (1 of 2)\n", loport); ++ break; ++ } ++ } ++ for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ ++ rtp_t->dst.u.udp.port = htons(hiport); ++ if (nf_ct_expect_related(rtp_exp) == 0) { ++ pr_debug("using port %hu (2 of 2)\n", hiport); ++ break; ++ } ++ } ++ if (loport != 0 && hiport != 0) { ++ rbuf1len = sprintf(rbuf1, "%hu", loport); ++ rbufalen = sprintf(rbufa, hiport == loport+1 ? ++ "%hu-%hu":"%hu/%hu", loport, hiport); ++ } ++ break; ++ } ++ ++ if (rbuf1len == 0) ++ return 0; /* cannot get replacement port(s) */ ++ ++ /* Transport: tran;field;field=val,tran;field;field=val,... ++ `off` is set to the start of Transport value from start of line ++ */ ++ while (off < tranlen) { ++ uint saveoff; ++ const char* pparamend; ++ uint nextparamoff; ++ ++ pparamend = memchr(ptran+off, ',', tranlen-off); ++ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; ++ nextparamoff = pparamend-ptran; ++ ++ /* ++ * We pass over each param twice. On the first pass, we look for a ++ * destination= field. It is handled by the security policy. If it ++ * is present, allowed, and equal to our external address, we assume ++ * that STUN is being used and we leave the client_port= field alone. ++ */ ++ is_stun = 0; ++ saveoff = off; ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) { ++ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) ++ is_stun = 1; ++ ++ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { ++ uint dstoff = (ptran-ptcp)+off; ++ uint dstlen = nextfieldoff-off; ++ char* pdstrep = NULL; ++ uint dstreplen = 0; ++ diff = dstlen; ++ if (dstact == DSTACT_AUTO && !is_stun) { ++ pr_debug("RTSP: replace dst addr\n"); ++ dstoff += 12; ++ dstlen -= 13; ++ pdstrep = szextaddr; ++ dstreplen = extaddrlen; ++ diff = nextfieldoff-off-13-extaddrlen; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, ++ dstoff, dstlen, pdstrep, dstreplen)) { ++#else ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, ++ dstoff, dstlen, pdstrep, dstreplen)) { ++#endif ++ /* mangle failed, all we can do is bail */ ++ nf_ct_unexpect_related(rtp_exp); ++ if (rtcp_exp) ++ nf_ct_unexpect_related(rtcp_exp); ++ return 0; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ tranlen -= diff; ++ nextparamoff -= diff; ++ nextfieldoff -= diff; ++ } ++ } ++ ++ off = nextfieldoff; ++ } ++ ++ if (is_stun) ++ continue; ++ ++ off = saveoff; ++ while (off < nextparamoff) { ++ const char* pfieldend; ++ uint nextfieldoff; ++ ++ pfieldend = memchr(ptran+off, ';', nextparamoff-off); ++ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; ++ ++ if (strncmp(ptran+off, "client_port=", 12) == 0) { ++ u_int16_t port; ++ uint numlen; ++ uint origoff; ++ uint origlen; ++ char* rbuf = rbuf1; ++ uint rbuflen = rbuf1len; ++ ++ off += 12; ++ origoff = (ptran-ptcp)+off; ++ origlen = 0; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ origlen += numlen; ++ if (port != prtspexp->loport) { ++ pr_debug("multiple ports found, port %hu ignored\n", port); ++ } else { ++ if (ptran[off] == '-' || ptran[off] == '/') { ++ off++; ++ origlen++; ++ numlen = nf_strtou16(ptran+off, &port); ++ off += numlen; ++ origlen += numlen; ++ rbuf = rbufa; ++ rbuflen = rbufalen; ++ } ++ ++ /* ++ * note we cannot just memcpy() if the sizes are the same. ++ * the mangle function does skb resizing, checks for a ++ * cloned skb, and updates the checksums. ++ * ++ * parameter 4 below is offset from start of tcp data. ++ */ ++ diff = origlen-rbuflen; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, ++ origoff, origlen, rbuf, rbuflen)) { ++#else ++ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, ++ origoff, origlen, rbuf, rbuflen)) { ++#endif ++ /* mangle failed, all we can do is bail */ ++ nf_ct_unexpect_related(rtp_exp); ++ if (rtcp_exp) ++ nf_ct_unexpect_related(rtcp_exp); ++ return 0; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ ptran = ptcp+tranoff; ++ tranlen -= diff; ++ nextparamoff -= diff; ++ nextfieldoff -= diff; ++ } ++ } ++ ++ off = nextfieldoff; ++ } ++ ++ off = nextparamoff; ++ } ++ ++ return 1; ++} ++ ++static uint ++help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp) ++{ ++ char* ptcp; ++ uint tcplen; ++ uint hdrsoff; ++ uint hdrslen; ++ uint lineoff; ++ uint linelen; ++ uint off; ++ int dir = CTINFO2DIR(ctinfo); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; ++#else ++ __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; ++#endif ++ ++ //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; ++ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); ++ ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); ++ hdrslen = matchlen; ++ off = hdrsoff; ++ pr_debug("NAT rtsp help_out\n"); ++ ++ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { ++ if (linelen == 0) ++ break; ++ ++ if (off > hdrsoff+hdrslen) { ++ pr_info("!! overrun !!"); ++ break; ++ } ++ pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); ++ ++ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { ++ uint oldtcplen = tcplen; ++ pr_debug("hdr: Transport\n"); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, ++ prtspexp, skb, lineoff, linelen)) { ++#else ++ if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, ++ skb, lineoff, linelen)) { ++#endif ++ pr_debug("hdr: Transport mangle failed"); ++ break; ++ } ++ rtp_exp->expectfn = nf_nat_rtsp_expected; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rtp_exp->saved_addr = saddr; ++#else ++ rtp_exp->saved_ip = saddr; ++#endif ++ rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); ++ rtp_exp->dir = !dir; ++ if (rtcp_exp) { ++ rtcp_exp->expectfn = nf_nat_rtsp_expected; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rtcp_exp->saved_addr = saddr; ++#else ++ rtcp_exp->saved_ip = saddr; ++#endif ++ rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); ++ rtcp_exp->dir = !dir; ++ } ++ get_skb_tcpdata(skb, &ptcp, &tcplen); ++ hdrslen -= (oldtcplen-tcplen); ++ off -= (oldtcplen-tcplen); ++ lineoff -= (oldtcplen-tcplen); ++ linelen -= (oldtcplen-tcplen); ++ pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); ++ } ++ } ++ ++ return NF_ACCEPT; ++} ++ ++static unsigned int ++nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ unsigned int protoff, ++#endif ++ unsigned int matchoff, unsigned int matchlen, ++ struct ip_ct_rtsp_expect* prtspexp, ++ struct nf_conntrack_expect* rtp_exp, ++ struct nf_conntrack_expect* rtcp_exp) ++{ ++ int dir = CTINFO2DIR(ctinfo); ++ int rc = NF_ACCEPT; ++ ++ switch (dir) { ++ case IP_CT_DIR_ORIGINAL: ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, ++ rtp_exp, rtcp_exp); ++#else ++ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, ++ rtp_exp, rtcp_exp); ++#endif ++ break; ++ case IP_CT_DIR_REPLY: ++ pr_debug("unmangle ! %u\n", ctinfo); ++ /* XXX: unmangle */ ++ rc = NF_ACCEPT; ++ break; ++ } ++ //UNLOCK_BH(&ip_rtsp_lock); ++ ++ return rc; ++} ++ ++static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ struct nf_nat_range range; ++#else ++ struct nf_nat_ipv4_range range; ++#endif ++ ++ /* This must be a fresh one. */ ++ BUG_ON(ct->status & IPS_NAT_DONE_MASK); ++ ++ /* For DST manip, map port here to where it's expected. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ range.min_proto = range.max_proto = exp->saved_proto; ++ range.min_addr = range.max_addr = exp->saved_addr; ++#else ++ range.min = range.max = exp->saved_proto; ++ range.min_ip = range.max_ip = exp->saved_ip; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); ++ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); ++#else ++ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); ++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); ++#endif ++ ++ /* Change src to where master sends to, but only if the connection ++ * actually came from the same source. */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) ++ if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, ++ &ct->master->tuplehash[exp->dir].tuple.src.u3)) { ++ range.min_addr = range.max_addr ++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3; ++#else ++ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == ++ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { ++ range.min_ip = range.max_ip ++ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) ++ range.flags = NF_NAT_RANGE_MAP_IPS; ++ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); ++#else ++ range.flags = IP_NAT_RANGE_MAP_IPS; ++ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); ++#endif ++ } ++} ++ ++ ++static void __exit fini(void) ++{ ++ rcu_assign_pointer(nf_nat_rtsp_hook, NULL); ++ synchronize_net(); ++} ++ ++static int __init init(void) ++{ ++ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); ++ ++ BUG_ON(nf_nat_rtsp_hook); ++ rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); ++ ++ if (stunaddr != NULL) ++ extip = in_aton(stunaddr); ++ ++ if (destaction != NULL) { ++ if (strcmp(destaction, "auto") == 0) ++ dstact = DSTACT_AUTO; ++ ++ if (strcmp(destaction, "strip") == 0) ++ dstact = DSTACT_STRIP; ++ ++ if (strcmp(destaction, "none") == 0) ++ dstact = DSTACT_NONE; ++ } ++ ++ return 0; ++} ++ ++module_init(init); ++module_exit(fini); +--- a/extensions/Kbuild ++++ b/extensions/Kbuild +@@ -28,6 +28,7 @@ obj-${build_lscan} += xt_lscan.o + obj-${build_pknock} += pknock/ + obj-${build_psd} += xt_psd.o + obj-${build_quota2} += xt_quota2.o ++obj-${build_rtsp} += rtsp/ + + -include ${M}/*.Kbuild + -include ${M}/Kbuild.* +--- a/mconfig ++++ b/mconfig +@@ -22,3 +22,4 @@ build_lscan=m + build_pknock=m + build_psd=m + build_quota2=m ++build_rtsp=m diff --git a/package/network/utils/xtables-addons/patches/200-add-lua-packetscript.patch b/package/network/utils/xtables-addons/patches/200-add-lua-packetscript.patch new file mode 100644 index 0000000..8bc30a7 --- /dev/null +++ b/package/network/utils/xtables-addons/patches/200-add-lua-packetscript.patch @@ -0,0 +1,18158 @@ +--- /dev/null ++++ b/extensions/LUA/byte_array.c +@@ -0,0 +1,145 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++#include "controller.h" ++ ++/* Initialization helper function. This function should be used whenever ++ * a new byte array need to be initialized. Depending on the arguments it ++ * initializes the array in a different way. Have a look at the inline ++ * comments */ ++lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy) ++{ ++ lua_packet_segment *array; ++ ++ if (length < 0) ++ luaL_error(L, "init_byte_array, requested size < 0"); ++ ++ if (start && do_copy) { ++ /* we have a start address where we copy from */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); ++ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ ++ memcpy(array->start, start, length); ++ }else if (start && !do_copy) { ++ /* just link the start pointer, in this case you have to free the memory yourself */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment)); ++ array->start = start; ++ }else{ ++ /* create an empty array, fully managed by Lua */ ++ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); ++ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ ++ memset(array->start, 0, length); ++ } ++ ++ array->length = length; ++ array->offset = 0; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ ++ return array; ++} ++ ++ ++ ++/* LUA_API: get one byte of the given byte array ++ * access-pattern: array[<index>] */ ++static int32_t get_byte_array(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ ++ ++ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); ++ lua_pushinteger(L, (array->start + array->offset)[index]); ++ ++ return 1; ++} ++ ++/* LUA_API: set one byte of the given byte array ++ * access-pattern: array[<index>]= 0xFF */ ++static int32_t set_byte_array(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ uint8_t byte; ++ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ ++ int32_t val = luaL_checkinteger(L, 3); ++ uint32_t nob = 1 << CHAR_BIT; /* we should use something like 1 << CHAR_BIT */ ++ ++ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); ++ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); ++ ++ byte = (uint8_t)val; ++ ++ (array->start + array->offset)[index] = byte; ++ ++ return 0; ++} ++ ++/* LUA_API: get size of the given byte array ++ * access-pattern: #array (__length meta-method) */ ++static int32_t get_byte_array_size(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ ++ lua_pushnumber(L, array->length); ++ ++ return 1; ++} ++ ++ ++/* LUA_API: converts a given byte array to a string. ++ * access-pattern: implicit through functions calling the ++ * __to_string() metamethod , e.g. print32_t */ ++static int32_t byte_array_to_string(lua_State *L) ++{ ++ lua_packet_segment * array = checkbytearray(L, 1); ++ uint8_t buf[(array->length * 3) + 255]; ++ uint8_t hexval[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; ++ char res[255 + (array->length * 3)]; /* make sure the buffer is big enough*/ ++ int32_t i, n; ++ uint8_t *ptr = array->start + array->offset; ++ ++ for (i = 0; i < array->length; i++) { ++ buf[i * 3] = hexval[(ptr[i] >> 4) & 0xF]; ++ buf[(i * 3) + 1] = hexval[ptr[i] & 0x0F]; ++ buf[(i * 3) + 2] = ' '; /* seperator */ ++ } ++ ++ buf[array->length * 3] = '\0'; ++ n = sprintf(res, "byte_array: length: %d value: %s", array->length, buf); ++ ++ lua_pushlstring(L, res, n); ++ ++ return 1; ++} ++ ++static const struct luaL_Reg bytearray_lib_m [] = { ++ { "__len", get_byte_array_size }, ++ { "__newindex", set_byte_array }, ++ { "__index", get_byte_array }, ++ { "__tostring", byte_array_to_string }, ++ { NULL, NULL } ++}; ++ ++void luaopen_bytearraylib(lua_State *L) ++{ ++ luaL_newmetatable(L, LUA_BYTE_ARRAY); ++ luaL_register(L, NULL, bytearray_lib_m); ++ lua_pop(L, 1); ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/controller.c +@@ -0,0 +1,604 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#if defined(__KERNEL__) ++ #include <linux/mm.h> ++#endif ++#include "controller.h" ++ ++/* the array 'supported_protocols' holds all pointers to the ++ * static and dynamic protocol buffers. It is filled by the ++ * call to register_protbuf */ ++static struct protocol_buf * supported_protocols[MAX_NR_OF_PROTOCOLS]; ++ ++/* C_API: the function 'get_protocol_buf' returns the pointer ++ * to the protocol buffer of a given protocol id. */ ++struct protocol_buf * get_protocol_buf(uint32_t protocol_id) ++{ ++ return (struct protocol_buf *)supported_protocols[protocol_id]; ++} ++ ++ ++/* LUA_INT: the function 'gc_packet_segment' is triggered by the ++ * garbage collector whenever a userdata annotated with one of ++ * the protocol buffer metatable should be collected. */ ++static int32_t gc_packet_segment(lua_State *L) ++{ ++ lua_packet_segment * seg = (lua_packet_segment *)lua_touserdata(L, 1); ++ if (seg && seg->changes) { ++ seg->changes->ref_count--; ++ if (seg->changes->ref_count <= 0) { ++ kfree(seg->changes->field_length_changes); ++ kfree(seg->changes->field_offset_changes); ++ kfree(seg->changes); ++ seg->changes = NULL; ++ } ++ } ++ return 0; ++} ++ ++ ++/* LUA_API: the function 'set_raw' is used to set the bytes of a segment ++ * in 'raw' mode. The function is per default available in each protocol ++ * buffer until it gets overridden by a specific setter function inside ++ * a protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * 2. int32_t byte_value ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: void ++ */ ++static int32_t set_raw(lua_State *L) ++{ ++ int32_t i; ++ uint32_t nob; ++ uint8_t byte; ++ uint8_t *ptr; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t val = luaL_checkinteger(L, 2); ++ ++ nob = 1 << CHAR_BIT; ++ ++ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); ++ ++ byte = (uint8_t)val; ++ ptr = seg->start + seg->offset; ++ ++ for (i = 0; i < seg->length; i++) ++ ptr[i] = byte; ++ ++ return 0; ++} ++ ++/* LUA_API: the function 'get_raw' is used to get the bytes of a segment ++ * in 'raw' mode. The function is per default available in each protocol ++ * buffer until it gets overridden by a specific getter function inside ++ * a protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * 2. uint32_t offset ++ * 3. uint32_t length ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * the byte array representing the given array ++ */ ++static int32_t get_raw(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ init_byte_array(L, seg->start + seg->offset, seg->length, 1); ++ ++ return 1; ++} ++/* LUA_API: The function 'get_segment' is used to get a new segment in 'raw' mode. ++ * Typically this function is applied on another raw segment in order ++ * to extract a part of the segment as new segment. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * 2. uint32_t offset, this indicates where to start the new segment, see e.g below. ++ * 3. uint32_t length, this indicates the size of the new segment ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. A lua_packet_segment annotated with the according metatable or False in ++ * case the input data is not valid ++ * ++ * Example: ++ * ++ * +------------------------+---------------------------------------+ ++ * | function call | resulting lua_packet_segment | ++ * +========================+===+===+===+===+===+===+===+===+===+===+ ++ * | seg = packet:raw(0,10) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ++ * +------------------------+---+---+---+---+---+---+---+---+---+---+ ++ * | 1st_half = seg:raw(0,5)| 0 | 1 | 2 | 3 | 4 | | ++ * +------------------------+---+---+---+---+---+---+---+---+---+---+ ++ * | 2nd_half = seg:raw(5,5)| | 5 | 6 | 7 | 8 | 9 | ++ * +------------------------+-------------------+---+---+---+---+---+ ++ */ ++static int32_t get_segment(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint32_t offset = luaL_checkinteger(L, 2); ++ uint32_t length = luaL_checkinteger(L, 3); ++ lua_packet_segment * new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ ++ new->start = seg->start; ++ new->offset = seg->offset + offset; ++ new->changes = NULL; ++ /* we allow a seg->length == 0 , this enables processing packets where the packetsize is not fixed (0 = not fixed)*/ ++ if (seg->length != 0 && length > seg->length) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ new->length = length; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ ++ return 1; ++} ++ ++/* LUA_API: the function 'get_segment_size' is used to get the size of a segment. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. Size as lua_Number ++ */ ++static int32_t get_segment_size(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushnumber(L, seg->length); ++ return 1; ++} ++ ++/* LUA_API: the function 'get_segment_offset' is used to get the real offset ++ * of a segment. This function returns the offset of the segment to the start ++ * of the buffer. This means the following ++ * seg1 = packet:raw(2,10) ++ * seg2 = seg1:raw(3,5) ++ * offset = seg2:get_offset() ++ * ++ * will give an offset of 5, since the seg1 starts at offset 2, and seg2 starts ++ * at offset (seg1:get_offset() + 3). ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index, not used in this function ++ * ++ * Return: ++ * 1. Offset as lua_Number ++ */ ++static int32_t get_segment_offset(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushnumber(L, seg->offset); ++ return 1; ++} ++ ++/* LUA_API: overwrites the __tostring function of a lua_packet_segment. ++ * this will print32_t a nicely formated string, including length, ++ * offset and name of the protocol buffer. ++ * ++ * Parameters: ++ * 1. lua_packet_segment (implicit) ++ * ++ * Returns: ++ * 1. the representing string ++ */ ++static int32_t packet_segment_tostring(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ int32_t n; ++ char buf[128]; ++ ++ n = sprintf(buf, "type: %s, offset: %d, length: %d", prot_buf->name, seg->offset, seg->length); ++ lua_pushlstring(L, buf, n); ++ ++ return 1; ++} ++ ++ ++static const struct luaL_Reg seg_access_functions [] = { ++ { "set", set_raw }, ++ { "get", get_raw }, ++ { "raw", get_segment }, ++ { "get_offset", get_segment_offset }, ++ { "get_size", get_segment_size }, ++ { "to_bytes", get_raw }, ++ { "__tostring", packet_segment_tostring }, ++ { "__gc", gc_packet_segment }, ++ { NULL, NULL } ++}; ++ ++/* C_API: the function 'get_metatable_from_protocol_type' is a helper ++ * used in controller.c as well as it may find usage in the static ++ * protocol buffers and byte array implementation. */ ++void get_metatable_from_protocol_type(lua_State *L, int32_t type) ++{ ++ char * table; ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ lua_rawgeti(L, -1, type); ++ table = (char *)luaL_checkstring(L, -1); ++ lua_pop(L, 2); /* pop the table SUPPORTED_PROTOCOL_TABLE and the string pushed by lua_gettable */ ++ luaL_getmetatable(L, table); ++ return; ++} ++ ++/* C_INT: the function 'payload_contains_protocol' is used internally. ++ * Depending if static or dynamic protocol buffer it calls the right ++ * validation function. */ ++static int32_t payload_contains_protocol(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment *seg, uint32_t prot_type) ++{ ++ if (prot_buf->is_dynamic) ++ return has_protocol_dynamic(L, prot_buf, seg, prot_type); ++ else ++ return prot_buf->has_protocol(L, prot_buf, seg, prot_type); ++} ++ ++/* C_INT: the function 'protocol_get_field_changes' is used interally. ++ * It requests the field_changes struct calling the protocol buffers ++ * 'get_field_changes' function. This funciton is called, whenever ++ * the payload field with a given protocol type is requested inside ++ * the function 'get_protocol_field' */ ++static struct field_changes * protocol_get_field_changes(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) ++{ ++ struct field_changes * changes = NULL; ++ ++ if (prot_buf->get_field_changes) { ++ if (prot_buf->is_dynamic) ++ changes = get_field_changes_dynamic(L, prot_buf, seg); ++ else ++ changes = prot_buf->get_field_changes(L, seg); ++ /* is already 1 when set by helper 'get_allocated_field_changes, ++ * since not every prot_buf may use this function we enforce it. */ ++ changes->ref_count = 1; ++ } ++ return changes; ++} ++ ++/* C_INT: the function 'get_field_offset_in_bytes' wrapps the logic of ++ * calculating the new length with considering the optional field_changes. */ ++static int32_t get_field_offset_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) ++{ ++ uint32_t nr_of_bits, nr_of_bytes, field_offset; ++ ++ field_offset = field->offset; ++ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ ++ if (seg->changes) ++ field_offset += seg->changes->field_offset_changes[field_index]; ++ /* how many bits remain */ ++ nr_of_bits = field_offset & (CHAR_BIT - 1); ++ /* assuming CHAR_BIT == 2 ^ 3 */ ++ nr_of_bytes = (field_offset - nr_of_bits) >> 3; ++ ++ return seg->offset + nr_of_bytes; ++} ++ ++/* C_INT: the function 'get_field_length_in_bytes' wrapps the logic of ++ * calculating the new offset with considering the optional field_changes. */ ++static int32_t get_field_length_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) ++{ ++ uint32_t nr_of_bits, nr_of_bytes, field_length; ++ ++ field_length = field->length; ++ /* if the field length is smaller than 1 byte, we take the size of one byte ++ * we treat the case where field_length == 0 in a special way ...*/ ++ if (field_length < CHAR_BIT && field_length > 0) ++ field_length = CHAR_BIT; ++ ++ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ ++ if (seg->changes) ++ field_length += seg->changes->field_length_changes[field_index]; ++ /* how many bits remain */ ++ nr_of_bits = field_length & (CHAR_BIT - 1); ++ /* assuming CHAR_BIT == 2 ^ 3 */ ++ nr_of_bytes = (field_length - nr_of_bits) >> 3; ++ return nr_of_bytes; ++} ++ ++/* C_INT: the function 'initialize_field_getter_and_setter' initializes ++ * the setter and getter function of the field, considering the optional ++ * field manipulator functions defined inside the protocol buffers. */ ++static void initialize_field_getter_and_setter(lua_State *L, struct protocol_buf *prot_buf, int32_t field_index) ++{ ++ /* lets check if there is a metatable on top of the stack */ ++ struct protocol_field * f = (struct protocol_field *)&prot_buf->protocol_fields[field_index]; ++ ++ if (!lua_istable(L, -1)) luaL_error(L, "cannot initialize getter and setter for field %s->%s, " ++ "not a table on top of the stack, is '%s'", prot_buf->name, f->name, lua_typename(L, lua_type(L, -1))); ++ ++ /* is there a 'getter' to initialize ? */ ++ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ ++ lua_pushinteger(L, field_index); /* push upvalue 2 */ ++ if (f->get) { ++ if (prot_buf->is_dynamic) ++ lua_pushcclosure(L, field_dynamic_getter, 2); ++ else ++ lua_pushcclosure(L, f->get, 2); ++ }else ++ /* there is no specific getter defined - fall back to 'get_raw' */ ++ lua_pushcclosure(L, get_raw, 2); ++ /* set the metatable field 'get' */ ++ lua_setfield(L, -2, "get"); ++ ++ /* is there a 'setter' to initialize ? */ ++ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ ++ lua_pushinteger(L, field_index); /* push upvalue 2 */ ++ if (f->set) { ++ if (prot_buf->is_dynamic) ++ lua_pushcclosure(L, field_dynamic_setter, 2); ++ else ++ lua_pushcclosure(L, f->set, 2); ++ }else ++ /* there is no specific setter defined - fall back to 'set_raw' */ ++ lua_pushcclosure(L, set_raw, 2); ++ /* set the metatable field 'set' */ ++ lua_setfield(L, -2, "set"); ++} ++ ++/* LUA_API: 'get_protocol_field' is used in Lua as a closure for each field of a protocol ++ * buffer. E.g a call to ip = packet:data(packet_ip) will go to this function, ++ * and trigger the conversion of the raw packet to a ip packet. Each call ++ * to a field function of an IP packet, like ip:daddr() uses this function ++ * to to return the right data. In each case you will end up either with a ++ * new packet segment (annotated with the proper metatable) or a boolean ++ * value (False) if something went wrong. In the case everything went fine, ++ * the newly created lua_packet_segment is annotated with the proper ++ * metatable where the fields get and set also contain the specific getter ++ * and setter functions given by the protocol buffer. E.g. the function call ++ * ip:daddr():get() or ip:daddr():set(...) will call the proper function ++ * defined inside the corresponding field definition. ++ * ++ * Parameters: ++ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) ++ * 2. type of the protocol buffer, optional, and only used if the accessed ++ * field is the payload field. If a type is provided for the access of the ++ * payload field, the function tries to convert the data pointed to by the ++ * payload field to the given type. To check if such a conversion is ++ * possible, it calls the function pointed to by the protocol buffer member ++ * has_protocol. If this function returns True, the conversion takes place. ++ * ++ * Upvalues: ++ * 1. struct protocol_buf* ++ * 2. int32_t field index ++ * ++ * Return: ++ * 1. A lua_packet_segment annotated with the according metatable or False in ++ * case the input data is not valid ++ */ ++static int32_t get_protocol_field(lua_State *L) ++{ ++ int32_t prot_type; ++ lua_packet_segment * seg, *new; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ struct protocol_field * field = &prot_buf->protocol_fields[field_index]; ++ ++ /* get the current packet segment */ ++ seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ /* initialize the new packet segment */ ++ new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ new->start = seg->start; /* the start is unchanged */ ++ new->offset = get_field_offset_in_bytes(field, seg, field_index); ++ new->length = get_field_length_in_bytes(field, seg, field_index); ++ ++ /* if new->length == 0 then no configuration was done, we guess the size by subtracting the ++ * new offset from the packet length. since the old length is getting initialized by the ++ * netfilter extension this assumption holds for the very last field of the protocol. ++ * this 'feature' should be used by protocol buffers containing a payload, whereas the ++ * payload field is the last field of the buffer. However, at compile-time unknown field ++ * sizes (and offsets) of fields not being placed at the end of the protocol should be ++ * initialized using the 'get_field_changes' hook system. */ ++ if (new->length == 0) ++ new->length = (seg->length + seg->offset) - (new->offset); ++ /* ++ printf("%s->%s:: seg->offset %i, seg->length %i, new->offset %i, new->length %i\n", ++ prot_buf->name, field->name, seg->offset, seg->length, new->offset, new->length); ++ */ ++ /* special care for packet payload requests */ ++ if (prot_buf->payload_field != NULL && strcmp(prot_buf->payload_field, field->name) == 0) { ++ /* we know the payload field is requested */ ++ /* the requested payload can be delivered either as a common segment or as ++ * an other packet type, such a conversion needs an extra protocol parameter ++ * ... so lets check */ ++ ++ if (lua_isnumber(L, 2)) { ++ /* we have an extra parameter, ... lets see if it is a valid protocol ++ * the parameter is the index of the 'supported_protocols'-array member */ ++ prot_type = lua_tointeger(L, 2); ++ if (prot_type >= 0 && prot_type < PACKET_SENTINEL) { ++ /* we are sure the purpose of the request is to get the payload data, ++ * converted to the given protocol. lets check if the payload contains ++ * data of the given protocol */ ++ if (payload_contains_protocol(L, prot_buf, seg, prot_type)) { ++ /* success, we can push the metatable for the given protocol */ ++ get_metatable_from_protocol_type(L, prot_type); ++ if (!lua_isnil(L, -1)) /* check if the metatable was found */ ++ /* perhaps the field offsets and lengths of the containing protocol ++ * are not set correctly. request the optional 'field_changes' structure ++ * holding the changes for lengths and offsets. */ ++ new->changes = protocol_get_field_changes(L, get_protocol_buf(prot_type), new); ++ else{ ++ /* failed, the requested protocol is not available ++ * we push false and return */ ++ lua_pop(L, 1); /* pop the userdata */ ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ }else{ ++ /* payload does not carry the provided protocol */ ++ /* we push false and return */ ++ lua_pop(L, 1); /* pop the userdata */ ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ }else{ ++ /* unknown protocol */ ++ lua_pop(L, 1); /* pop the userdata */ ++ luaL_error(L, "provided protocol is unknown"); ++ } ++ } ++ } ++ ++ /* if there is still the 'new' userdata on the top, we push our own metatable */ ++ if (lua_isuserdata(L, -1)) { ++ luaL_getmetatable(L, prot_buf->name); ++ new->changes = seg->changes; ++ if (seg->changes) ++ new->changes->ref_count++; ++ } ++ ++ /* a new packet segment is at index -2 , and the proper metatable at index -1 of the stack ++ * lets set the propper setter and getter function for the requested field */ ++ initialize_field_getter_and_setter(L, prot_buf, field_index); ++ ++ lua_setmetatable(L, -2); ++ return 1; ++} ++ ++/* C_API: 'register_protbuf' is only used internally. This function takes a ++ * pointer to a fully initialized protocol buffer struct and registers it ++ * inside the Lua state. Registering means: ++ * ++ * 1. it creates a new metatable with the name of the protocol buffer. ++ * 2. it registers the default functions which are stored in the luaL_Reg ++ * array seg_access_functions. ++ * 3. it loops over the protocol fields stored at prot_buf->protocol_fields ++ * and registers a new function (using the field name) inside the ++ * metatable. Each field points to the function 'get_protocol_field' ++ * which acts as a closure taking a pointer to the protocol buffer as ++ * well as the index of the field as upvalues. ++ * 4. The protocol index, serves as numerical identifier of this protocol ++ * buffer or even of the protocol itself. This index is stored as a ++ * global value inside the Lua state as well as inside the Lua table ++ * 'supported_protocols'. Assuming the name of a procotol buffer is ++ * "packet_ip" the following statements are true: ++ * ++ * supported_protocols[protocol_index] == "packet_ip" ++ * packet_ip == protocol_index ++ * ++ * This allows you to get all registered protocols from within Lua. This ++ * is especially usefull for the dynamic protocol buffers where you have ++ * to provide your own "has_protocol"-function, which probably needs the ++ * information on which protocols it is able to contain. ++ */ ++void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, uint32_t protocol_index) ++{ ++ int32_t field_index; ++ luaL_Reg *reg = (struct luaL_Reg *)seg_access_functions; ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ luaL_newmetatable(L, prot_buf->name); ++ ++ /* metatable.__index = metatable */ ++ lua_pushvalue(L, -1); /* duplicates the metatable */ ++ lua_setfield(L, -2, "__index"); ++ ++ /* pushing default functions */ ++ for (; reg->name; reg++) { ++ lua_pushlightuserdata(L, (void *)prot_buf); ++ lua_pushcclosure(L, reg->func, 1); ++ lua_setfield(L, -2, reg->name); ++ } ++ ++ /* pushing functions specific to the protocol buffer */ ++ for (field_index = 0; field->name; field++, field_index++) { ++ lua_pushlightuserdata(L, (void *)prot_buf); /* upvalue: prot_buf */ ++ lua_pushinteger(L, field_index); /* upvalue: index of protocol field */ ++ lua_pushcclosure(L, get_protocol_field, 2); ++ lua_setfield(L, -2, field->name); ++ } ++ /* pop the metatable */ ++ lua_pop(L, 1); ++ ++ /* registering the array-index as the protocol_id*/ ++ lua_getglobal(L, "_G"); ++ lua_pushinteger(L, protocol_index); ++ lua_setfield(L, -2, prot_buf->name); ++ lua_pop(L, 1); /* pop _G */ ++ ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ lua_pushstring(L, prot_buf->name); ++ lua_rawseti(L, -2, protocol_index); ++ ++ lua_pop(L, 1); /* pop SUPPORTED_PROTOCOL_TABLE */ ++ ++ supported_protocols[protocol_index] = prot_buf; ++} ++ ++void luaopen_controller(lua_State *L) ++{ ++ /* registering a table inside the _G with table[protocol_index] = prot_buf->name */ ++ lua_getglobal(L, "_G"); ++ lua_newtable(L); ++ lua_setfield(L, -2, SUPPORTED_PROTOCOL_TABLE); ++ lua_pop(L, 1); /* pop _G */ ++ ++ luaopen_protbuf_raw(L); ++ luaopen_protbuf_eth(L); ++ luaopen_protbuf_ip(L); ++ luaopen_protbuf_icmp(L); ++ luaopen_protbuf_tcp(L); ++ luaopen_protbuf_tcp_options(L); ++ luaopen_protbuf_udp(L); ++ luaopen_protbuf_tftp(L); ++ luaopen_protbuf_dynamic(L); ++ /* should follow all other static buffers */ ++#if defined(__KERNEL__) ++ luaopen_nflib(L); ++#endif ++ ++ luaopen_bytearraylib(L); ++} ++ ++ ++ ++ +--- /dev/null ++++ b/extensions/LUA/controller.h +@@ -0,0 +1,264 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef CONTROLLER_H_ ++#define CONTROLLER_H_ ++ ++#include "stdlib.h" /* wrapper */ ++#include "string.h" /* wrapper */ ++#include "lua.h" ++#include "lualib.h" ++#include "lauxlib.h" ++ ++#if defined(__KERNEL__) ++#include <linux/skbuff.h> ++#include <linux/slab.h> ++#include <linux/vmalloc.h> ++#endif ++ ++ ++/* to compile the stuff in userspace (for testing)*/ ++#if !defined(__KERNEL__) ++#include <stdint.h> ++#define pr_debug printf; ++ ++#define kmalloc(size, type) malloc(size) ++#define kfree(ptr) free(ptr) ++ ++#endif ++ ++ ++/**********************************************************************/ ++/* nf Lua configuration */ ++/**********************************************************************/ ++#define MAX_NR_OF_PROTOCOLS 16 ++#define SUPPORTED_PROTOCOL_TABLE "supported_protocols" ++ ++#define MAX_NR_OF_FIELDS_IN_DYN_PROT_BUF 32 ++ ++ ++/**********************************************************************/ ++/* Static Protocol Buffer configuration */ ++/**********************************************************************/ ++ ++/* the definitions of the stringified expression of the prot_bufs... ++ * make sure all static prot_bufs are listed and are unique */ ++#define LUA_PACKET_SEG_RAW "packet_raw" ++#define LUA_PACKET_SEG_ETH "packet_eth" ++#define LUA_PACKET_SEG_ICMP "packet_icmp" ++#define LUA_PACKET_SEG_IP "packet_ip" ++#define LUA_PACKET_SEG_TCP "packet_tcp" ++#define LUA_PACKET_SEG_TCP_OPT "packet_tcp_opt" ++#define LUA_PACKET_SEG_UDP "packet_udp" ++#define LUA_PACKET_SEG_TFTP "packet_tftp" ++ ++/* the enum holding all static prot_bufs... make sure it contains all ++ * static prot_bufs */ ++enum PROT_BUF { ++ PACKET_RAW, ++ PACKET_ETH, ++ PACKET_IP, ++ PACKET_ICMP, ++ PACKET_TCP, ++ PACKET_TCP_OPTIONS, ++ PACKET_UDP, ++ PACKET_TFTP, ++ PACKET_DYNAMIC, ++ PACKET_SENTINEL ++}; ++ ++/* the luaopen-function of the prot_bufs... make sure it is called ++ * inside luaopen_controller */ ++void luaopen_protbuf_raw(lua_State *L); ++void luaopen_protbuf_eth(lua_State *L); ++void luaopen_protbuf_ip(lua_State *L); ++void luaopen_protbuf_icmp(lua_State *L); ++void luaopen_protbuf_tcp(lua_State *L); ++void luaopen_protbuf_tcp_options(lua_State *L); ++void luaopen_protbuf_udp(lua_State *L); ++void luaopen_protbuf_tftp(lua_State *L); ++void luaopen_protbuf_dynamic(lua_State *L); ++ ++/**********************************************************************/ ++/* field changes */ ++/**********************************************************************/ ++struct field_changes { ++ int ref_count; ++ int *field_length_changes; ++ int *field_offset_changes; ++}; ++ ++/**********************************************************************/ ++/* lua packet segment */ ++/* ------------------ */ ++/* The struct lua_packet_segment is the integral part of a Lua packet.*/ ++/* At the very beginning, when a new packet arrives in `lua_tg`_ such */ ++/* a struct is initialized. The field start then points to the lowest */ ++/* available header inside the sk_buff structure. During packet */ ++/* processing the start pointer remains the same, only the offset and */ ++/* length value change. */ ++/**********************************************************************/ ++#define checkpacketseg(L, i, seg_type) \ ++ (lua_packet_segment *)luaL_checkudata(L, i, seg_type) ++ ++typedef struct lua_packet_segment { ++ unsigned int offset; ++ unsigned int length; ++ struct field_changes * changes; ++ unsigned char * start; /* need to be at the end because of the memory alignment */ ++} lua_packet_segment; ++ ++/**********************************************************************/ ++/* protocol field */ ++/* -------------- */ ++/* This structure is a container for the field definitions used by the*/ ++/* protocol buffer. Each protocol field is expressed using this struct*/ ++/* Have a look at the protocol buffers to see how the struct gets */ ++/* initialized. */ ++/* */ ++/* name: */ ++/* This member expresses the name of the field, ending */ ++/* in its own Lua function to access the field. */ ++/* offset / length: */ ++/* These members do specify the position inside the protocol header */ ++/* in bits (not bytes!). */ ++/* get / set: */ ++/* The get and set functions take a function pointer pointing to the*/ ++/* specific getter and setter function for this field. */ ++/**********************************************************************/ ++struct protocol_field { ++ const char * name; ++ uint32_t offset; ++ uint32_t length; ++ lua_CFunction get; ++ lua_CFunction set; ++}; ++#define PROT_FIELD_SENTINEL { NULL, 0, 0, NULL, NULL } ++ ++ ++/**********************************************************************/ ++/* protocol_buf */ ++/**********************************************************************/ ++/* This structure is a container for all the information needed for a ++ * protocol buffer. It gets initialized in each protocol buffer header ++ * file or for the dynamic protocol buffers on runtime using the ++ * 'register_dynamic_protocol_buffer' function. ++ * ++ * name: ++ * This member is used throughout the system. It is also exported ++ * to Lua as a variable name holding the index of the 'supported_protocols' ++ * array. The name is also used as the name of the generated Lua ++ * metatable, that is why inside the macro checkpacketseg_ it ++ * is always the name of a protocol buffer that is passed as the ++ * second parameter. ++ * payload_field: ++ * This member holds the string of the field responsible for payload ++ * data. The payload field of a protocol has an extra property, since ++ * it can be used to invoke another protocol buffer that is applied to ++ * the payload content. ++ * has_protocol: ++ * This member is used together with the payload_field. Since we must ++ * be sure that the payload content does really contain a protocol ++ * of type X. The function pointed to by has_protocol checks if the ++ * protocol buffer X can be applied on the payload_data. ++ * protocol_fields: ++ * This member points to the array of 'protocol_field' structures ++ * get_field_changes: ++ * This member is optional. It is used to return a pointer to an initialized ++ * field_changes struct. The function is called, whenever the payload field ++ * is requested with a given protocol type. Usually this function will ++ * initialize the field_changes struct depending on the content of the ++ * payload data. e.g. ++ * tcp = ip:data(packet_tcp) ++ * such a request will call the 'get_field_changes' function of the tcp ++ * protocol buffer. This enables, that the tcp options field have the proper ++ * length as well as the tcp data start at the right offset. ++ */ ++struct protocol_buf { ++ int is_dynamic; ++ const char * name; ++ char * payload_field; ++ int (*has_protocol)(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg, int type); ++ struct protocol_field * protocol_fields; ++ struct field_changes * (*get_field_changes)(lua_State *L, lua_packet_segment * seg); ++}; ++ ++/**********************************************************************/ ++/* lua byte array library */ ++/**********************************************************************/ ++#define LUA_BYTE_ARRAY "byte_array" ++#define checkbytearray(L, i) \ ++ (lua_packet_segment *)luaL_checkudata(L, i, LUA_BYTE_ARRAY) ++lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy); ++void luaopen_bytearraylib(lua_State *L); ++ ++ ++/**********************************************************************/ ++/* lua netfilter environment library */ ++/**********************************************************************/ ++#define NETFILTER_LIB "nf" ++#if defined(__KERNEL__) ++ struct lua_env { ++ lua_State *L; ++ /* perhaps more to come here (e.g. a state per CPU) */ ++ }; ++ #define LUA_ENV "lua_env" ++ #define checkluaenv(L, i) \ ++ (struct lua_env *)luaL_checkudata(L, i, LUA_ENV) ++ ++ void luaopen_nflib(lua_State *L); ++#endif ++ ++void cleanup_dynamic_prot_bufs(void); /* freeing all dynamic prot bufs */ ++/**********************************************************************/ ++/* lua protbuf helpers */ ++/**********************************************************************/ ++int get_1_bit_generic(lua_State *L); ++int set_1_bit_generic(lua_State *L); ++int get_lower_4_bit_generic(lua_State *L); ++int set_lower_4_bit_generic(lua_State *L); ++int get_upper_4_bit_generic(lua_State *L); ++int set_upper_4_bit_generic(lua_State *L); ++int get_8_bit_generic(lua_State *L); ++int set_8_bit_generic(lua_State *L); ++int get_16_bit_generic(lua_State *L); ++int set_16_bit_generic(lua_State *L); ++int get_32_bit_generic(lua_State *L); ++int set_32_bit_generic(lua_State *L); ++int set_data_generic(lua_State *L); ++int get_string_generic(lua_State *L); ++int get_byte_generic_str(lua_State *L); ++struct field_changes * get_allocated_field_changes(lua_State *L, int nr_of_fields); ++ ++/* only used by the dynamic prot buf subsystem */ ++#define MAX_NR_OF_DYN_PROT_BUFS 16 ++int field_dynamic_setter(lua_State *L); ++int field_dynamic_getter(lua_State *L); ++int has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int type); ++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg); ++ ++/**********************************************************************/ ++/* lua controller API */ ++/**********************************************************************/ ++void luaopen_controller(lua_State *L); ++struct protocol_buf * get_protocol_buf(unsigned int protocol_id); ++void get_metatable_from_protocol_type(lua_State *L, int type); ++void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, unsigned int protocol_index); ++ ++ ++#endif /* CONTROLLER_H_ */ +--- /dev/null ++++ b/extensions/LUA/Kbuild +@@ -0,0 +1,49 @@ ++# -*- Makefile -*- ++ ++# Adding debug options ++EXTRA_CFLAGS += -DDEBUG ++ ++obj-m += xt_LUA.o ++ ++EXTRA_CFLAGS += -I$(src)/prot_buf_new ++xt_LUA-y += xt_LUA_target.o \ ++ ++xt_LUA-y += nf_lua.o \ ++ prot_buf_helpers.o \ ++ byte_array.o \ ++ controller.o \ ++ prot_buf_ethernet.o \ ++ prot_buf_icmp.o \ ++ prot_buf_ip.o \ ++ prot_buf_raw.o \ ++ prot_buf_tcp.o \ ++ prot_buf_udp.o \ ++ prot_buf_tftp.o \ ++ prot_buf_dynamic.o \ ++ ++ ++# Adding Lua Support ++EXTRA_CFLAGS += -I$(src)/lua -I$(src)/lua/include ++xt_LUA-y += lua/lapi.o \ ++ lua/lbaselib.o \ ++ lua/lcode.o \ ++ lua/ldebug.o \ ++ lua/ldo.o \ ++ lua/ldump.o \ ++ lua/lfunc.o \ ++ lua/lgc.o \ ++ lua/llex.o \ ++ lua/lmem.o \ ++ lua/lobject.o \ ++ lua/lopcodes.o \ ++ lua/lparser.o \ ++ lua/lstate.o \ ++ lua/lstring.o \ ++ lua/lstrlib.o \ ++ lua/ltable.o \ ++ lua/ltablib.o \ ++ lua/ltm.o \ ++ lua/lundump.o \ ++ lua/lvm.o \ ++ lua/lzio.o \ ++ lua/lauxlib.o \ +--- /dev/null ++++ b/extensions/LUA/libxt_LUA.c +@@ -0,0 +1,191 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <getopt.h> ++#include <stdio.h> ++#include <stdbool.h> ++#include <stdlib.h> ++#include <string.h> ++#include <xtables.h> ++#include <linux/netfilter.h> ++#include <linux/netfilter/x_tables.h> ++#include "xt_LUA.h" ++ ++enum { ++ FLAG_SCRIPT = 1 << 0, ++ FLAG_STATE = 1 << 1, ++ FLAG_FUNCTION = 1 << 2, ++}; ++ ++static const struct option lua_tg_opts[] = { ++ { .name = "script", .has_arg = true, .val = 's' }, ++ { .name = "state", .has_arg = true, .val = 'l' }, ++ { .name = "function", .has_arg = true, .val = 'f' }, ++ { NULL }, ++}; ++ ++ ++static void lua_tg_help(void) ++{ ++ printf( ++ "LUA target options:\n" ++ " --script SCRIPT Process packet with the Lua script given by SCRIPT\n" ++ " \n" ++ " --state ID Process packet within the Lua state given by ID.\n" ++ " Omitting --state infers the ID 0, which can be\n" ++ " refered to the 'global' state.\n" ++ " \n" ++ " --function FUNCTION Name of the function that processes the Lua packet\n" ++ "\n"); ++} ++ ++static void ++lua_tg_init(struct xt_entry_target *target) ++{ ++ struct xt_lua_tginfo *info = (void *)target->data; ++ ++ info->state_id = 0; ++ strncpy(info->function, "process_packet\0", sizeof("process_packet\0")); ++} ++ ++static int ++lua_tg_parse(int32_t c, char **argv, int32_t invert, uint32_t *flags, ++ const void *entry, struct xt_entry_target **target) ++{ ++ struct xt_lua_tginfo *info = (void *)(*target)->data; ++ char buf[MAX_SCRIPT_SIZE]; ++ long script_size; ++ uint32_t state_id; ++ FILE *file; ++ ++ switch (c) { ++ case 's': ++ if (*flags & FLAG_SCRIPT) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --script more than once"); ++ ++ if (strlen(optarg) > sizeof(info->filename)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Maximum script length is %zu", ++ sizeof(info->filename)); ++ ++ if (strchr(optarg, '\n')) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Newlines not allowed in script name"); ++ file = fopen(optarg, "rb"); ++ if (file != NULL) { ++ fseek(file, 0, SEEK_END); ++ script_size = ftell(file); ++ if (script_size > MAX_SCRIPT_SIZE) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: The size of the script is too big"); ++ ++ fseek(file, 0, SEEK_SET); ++ fread(buf, script_size, 1, file); ++ fclose(file); ++ } else ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot open script %s", optarg); ++ ++ strncpy(info->filename, optarg, sizeof(info->filename)); ++ strncpy(info->buf, buf, sizeof(info->buf)); ++ info->script_size = script_size; ++ ++ *flags |= FLAG_SCRIPT; ++ return true; ++ ++ case 'l': ++ if (*flags & FLAG_STATE) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --state more than once"); ++ ++ if (!xtables_strtoui(optarg, NULL, &state_id, 0, 8)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Invalid --state %s", optarg); ++ ++ info->state_id = state_id; ++ *flags |= FLAG_STATE; ++ return true; ++ ++ case 'f': ++ if (*flags & FLAG_FUNCTION) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Cannot specify --function more than once"); ++ if (strlen(optarg) > sizeof(info->function)) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Maximum function length is %zu", ++ sizeof(info->function)); ++ ++ if (strchr(optarg, '\n')) ++ xtables_error(PARAMETER_PROBLEM, ++ "LUA: Newlines not allowed in function name"); ++ ++ strncpy(info->function, optarg, sizeof(info->function)); ++ ++ *flags |= FLAG_FUNCTION; ++ return true; ++ } ++ ++ return false; ++} ++ ++static void ++lua_tg_check(uint32_t flags) ++{ ++ if (flags == 0) ++ xtables_error(PARAMETER_PROBLEM, "LUA: --script parameter required"); ++} ++ ++static void ++lua_tg_print(const void *entry, const struct xt_entry_target *target, ++ int32_t numeric) ++{ ++ const struct xt_lua_tginfo *info = (const void *)target->data; ++ ++ printf("LUA script: %s ", info->filename); ++} ++ ++static void ++lua_tg_save(const void *entry, const struct xt_entry_target *target) ++{ ++ const struct xt_lua_tginfo *info = (const void *)target->data; ++ ++ printf("--script %s ", info->filename); ++} ++ ++static struct xtables_target lua_tg_reg = { ++ .name = "LUA", ++ .version = XTABLES_VERSION, ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .size = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .help = lua_tg_help, ++ .init = lua_tg_init, ++ .parse = lua_tg_parse, ++ .final_check = lua_tg_check, ++ .print = lua_tg_print, ++ .save = lua_tg_save, ++ .extra_opts = lua_tg_opts, ++}; ++ ++static __attribute__((constructor)) void lua_tg_ldr(void) ++{ ++ xtables_register_target(&lua_tg_reg); ++} ++ +--- /dev/null ++++ b/extensions/LUA/libxt_LUA.man +@@ -0,0 +1 @@ ++Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +--- /dev/null ++++ b/extensions/LUA/lua/include/ctype.h +@@ -0,0 +1,11 @@ ++#include <linux/ctype.h> ++#undef isalnum ++#define isalnum(c) (((__ismask(c)&(_U|_L|_D)) != 0) && (c > 0)) ++#undef isalpha ++#define isalpha(c) (((__ismask(c)&(_U|_L)) != 0) && (c > 0)) ++#undef iscntrl ++#define iscntrl(c) (((__ismask(c)&(_C)) != 0) && (c > 0)) ++#undef isdigit ++#define isdigit(c) (((__ismask(c)&(_D)) != 0) && (c > 0)) ++#undef isspace ++#define isspace(c) (((__ismask(c)&(_S)) != 0) && (c > 0)) +--- /dev/null ++++ b/extensions/LUA/lua/include/errno.h +@@ -0,0 +1 @@ ++#include <linux/errno.h> +--- /dev/null ++++ b/extensions/LUA/lua/include/locale.h +@@ -0,0 +1,5 @@ ++struct lconv { ++ char * decimal_point ; ++} ; ++ ++#define localeconv() NULL +--- /dev/null ++++ b/extensions/LUA/lua/include/setjmp.h +@@ -0,0 +1,26 @@ ++/* ++ * arch/um/include/sysdep-i386/archsetjmp.h ++ */ ++ ++#ifndef _KLIBC_ARCHSETJMP_H ++#define _KLIBC_ARCHSETJMP_H ++ ++struct __jmp_buf { ++ unsigned int __ebx; ++ unsigned int __esp; ++ unsigned int __ebp; ++ unsigned int __esi; ++ unsigned int __edi; ++ unsigned int __eip; ++}; ++ ++typedef struct __jmp_buf jmp_buf[1]; ++ ++#define JB_IP __eip ++#define JB_SP __esp ++ ++int setjmp(jmp_buf); ++void longjmp(jmp_buf, int); ++ ++#endif /* _SETJMP_H */ ++ +--- /dev/null ++++ b/extensions/LUA/lua/include/stdio.h +@@ -0,0 +1 @@ ++#include <linux/kernel.h> +--- /dev/null ++++ b/extensions/LUA/lua/include/stdlib.h +@@ -0,0 +1,7 @@ ++#include <linux/kernel.h> ++ ++#define exit(E) return ++#define strtoul simple_strtoul ++#define strcoll strcmp ++ ++#define CHAR_BIT 8 +--- /dev/null ++++ b/extensions/LUA/lua/include/string.h +@@ -0,0 +1 @@ ++#include <linux/string.h> +--- /dev/null ++++ b/extensions/LUA/lua/lapi.c +@@ -0,0 +1,1086 @@ ++/* ++** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ ++** Lua API ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdarg.h> ++#include <math.h> ++#include <assert.h> ++#include <string.h> ++ ++#define lapi_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lapi.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lundump.h" ++#include "lvm.h" ++ ++ ++ ++const char lua_ident[] = ++ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" ++ "$Authors: " LUA_AUTHORS " $\n" ++ "$URL: www.lua.org $\n"; ++ ++ ++ ++#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) ++ ++#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) ++ ++#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} ++ ++ ++ ++static TValue *index2adr (lua_State *L, int idx) { ++ if (idx > 0) { ++ TValue *o = L->base + (idx - 1); ++ api_check(L, idx <= L->ci->top - L->base); ++ if (o >= L->top) return cast(TValue *, luaO_nilobject); ++ else return o; ++ } ++ else if (idx > LUA_REGISTRYINDEX) { ++ api_check(L, idx != 0 && -idx <= L->top - L->base); ++ return L->top + idx; ++ } ++ else switch (idx) { /* pseudo-indices */ ++ case LUA_REGISTRYINDEX: return registry(L); ++ case LUA_ENVIRONINDEX: { ++ Closure *func = curr_func(L); ++ sethvalue(L, &L->env, func->c.env); ++ return &L->env; ++ } ++ case LUA_GLOBALSINDEX: return gt(L); ++ default: { ++ Closure *func = curr_func(L); ++ idx = LUA_GLOBALSINDEX - idx; ++ return (idx <= func->c.nupvalues) ++ ? &func->c.upvalue[idx-1] ++ : cast(TValue *, luaO_nilobject); ++ } ++ } ++} ++ ++ ++static Table *getcurrenv (lua_State *L) { ++ if (L->ci == L->base_ci) /* no enclosing function? */ ++ return hvalue(gt(L)); /* use global table as environment */ ++ else { ++ Closure *func = curr_func(L); ++ return func->c.env; ++ } ++} ++ ++ ++void luaA_pushobject (lua_State *L, const TValue *o) { ++ setobj2s(L, L->top, o); ++ api_incr_top(L); ++} ++ ++ ++LUA_API int lua_checkstack (lua_State *L, int size) { ++ int res = 1; ++ lua_lock(L); ++ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) ++ res = 0; /* stack overflow */ ++ else if (size > 0) { ++ luaD_checkstack(L, size); ++ if (L->ci->top < L->top + size) ++ L->ci->top = L->top + size; ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { ++ int i; ++ if (from == to) return; ++ lua_lock(to); ++ api_checknelems(from, n); ++ api_check(from, G(from) == G(to)); ++ api_check(from, to->ci->top - to->top >= n); ++ from->top -= n; ++ for (i = 0; i < n; i++) { ++ setobj2s(to, to->top++, from->top + i); ++ } ++ lua_unlock(to); ++} ++ ++ ++LUA_API void lua_setlevel (lua_State *from, lua_State *to) { ++ to->nCcalls = from->nCcalls; ++} ++ ++ ++LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { ++ lua_CFunction old; ++ lua_lock(L); ++ old = G(L)->panic; ++ G(L)->panic = panicf; ++ lua_unlock(L); ++ return old; ++} ++ ++ ++LUA_API lua_State *lua_newthread (lua_State *L) { ++ lua_State *L1; ++ lua_lock(L); ++ luaC_checkGC(L); ++ L1 = luaE_newthread(L); ++ setthvalue(L, L->top, L1); ++ api_incr_top(L); ++ lua_unlock(L); ++ luai_userstatethread(L, L1); ++ return L1; ++} ++ ++ ++ ++/* ++** basic stack manipulation ++*/ ++ ++ ++LUA_API int lua_gettop (lua_State *L) { ++ return cast_int(L->top - L->base); ++} ++ ++ ++LUA_API void lua_settop (lua_State *L, int idx) { ++ lua_lock(L); ++ if (idx >= 0) { ++ api_check(L, idx <= L->stack_last - L->base); ++ while (L->top < L->base + idx) ++ setnilvalue(L->top++); ++ L->top = L->base + idx; ++ } ++ else { ++ api_check(L, -(idx+1) <= (L->top - L->base)); ++ L->top += idx+1; /* `subtract' index (index is negative) */ ++ } ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_remove (lua_State *L, int idx) { ++ StkId p; ++ lua_lock(L); ++ p = index2adr(L, idx); ++ api_checkvalidindex(L, p); ++ while (++p < L->top) setobjs2s(L, p-1, p); ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_insert (lua_State *L, int idx) { ++ StkId p; ++ StkId q; ++ lua_lock(L); ++ p = index2adr(L, idx); ++ api_checkvalidindex(L, p); ++ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); ++ setobjs2s(L, p, L->top); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_replace (lua_State *L, int idx) { ++ StkId o; ++ lua_lock(L); ++ /* explicit test for incompatible code */ ++ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) ++ luaG_runerror(L, "no calling environment"); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ if (idx == LUA_ENVIRONINDEX) { ++ Closure *func = curr_func(L); ++ api_check(L, ttistable(L->top - 1)); ++ func->c.env = hvalue(L->top - 1); ++ luaC_barrier(L, func, L->top - 1); ++ } ++ else { ++ setobj(L, o, L->top - 1); ++ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ ++ luaC_barrier(L, curr_func(L), L->top - 1); ++ } ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushvalue (lua_State *L, int idx) { ++ lua_lock(L); ++ setobj2s(L, L->top, index2adr(L, idx)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++ ++/* ++** access functions (stack -> C) ++*/ ++ ++ ++LUA_API int lua_type (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); ++} ++ ++ ++LUA_API const char *lua_typename (lua_State *L, int t) { ++ UNUSED(L); ++ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; ++} ++ ++ ++LUA_API int lua_iscfunction (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return iscfunction(o); ++} ++ ++ ++LUA_API int lua_isnumber (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ return tonumber(o, &n); ++} ++ ++ ++LUA_API int lua_isstring (lua_State *L, int idx) { ++ int t = lua_type(L, idx); ++ return (t == LUA_TSTRING || t == LUA_TNUMBER); ++} ++ ++ ++LUA_API int lua_isuserdata (lua_State *L, int idx) { ++ const TValue *o = index2adr(L, idx); ++ return (ttisuserdata(o) || ttislightuserdata(o)); ++} ++ ++ ++LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { ++ StkId o1 = index2adr(L, index1); ++ StkId o2 = index2adr(L, index2); ++ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 ++ : luaO_rawequalObj(o1, o2); ++} ++ ++ ++LUA_API int lua_equal (lua_State *L, int index1, int index2) { ++ StkId o1, o2; ++ int i; ++ lua_lock(L); /* may call tag method */ ++ o1 = index2adr(L, index1); ++ o2 = index2adr(L, index2); ++ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); ++ lua_unlock(L); ++ return i; ++} ++ ++ ++LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { ++ StkId o1, o2; ++ int i; ++ lua_lock(L); /* may call tag method */ ++ o1 = index2adr(L, index1); ++ o2 = index2adr(L, index2); ++ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 ++ : luaV_lessthan(L, o1, o2); ++ lua_unlock(L); ++ return i; ++} ++ ++ ++ ++LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) ++ return nvalue(o); ++ else ++ return 0; ++} ++ ++ ++LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { ++ TValue n; ++ const TValue *o = index2adr(L, idx); ++ if (tonumber(o, &n)) { ++ lua_Integer res; ++ lua_Number num = nvalue(o); ++ lua_number2integer(res, num); ++ return res; ++ } ++ else ++ return 0; ++} ++ ++ ++LUA_API int lua_toboolean (lua_State *L, int idx) { ++ const TValue *o = index2adr(L, idx); ++ return !l_isfalse(o); ++} ++ ++ ++LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { ++ StkId o = index2adr(L, idx); ++ if (!ttisstring(o)) { ++ lua_lock(L); /* `luaV_tostring' may create a new string */ ++ if (!luaV_tostring(L, o)) { /* conversion failed? */ ++ if (len != NULL) *len = 0; ++ lua_unlock(L); ++ return NULL; ++ } ++ luaC_checkGC(L); ++ o = index2adr(L, idx); /* previous call may reallocate the stack */ ++ lua_unlock(L); ++ } ++ if (len != NULL) *len = tsvalue(o)->len; ++ return svalue(o); ++} ++ ++ ++LUA_API size_t lua_objlen (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TSTRING: return tsvalue(o)->len; ++ case LUA_TUSERDATA: return uvalue(o)->len; ++ case LUA_TTABLE: return luaH_getn(hvalue(o)); ++ case LUA_TNUMBER: { ++ size_t l; ++ lua_lock(L); /* `luaV_tostring' may create a new string */ ++ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); ++ lua_unlock(L); ++ return l; ++ } ++ default: return 0; ++ } ++} ++ ++ ++LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; ++} ++ ++ ++LUA_API void *lua_touserdata (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TUSERDATA: return (rawuvalue(o) + 1); ++ case LUA_TLIGHTUSERDATA: return pvalue(o); ++ default: return NULL; ++ } ++} ++ ++ ++LUA_API lua_State *lua_tothread (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ return (!ttisthread(o)) ? NULL : thvalue(o); ++} ++ ++ ++LUA_API const void *lua_topointer (lua_State *L, int idx) { ++ StkId o = index2adr(L, idx); ++ switch (ttype(o)) { ++ case LUA_TTABLE: return hvalue(o); ++ case LUA_TFUNCTION: return clvalue(o); ++ case LUA_TTHREAD: return thvalue(o); ++ case LUA_TUSERDATA: ++ case LUA_TLIGHTUSERDATA: ++ return lua_touserdata(L, idx); ++ default: return NULL; ++ } ++} ++ ++ ++ ++/* ++** push functions (C -> stack) ++*/ ++ ++ ++LUA_API void lua_pushnil (lua_State *L) { ++ lua_lock(L); ++ setnilvalue(L->top); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { ++ lua_lock(L); ++ setnvalue(L->top, n); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { ++ lua_lock(L); ++ setnvalue(L->top, cast_num(n)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { ++ lua_lock(L); ++ luaC_checkGC(L); ++ setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushstring (lua_State *L, const char *s) { ++ if (s == NULL) ++ lua_pushnil(L); ++ else ++ lua_pushlstring(L, s, strlen(s)); ++} ++ ++ ++LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, ++ va_list argp) { ++ const char *ret; ++ lua_lock(L); ++ luaC_checkGC(L); ++ ret = luaO_pushvfstring(L, fmt, argp); ++ lua_unlock(L); ++ return ret; ++} ++ ++ ++LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { ++ const char *ret; ++ va_list argp; ++ lua_lock(L); ++ luaC_checkGC(L); ++ va_start(argp, fmt); ++ ret = luaO_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ lua_unlock(L); ++ return ret; ++} ++ ++ ++LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { ++ Closure *cl; ++ lua_lock(L); ++ luaC_checkGC(L); ++ api_checknelems(L, n); ++ cl = luaF_newCclosure(L, n, getcurrenv(L)); ++ cl->c.f = fn; ++ L->top -= n; ++ while (n--) ++ setobj2n(L, &cl->c.upvalue[n], L->top+n); ++ setclvalue(L, L->top, cl); ++ lua_assert(iswhite(obj2gco(cl))); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushboolean (lua_State *L, int b) { ++ lua_lock(L); ++ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { ++ lua_lock(L); ++ setpvalue(L->top, p); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_pushthread (lua_State *L) { ++ lua_lock(L); ++ setthvalue(L, L->top, L); ++ api_incr_top(L); ++ lua_unlock(L); ++ return (G(L)->mainthread == L); ++} ++ ++ ++ ++/* ++** get functions (Lua -> stack) ++*/ ++ ++ ++LUA_API void lua_gettable (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ luaV_gettable(L, t, L->top - 1, L->top - 1); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { ++ StkId t; ++ TValue key; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ setsvalue(L, &key, luaS_new(L, k)); ++ luaV_gettable(L, t, &key, L->top); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawget (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { ++ StkId o; ++ lua_lock(L); ++ o = index2adr(L, idx); ++ api_check(L, ttistable(o)); ++ setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { ++ lua_lock(L); ++ luaC_checkGC(L); ++ sethvalue(L, L->top, luaH_new(L, narray, nrec)); ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_getmetatable (lua_State *L, int objindex) { ++ const TValue *obj; ++ Table *mt = NULL; ++ int res; ++ lua_lock(L); ++ obj = index2adr(L, objindex); ++ switch (ttype(obj)) { ++ case LUA_TTABLE: ++ mt = hvalue(obj)->metatable; ++ break; ++ case LUA_TUSERDATA: ++ mt = uvalue(obj)->metatable; ++ break; ++ default: ++ mt = G(L)->mt[ttype(obj)]; ++ break; ++ } ++ if (mt == NULL) ++ res = 0; ++ else { ++ sethvalue(L, L->top, mt); ++ api_incr_top(L); ++ res = 1; ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++LUA_API void lua_getfenv (lua_State *L, int idx) { ++ StkId o; ++ lua_lock(L); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ switch (ttype(o)) { ++ case LUA_TFUNCTION: ++ sethvalue(L, L->top, clvalue(o)->c.env); ++ break; ++ case LUA_TUSERDATA: ++ sethvalue(L, L->top, uvalue(o)->env); ++ break; ++ case LUA_TTHREAD: ++ setobj2s(L, L->top, gt(thvalue(o))); ++ break; ++ default: ++ setnilvalue(L->top); ++ break; ++ } ++ api_incr_top(L); ++ lua_unlock(L); ++} ++ ++ ++/* ++** set functions (stack -> Lua) ++*/ ++ ++ ++LUA_API void lua_settable (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ api_checknelems(L, 2); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ luaV_settable(L, t, L->top - 2, L->top - 1); ++ L->top -= 2; /* pop index and value */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { ++ StkId t; ++ TValue key; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ t = index2adr(L, idx); ++ api_checkvalidindex(L, t); ++ setsvalue(L, &key, luaS_new(L, k)); ++ luaV_settable(L, t, &key, L->top - 1); ++ L->top--; /* pop value */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawset (lua_State *L, int idx) { ++ StkId t; ++ lua_lock(L); ++ api_checknelems(L, 2); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); ++ luaC_barriert(L, hvalue(t), L->top-1); ++ L->top -= 2; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void lua_rawseti (lua_State *L, int idx, int n) { ++ StkId o; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_check(L, ttistable(o)); ++ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); ++ luaC_barriert(L, hvalue(o), L->top-1); ++ L->top--; ++ lua_unlock(L); ++} ++ ++ ++LUA_API int lua_setmetatable (lua_State *L, int objindex) { ++ TValue *obj; ++ Table *mt; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ obj = index2adr(L, objindex); ++ api_checkvalidindex(L, obj); ++ if (ttisnil(L->top - 1)) ++ mt = NULL; ++ else { ++ api_check(L, ttistable(L->top - 1)); ++ mt = hvalue(L->top - 1); ++ } ++ switch (ttype(obj)) { ++ case LUA_TTABLE: { ++ hvalue(obj)->metatable = mt; ++ if (mt) ++ luaC_objbarriert(L, hvalue(obj), mt); ++ break; ++ } ++ case LUA_TUSERDATA: { ++ uvalue(obj)->metatable = mt; ++ if (mt) ++ luaC_objbarrier(L, rawuvalue(obj), mt); ++ break; ++ } ++ default: { ++ G(L)->mt[ttype(obj)] = mt; ++ break; ++ } ++ } ++ L->top--; ++ lua_unlock(L); ++ return 1; ++} ++ ++ ++LUA_API int lua_setfenv (lua_State *L, int idx) { ++ StkId o; ++ int res = 1; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = index2adr(L, idx); ++ api_checkvalidindex(L, o); ++ api_check(L, ttistable(L->top - 1)); ++ switch (ttype(o)) { ++ case LUA_TFUNCTION: ++ clvalue(o)->c.env = hvalue(L->top - 1); ++ break; ++ case LUA_TUSERDATA: ++ uvalue(o)->env = hvalue(L->top - 1); ++ break; ++ case LUA_TTHREAD: ++ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); ++ break; ++ default: ++ res = 0; ++ break; ++ } ++ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); ++ L->top--; ++ lua_unlock(L); ++ return res; ++} ++ ++ ++/* ++** `load' and `call' functions (run Lua code) ++*/ ++ ++ ++#define adjustresults(L,nres) \ ++ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } ++ ++ ++#define checkresults(L,na,nr) \ ++ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) ++ ++ ++LUA_API void lua_call (lua_State *L, int nargs, int nresults) { ++ StkId func; ++ lua_lock(L); ++ api_checknelems(L, nargs+1); ++ checkresults(L, nargs, nresults); ++ func = L->top - (nargs+1); ++ luaD_call(L, func, nresults); ++ adjustresults(L, nresults); ++ lua_unlock(L); ++} ++ ++ ++ ++/* ++** Execute a protected call. ++*/ ++struct CallS { /* data to `f_call' */ ++ StkId func; ++ int nresults; ++}; ++ ++ ++static void f_call (lua_State *L, void *ud) { ++ struct CallS *c = cast(struct CallS *, ud); ++ luaD_call(L, c->func, c->nresults); ++} ++ ++ ++ ++LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { ++ struct CallS c; ++ int status; ++ ptrdiff_t func; ++ lua_lock(L); ++ api_checknelems(L, nargs+1); ++ checkresults(L, nargs, nresults); ++ if (errfunc == 0) ++ func = 0; ++ else { ++ StkId o = index2adr(L, errfunc); ++ api_checkvalidindex(L, o); ++ func = savestack(L, o); ++ } ++ c.func = L->top - (nargs+1); /* function to be called */ ++ c.nresults = nresults; ++ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); ++ adjustresults(L, nresults); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++/* ++** Execute a protected C call. ++*/ ++struct CCallS { /* data to `f_Ccall' */ ++ lua_CFunction func; ++ void *ud; ++}; ++ ++ ++static void f_Ccall (lua_State *L, void *ud) { ++ struct CCallS *c = cast(struct CCallS *, ud); ++ Closure *cl; ++ cl = luaF_newCclosure(L, 0, getcurrenv(L)); ++ cl->c.f = c->func; ++ setclvalue(L, L->top, cl); /* push function */ ++ api_incr_top(L); ++ setpvalue(L->top, c->ud); /* push only argument */ ++ api_incr_top(L); ++ luaD_call(L, L->top - 2, 0); ++} ++ ++ ++LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { ++ struct CCallS c; ++ int status; ++ lua_lock(L); ++ c.func = func; ++ c.ud = ud; ++ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, ++ const char *chunkname) { ++ ZIO z; ++ int status; ++ lua_lock(L); ++ if (!chunkname) chunkname = "?"; ++ luaZ_init(L, &z, reader, data); ++ status = luaD_protectedparser(L, &z, chunkname); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { ++ int status; ++ TValue *o; ++ lua_lock(L); ++ api_checknelems(L, 1); ++ o = L->top - 1; ++ if (isLfunction(o)) ++ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); ++ else ++ status = 1; ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_status (lua_State *L) { ++ return L->status; ++} ++ ++ ++/* ++** Garbage-collection function ++*/ ++ ++LUA_API int lua_gc (lua_State *L, int what, int data) { ++ int res = 0; ++ global_State *g; ++ lua_lock(L); ++ g = G(L); ++ switch (what) { ++ case LUA_GCSTOP: { ++ g->GCthreshold = MAX_LUMEM; ++ break; ++ } ++ case LUA_GCRESTART: { ++ g->GCthreshold = g->totalbytes; ++ break; ++ } ++ case LUA_GCCOLLECT: { ++ luaC_fullgc(L); ++ break; ++ } ++ case LUA_GCCOUNT: { ++ /* GC values are expressed in Kbytes: #bytes/2^10 */ ++ res = cast_int(g->totalbytes >> 10); ++ break; ++ } ++ case LUA_GCCOUNTB: { ++ res = cast_int(g->totalbytes & 0x3ff); ++ break; ++ } ++ case LUA_GCSTEP: { ++ lu_mem a = (cast(lu_mem, data) << 10); ++ if (a <= g->totalbytes) ++ g->GCthreshold = g->totalbytes - a; ++ else ++ g->GCthreshold = 0; ++ while (g->GCthreshold <= g->totalbytes) { ++ luaC_step(L); ++ if (g->gcstate == GCSpause) { /* end of cycle? */ ++ res = 1; /* signal it */ ++ break; ++ } ++ } ++ break; ++ } ++ case LUA_GCSETPAUSE: { ++ res = g->gcpause; ++ g->gcpause = data; ++ break; ++ } ++ case LUA_GCSETSTEPMUL: { ++ res = g->gcstepmul; ++ g->gcstepmul = data; ++ break; ++ } ++ default: res = -1; /* invalid option */ ++ } ++ lua_unlock(L); ++ return res; ++} ++ ++ ++ ++/* ++** miscellaneous functions ++*/ ++ ++ ++LUA_API int lua_error (lua_State *L) { ++ lua_lock(L); ++ api_checknelems(L, 1); ++ luaG_errormsg(L); ++ lua_unlock(L); ++ return 0; /* to avoid warnings */ ++} ++ ++ ++LUA_API int lua_next (lua_State *L, int idx) { ++ StkId t; ++ int more; ++ lua_lock(L); ++ t = index2adr(L, idx); ++ api_check(L, ttistable(t)); ++ more = luaH_next(L, hvalue(t), L->top - 1); ++ if (more) { ++ api_incr_top(L); ++ } ++ else /* no more elements */ ++ L->top -= 1; /* remove key */ ++ lua_unlock(L); ++ return more; ++} ++ ++ ++LUA_API void lua_concat (lua_State *L, int n) { ++ lua_lock(L); ++ api_checknelems(L, n); ++ if (n >= 2) { ++ luaC_checkGC(L); ++ luaV_concat(L, n, cast_int(L->top - L->base) - 1); ++ L->top -= (n-1); ++ } ++ else if (n == 0) { /* push empty string */ ++ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); ++ api_incr_top(L); ++ } ++ /* else n == 1; nothing to do */ ++ lua_unlock(L); ++} ++ ++ ++LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { ++ lua_Alloc f; ++ lua_lock(L); ++ if (ud) *ud = G(L)->ud; ++ f = G(L)->frealloc; ++ lua_unlock(L); ++ return f; ++} ++ ++ ++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { ++ lua_lock(L); ++ G(L)->ud = ud; ++ G(L)->frealloc = f; ++ lua_unlock(L); ++} ++ ++ ++LUA_API void *lua_newuserdata (lua_State *L, size_t size) { ++ Udata *u; ++ lua_lock(L); ++ luaC_checkGC(L); ++ u = luaS_newudata(L, size, getcurrenv(L)); ++ setuvalue(L, L->top, u); ++ api_incr_top(L); ++ lua_unlock(L); ++ return u + 1; ++} ++ ++ ++ ++ ++static const char *aux_upvalue (StkId fi, int n, TValue **val) { ++ Closure *f; ++ if (!ttisfunction(fi)) return NULL; ++ f = clvalue(fi); ++ if (f->c.isC) { ++ if (!(1 <= n && n <= f->c.nupvalues)) return NULL; ++ *val = &f->c.upvalue[n-1]; ++ return ""; ++ } ++ else { ++ Proto *p = f->l.p; ++ if (!(1 <= n && n <= p->sizeupvalues)) return NULL; ++ *val = f->l.upvals[n-1]->v; ++ return getstr(p->upvalues[n-1]); ++ } ++} ++ ++ ++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { ++ const char *name; ++ TValue *val; ++ lua_lock(L); ++ name = aux_upvalue(index2adr(L, funcindex), n, &val); ++ if (name) { ++ setobj2s(L, L->top, val); ++ api_incr_top(L); ++ } ++ lua_unlock(L); ++ return name; ++} ++ ++ ++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { ++ const char *name; ++ TValue *val; ++ StkId fi; ++ lua_lock(L); ++ fi = index2adr(L, funcindex); ++ api_checknelems(L, 1); ++ name = aux_upvalue(fi, n, &val); ++ if (name) { ++ L->top--; ++ setobj(L, val, L->top); ++ luaC_barrier(L, clvalue(fi), L->top); ++ } ++ lua_unlock(L); ++ return name; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lapi.h +@@ -0,0 +1,16 @@ ++/* ++** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions from Lua API ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lapi_h ++#define lapi_h ++ ++ ++#include "lobject.h" ++ ++ ++LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lauxlib.c +@@ -0,0 +1,674 @@ ++/* ++** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ ++** Auxiliary functions for building Lua libraries ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdarg.h> ++ ++#if !defined(__KERNEL__) ++#include <ctype.h> ++#include <errno.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#else ++#include <linux/ctype.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++#endif ++ ++/* This file uses only the official API of Lua. ++** Any function declared here could be written as an application function. ++*/ ++ ++#define lauxlib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++ ++ ++#define FREELIST_REF 0 /* free list of references */ ++ ++ ++/* convert a stack index to positive */ ++#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ ++ lua_gettop(L) + (i) + 1) ++ ++ ++/* ++** {====================================================== ++** Error-report functions ++** ======================================================= ++*/ ++ ++ ++LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { ++ lua_Debug ar; ++ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ ++ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); ++ lua_getinfo(L, "n", &ar); ++ if (strcmp(ar.namewhat, "method") == 0) { ++ narg--; /* do not count `self' */ ++ if (narg == 0) /* error is in the self argument itself? */ ++ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", ++ ar.name, extramsg); ++ } ++ if (ar.name == NULL) ++ ar.name = "?"; ++ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", ++ narg, ar.name, extramsg); ++} ++ ++ ++LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { ++ const char *msg = lua_pushfstring(L, "%s expected, got %s", ++ tname, luaL_typename(L, narg)); ++ return luaL_argerror(L, narg, msg); ++} ++ ++ ++static void tag_error (lua_State *L, int narg, int tag) { ++ luaL_typerror(L, narg, lua_typename(L, tag)); ++} ++ ++ ++LUALIB_API void luaL_where (lua_State *L, int level) { ++ lua_Debug ar; ++ if (lua_getstack(L, level, &ar)) { /* check function at level */ ++ lua_getinfo(L, "Sl", &ar); /* get info about it */ ++ if (ar.currentline > 0) { /* is there info? */ ++ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); ++ return; ++ } ++ } ++ lua_pushliteral(L, ""); /* else, no information available... */ ++} ++ ++ ++LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { ++ va_list argp; ++ va_start(argp, fmt); ++ luaL_where(L, 1); ++ lua_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ lua_concat(L, 2); ++ return lua_error(L); ++} ++ ++/* }====================================================== */ ++ ++ ++LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, ++ const char *const lst[]) { ++ const char *name = (def) ? luaL_optstring(L, narg, def) : ++ luaL_checkstring(L, narg); ++ int i; ++ for (i=0; lst[i]; i++) ++ if (strcmp(lst[i], name) == 0) ++ return i; ++ return luaL_argerror(L, narg, ++ lua_pushfstring(L, "invalid option " LUA_QS, name)); ++} ++ ++ ++LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ ++ if (!lua_isnil(L, -1)) /* name already in use? */ ++ return 0; /* leave previous value on top, but return 0 */ ++ lua_pop(L, 1); ++ lua_newtable(L); /* create metatable */ ++ lua_pushvalue(L, -1); ++ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ ++ return 1; ++} ++ ++ ++LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { ++ void *p = lua_touserdata(L, ud); ++ if (p != NULL) { /* value is a userdata? */ ++ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ ++ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ ++ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ ++ lua_pop(L, 2); /* remove both metatables */ ++ return p; ++ } ++ } ++ } ++ luaL_typerror(L, ud, tname); /* else error */ ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { ++ if (!lua_checkstack(L, space)) ++ luaL_error(L, "stack overflow (%s)", mes); ++} ++ ++ ++LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { ++ if (lua_type(L, narg) != t) ++ tag_error(L, narg, t); ++} ++ ++ ++LUALIB_API void luaL_checkany (lua_State *L, int narg) { ++ if (lua_type(L, narg) == LUA_TNONE) ++ luaL_argerror(L, narg, "value expected"); ++} ++ ++ ++LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { ++ const char *s = lua_tolstring(L, narg, len); ++ if (!s) tag_error(L, narg, LUA_TSTRING); ++ return s; ++} ++ ++ ++LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, ++ const char *def, size_t *len) { ++ if (lua_isnoneornil(L, narg)) { ++ if (len) ++ *len = (def ? strlen(def) : 0); ++ return def; ++ } ++ else return luaL_checklstring(L, narg, len); ++} ++ ++ ++LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { ++ lua_Number d = lua_tonumber(L, narg); ++ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return d; ++} ++ ++ ++LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { ++ return luaL_opt(L, luaL_checknumber, narg, def); ++} ++ ++ ++LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { ++ lua_Integer d = lua_tointeger(L, narg); ++ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ ++ tag_error(L, narg, LUA_TNUMBER); ++ return d; ++} ++ ++ ++LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, ++ lua_Integer def) { ++ return luaL_opt(L, luaL_checkinteger, narg, def); ++} ++ ++ ++LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { ++ if (!lua_getmetatable(L, obj)) /* no metatable? */ ++ return 0; ++ lua_pushstring(L, event); ++ lua_rawget(L, -2); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 2); /* remove metatable and metafield */ ++ return 0; ++ } ++ else { ++ lua_remove(L, -2); /* remove only metatable */ ++ return 1; ++ } ++} ++ ++ ++LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { ++ obj = abs_index(L, obj); ++ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ ++ return 0; ++ lua_pushvalue(L, obj); ++ lua_call(L, 1, 1); ++ return 1; ++} ++ ++ ++LUALIB_API void (luaL_register) (lua_State *L, const char *libname, ++ const luaL_Reg *l) { ++ luaI_openlib(L, libname, l, 0); ++} ++ ++ ++static int libsize (const luaL_Reg *l) { ++ int size = 0; ++ for (; l->name; l++) size++; ++ return size; ++} ++ ++ ++LUALIB_API void luaI_openlib (lua_State *L, const char *libname, ++ const luaL_Reg *l, int nup) { ++ if (libname) { ++ int size = libsize(l); ++ /* check whether lib already exists */ ++ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); ++ lua_getfield(L, -1, libname); /* get _LOADED[libname] */ ++ if (!lua_istable(L, -1)) { /* not found? */ ++ lua_pop(L, 1); /* remove previous result */ ++ /* try global variable (and create one if it does not exist) */ ++ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) ++ luaL_error(L, "name conflict for module " LUA_QS, libname); ++ lua_pushvalue(L, -1); ++ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ ++ } ++ lua_remove(L, -2); /* remove _LOADED table */ ++ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ ++ } ++ for (; l->name; l++) { ++ int i; ++ for (i=0; i<nup; i++) /* copy upvalues to the top */ ++ lua_pushvalue(L, -nup); ++ lua_pushcclosure(L, l->func, nup); ++ lua_setfield(L, -(nup+2), l->name); ++ } ++ lua_pop(L, nup); /* remove upvalues */ ++} ++ ++ ++ ++/* ++** {====================================================== ++** getn-setn: size for arrays ++** ======================================================= ++*/ ++ ++#if defined(LUA_COMPAT_GETN) ++ ++static int checkint (lua_State *L, int topop) { ++ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; ++ lua_pop(L, topop); ++ return n; ++} ++ ++ ++static void getsizes (lua_State *L) { ++ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); ++ if (lua_isnil(L, -1)) { /* no `size' table? */ ++ lua_pop(L, 1); /* remove nil */ ++ lua_newtable(L); /* create it */ ++ lua_pushvalue(L, -1); /* `size' will be its own metatable */ ++ lua_setmetatable(L, -2); ++ lua_pushliteral(L, "kv"); ++ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ ++ lua_pushvalue(L, -1); ++ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ ++ } ++} ++ ++ ++LUALIB_API void luaL_setn (lua_State *L, int t, int n) { ++ t = abs_index(L, t); ++ lua_pushliteral(L, "n"); ++ lua_rawget(L, t); ++ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ ++ lua_pushliteral(L, "n"); /* use it */ ++ lua_pushinteger(L, n); ++ lua_rawset(L, t); ++ } ++ else { /* use `sizes' */ ++ getsizes(L); ++ lua_pushvalue(L, t); ++ lua_pushinteger(L, n); ++ lua_rawset(L, -3); /* sizes[t] = n */ ++ lua_pop(L, 1); /* remove `sizes' */ ++ } ++} ++ ++ ++LUALIB_API int luaL_getn (lua_State *L, int t) { ++ int n; ++ t = abs_index(L, t); ++ lua_pushliteral(L, "n"); /* try t.n */ ++ lua_rawget(L, t); ++ if ((n = checkint(L, 1)) >= 0) return n; ++ getsizes(L); /* else try sizes[t] */ ++ lua_pushvalue(L, t); ++ lua_rawget(L, -2); ++ if ((n = checkint(L, 2)) >= 0) return n; ++ return (int)lua_objlen(L, t); ++} ++ ++#endif ++ ++/* }====================================================== */ ++ ++ ++ ++LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, ++ const char *r) { ++ const char *wild; ++ size_t l = strlen(p); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "luaL_gsub: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while ((wild = strstr(s, p)) != NULL) { ++ luaL_addlstring(b, s, wild - s); /* push prefix */ ++ luaL_addstring(b, r); /* push replacement in place of pattern */ ++ s = wild + l; /* continue after `p' */ ++ } ++ luaL_addstring(b, s); /* push last suffix */ ++ luaL_pushresult(b); ++ kfree(b); ++ return lua_tostring(L, -1); ++} ++ ++ ++LUALIB_API const char *luaL_findtable (lua_State *L, int idx, ++ const char *fname, int szhint) { ++ const char *e; ++ lua_pushvalue(L, idx); ++ do { ++ e = strchr(fname, '.'); ++ if (e == NULL) e = fname + strlen(fname); ++ lua_pushlstring(L, fname, e - fname); ++ lua_rawget(L, -2); ++ if (lua_isnil(L, -1)) { /* no such field? */ ++ lua_pop(L, 1); /* remove this nil */ ++ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ ++ lua_pushlstring(L, fname, e - fname); ++ lua_pushvalue(L, -2); ++ lua_settable(L, -4); /* set new table into field */ ++ } ++ else if (!lua_istable(L, -1)) { /* field has a non-table value? */ ++ lua_pop(L, 2); /* remove table and value */ ++ return fname; /* return problematic part of the name */ ++ } ++ lua_remove(L, -2); /* remove previous table */ ++ fname = e + 1; ++ } while (*e == '.'); ++ return NULL; ++} ++ ++ ++ ++/* ++** {====================================================== ++** Generic Buffer manipulation ++** ======================================================= ++*/ ++ ++ ++#define bufflen(B) ((B)->p - (B)->buffer) ++#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) ++ ++#define LIMIT (LUA_MINSTACK/2) ++ ++ ++static int emptybuffer (luaL_Buffer *B) { ++ size_t l = bufflen(B); ++ if (l == 0) return 0; /* put nothing on stack */ ++ else { ++ lua_pushlstring(B->L, B->buffer, l); ++ B->p = B->buffer; ++ B->lvl++; ++ return 1; ++ } ++} ++ ++ ++static void adjuststack (luaL_Buffer *B) { ++ if (B->lvl > 1) { ++ lua_State *L = B->L; ++ int toget = 1; /* number of levels to concat */ ++ size_t toplen = lua_strlen(L, -1); ++ do { ++ size_t l = lua_strlen(L, -(toget+1)); ++ if (B->lvl - toget + 1 >= LIMIT || toplen > l) { ++ toplen += l; ++ toget++; ++ } ++ else break; ++ } while (toget < B->lvl); ++ lua_concat(L, toget); ++ B->lvl = B->lvl - toget + 1; ++ } ++} ++ ++ ++LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { ++ if (emptybuffer(B)) ++ adjuststack(B); ++ return B->buffer; ++} ++ ++ ++LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { ++ while (l--) ++ luaL_addchar(B, *s++); ++} ++ ++ ++LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { ++ luaL_addlstring(B, s, strlen(s)); ++} ++ ++ ++LUALIB_API void luaL_pushresult (luaL_Buffer *B) { ++ emptybuffer(B); ++ lua_concat(B->L, B->lvl); ++ B->lvl = 1; ++} ++ ++ ++LUALIB_API void luaL_addvalue (luaL_Buffer *B) { ++ lua_State *L = B->L; ++ size_t vl; ++ const char *s = lua_tolstring(L, -1, &vl); ++ if (vl <= bufffree(B)) { /* fit into buffer? */ ++ memcpy(B->p, s, vl); /* put it there */ ++ B->p += vl; ++ lua_pop(L, 1); /* remove from stack */ ++ } ++ else { ++ if (emptybuffer(B)) ++ lua_insert(L, -2); /* put buffer before new value */ ++ B->lvl++; /* add new value into B stack */ ++ adjuststack(B); ++ } ++} ++ ++ ++LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { ++ B->L = L; ++ B->p = B->buffer; ++ B->lvl = 0; ++} ++ ++/* }====================================================== */ ++ ++ ++LUALIB_API int luaL_ref (lua_State *L, int t) { ++ int ref; ++ t = abs_index(L, t); ++ if (lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* remove from stack */ ++ return LUA_REFNIL; /* `nil' has a unique fixed reference */ ++ } ++ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ ++ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ ++ lua_pop(L, 1); /* remove it from stack */ ++ if (ref != 0) { /* any free element? */ ++ lua_rawgeti(L, t, ref); /* remove it from list */ ++ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ ++ } ++ else { /* no free elements */ ++ ref = (int)lua_objlen(L, t); ++ ref++; /* create new reference */ ++ } ++ lua_rawseti(L, t, ref); ++ return ref; ++} ++ ++ ++LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { ++ if (ref >= 0) { ++ t = abs_index(L, t); ++ lua_rawgeti(L, t, FREELIST_REF); ++ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ ++ lua_pushinteger(L, ref); ++ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ ++ } ++} ++ ++ ++ ++/* ++** {====================================================== ++** Load functions ++** ======================================================= ++*/ ++ ++#if !defined(__KERNEL__) ++typedef struct LoadF { ++ int extraline; ++ FILE *f; ++ char buff[LUAL_BUFFERSIZE]; ++} LoadF; ++ ++ ++static const char *getF (lua_State *L, void *ud, size_t *size) { ++ LoadF *lf = (LoadF *)ud; ++ (void)L; ++ if (lf->extraline) { ++ lf->extraline = 0; ++ *size = 1; ++ return "\n"; ++ } ++ if (feof(lf->f)) return NULL; ++ *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); ++ return (*size > 0) ? lf->buff : NULL; ++} ++ ++ ++static int errfile (lua_State *L, const char *what, int fnameindex) { ++ const char *serr = strerror(errno); ++ const char *filename = lua_tostring(L, fnameindex) + 1; ++ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); ++ lua_remove(L, fnameindex); ++ return LUA_ERRFILE; ++} ++ ++ ++LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { ++ LoadF lf; ++ int status, readstatus; ++ int c; ++ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ ++ lf.extraline = 0; ++ if (filename == NULL) { ++ lua_pushliteral(L, "=stdin"); ++ lf.f = stdin; ++ } ++ else { ++ lua_pushfstring(L, "@%s", filename); ++ lf.f = fopen(filename, "r"); ++ if (lf.f == NULL) return errfile(L, "open", fnameindex); ++ } ++ c = getc(lf.f); ++ if (c == '#') { /* Unix exec. file? */ ++ lf.extraline = 1; ++ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ ++ if (c == '\n') c = getc(lf.f); ++ } ++ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ ++ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ ++ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); ++ /* skip eventual `#!...' */ ++ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; ++ lf.extraline = 0; ++ } ++ ungetc(c, lf.f); ++ status = lua_load(L, getF, &lf, lua_tostring(L, -1)); ++ readstatus = ferror(lf.f); ++ if (filename) fclose(lf.f); /* close file (even in case of errors) */ ++ if (readstatus) { ++ lua_settop(L, fnameindex); /* ignore results from `lua_load' */ ++ return errfile(L, "read", fnameindex); ++ } ++ lua_remove(L, fnameindex); ++ return status; ++} ++#endif ++ ++typedef struct LoadS { ++ const char *s; ++ size_t size; ++} LoadS; ++ ++ ++static const char *getS (lua_State *L, void *ud, size_t *size) { ++ LoadS *ls = (LoadS *)ud; ++ (void)L; ++ if (ls->size == 0) return NULL; ++ *size = ls->size; ++ ls->size = 0; ++ return ls->s; ++} ++ ++ ++LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, ++ const char *name) { ++ LoadS ls; ++ ls.s = buff; ++ ls.size = size; ++ return lua_load(L, getS, &ls, name); ++} ++ ++ ++LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { ++ return luaL_loadbuffer(L, s, strlen(s), s); ++} ++ ++ ++ ++/* }====================================================== */ ++ ++ ++static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { ++ (void)ud; ++ (void)osize; ++ if (nsize == 0) { ++#if !defined(__KERNEL__) ++ free(ptr); ++#else ++ kfree(ptr); ++#endif ++ return NULL; ++ } ++ else ++#if !defined(__KERNEL__) ++ return realloc(ptr, nsize); ++#else ++ return krealloc(ptr, nsize, GFP_ATOMIC); ++#endif ++} ++ ++ ++static int lpanic (lua_State *L) { ++ (void)L; /* to avoid warnings */ ++#if !defined(__KERNEL__) ++ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", ++#else ++ printk( "PANIC: unprotected error in call to Lua API (%s)\n", ++#endif ++ lua_tostring(L, -1)); ++ return 0; ++} ++ ++ ++LUALIB_API lua_State *luaL_newstate (void) { ++ lua_State *L = lua_newstate(l_alloc, NULL); ++ if (L) lua_atpanic(L, &lpanic); ++ return L; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lauxlib.h +@@ -0,0 +1,184 @@ ++/* ++** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions for building Lua libraries ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lauxlib_h ++#define lauxlib_h ++ ++ ++#include <stddef.h> ++#include <linux/slab.h> /* for kmalloc and kfree when allocating luaL_Buffer */ ++ ++#if !defined(__KERNEL__) ++#include <stdio.h> ++#endif ++ ++#include "lua.h" ++ ++ ++#if defined(LUA_COMPAT_GETN) ++LUALIB_API int (luaL_getn) (lua_State *L, int t); ++LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); ++#else ++#define luaL_getn(L,i) ((int)lua_objlen(L, i)) ++#define luaL_setn(L,i,j) ((void)0) /* no op! */ ++#endif ++ ++#if defined(LUA_COMPAT_OPENLIB) ++#define luaI_openlib luaL_openlib ++#endif ++ ++ ++/* extra error code for `luaL_load' */ ++#define LUA_ERRFILE (LUA_ERRERR+1) ++ ++ ++typedef struct luaL_Reg { ++ const char *name; ++ lua_CFunction func; ++} luaL_Reg; ++ ++ ++ ++LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, ++ const luaL_Reg *l, int nup); ++LUALIB_API void (luaL_register) (lua_State *L, const char *libname, ++ const luaL_Reg *l); ++LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); ++LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); ++LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); ++LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); ++LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, ++ size_t *l); ++LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, ++ const char *def, size_t *l); ++LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); ++LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); ++ ++LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); ++LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, ++ lua_Integer def); ++ ++LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); ++LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); ++LUALIB_API void (luaL_checkany) (lua_State *L, int narg); ++ ++LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); ++LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); ++ ++LUALIB_API void (luaL_where) (lua_State *L, int lvl); ++LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); ++ ++LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, ++ const char *const lst[]); ++ ++LUALIB_API int (luaL_ref) (lua_State *L, int t); ++LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); ++ ++#if !defined(__KERNEL__) ++LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); ++#endif ++ ++LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, ++ const char *name); ++LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); ++ ++LUALIB_API lua_State *(luaL_newstate) (void); ++ ++ ++LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, ++ const char *r); ++ ++LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, ++ const char *fname, int szhint); ++ ++ ++ ++ ++/* ++** =============================================================== ++** some useful macros ++** =============================================================== ++*/ ++ ++#define luaL_argcheck(L, cond,numarg,extramsg) \ ++ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) ++#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) ++#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) ++#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) ++#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) ++#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) ++#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) ++ ++#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) ++ ++#if !defined(__KERNEL__) ++#define luaL_dofile(L, fn) \ ++ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) ++#endif ++ ++#define luaL_dostring(L, s) \ ++ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) ++ ++#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) ++ ++#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) ++ ++/* ++** {====================================================== ++** Generic Buffer manipulation ++** ======================================================= ++*/ ++ ++ ++ ++typedef struct luaL_Buffer { ++ char *p; /* current position in buffer */ ++ int lvl; /* number of strings in the stack (level) */ ++ lua_State *L; ++ char buffer[LUAL_BUFFERSIZE]; ++} luaL_Buffer; ++ ++#define luaL_addchar(B,c) \ ++ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ ++ (*(B)->p++ = (char)(c))) ++ ++/* compatibility only */ ++#define luaL_putchar(B,c) luaL_addchar(B,c) ++ ++#define luaL_addsize(B,n) ((B)->p += (n)) ++ ++ ++LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); ++LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); ++LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); ++LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); ++LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); ++LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); ++ ++ ++/* }====================================================== */ ++ ++ ++/* compatibility with ref system */ ++ ++/* pre-defined references */ ++#define LUA_NOREF (-2) ++#define LUA_REFNIL (-1) ++ ++#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ ++ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) ++ ++#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) ++ ++#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) ++ ++ ++#define luaL_reg luaL_Reg ++ ++#endif ++ ++ +--- /dev/null ++++ b/extensions/LUA/lua/lbaselib.c +@@ -0,0 +1,647 @@ ++/* ++** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ ++** Basic library ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <linux/kernel.h> ++#include <linux/ctype.h> ++#include <linux/string.h> ++ ++#define lbaselib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++ ++ ++/* ++** If your system does not support `stdout', you can just remove this function. ++** If you need, you can define your own `print' function, following this ++** model but changing `fputs' to put the strings at a proper place ++** (a console window or a log file, for instance). ++*/ ++static int luaB_print (lua_State *L) { ++ int n = lua_gettop(L); /* number of arguments */ ++ int i; ++ lua_getglobal(L, "tostring"); ++ for (i=1; i<=n; i++) { ++ const char *s; ++ lua_pushvalue(L, -1); /* function to be called */ ++ lua_pushvalue(L, i); /* value to print */ ++ lua_call(L, 1, 1); ++ s = lua_tostring(L, -1); /* get result */ ++ if (s == NULL) ++ return luaL_error(L, LUA_QL("tostring") " must return a string to " ++ LUA_QL("print")); ++ printk(KERN_INFO "LUA[print]: %s", s); ++ lua_pop(L, 1); /* pop result */ ++ } ++ return 0; ++} ++ ++ ++static int luaB_tonumber (lua_State *L) { ++ int base = luaL_optint(L, 2, 10); ++ if (base == 10) { /* standard conversion */ ++ luaL_checkany(L, 1); ++ if (lua_isnumber(L, 1)) { ++ lua_pushnumber(L, lua_tonumber(L, 1)); ++ return 1; ++ } ++ } ++ else { ++ const char *s1 = luaL_checkstring(L, 1); ++ char *s2; ++ unsigned long n; ++ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); ++ n = simple_strtoul(s1, &s2, base); ++ if (s1 != s2) { /* at least one valid digit? */ ++ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ ++ if (*s2 == '\0') { /* no invalid trailing characters? */ ++ lua_pushnumber(L, (lua_Number)n); ++ return 1; ++ } ++ } ++ } ++ lua_pushnil(L); /* else not a number */ ++ return 1; ++} ++ ++ ++static int luaB_error (lua_State *L) { ++ int level = luaL_optint(L, 2, 1); ++ lua_settop(L, 1); ++ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ ++ luaL_where(L, level); ++ lua_pushvalue(L, 1); ++ lua_concat(L, 2); ++ } ++ return lua_error(L); ++} ++ ++ ++static int luaB_getmetatable (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (!lua_getmetatable(L, 1)) { ++ lua_pushnil(L); ++ return 1; /* no metatable */ ++ } ++ luaL_getmetafield(L, 1, "__metatable"); ++ return 1; /* returns either __metatable field (if present) or metatable */ ++} ++ ++ ++static int luaB_setmetatable (lua_State *L) { ++ int t = lua_type(L, 2); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, ++ "nil or table expected"); ++ if (luaL_getmetafield(L, 1, "__metatable")) ++ luaL_error(L, "cannot change a protected metatable"); ++ lua_settop(L, 2); ++ lua_setmetatable(L, 1); ++ return 1; ++} ++ ++ ++static void getfunc (lua_State *L, int opt) { ++ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); ++ else { ++ lua_Debug ar; ++ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); ++ luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); ++ if (lua_getstack(L, level, &ar) == 0) ++ luaL_argerror(L, 1, "invalid level"); ++ lua_getinfo(L, "f", &ar); ++ if (lua_isnil(L, -1)) ++ luaL_error(L, "no function environment for tail call at level %d", ++ level); ++ } ++} ++ ++ ++static int luaB_getfenv (lua_State *L) { ++ getfunc(L, 1); ++ if (lua_iscfunction(L, -1)) /* is a C function? */ ++ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ ++ else ++ lua_getfenv(L, -1); ++ return 1; ++} ++ ++ ++static int luaB_setfenv (lua_State *L) { ++ luaL_checktype(L, 2, LUA_TTABLE); ++ getfunc(L, 0); ++ lua_pushvalue(L, 2); ++ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { ++ /* change environment of current thread */ ++ lua_pushthread(L); ++ lua_insert(L, -2); ++ lua_setfenv(L, -2); ++ return 0; ++ } ++ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) ++ luaL_error(L, ++ LUA_QL("setfenv") " cannot change environment of given object"); ++ return 1; ++} ++ ++ ++static int luaB_rawequal (lua_State *L) { ++ luaL_checkany(L, 1); ++ luaL_checkany(L, 2); ++ lua_pushboolean(L, lua_rawequal(L, 1, 2)); ++ return 1; ++} ++ ++ ++static int luaB_rawget (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checkany(L, 2); ++ lua_settop(L, 2); ++ lua_rawget(L, 1); ++ return 1; ++} ++ ++static int luaB_rawset (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checkany(L, 2); ++ luaL_checkany(L, 3); ++ lua_settop(L, 3); ++ lua_rawset(L, 1); ++ return 1; ++} ++ ++ ++static int luaB_gcinfo (lua_State *L) { ++ lua_pushinteger(L, lua_getgccount(L)); ++ return 1; ++} ++ ++static int luaB_collectgarbage (lua_State *L) { ++ static const char *const opts[] = {"stop", "restart", "collect", ++ "count", "step", "setpause", "setstepmul", NULL}; ++ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, ++ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; ++ int o = luaL_checkoption(L, 1, "collect", opts); ++ int ex = luaL_optint(L, 2, 0); ++ int res = lua_gc(L, optsnum[o], ex); ++ switch (optsnum[o]) { ++ case LUA_GCCOUNT: { ++ int b = lua_gc(L, LUA_GCCOUNTB, 0); ++ lua_pushnumber(L, res + ((lua_Number)b/1024)); ++ return 1; ++ } ++ case LUA_GCSTEP: { ++ lua_pushboolean(L, res); ++ return 1; ++ } ++ default: { ++ lua_pushnumber(L, res); ++ return 1; ++ } ++ } ++} ++ ++ ++static int luaB_type (lua_State *L) { ++ luaL_checkany(L, 1); ++ lua_pushstring(L, luaL_typename(L, 1)); ++ return 1; ++} ++ ++ ++static int luaB_next (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_settop(L, 2); /* create a 2nd argument if there isn't one */ ++ if (lua_next(L, 1)) ++ return 2; ++ else { ++ lua_pushnil(L); ++ return 1; ++ } ++} ++ ++ ++static int luaB_pairs (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ ++ lua_pushvalue(L, 1); /* state, */ ++ lua_pushnil(L); /* and initial value */ ++ return 3; ++} ++ ++ ++static int ipairsaux (lua_State *L) { ++ int i = luaL_checkint(L, 2); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i++; /* next value */ ++ lua_pushinteger(L, i); ++ lua_rawgeti(L, 1, i); ++ return (lua_isnil(L, -1)) ? 0 : 2; ++} ++ ++ ++static int luaB_ipairs (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ ++ lua_pushvalue(L, 1); /* state, */ ++ lua_pushinteger(L, 0); /* and initial value */ ++ return 3; ++} ++ ++ ++static int load_aux (lua_State *L, int status) { ++ if (status == 0) /* OK? */ ++ return 1; ++ else { ++ lua_pushnil(L); ++ lua_insert(L, -2); /* put before error message */ ++ return 2; /* return nil plus error message */ ++ } ++} ++ ++ ++static int luaB_loadstring (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ const char *chunkname = luaL_optstring(L, 2, s); ++ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); ++} ++ ++/* ++static int luaB_loadfile (lua_State *L) { ++ const char *fname = luaL_optstring(L, 1, NULL); ++ return load_aux(L, luaL_loadfile(L, fname)); ++} ++*/ ++ ++/* ++** Reader for generic `load' function: `lua_load' uses the ++** stack for internal stuff, so the reader cannot change the ++** stack top. Instead, it keeps its resulting string in a ++** reserved slot inside the stack. ++*/ ++static const char *generic_reader (lua_State *L, void *ud, size_t *size) { ++ (void)ud; /* to avoid warnings */ ++ luaL_checkstack(L, 2, "too many nested functions"); ++ lua_pushvalue(L, 1); /* get function */ ++ lua_call(L, 0, 1); /* call it */ ++ if (lua_isnil(L, -1)) { ++ *size = 0; ++ return NULL; ++ } ++ else if (lua_isstring(L, -1)) { ++ lua_replace(L, 3); /* save string in a reserved stack slot */ ++ return lua_tolstring(L, 3, size); ++ } ++ else luaL_error(L, "reader function must return a string"); ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++static int luaB_load (lua_State *L) { ++ int status; ++ const char *cname = luaL_optstring(L, 2, "=(load)"); ++ luaL_checktype(L, 1, LUA_TFUNCTION); ++ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ ++ status = lua_load(L, generic_reader, NULL, cname); ++ return load_aux(L, status); ++} ++ ++/* ++static int luaB_dofile (lua_State *L) { ++ const char *fname = luaL_optstring(L, 1, NULL); ++ int n = lua_gettop(L); ++ if (luaL_loadfile(L, fname) != 0) lua_error(L); ++ lua_call(L, 0, LUA_MULTRET); ++ return lua_gettop(L) - n; ++} ++*/ ++ ++static int luaB_assert (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (!lua_toboolean(L, 1)) ++ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); ++ return lua_gettop(L); ++} ++ ++ ++static int luaB_unpack (lua_State *L) { ++ int i, e, n; ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i = luaL_optint(L, 2, 1); ++ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); ++ if (i > e) return 0; /* empty range */ ++ n = e - i + 1; /* number of elements */ ++ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ ++ return luaL_error(L, "too many results to unpack"); ++ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ ++ while (i++ < e) /* push arg[i + 1...e] */ ++ lua_rawgeti(L, 1, i); ++ return n; ++} ++ ++ ++static int luaB_select (lua_State *L) { ++ int n = lua_gettop(L); ++ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { ++ lua_pushinteger(L, n-1); ++ return 1; ++ } ++ else { ++ int i = luaL_checkint(L, 1); ++ if (i < 0) i = n + i; ++ else if (i > n) i = n; ++ luaL_argcheck(L, 1 <= i, 1, "index out of range"); ++ return n - i; ++ } ++} ++ ++ ++static int luaB_pcall (lua_State *L) { ++ int status; ++ luaL_checkany(L, 1); ++ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); ++ lua_pushboolean(L, (status == 0)); ++ lua_insert(L, 1); ++ return lua_gettop(L); /* return status + all results */ ++} ++ ++ ++static int luaB_xpcall (lua_State *L) { ++ int status; ++ luaL_checkany(L, 2); ++ lua_settop(L, 2); ++ lua_insert(L, 1); /* put error function under function to be called */ ++ status = lua_pcall(L, 0, LUA_MULTRET, 1); ++ lua_pushboolean(L, (status == 0)); ++ lua_replace(L, 1); ++ return lua_gettop(L); /* return status + all results */ ++} ++ ++ ++static int luaB_tostring (lua_State *L) { ++ luaL_checkany(L, 1); ++ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ ++ return 1; /* use its value */ ++ switch (lua_type(L, 1)) { ++ case LUA_TNUMBER: ++ lua_pushstring(L, lua_tostring(L, 1)); ++ break; ++ case LUA_TSTRING: ++ lua_pushvalue(L, 1); ++ break; ++ case LUA_TBOOLEAN: ++ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); ++ break; ++ case LUA_TNIL: ++ lua_pushliteral(L, "nil"); ++ break; ++ default: ++ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); ++ break; ++ } ++ return 1; ++} ++ ++ ++static int luaB_newproxy (lua_State *L) { ++ lua_settop(L, 1); ++ lua_newuserdata(L, 0); /* create proxy */ ++ if (lua_toboolean(L, 1) == 0) ++ return 1; /* no metatable */ ++ else if (lua_isboolean(L, 1)) { ++ lua_newtable(L); /* create a new metatable `m' ... */ ++ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ ++ lua_pushboolean(L, 1); ++ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ ++ } ++ else { ++ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ ++ if (lua_getmetatable(L, 1)) { ++ lua_rawget(L, lua_upvalueindex(1)); ++ validproxy = lua_toboolean(L, -1); ++ lua_pop(L, 1); /* remove value */ ++ } ++ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); ++ lua_getmetatable(L, 1); /* metatable is valid; get it */ ++ } ++ lua_setmetatable(L, 2); ++ return 1; ++} ++ ++ ++static const luaL_Reg base_funcs[] = { ++ {"assert", luaB_assert}, ++ {"collectgarbage", luaB_collectgarbage}, ++// {"dofile", luaB_dofile}, ++ {"error", luaB_error}, ++ {"gcinfo", luaB_gcinfo}, ++ {"getfenv", luaB_getfenv}, ++ {"getmetatable", luaB_getmetatable}, ++// {"loadfile", luaB_loadfile}, ++ {"load", luaB_load}, ++ {"loadstring", luaB_loadstring}, ++ {"next", luaB_next}, ++ {"pcall", luaB_pcall}, ++ {"print", luaB_print}, ++ {"rawequal", luaB_rawequal}, ++ {"rawget", luaB_rawget}, ++ {"rawset", luaB_rawset}, ++ {"select", luaB_select}, ++ {"setfenv", luaB_setfenv}, ++ {"setmetatable", luaB_setmetatable}, ++ {"tonumber", luaB_tonumber}, ++ {"tostring", luaB_tostring}, ++ {"type", luaB_type}, ++ {"unpack", luaB_unpack}, ++ {"xpcall", luaB_xpcall}, ++ {NULL, NULL} ++}; ++ ++ ++/* ++** {====================================================== ++** Coroutine library ++** ======================================================= ++*/ ++ ++#define CO_RUN 0 /* running */ ++#define CO_SUS 1 /* suspended */ ++#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ ++#define CO_DEAD 3 ++ ++static const char *const statnames[] = ++ {"running", "suspended", "normal", "dead"}; ++ ++static int costatus (lua_State *L, lua_State *co) { ++ if (L == co) return CO_RUN; ++ switch (lua_status(co)) { ++ case LUA_YIELD: ++ return CO_SUS; ++ case 0: { ++ lua_Debug ar; ++ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ ++ return CO_NOR; /* it is running */ ++ else if (lua_gettop(co) == 0) ++ return CO_DEAD; ++ else ++ return CO_SUS; /* initial state */ ++ } ++ default: /* some error occured */ ++ return CO_DEAD; ++ } ++} ++ ++ ++static int luaB_costatus (lua_State *L) { ++ lua_State *co = lua_tothread(L, 1); ++ luaL_argcheck(L, co, 1, "coroutine expected"); ++ lua_pushstring(L, statnames[costatus(L, co)]); ++ return 1; ++} ++ ++ ++static int auxresume (lua_State *L, lua_State *co, int narg) { ++ int status = costatus(L, co); ++ if (!lua_checkstack(co, narg)) ++ luaL_error(L, "too many arguments to resume"); ++ if (status != CO_SUS) { ++ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); ++ return -1; /* error flag */ ++ } ++ lua_xmove(L, co, narg); ++ lua_setlevel(L, co); ++ status = lua_resume(co, narg); ++ if (status == 0 || status == LUA_YIELD) { ++ int nres = lua_gettop(co); ++ if (!lua_checkstack(L, nres + 1)) ++ luaL_error(L, "too many results to resume"); ++ lua_xmove(co, L, nres); /* move yielded values */ ++ return nres; ++ } ++ else { ++ lua_xmove(co, L, 1); /* move error message */ ++ return -1; /* error flag */ ++ } ++} ++ ++ ++static int luaB_coresume (lua_State *L) { ++ lua_State *co = lua_tothread(L, 1); ++ int r; ++ luaL_argcheck(L, co, 1, "coroutine expected"); ++ r = auxresume(L, co, lua_gettop(L) - 1); ++ if (r < 0) { ++ lua_pushboolean(L, 0); ++ lua_insert(L, -2); ++ return 2; /* return false + error message */ ++ } ++ else { ++ lua_pushboolean(L, 1); ++ lua_insert(L, -(r + 1)); ++ return r + 1; /* return true + `resume' returns */ ++ } ++} ++ ++ ++static int luaB_auxwrap (lua_State *L) { ++ lua_State *co = lua_tothread(L, lua_upvalueindex(1)); ++ int r = auxresume(L, co, lua_gettop(L)); ++ if (r < 0) { ++ if (lua_isstring(L, -1)) { /* error object is a string? */ ++ luaL_where(L, 1); /* add extra info */ ++ lua_insert(L, -2); ++ lua_concat(L, 2); ++ } ++ lua_error(L); /* propagate error */ ++ } ++ return r; ++} ++ ++ ++static int luaB_cocreate (lua_State *L) { ++ lua_State *NL = lua_newthread(L); ++ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, ++ "Lua function expected"); ++ lua_pushvalue(L, 1); /* move function to top */ ++ lua_xmove(L, NL, 1); /* move function from L to NL */ ++ return 1; ++} ++ ++ ++static int luaB_cowrap (lua_State *L) { ++ luaB_cocreate(L); ++ lua_pushcclosure(L, luaB_auxwrap, 1); ++ return 1; ++} ++ ++ ++static int luaB_yield (lua_State *L) { ++ return lua_yield(L, lua_gettop(L)); ++} ++ ++ ++static int luaB_corunning (lua_State *L) { ++ if (lua_pushthread(L)) ++ lua_pushnil(L); /* main thread is not a coroutine */ ++ return 1; ++} ++ ++ ++static const luaL_Reg co_funcs[] = { ++ {"create", luaB_cocreate}, ++ {"resume", luaB_coresume}, ++ {"running", luaB_corunning}, ++ {"status", luaB_costatus}, ++ {"wrap", luaB_cowrap}, ++ {"yield", luaB_yield}, ++ {NULL, NULL} ++}; ++ ++/* }====================================================== */ ++ ++ ++static void auxopen (lua_State *L, const char *name, ++ lua_CFunction f, lua_CFunction u) { ++ lua_pushcfunction(L, u); ++ lua_pushcclosure(L, f, 1); ++ lua_setfield(L, -2, name); ++} ++ ++ ++static void base_open (lua_State *L) { ++ /* set global _G */ ++ lua_pushvalue(L, LUA_GLOBALSINDEX); ++ lua_setglobal(L, "_G"); ++ /* open lib into global table */ ++ luaL_register(L, "_G", base_funcs); ++ lua_pushliteral(L, LUA_VERSION); ++ lua_setglobal(L, "_VERSION"); /* set global _VERSION */ ++ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ ++ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); ++ auxopen(L, "pairs", luaB_pairs, luaB_next); ++ /* `newproxy' needs a weaktable as upvalue */ ++ lua_createtable(L, 0, 1); /* new table `w' */ ++ lua_pushvalue(L, -1); /* `w' will be its own metatable */ ++ lua_setmetatable(L, -2); ++ lua_pushliteral(L, "kv"); ++ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ ++ lua_pushcclosure(L, luaB_newproxy, 1); ++ lua_setglobal(L, "newproxy"); /* set global `newproxy' */ ++} ++ ++ ++LUALIB_API int luaopen_base (lua_State *L) { ++ base_open(L); ++ luaL_register(L, LUA_COLIBNAME, co_funcs); ++ return 2; ++} +--- /dev/null ++++ b/extensions/LUA/lua/lcode.c +@@ -0,0 +1,838 @@ ++/* ++** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Code generator for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdlib.h> ++ ++#define lcode_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lgc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "ltable.h" ++ ++ ++#define hasjumps(e) ((e)->t != (e)->f) ++ ++ ++static int isnumeral(expdesc *e) { ++ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); ++} ++ ++ ++void luaK_nil (FuncState *fs, int from, int n) { ++ Instruction *previous; ++ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ ++ if (fs->pc == 0) { /* function start? */ ++ if (from >= fs->nactvar) ++ return; /* positions are already clean */ ++ } ++ else { ++ previous = &fs->f->code[fs->pc-1]; ++ if (GET_OPCODE(*previous) == OP_LOADNIL) { ++ int pfrom = GETARG_A(*previous); ++ int pto = GETARG_B(*previous); ++ if (pfrom <= from && from <= pto+1) { /* can connect both? */ ++ if (from+n-1 > pto) ++ SETARG_B(*previous, from+n-1); ++ return; ++ } ++ } ++ } ++ } ++ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ ++} ++ ++ ++int luaK_jump (FuncState *fs) { ++ int jpc = fs->jpc; /* save list of jumps to here */ ++ int j; ++ fs->jpc = NO_JUMP; ++ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); ++ luaK_concat(fs, &j, jpc); /* keep them on hold */ ++ return j; ++} ++ ++ ++void luaK_ret (FuncState *fs, int first, int nret) { ++ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); ++} ++ ++ ++static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { ++ luaK_codeABC(fs, op, A, B, C); ++ return luaK_jump(fs); ++} ++ ++ ++static void fixjump (FuncState *fs, int pc, int dest) { ++ Instruction *jmp = &fs->f->code[pc]; ++ int offset = dest-(pc+1); ++ lua_assert(dest != NO_JUMP); ++ if (abs(offset) > MAXARG_sBx) ++ luaX_syntaxerror(fs->ls, "control structure too long"); ++ SETARG_sBx(*jmp, offset); ++} ++ ++ ++/* ++** returns current `pc' and marks it as a jump target (to avoid wrong ++** optimizations with consecutive instructions not in the same basic block). ++*/ ++int luaK_getlabel (FuncState *fs) { ++ fs->lasttarget = fs->pc; ++ return fs->pc; ++} ++ ++ ++static int getjump (FuncState *fs, int pc) { ++ int offset = GETARG_sBx(fs->f->code[pc]); ++ if (offset == NO_JUMP) /* point to itself represents end of list */ ++ return NO_JUMP; /* end of list */ ++ else ++ return (pc+1)+offset; /* turn offset into absolute position */ ++} ++ ++ ++static Instruction *getjumpcontrol (FuncState *fs, int pc) { ++ Instruction *pi = &fs->f->code[pc]; ++ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) ++ return pi-1; ++ else ++ return pi; ++} ++ ++ ++/* ++** check whether list has any jump that do not produce a value ++** (or produce an inverted value) ++*/ ++static int need_value (FuncState *fs, int list) { ++ for (; list != NO_JUMP; list = getjump(fs, list)) { ++ Instruction i = *getjumpcontrol(fs, list); ++ if (GET_OPCODE(i) != OP_TESTSET) return 1; ++ } ++ return 0; /* not found */ ++} ++ ++ ++static int patchtestreg (FuncState *fs, int node, int reg) { ++ Instruction *i = getjumpcontrol(fs, node); ++ if (GET_OPCODE(*i) != OP_TESTSET) ++ return 0; /* cannot patch other instructions */ ++ if (reg != NO_REG && reg != GETARG_B(*i)) ++ SETARG_A(*i, reg); ++ else /* no register to put value or register already has the value */ ++ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); ++ ++ return 1; ++} ++ ++ ++static void removevalues (FuncState *fs, int list) { ++ for (; list != NO_JUMP; list = getjump(fs, list)) ++ patchtestreg(fs, list, NO_REG); ++} ++ ++ ++static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, ++ int dtarget) { ++ while (list != NO_JUMP) { ++ int next = getjump(fs, list); ++ if (patchtestreg(fs, list, reg)) ++ fixjump(fs, list, vtarget); ++ else ++ fixjump(fs, list, dtarget); /* jump to default target */ ++ list = next; ++ } ++} ++ ++ ++static void dischargejpc (FuncState *fs) { ++ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); ++ fs->jpc = NO_JUMP; ++} ++ ++ ++void luaK_patchlist (FuncState *fs, int list, int target) { ++ if (target == fs->pc) ++ luaK_patchtohere(fs, list); ++ else { ++ lua_assert(target < fs->pc); ++ patchlistaux(fs, list, target, NO_REG, target); ++ } ++} ++ ++ ++void luaK_patchtohere (FuncState *fs, int list) { ++ luaK_getlabel(fs); ++ luaK_concat(fs, &fs->jpc, list); ++} ++ ++ ++void luaK_concat (FuncState *fs, int *l1, int l2) { ++ if (l2 == NO_JUMP) return; ++ else if (*l1 == NO_JUMP) ++ *l1 = l2; ++ else { ++ int list = *l1; ++ int next; ++ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ ++ list = next; ++ fixjump(fs, list, l2); ++ } ++} ++ ++ ++void luaK_checkstack (FuncState *fs, int n) { ++ int newstack = fs->freereg + n; ++ if (newstack > fs->f->maxstacksize) { ++ if (newstack >= MAXSTACK) ++ luaX_syntaxerror(fs->ls, "function or expression too complex"); ++ fs->f->maxstacksize = cast_byte(newstack); ++ } ++} ++ ++ ++void luaK_reserveregs (FuncState *fs, int n) { ++ luaK_checkstack(fs, n); ++ fs->freereg += n; ++} ++ ++ ++static void freereg (FuncState *fs, int reg) { ++ if (!ISK(reg) && reg >= fs->nactvar) { ++ fs->freereg--; ++ lua_assert(reg == fs->freereg); ++ } ++} ++ ++ ++static void freeexp (FuncState *fs, expdesc *e) { ++ if (e->k == VNONRELOC) ++ freereg(fs, e->u.s.info); ++} ++ ++ ++static int addk (FuncState *fs, TValue *k, TValue *v) { ++ lua_State *L = fs->L; ++ TValue *idx = luaH_set(L, fs->h, k); ++ Proto *f = fs->f; ++ int oldsize = f->sizek; ++ if (ttisnumber(idx)) { ++ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); ++ return cast_int(nvalue(idx)); ++ } ++ else { /* constant not found; create a new entry */ ++ setnvalue(idx, cast_num(fs->nk)); ++ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, ++ MAXARG_Bx, "constant table overflow"); ++ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); ++ setobj(L, &f->k[fs->nk], v); ++ luaC_barrier(L, f, v); ++ return fs->nk++; ++ } ++} ++ ++ ++int luaK_stringK (FuncState *fs, TString *s) { ++ TValue o; ++ setsvalue(fs->L, &o, s); ++ return addk(fs, &o, &o); ++} ++ ++ ++int luaK_numberK (FuncState *fs, lua_Number r) { ++ TValue o; ++ setnvalue(&o, r); ++ return addk(fs, &o, &o); ++} ++ ++ ++static int boolK (FuncState *fs, int b) { ++ TValue o; ++ setbvalue(&o, b); ++ return addk(fs, &o, &o); ++} ++ ++ ++static int nilK (FuncState *fs) { ++ TValue k, v; ++ setnilvalue(&v); ++ /* cannot use nil as key; instead use table itself to represent nil */ ++ sethvalue(fs->L, &k, fs->h); ++ return addk(fs, &k, &v); ++} ++ ++ ++void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { ++ if (e->k == VCALL) { /* expression is an open function call? */ ++ SETARG_C(getcode(fs, e), nresults+1); ++ } ++ else if (e->k == VVARARG) { ++ SETARG_B(getcode(fs, e), nresults+1); ++ SETARG_A(getcode(fs, e), fs->freereg); ++ luaK_reserveregs(fs, 1); ++ } ++} ++ ++ ++void luaK_setoneret (FuncState *fs, expdesc *e) { ++ if (e->k == VCALL) { /* expression is an open function call? */ ++ e->k = VNONRELOC; ++ e->u.s.info = GETARG_A(getcode(fs, e)); ++ } ++ else if (e->k == VVARARG) { ++ SETARG_B(getcode(fs, e), 2); ++ e->k = VRELOCABLE; /* can relocate its simple result */ ++ } ++} ++ ++ ++void luaK_dischargevars (FuncState *fs, expdesc *e) { ++ switch (e->k) { ++ case VLOCAL: { ++ e->k = VNONRELOC; ++ break; ++ } ++ case VUPVAL: { ++ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VGLOBAL: { ++ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VINDEXED: { ++ freereg(fs, e->u.s.aux); ++ freereg(fs, e->u.s.info); ++ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); ++ e->k = VRELOCABLE; ++ break; ++ } ++ case VVARARG: ++ case VCALL: { ++ luaK_setoneret(fs, e); ++ break; ++ } ++ default: break; /* there is one value available (somewhere) */ ++ } ++} ++ ++ ++static int code_label (FuncState *fs, int A, int b, int jump) { ++ luaK_getlabel(fs); /* those instructions may be jump targets */ ++ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); ++} ++ ++ ++static void discharge2reg (FuncState *fs, expdesc *e, int reg) { ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: { ++ luaK_nil(fs, reg, 1); ++ break; ++ } ++ case VFALSE: case VTRUE: { ++ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); ++ break; ++ } ++ case VK: { ++ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); ++ break; ++ } ++ case VKNUM: { ++ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); ++ break; ++ } ++ case VRELOCABLE: { ++ Instruction *pc = &getcode(fs, e); ++ SETARG_A(*pc, reg); ++ break; ++ } ++ case VNONRELOC: { ++ if (reg != e->u.s.info) ++ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); ++ break; ++ } ++ default: { ++ lua_assert(e->k == VVOID || e->k == VJMP); ++ return; /* nothing to do... */ ++ } ++ } ++ e->u.s.info = reg; ++ e->k = VNONRELOC; ++} ++ ++ ++static void discharge2anyreg (FuncState *fs, expdesc *e) { ++ if (e->k != VNONRELOC) { ++ luaK_reserveregs(fs, 1); ++ discharge2reg(fs, e, fs->freereg-1); ++ } ++} ++ ++ ++static void exp2reg (FuncState *fs, expdesc *e, int reg) { ++ discharge2reg(fs, e, reg); ++ if (e->k == VJMP) ++ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ ++ if (hasjumps(e)) { ++ int final; /* position after whole expression */ ++ int p_f = NO_JUMP; /* position of an eventual LOAD false */ ++ int p_t = NO_JUMP; /* position of an eventual LOAD true */ ++ if (need_value(fs, e->t) || need_value(fs, e->f)) { ++ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); ++ p_f = code_label(fs, reg, 0, 1); ++ p_t = code_label(fs, reg, 1, 0); ++ luaK_patchtohere(fs, fj); ++ } ++ final = luaK_getlabel(fs); ++ patchlistaux(fs, e->f, final, reg, p_f); ++ patchlistaux(fs, e->t, final, reg, p_t); ++ } ++ e->f = e->t = NO_JUMP; ++ e->u.s.info = reg; ++ e->k = VNONRELOC; ++} ++ ++ ++void luaK_exp2nextreg (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ freeexp(fs, e); ++ luaK_reserveregs(fs, 1); ++ exp2reg(fs, e, fs->freereg - 1); ++} ++ ++ ++int luaK_exp2anyreg (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ if (e->k == VNONRELOC) { ++ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ ++ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ ++ exp2reg(fs, e, e->u.s.info); /* put value on it */ ++ return e->u.s.info; ++ } ++ } ++ luaK_exp2nextreg(fs, e); /* default */ ++ return e->u.s.info; ++} ++ ++ ++void luaK_exp2val (FuncState *fs, expdesc *e) { ++ if (hasjumps(e)) ++ luaK_exp2anyreg(fs, e); ++ else ++ luaK_dischargevars(fs, e); ++} ++ ++ ++int luaK_exp2RK (FuncState *fs, expdesc *e) { ++ luaK_exp2val(fs, e); ++ switch (e->k) { ++ case VKNUM: ++ case VTRUE: ++ case VFALSE: ++ case VNIL: { ++ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ ++ e->u.s.info = (e->k == VNIL) ? nilK(fs) : ++ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : ++ boolK(fs, (e->k == VTRUE)); ++ e->k = VK; ++ return RKASK(e->u.s.info); ++ } ++ else break; ++ } ++ case VK: { ++ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ ++ return RKASK(e->u.s.info); ++ else break; ++ } ++ default: break; ++ } ++ /* not a constant in the right range: put it in a register */ ++ return luaK_exp2anyreg(fs, e); ++} ++ ++ ++void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { ++ switch (var->k) { ++ case VLOCAL: { ++ freeexp(fs, ex); ++ exp2reg(fs, ex, var->u.s.info); ++ return; ++ } ++ case VUPVAL: { ++ int e = luaK_exp2anyreg(fs, ex); ++ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); ++ break; ++ } ++ case VGLOBAL: { ++ int e = luaK_exp2anyreg(fs, ex); ++ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); ++ break; ++ } ++ case VINDEXED: { ++ int e = luaK_exp2RK(fs, ex); ++ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); ++ break; ++ } ++ default: { ++ lua_assert(0); /* invalid var kind to store */ ++ break; ++ } ++ } ++ freeexp(fs, ex); ++} ++ ++ ++void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { ++ int func; ++ luaK_exp2anyreg(fs, e); ++ freeexp(fs, e); ++ func = fs->freereg; ++ luaK_reserveregs(fs, 2); ++ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); ++ freeexp(fs, key); ++ e->u.s.info = func; ++ e->k = VNONRELOC; ++} ++ ++ ++static void invertjump (FuncState *fs, expdesc *e) { ++ Instruction *pc = getjumpcontrol(fs, e->u.s.info); ++ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && ++ GET_OPCODE(*pc) != OP_TEST); ++ SETARG_A(*pc, !(GETARG_A(*pc))); ++} ++ ++ ++static int jumponcond (FuncState *fs, expdesc *e, int cond) { ++ if (e->k == VRELOCABLE) { ++ Instruction ie = getcode(fs, e); ++ if (GET_OPCODE(ie) == OP_NOT) { ++ fs->pc--; /* remove previous OP_NOT */ ++ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); ++ } ++ /* else go through */ ++ } ++ discharge2anyreg(fs, e); ++ freeexp(fs, e); ++ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); ++} ++ ++ ++void luaK_goiftrue (FuncState *fs, expdesc *e) { ++ int pc; /* pc of last jump */ ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VK: case VKNUM: case VTRUE: { ++ pc = NO_JUMP; /* always true; do nothing */ ++ break; ++ } ++ case VFALSE: { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ case VJMP: { ++ invertjump(fs, e); ++ pc = e->u.s.info; ++ break; ++ } ++ default: { ++ pc = jumponcond(fs, e, 0); ++ break; ++ } ++ } ++ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ ++ luaK_patchtohere(fs, e->t); ++ e->t = NO_JUMP; ++} ++ ++ ++static void luaK_goiffalse (FuncState *fs, expdesc *e) { ++ int pc; /* pc of last jump */ ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: case VFALSE: { ++ pc = NO_JUMP; /* always false; do nothing */ ++ break; ++ } ++ case VTRUE: { ++ pc = luaK_jump(fs); /* always jump */ ++ break; ++ } ++ case VJMP: { ++ pc = e->u.s.info; ++ break; ++ } ++ default: { ++ pc = jumponcond(fs, e, 1); ++ break; ++ } ++ } ++ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ ++ luaK_patchtohere(fs, e->f); ++ e->f = NO_JUMP; ++} ++ ++ ++static void codenot (FuncState *fs, expdesc *e) { ++ luaK_dischargevars(fs, e); ++ switch (e->k) { ++ case VNIL: case VFALSE: { ++ e->k = VTRUE; ++ break; ++ } ++ case VK: case VKNUM: case VTRUE: { ++ e->k = VFALSE; ++ break; ++ } ++ case VJMP: { ++ invertjump(fs, e); ++ break; ++ } ++ case VRELOCABLE: ++ case VNONRELOC: { ++ discharge2anyreg(fs, e); ++ freeexp(fs, e); ++ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); ++ e->k = VRELOCABLE; ++ break; ++ } ++ default: { ++ lua_assert(0); /* cannot happen */ ++ break; ++ } ++ } ++ /* interchange true and false lists */ ++ { int temp = e->f; e->f = e->t; e->t = temp; } ++ removevalues(fs, e->f); ++ removevalues(fs, e->t); ++} ++ ++ ++void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { ++ t->u.s.aux = luaK_exp2RK(fs, k); ++ t->k = VINDEXED; ++} ++ ++ ++static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { ++ lua_Number v1, v2, r; ++ if (!isnumeral(e1) || !isnumeral(e2)) return 0; ++ v1 = e1->u.nval; ++ v2 = e2->u.nval; ++ switch (op) { ++ case OP_ADD: r = luai_numadd(v1, v2); break; ++ case OP_SUB: r = luai_numsub(v1, v2); break; ++ case OP_MUL: r = luai_nummul(v1, v2); break; ++ case OP_DIV: ++ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++ r = luai_numdiv(v1, v2); break; ++ case OP_MOD: ++ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ ++ r = luai_nummod(v1, v2); break; ++ case OP_POW: r = luai_numpow(v1, v2); break; ++ case OP_UNM: r = luai_numunm(v1); break; ++ case OP_LEN: return 0; /* no constant folding for 'len' */ ++ default: lua_assert(0); r = 0; break; ++ } ++ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ ++ e1->u.nval = r; ++ return 1; ++} ++ ++ ++static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { ++ if (constfolding(op, e1, e2)) ++ return; ++ else { ++ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; ++ int o1 = luaK_exp2RK(fs, e1); ++ if (o1 > o2) { ++ freeexp(fs, e1); ++ freeexp(fs, e2); ++ } ++ else { ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ } ++ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); ++ e1->k = VRELOCABLE; ++ } ++} ++ ++ ++static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, ++ expdesc *e2) { ++ int o1 = luaK_exp2RK(fs, e1); ++ int o2 = luaK_exp2RK(fs, e2); ++ freeexp(fs, e2); ++ freeexp(fs, e1); ++ if (cond == 0 && op != OP_EQ) { ++ int temp; /* exchange args to replace by `<' or `<=' */ ++ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ ++ cond = 1; ++ } ++ e1->u.s.info = condjump(fs, op, cond, o1, o2); ++ e1->k = VJMP; ++} ++ ++ ++void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { ++ expdesc e2; ++ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; ++ switch (op) { ++ case OPR_MINUS: { ++ if (!isnumeral(e)) ++ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ ++ codearith(fs, OP_UNM, e, &e2); ++ break; ++ } ++ case OPR_NOT: codenot(fs, e); break; ++ case OPR_LEN: { ++ luaK_exp2anyreg(fs, e); /* cannot operate on constants */ ++ codearith(fs, OP_LEN, e, &e2); ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { ++ switch (op) { ++ case OPR_AND: { ++ luaK_goiftrue(fs, v); ++ break; ++ } ++ case OPR_OR: { ++ luaK_goiffalse(fs, v); ++ break; ++ } ++ case OPR_CONCAT: { ++ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ ++ break; ++ } ++ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: ++ case OPR_MOD: case OPR_POW: { ++ if (!isnumeral(v)) luaK_exp2RK(fs, v); ++ break; ++ } ++ default: { ++ luaK_exp2RK(fs, v); ++ break; ++ } ++ } ++} ++ ++ ++void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { ++ switch (op) { ++ case OPR_AND: { ++ lua_assert(e1->t == NO_JUMP); /* list must be closed */ ++ luaK_dischargevars(fs, e2); ++ luaK_concat(fs, &e2->f, e1->f); ++ *e1 = *e2; ++ break; ++ } ++ case OPR_OR: { ++ lua_assert(e1->f == NO_JUMP); /* list must be closed */ ++ luaK_dischargevars(fs, e2); ++ luaK_concat(fs, &e2->t, e1->t); ++ *e1 = *e2; ++ break; ++ } ++ case OPR_CONCAT: { ++ luaK_exp2val(fs, e2); ++ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { ++ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); ++ freeexp(fs, e1); ++ SETARG_B(getcode(fs, e2), e1->u.s.info); ++ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; ++ } ++ else { ++ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ ++ codearith(fs, OP_CONCAT, e1, e2); ++ } ++ break; ++ } ++ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; ++ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; ++ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; ++ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; ++ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; ++ case OPR_POW: codearith(fs, OP_POW, e1, e2); break; ++ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; ++ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; ++ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; ++ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; ++ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; ++ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; ++ default: lua_assert(0); ++ } ++} ++ ++ ++void luaK_fixline (FuncState *fs, int line) { ++ fs->f->lineinfo[fs->pc - 1] = line; ++} ++ ++ ++static int luaK_code (FuncState *fs, Instruction i, int line) { ++ Proto *f = fs->f; ++ dischargejpc(fs); /* `pc' will change */ ++ /* put new instruction in code array */ ++ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, ++ MAX_INT, "code size overflow"); ++ f->code[fs->pc] = i; ++ /* save corresponding line information */ ++ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, ++ MAX_INT, "code size overflow"); ++ f->lineinfo[fs->pc] = line; ++ return fs->pc++; ++} ++ ++ ++int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { ++ lua_assert(getOpMode(o) == iABC); ++ lua_assert(getBMode(o) != OpArgN || b == 0); ++ lua_assert(getCMode(o) != OpArgN || c == 0); ++ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); ++} ++ ++ ++int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { ++ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); ++ lua_assert(getCMode(o) == OpArgN); ++ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); ++} ++ ++ ++void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { ++ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; ++ int b = (tostore == LUA_MULTRET) ? 0 : tostore; ++ lua_assert(tostore != 0); ++ if (c <= MAXARG_C) ++ luaK_codeABC(fs, OP_SETLIST, base, b, c); ++ else { ++ luaK_codeABC(fs, OP_SETLIST, base, b, 0); ++ luaK_code(fs, cast(Instruction, c), fs->ls->lastline); ++ } ++ fs->freereg = base + 1; /* free registers with list values */ ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lcode.h +@@ -0,0 +1,76 @@ ++/* ++** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Code generator for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lcode_h ++#define lcode_h ++ ++#include "llex.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++ ++ ++/* ++** Marks the end of a patch list. It is an invalid value both as an absolute ++** address, and as a list link (would link an element to itself). ++*/ ++#define NO_JUMP (-1) ++ ++ ++/* ++** grep "ORDER OPR" if you change these enums ++*/ ++typedef enum BinOpr { ++ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, ++ OPR_CONCAT, ++ OPR_NE, OPR_EQ, ++ OPR_LT, OPR_LE, OPR_GT, OPR_GE, ++ OPR_AND, OPR_OR, ++ OPR_NOBINOPR ++} BinOpr; ++ ++ ++typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; ++ ++ ++#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) ++ ++#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) ++ ++#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) ++ ++LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); ++LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); ++LUAI_FUNC void luaK_fixline (FuncState *fs, int line); ++LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); ++LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); ++LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); ++LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); ++LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); ++LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); ++LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); ++LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); ++LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); ++LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); ++LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); ++LUAI_FUNC int luaK_jump (FuncState *fs); ++LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); ++LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); ++LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); ++LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); ++LUAI_FUNC int luaK_getlabel (FuncState *fs); ++LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); ++LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); ++LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); ++LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ldebug.c +@@ -0,0 +1,637 @@ ++/* ++** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ ++** Debug Interface ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <stdarg.h> ++#include <stddef.h> ++#include <string.h> ++ ++#define ldebug_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lapi.h" ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lvm.h" ++ ++ ++ ++static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); ++ ++ ++static int currentpc (lua_State *L, CallInfo *ci) { ++ if (!isLua(ci)) return -1; /* function is not a Lua function? */ ++ if (ci == L->ci) ++ ci->savedpc = L->savedpc; ++ return pcRel(ci->savedpc, ci_func(ci)->l.p); ++} ++ ++ ++static int currentline (lua_State *L, CallInfo *ci) { ++ int pc = currentpc(L, ci); ++ if (pc < 0) ++ return -1; /* only active lua functions have current-line information */ ++ else ++ return getline(ci_func(ci)->l.p, pc); ++} ++ ++ ++/* ++** this function can be called asynchronous (e.g. during a signal) ++*/ ++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { ++ if (func == NULL || mask == 0) { /* turn off hooks? */ ++ mask = 0; ++ func = NULL; ++ } ++ L->hook = func; ++ L->basehookcount = count; ++ resethookcount(L); ++ L->hookmask = cast_byte(mask); ++ return 1; ++} ++ ++ ++LUA_API lua_Hook lua_gethook (lua_State *L) { ++ return L->hook; ++} ++ ++ ++LUA_API int lua_gethookmask (lua_State *L) { ++ return L->hookmask; ++} ++ ++ ++LUA_API int lua_gethookcount (lua_State *L) { ++ return L->basehookcount; ++} ++ ++ ++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { ++ int status; ++ CallInfo *ci; ++ lua_lock(L); ++ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { ++ level--; ++ if (f_isLua(ci)) /* Lua function? */ ++ level -= ci->tailcalls; /* skip lost tail calls */ ++ } ++ if (level == 0 && ci > L->base_ci) { /* level found? */ ++ status = 1; ++ ar->i_ci = cast_int(ci - L->base_ci); ++ } ++ else if (level < 0) { /* level is of a lost tail call? */ ++ status = 1; ++ ar->i_ci = 0; ++ } ++ else status = 0; /* no such level */ ++ lua_unlock(L); ++ return status; ++} ++ ++ ++static Proto *getluaproto (CallInfo *ci) { ++ return (isLua(ci) ? ci_func(ci)->l.p : NULL); ++} ++ ++ ++static const char *findlocal (lua_State *L, CallInfo *ci, int n) { ++ const char *name; ++ Proto *fp = getluaproto(ci); ++ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) ++ return name; /* is a local variable in a Lua function */ ++ else { ++ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; ++ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ ++ return "(*temporary)"; ++ else ++ return NULL; ++ } ++} ++ ++ ++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { ++ CallInfo *ci = L->base_ci + ar->i_ci; ++ const char *name = findlocal(L, ci, n); ++ lua_lock(L); ++ if (name) ++ luaA_pushobject(L, ci->base + (n - 1)); ++ lua_unlock(L); ++ return name; ++} ++ ++ ++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { ++ CallInfo *ci = L->base_ci + ar->i_ci; ++ const char *name = findlocal(L, ci, n); ++ lua_lock(L); ++ if (name) ++ setobjs2s(L, ci->base + (n - 1), L->top - 1); ++ L->top--; /* pop value */ ++ lua_unlock(L); ++ return name; ++} ++ ++ ++static void funcinfo (lua_Debug *ar, Closure *cl) { ++ if (cl->c.isC) { ++ ar->source = "=[C]"; ++ ar->linedefined = -1; ++ ar->lastlinedefined = -1; ++ ar->what = "C"; ++ } ++ else { ++ ar->source = getstr(cl->l.p->source); ++ ar->linedefined = cl->l.p->linedefined; ++ ar->lastlinedefined = cl->l.p->lastlinedefined; ++ ar->what = (ar->linedefined == 0) ? "main" : "Lua"; ++ } ++ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ++} ++ ++ ++static void info_tailcall (lua_Debug *ar) { ++ ar->name = ar->namewhat = ""; ++ ar->what = "tail"; ++ ar->lastlinedefined = ar->linedefined = ar->currentline = -1; ++ ar->source = "=(tail call)"; ++ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ++ ar->nups = 0; ++} ++ ++ ++static void collectvalidlines (lua_State *L, Closure *f) { ++ if (f == NULL || f->c.isC) { ++ setnilvalue(L->top); ++ } ++ else { ++ Table *t = luaH_new(L, 0, 0); ++ int *lineinfo = f->l.p->lineinfo; ++ int i; ++ for (i=0; i<f->l.p->sizelineinfo; i++) ++ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); ++ sethvalue(L, L->top, t); ++ } ++ incr_top(L); ++} ++ ++ ++static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ++ Closure *f, CallInfo *ci) { ++ int status = 1; ++ if (f == NULL) { ++ info_tailcall(ar); ++ return status; ++ } ++ for (; *what; what++) { ++ switch (*what) { ++ case 'S': { ++ funcinfo(ar, f); ++ break; ++ } ++ case 'l': { ++ ar->currentline = (ci) ? currentline(L, ci) : -1; ++ break; ++ } ++ case 'u': { ++ ar->nups = f->c.nupvalues; ++ break; ++ } ++ case 'n': { ++ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; ++ if (ar->namewhat == NULL) { ++ ar->namewhat = ""; /* not found */ ++ ar->name = NULL; ++ } ++ break; ++ } ++ case 'L': ++ case 'f': /* handled by lua_getinfo */ ++ break; ++ default: status = 0; /* invalid option */ ++ } ++ } ++ return status; ++} ++ ++ ++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { ++ int status; ++ Closure *f = NULL; ++ CallInfo *ci = NULL; ++ lua_lock(L); ++ if (*what == '>') { ++ StkId func = L->top - 1; ++ luai_apicheck(L, ttisfunction(func)); ++ what++; /* skip the '>' */ ++ f = clvalue(func); ++ L->top--; /* pop function */ ++ } ++ else if (ar->i_ci != 0) { /* no tail call? */ ++ ci = L->base_ci + ar->i_ci; ++ lua_assert(ttisfunction(ci->func)); ++ f = clvalue(ci->func); ++ } ++ status = auxgetinfo(L, what, ar, f, ci); ++ if (strchr(what, 'f')) { ++ if (f == NULL) setnilvalue(L->top); ++ else setclvalue(L, L->top, f); ++ incr_top(L); ++ } ++ if (strchr(what, 'L')) ++ collectvalidlines(L, f); ++ lua_unlock(L); ++ return status; ++} ++ ++ ++/* ++** {====================================================== ++** Symbolic Execution and code checker ++** ======================================================= ++*/ ++ ++#define check(x) if (!(x)) return 0; ++ ++#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) ++ ++#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) ++ ++ ++ ++static int precheck (const Proto *pt) { ++ check(pt->maxstacksize <= MAXSTACK); ++ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); ++ check(!(pt->is_vararg & VARARG_NEEDSARG) || ++ (pt->is_vararg & VARARG_HASARG)); ++ check(pt->sizeupvalues <= pt->nups); ++ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); ++ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); ++ return 1; ++} ++ ++ ++#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) ++ ++int luaG_checkopenop (Instruction i) { ++ switch (GET_OPCODE(i)) { ++ case OP_CALL: ++ case OP_TAILCALL: ++ case OP_RETURN: ++ case OP_SETLIST: { ++ check(GETARG_B(i) == 0); ++ return 1; ++ } ++ default: return 0; /* invalid instruction after an open call */ ++ } ++} ++ ++ ++static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { ++ switch (mode) { ++ case OpArgN: check(r == 0); break; ++ case OpArgU: break; ++ case OpArgR: checkreg(pt, r); break; ++ case OpArgK: ++ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); ++ break; ++ } ++ return 1; ++} ++ ++ ++static Instruction symbexec (const Proto *pt, int lastpc, int reg) { ++ int pc; ++ int last; /* stores position of last instruction that changed `reg' */ ++ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ ++ check(precheck(pt)); ++ for (pc = 0; pc < lastpc; pc++) { ++ Instruction i = pt->code[pc]; ++ OpCode op = GET_OPCODE(i); ++ int a = GETARG_A(i); ++ int b = 0; ++ int c = 0; ++ check(op < NUM_OPCODES); ++ checkreg(pt, a); ++ switch (getOpMode(op)) { ++ case iABC: { ++ b = GETARG_B(i); ++ c = GETARG_C(i); ++ check(checkArgMode(pt, b, getBMode(op))); ++ check(checkArgMode(pt, c, getCMode(op))); ++ break; ++ } ++ case iABx: { ++ b = GETARG_Bx(i); ++ if (getBMode(op) == OpArgK) check(b < pt->sizek); ++ break; ++ } ++ case iAsBx: { ++ b = GETARG_sBx(i); ++ if (getBMode(op) == OpArgR) { ++ int dest = pc+1+b; ++ check(0 <= dest && dest < pt->sizecode); ++ if (dest > 0) { ++ int j; ++ /* check that it does not jump to a setlist count; this ++ is tricky, because the count from a previous setlist may ++ have the same value of an invalid setlist; so, we must ++ go all the way back to the first of them (if any) */ ++ for (j = 0; j < dest; j++) { ++ Instruction d = pt->code[dest-1-j]; ++ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; ++ } ++ /* if 'j' is even, previous value is not a setlist (even if ++ it looks like one) */ ++ check((j&1) == 0); ++ } ++ } ++ break; ++ } ++ } ++ if (testAMode(op)) { ++ if (a == reg) last = pc; /* change register `a' */ ++ } ++ if (testTMode(op)) { ++ check(pc+2 < pt->sizecode); /* check skip */ ++ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); ++ } ++ switch (op) { ++ case OP_LOADBOOL: { ++ if (c == 1) { /* does it jump? */ ++ check(pc+2 < pt->sizecode); /* check its jump */ ++ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || ++ GETARG_C(pt->code[pc+1]) != 0); ++ } ++ break; ++ } ++ case OP_LOADNIL: { ++ if (a <= reg && reg <= b) ++ last = pc; /* set registers from `a' to `b' */ ++ break; ++ } ++ case OP_GETUPVAL: ++ case OP_SETUPVAL: { ++ check(b < pt->nups); ++ break; ++ } ++ case OP_GETGLOBAL: ++ case OP_SETGLOBAL: { ++ check(ttisstring(&pt->k[b])); ++ break; ++ } ++ case OP_SELF: { ++ checkreg(pt, a+1); ++ if (reg == a+1) last = pc; ++ break; ++ } ++ case OP_CONCAT: { ++ check(b < c); /* at least two operands */ ++ break; ++ } ++ case OP_TFORLOOP: { ++ check(c >= 1); /* at least one result (control variable) */ ++ checkreg(pt, a+2+c); /* space for results */ ++ if (reg >= a+2) last = pc; /* affect all regs above its base */ ++ break; ++ } ++ case OP_FORLOOP: ++ case OP_FORPREP: ++ checkreg(pt, a+3); ++ /* go through */ ++ case OP_JMP: { ++ int dest = pc+1+b; ++ /* not full check and jump is forward and do not skip `lastpc'? */ ++ if (reg != NO_REG && pc < dest && dest <= lastpc) ++ pc += b; /* do the jump */ ++ break; ++ } ++ case OP_CALL: ++ case OP_TAILCALL: { ++ if (b != 0) { ++ checkreg(pt, a+b-1); ++ } ++ c--; /* c = num. returns */ ++ if (c == LUA_MULTRET) { ++ check(checkopenop(pt, pc)); ++ } ++ else if (c != 0) ++ checkreg(pt, a+c-1); ++ if (reg >= a) last = pc; /* affect all registers above base */ ++ break; ++ } ++ case OP_RETURN: { ++ b--; /* b = num. returns */ ++ if (b > 0) checkreg(pt, a+b-1); ++ break; ++ } ++ case OP_SETLIST: { ++ if (b > 0) checkreg(pt, a + b); ++ if (c == 0) { ++ pc++; ++ check(pc < pt->sizecode - 1); ++ } ++ break; ++ } ++ case OP_CLOSURE: { ++ int nup, j; ++ check(b < pt->sizep); ++ nup = pt->p[b]->nups; ++ check(pc + nup < pt->sizecode); ++ for (j = 1; j <= nup; j++) { ++ OpCode op1 = GET_OPCODE(pt->code[pc + j]); ++ check(op1 == OP_GETUPVAL || op1 == OP_MOVE); ++ } ++ if (reg != NO_REG) /* tracing? */ ++ pc += nup; /* do not 'execute' these pseudo-instructions */ ++ break; ++ } ++ case OP_VARARG: { ++ check((pt->is_vararg & VARARG_ISVARARG) && ++ !(pt->is_vararg & VARARG_NEEDSARG)); ++ b--; ++ if (b == LUA_MULTRET) check(checkopenop(pt, pc)); ++ checkreg(pt, a+b-1); ++ break; ++ } ++ default: break; ++ } ++ } ++ return pt->code[last]; ++} ++ ++#undef check ++#undef checkjump ++#undef checkreg ++ ++/* }====================================================== */ ++ ++ ++int luaG_checkcode (const Proto *pt) { ++ return (symbexec(pt, pt->sizecode, NO_REG) != 0); ++} ++ ++ ++static const char *kname (Proto *p, int c) { ++ if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) ++ return svalue(&p->k[INDEXK(c)]); ++ else ++ return "?"; ++} ++ ++ ++static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, ++ const char **name) { ++ if (isLua(ci)) { /* a Lua function? */ ++ Proto *p = ci_func(ci)->l.p; ++ int pc = currentpc(L, ci); ++ Instruction i; ++ *name = luaF_getlocalname(p, stackpos+1, pc); ++ if (*name) /* is a local? */ ++ return "local"; ++ i = symbexec(p, pc, stackpos); /* try symbolic execution */ ++ lua_assert(pc != -1); ++ switch (GET_OPCODE(i)) { ++ case OP_GETGLOBAL: { ++ int g = GETARG_Bx(i); /* global index */ ++ lua_assert(ttisstring(&p->k[g])); ++ *name = svalue(&p->k[g]); ++ return "global"; ++ } ++ case OP_MOVE: { ++ int a = GETARG_A(i); ++ int b = GETARG_B(i); /* move from `b' to `a' */ ++ if (b < a) ++ return getobjname(L, ci, b, name); /* get name for `b' */ ++ break; ++ } ++ case OP_GETTABLE: { ++ int k = GETARG_C(i); /* key index */ ++ *name = kname(p, k); ++ return "field"; ++ } ++ case OP_GETUPVAL: { ++ int u = GETARG_B(i); /* upvalue index */ ++ *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; ++ return "upvalue"; ++ } ++ case OP_SELF: { ++ int k = GETARG_C(i); /* key index */ ++ *name = kname(p, k); ++ return "method"; ++ } ++ default: break; ++ } ++ } ++ return NULL; /* no useful name found */ ++} ++ ++ ++static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { ++ Instruction i; ++ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) ++ return NULL; /* calling function is not Lua (or is unknown) */ ++ ci--; /* calling function */ ++ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; ++ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || ++ GET_OPCODE(i) == OP_TFORLOOP) ++ return getobjname(L, ci, GETARG_A(i), name); ++ else ++ return NULL; /* no useful name can be found */ ++} ++ ++ ++/* only ANSI way to check whether a pointer points to an array */ ++static int isinstack (CallInfo *ci, const TValue *o) { ++ StkId p; ++ for (p = ci->base; p < ci->top; p++) ++ if (o == p) return 1; ++ return 0; ++} ++ ++ ++void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { ++ const char *name = NULL; ++ const char *t = luaT_typenames[ttype(o)]; ++ const char *kind = (isinstack(L->ci, o)) ? ++ getobjname(L, L->ci, cast_int(o - L->base), &name) : ++ NULL; ++ if (kind) ++ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", ++ op, kind, name, t); ++ else ++ luaG_runerror(L, "attempt to %s a %s value", op, t); ++} ++ ++ ++void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { ++ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; ++ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); ++ luaG_typeerror(L, p1, "concatenate"); ++} ++ ++ ++void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { ++ TValue temp; ++ if (luaV_tonumber(p1, &temp) == NULL) ++ p2 = p1; /* first operand is wrong */ ++ luaG_typeerror(L, p2, "perform arithmetic on"); ++} ++ ++ ++int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { ++ const char *t1 = luaT_typenames[ttype(p1)]; ++ const char *t2 = luaT_typenames[ttype(p2)]; ++ if (t1[2] == t2[2]) ++ luaG_runerror(L, "attempt to compare two %s values", t1); ++ else ++ luaG_runerror(L, "attempt to compare %s with %s", t1, t2); ++ return 0; ++} ++ ++ ++static void addinfo (lua_State *L, const char *msg) { ++ CallInfo *ci = L->ci; ++ if (isLua(ci)) { /* is Lua code? */ ++ char buff[LUA_IDSIZE]; /* add file:line information */ ++ int line = currentline(L, ci); ++ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); ++ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); ++ } ++} ++ ++ ++void luaG_errormsg (lua_State *L) { ++ if (L->errfunc != 0) { /* is there an error handling function? */ ++ StkId errfunc = restorestack(L, L->errfunc); ++ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); ++ setobjs2s(L, L->top, L->top - 1); /* move argument */ ++ setobjs2s(L, L->top - 1, errfunc); /* push function */ ++ incr_top(L); ++ luaD_call(L, L->top - 2, 1); /* call it */ ++ } ++ luaD_throw(L, LUA_ERRRUN); ++} ++ ++ ++void luaG_runerror (lua_State *L, const char *fmt, ...) { ++ va_list argp; ++ va_start(argp, fmt); ++ addinfo(L, luaO_pushvfstring(L, fmt, argp)); ++ va_end(argp); ++ luaG_errormsg(L); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldebug.h +@@ -0,0 +1,33 @@ ++/* ++** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions from Debug Interface module ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ldebug_h ++#define ldebug_h ++ ++ ++#include "lstate.h" ++ ++ ++#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) ++ ++#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) ++ ++#define resethookcount(L) (L->hookcount = L->basehookcount) ++ ++ ++LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, ++ const char *opname); ++LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); ++LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, ++ const TValue *p2); ++LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, ++ const TValue *p2); ++LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); ++LUAI_FUNC void luaG_errormsg (lua_State *L); ++LUAI_FUNC int luaG_checkcode (const Proto *pt); ++LUAI_FUNC int luaG_checkopenop (Instruction i); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ldo.c +@@ -0,0 +1,515 @@ ++/* ++** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ ++** Stack and Call structure of Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#include <setjmp.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#define ldo_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lundump.h" ++#include "lvm.h" ++#include "lzio.h" ++ ++ ++ ++/* ++** {====================================================== ++** Error-recovery functions ++** ======================================================= ++*/ ++ ++ ++/* chain list of long jump buffers */ ++struct lua_longjmp { ++ struct lua_longjmp *previous; ++ luai_jmpbuf b; ++ volatile int status; /* error code */ ++}; ++ ++ ++void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { ++ switch (errcode) { ++ case LUA_ERRMEM: { ++ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); ++ break; ++ } ++ case LUA_ERRERR: { ++ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); ++ break; ++ } ++ case LUA_ERRSYNTAX: ++ case LUA_ERRRUN: { ++ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ ++ break; ++ } ++ } ++ L->top = oldtop + 1; ++} ++ ++ ++static void restore_stack_limit (lua_State *L) { ++ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); ++ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ ++ int inuse = cast_int(L->ci - L->base_ci); ++ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ ++ luaD_reallocCI(L, LUAI_MAXCALLS); ++ } ++} ++ ++ ++static void resetstack (lua_State *L, int status) { ++ L->ci = L->base_ci; ++ L->base = L->ci->base; ++ luaF_close(L, L->base); /* close eventual pending closures */ ++ luaD_seterrorobj(L, status, L->base); ++ L->nCcalls = L->baseCcalls; ++ L->allowhook = 1; ++ restore_stack_limit(L); ++ L->errfunc = 0; ++ L->errorJmp = NULL; ++} ++ ++ ++void luaD_throw (lua_State *L, int errcode) { ++ if (L->errorJmp) { ++ L->errorJmp->status = errcode; ++ LUAI_THROW(L, L->errorJmp); ++ } ++ else { ++ L->status = cast_byte(errcode); ++ if (G(L)->panic) { ++ resetstack(L, errcode); ++ lua_unlock(L); ++ G(L)->panic(L); ++ } ++ exit(EXIT_FAILURE); ++ } ++} ++ ++ ++int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ++ struct lua_longjmp lj; ++ lj.status = 0; ++ lj.previous = L->errorJmp; /* chain new error handler */ ++ L->errorJmp = &lj; ++ LUAI_TRY(L, &lj, ++ (*f)(L, ud); ++ ); ++ L->errorJmp = lj.previous; /* restore old error handler */ ++ return lj.status; ++} ++ ++/* }====================================================== */ ++ ++ ++static void correctstack (lua_State *L, TValue *oldstack) { ++ CallInfo *ci; ++ GCObject *up; ++ L->top = (L->top - oldstack) + L->stack; ++ for (up = L->openupval; up != NULL; up = up->gch.next) ++ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; ++ for (ci = L->base_ci; ci <= L->ci; ci++) { ++ ci->top = (ci->top - oldstack) + L->stack; ++ ci->base = (ci->base - oldstack) + L->stack; ++ ci->func = (ci->func - oldstack) + L->stack; ++ } ++ L->base = (L->base - oldstack) + L->stack; ++} ++ ++ ++void luaD_reallocstack (lua_State *L, int newsize) { ++ TValue *oldstack = L->stack; ++ int realsize = newsize + 1 + EXTRA_STACK; ++ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); ++ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); ++ L->stacksize = realsize; ++ L->stack_last = L->stack+newsize; ++ correctstack(L, oldstack); ++} ++ ++ ++void luaD_reallocCI (lua_State *L, int newsize) { ++ CallInfo *oldci = L->base_ci; ++ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); ++ L->size_ci = newsize; ++ L->ci = (L->ci - oldci) + L->base_ci; ++ L->end_ci = L->base_ci + L->size_ci - 1; ++} ++ ++ ++void luaD_growstack (lua_State *L, int n) { ++ if (n <= L->stacksize) /* double size is enough? */ ++ luaD_reallocstack(L, 2*L->stacksize); ++ else ++ luaD_reallocstack(L, L->stacksize + n); ++} ++ ++ ++static CallInfo *growCI (lua_State *L) { ++ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ ++ luaD_throw(L, LUA_ERRERR); ++ else { ++ luaD_reallocCI(L, 2*L->size_ci); ++ if (L->size_ci > LUAI_MAXCALLS) ++ luaG_runerror(L, "stack overflow"); ++ } ++ return ++L->ci; ++} ++ ++ ++void luaD_callhook (lua_State *L, int event, int line) { ++ lua_Hook hook = L->hook; ++ if (hook && L->allowhook) { ++ ptrdiff_t top = savestack(L, L->top); ++ ptrdiff_t ci_top = savestack(L, L->ci->top); ++ lua_Debug ar; ++ ar.event = event; ++ ar.currentline = line; ++ if (event == LUA_HOOKTAILRET) ++ ar.i_ci = 0; /* tail call; no debug information about it */ ++ else ++ ar.i_ci = cast_int(L->ci - L->base_ci); ++ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ++ L->ci->top = L->top + LUA_MINSTACK; ++ lua_assert(L->ci->top <= L->stack_last); ++ L->allowhook = 0; /* cannot call hooks inside a hook */ ++ lua_unlock(L); ++ (*hook)(L, &ar); ++ lua_lock(L); ++ lua_assert(!L->allowhook); ++ L->allowhook = 1; ++ L->ci->top = restorestack(L, ci_top); ++ L->top = restorestack(L, top); ++ } ++} ++ ++ ++static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { ++ int i; ++ int nfixargs = p->numparams; ++ Table *htab = NULL; ++ StkId base, fixed; ++ for (; actual < nfixargs; ++actual) ++ setnilvalue(L->top++); ++#if defined(LUA_COMPAT_VARARG) ++ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ ++ int nvar = actual - nfixargs; /* number of extra arguments */ ++ lua_assert(p->is_vararg & VARARG_HASARG); ++ luaC_checkGC(L); ++ htab = luaH_new(L, nvar, 1); /* create `arg' table */ ++ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ ++ setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i); ++ /* store counter in field `n' */ ++ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); ++ } ++#endif ++ /* move fixed parameters to final position */ ++ fixed = L->top - actual; /* first fixed argument */ ++ base = L->top; /* final position of first argument */ ++ for (i=0; i<nfixargs; i++) { ++ setobjs2s(L, L->top++, fixed+i); ++ setnilvalue(fixed+i); ++ } ++ /* add `arg' parameter */ ++ if (htab) { ++ sethvalue(L, L->top++, htab); ++ lua_assert(iswhite(obj2gco(htab))); ++ } ++ return base; ++} ++ ++ ++static StkId tryfuncTM (lua_State *L, StkId func) { ++ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); ++ StkId p; ++ ptrdiff_t funcr = savestack(L, func); ++ if (!ttisfunction(tm)) ++ luaG_typeerror(L, func, "call"); ++ /* Open a hole inside the stack at `func' */ ++ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); ++ incr_top(L); ++ func = restorestack(L, funcr); /* previous call may change stack */ ++ setobj2s(L, func, tm); /* tag method is the new function to be called */ ++ return func; ++} ++ ++ ++ ++#define inc_ci(L) \ ++ ((L->ci == L->end_ci) ? growCI(L) : \ ++ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) ++ ++ ++int luaD_precall (lua_State *L, StkId func, int nresults) { ++ LClosure *cl; ++ ptrdiff_t funcr; ++ if (!ttisfunction(func)) /* `func' is not a function? */ ++ func = tryfuncTM(L, func); /* check the `function' tag method */ ++ funcr = savestack(L, func); ++ cl = &clvalue(func)->l; ++ L->ci->savedpc = L->savedpc; ++ if (!cl->isC) { /* Lua function? prepare its call */ ++ CallInfo *ci; ++ StkId st, base; ++ Proto *p = cl->p; ++ luaD_checkstack(L, p->maxstacksize); ++ func = restorestack(L, funcr); ++ if (!p->is_vararg) { /* no varargs? */ ++ base = func + 1; ++ if (L->top > base + p->numparams) ++ L->top = base + p->numparams; ++ } ++ else { /* vararg function */ ++ int nargs = cast_int(L->top - func) - 1; ++ base = adjust_varargs(L, p, nargs); ++ func = restorestack(L, funcr); /* previous call may change the stack */ ++ } ++ ci = inc_ci(L); /* now `enter' new function */ ++ ci->func = func; ++ L->base = ci->base = base; ++ ci->top = L->base + p->maxstacksize; ++ lua_assert(ci->top <= L->stack_last); ++ L->savedpc = p->code; /* starting point */ ++ ci->tailcalls = 0; ++ ci->nresults = nresults; ++ for (st = L->top; st < ci->top; st++) ++ setnilvalue(st); ++ L->top = ci->top; ++ if (L->hookmask & LUA_MASKCALL) { ++ L->savedpc++; /* hooks assume 'pc' is already incremented */ ++ luaD_callhook(L, LUA_HOOKCALL, -1); ++ L->savedpc--; /* correct 'pc' */ ++ } ++ return PCRLUA; ++ } ++ else { /* if is a C function, call it */ ++ CallInfo *ci; ++ int n; ++ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ++ ci = inc_ci(L); /* now `enter' new function */ ++ ci->func = restorestack(L, funcr); ++ L->base = ci->base = ci->func + 1; ++ ci->top = L->top + LUA_MINSTACK; ++ lua_assert(ci->top <= L->stack_last); ++ ci->nresults = nresults; ++ if (L->hookmask & LUA_MASKCALL) ++ luaD_callhook(L, LUA_HOOKCALL, -1); ++ lua_unlock(L); ++ n = (*curr_func(L)->c.f)(L); /* do the actual call */ ++ lua_lock(L); ++ if (n < 0) /* yielding? */ ++ return PCRYIELD; ++ else { ++ luaD_poscall(L, L->top - n); ++ return PCRC; ++ } ++ } ++} ++ ++ ++static StkId callrethooks (lua_State *L, StkId firstResult) { ++ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ ++ luaD_callhook(L, LUA_HOOKRET, -1); ++ if (f_isLua(L->ci)) { /* Lua function? */ ++ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ ++ luaD_callhook(L, LUA_HOOKTAILRET, -1); ++ } ++ return restorestack(L, fr); ++} ++ ++ ++int luaD_poscall (lua_State *L, StkId firstResult) { ++ StkId res; ++ int wanted, i; ++ CallInfo *ci; ++ if (L->hookmask & LUA_MASKRET) ++ firstResult = callrethooks(L, firstResult); ++ ci = L->ci--; ++ res = ci->func; /* res == final position of 1st result */ ++ wanted = ci->nresults; ++ L->base = (ci - 1)->base; /* restore base */ ++ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ ++ /* move results to correct place */ ++ for (i = wanted; i != 0 && firstResult < L->top; i--) ++ setobjs2s(L, res++, firstResult++); ++ while (i-- > 0) ++ setnilvalue(res++); ++ L->top = res; ++ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ ++} ++ ++ ++/* ++** Call a function (C or Lua). The function to be called is at *func. ++** The arguments are on the stack, right after the function. ++** When returns, all the results are on the stack, starting at the original ++** function position. ++*/ ++void luaD_call (lua_State *L, StkId func, int nResults) { ++ if (++L->nCcalls >= LUAI_MAXCCALLS) { ++ if (L->nCcalls == LUAI_MAXCCALLS) ++ luaG_runerror(L, "C stack overflow"); ++ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) ++ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ ++ } ++ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ ++ luaV_execute(L, 1); /* call it */ ++ L->nCcalls--; ++ luaC_checkGC(L); ++} ++ ++ ++static void resume (lua_State *L, void *ud) { ++ StkId firstArg = cast(StkId, ud); ++ CallInfo *ci = L->ci; ++ if (L->status == 0) { /* start coroutine? */ ++ lua_assert(ci == L->base_ci && firstArg > L->base); ++ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) ++ return; ++ } ++ else { /* resuming from previous yield */ ++ lua_assert(L->status == LUA_YIELD); ++ L->status = 0; ++ if (!f_isLua(ci)) { /* `common' yield? */ ++ /* finish interrupted execution of `OP_CALL' */ ++ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || ++ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); ++ if (luaD_poscall(L, firstArg)) /* complete it... */ ++ L->top = L->ci->top; /* and correct top if not multiple results */ ++ } ++ else /* yielded inside a hook: just continue its execution */ ++ L->base = L->ci->base; ++ } ++ luaV_execute(L, cast_int(L->ci - L->base_ci)); ++} ++ ++ ++static int resume_error (lua_State *L, const char *msg) { ++ L->top = L->ci->base; ++ setsvalue2s(L, L->top, luaS_new(L, msg)); ++ incr_top(L); ++ lua_unlock(L); ++ return LUA_ERRRUN; ++} ++ ++ ++LUA_API int lua_resume (lua_State *L, int nargs) { ++ int status; ++ lua_lock(L); ++ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) ++ return resume_error(L, "cannot resume non-suspended coroutine"); ++ if (L->nCcalls >= LUAI_MAXCCALLS) ++ return resume_error(L, "C stack overflow"); ++ luai_userstateresume(L, nargs); ++ lua_assert(L->errfunc == 0); ++ L->baseCcalls = ++L->nCcalls; ++ status = luaD_rawrunprotected(L, resume, L->top - nargs); ++ if (status != 0) { /* error? */ ++ L->status = cast_byte(status); /* mark thread as `dead' */ ++ luaD_seterrorobj(L, status, L->top); ++ L->ci->top = L->top; ++ } ++ else { ++ lua_assert(L->nCcalls == L->baseCcalls); ++ status = L->status; ++ } ++ --L->nCcalls; ++ lua_unlock(L); ++ return status; ++} ++ ++ ++LUA_API int lua_yield (lua_State *L, int nresults) { ++ luai_userstateyield(L, nresults); ++ lua_lock(L); ++ if (L->nCcalls > L->baseCcalls) ++ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); ++ L->base = L->top - nresults; /* protect stack slots below */ ++ L->status = LUA_YIELD; ++ lua_unlock(L); ++ return -1; ++} ++ ++ ++int luaD_pcall (lua_State *L, Pfunc func, void *u, ++ ptrdiff_t old_top, ptrdiff_t ef) { ++ int status; ++ unsigned short oldnCcalls = L->nCcalls; ++ ptrdiff_t old_ci = saveci(L, L->ci); ++ lu_byte old_allowhooks = L->allowhook; ++ ptrdiff_t old_errfunc = L->errfunc; ++ L->errfunc = ef; ++ status = luaD_rawrunprotected(L, func, u); ++ if (status != 0) { /* an error occurred? */ ++ StkId oldtop = restorestack(L, old_top); ++ luaF_close(L, oldtop); /* close eventual pending closures */ ++ luaD_seterrorobj(L, status, oldtop); ++ L->nCcalls = oldnCcalls; ++ L->ci = restoreci(L, old_ci); ++ L->base = L->ci->base; ++ L->savedpc = L->ci->savedpc; ++ L->allowhook = old_allowhooks; ++ restore_stack_limit(L); ++ } ++ L->errfunc = old_errfunc; ++ return status; ++} ++ ++ ++ ++/* ++** Execute a protected parser. ++*/ ++struct SParser { /* data to `f_parser' */ ++ ZIO *z; ++ Mbuffer buff; /* buffer to be used by the scanner */ ++ const char *name; ++}; ++ ++static void f_parser (lua_State *L, void *ud) { ++ int i; ++ Proto *tf; ++ Closure *cl; ++ struct SParser *p = cast(struct SParser *, ud); ++ int c = luaZ_lookahead(p->z); ++ luaC_checkGC(L); ++ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, ++ &p->buff, p->name); ++ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); ++ cl->l.p = tf; ++ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ ++ cl->l.upvals[i] = luaF_newupval(L); ++ setclvalue(L, L->top, cl); ++ incr_top(L); ++} ++ ++ ++int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { ++ struct SParser p; ++ int status; ++ p.z = z; p.name = name; ++ luaZ_initbuffer(L, &p.buff); ++ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); ++ luaZ_freebuffer(L, &p.buff); ++ return status; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldo.h +@@ -0,0 +1,57 @@ ++/* ++** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Stack and Call structure of Lua ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ldo_h ++#define ldo_h ++ ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lzio.h" ++ ++ ++#define luaD_checkstack(L,n) \ ++ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ ++ luaD_growstack(L, n); \ ++ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); ++ ++ ++#define incr_top(L) {luaD_checkstack(L,1); L->top++;} ++ ++#define savestack(L,p) ((char *)(p) - (char *)L->stack) ++#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) ++ ++#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) ++#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) ++ ++ ++/* results from luaD_precall */ ++#define PCRLUA 0 /* initiated a call to a Lua function */ ++#define PCRC 1 /* did a call to a C function */ ++#define PCRYIELD 2 /* C funtion yielded */ ++ ++ ++/* type of protected functions, to be ran by `runprotected' */ ++typedef void (*Pfunc) (lua_State *L, void *ud); ++ ++LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); ++LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); ++LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); ++LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); ++LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ++ ptrdiff_t oldtop, ptrdiff_t ef); ++LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); ++LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); ++LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); ++LUAI_FUNC void luaD_growstack (lua_State *L, int n); ++ ++LUAI_FUNC void luaD_throw (lua_State *L, int errcode); ++LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); ++ ++LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/ldump.c +@@ -0,0 +1,164 @@ ++/* ++** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** save precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stddef.h> ++ ++#define ldump_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lundump.h" ++ ++typedef struct { ++ lua_State* L; ++ lua_Writer writer; ++ void* data; ++ int strip; ++ int status; ++} DumpState; ++ ++#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) ++#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) ++ ++static void DumpBlock(const void* b, size_t size, DumpState* D) ++{ ++ if (D->status==0) ++ { ++ lua_unlock(D->L); ++ D->status=(*D->writer)(D->L,b,size,D->data); ++ lua_lock(D->L); ++ } ++} ++ ++static void DumpChar(int y, DumpState* D) ++{ ++ char x=(char)y; ++ DumpVar(x,D); ++} ++ ++static void DumpInt(int x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ ++static void DumpNumber(lua_Number x, DumpState* D) ++{ ++ DumpVar(x,D); ++} ++ ++static void DumpVector(const void* b, int n, size_t size, DumpState* D) ++{ ++ DumpInt(n,D); ++ DumpMem(b,n,size,D); ++} ++ ++static void DumpString(const TString* s, DumpState* D) ++{ ++ if (s==NULL || getstr(s)==NULL) ++ { ++ size_t size=0; ++ DumpVar(size,D); ++ } ++ else ++ { ++ size_t size=s->tsv.len+1; /* include trailing '\0' */ ++ DumpVar(size,D); ++ DumpBlock(getstr(s),size,D); ++ } ++} ++ ++#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) ++ ++static void DumpFunction(const Proto* f, const TString* p, DumpState* D); ++ ++static void DumpConstants(const Proto* f, DumpState* D) ++{ ++ int i,n=f->sizek; ++ DumpInt(n,D); ++ for (i=0; i<n; i++) ++ { ++ const TValue* o=&f->k[i]; ++ DumpChar(ttype(o),D); ++ switch (ttype(o)) ++ { ++ case LUA_TNIL: ++ break; ++ case LUA_TBOOLEAN: ++ DumpChar(bvalue(o),D); ++ break; ++ case LUA_TNUMBER: ++ DumpNumber(nvalue(o),D); ++ break; ++ case LUA_TSTRING: ++ DumpString(rawtsvalue(o),D); ++ break; ++ default: ++ lua_assert(0); /* cannot happen */ ++ break; ++ } ++ } ++ n=f->sizep; ++ DumpInt(n,D); ++ for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D); ++} ++ ++static void DumpDebug(const Proto* f, DumpState* D) ++{ ++ int i,n; ++ n= (D->strip) ? 0 : f->sizelineinfo; ++ DumpVector(f->lineinfo,n,sizeof(int),D); ++ n= (D->strip) ? 0 : f->sizelocvars; ++ DumpInt(n,D); ++ for (i=0; i<n; i++) ++ { ++ DumpString(f->locvars[i].varname,D); ++ DumpInt(f->locvars[i].startpc,D); ++ DumpInt(f->locvars[i].endpc,D); ++ } ++ n= (D->strip) ? 0 : f->sizeupvalues; ++ DumpInt(n,D); ++ for (i=0; i<n; i++) DumpString(f->upvalues[i],D); ++} ++ ++static void DumpFunction(const Proto* f, const TString* p, DumpState* D) ++{ ++ DumpString((f->source==p || D->strip) ? NULL : f->source,D); ++ DumpInt(f->linedefined,D); ++ DumpInt(f->lastlinedefined,D); ++ DumpChar(f->nups,D); ++ DumpChar(f->numparams,D); ++ DumpChar(f->is_vararg,D); ++ DumpChar(f->maxstacksize,D); ++ DumpCode(f,D); ++ DumpConstants(f,D); ++ DumpDebug(f,D); ++} ++ ++static void DumpHeader(DumpState* D) ++{ ++ char h[LUAC_HEADERSIZE]; ++ luaU_header(h); ++ DumpBlock(h,LUAC_HEADERSIZE,D); ++} ++ ++/* ++** dump Lua function as precompiled chunk ++*/ ++int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) ++{ ++ DumpState D; ++ D.L=L; ++ D.writer=w; ++ D.data=data; ++ D.strip=strip; ++ D.status=0; ++ DumpHeader(&D); ++ DumpFunction(f,NULL,&D); ++ return D.status; ++} +--- /dev/null ++++ b/extensions/LUA/lua/lfunc.c +@@ -0,0 +1,174 @@ ++/* ++** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ ++** Auxiliary functions to manipulate prototypes and closures ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <stddef.h> ++ ++#define lfunc_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++ ++Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { ++ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); ++ luaC_link(L, obj2gco(c), LUA_TFUNCTION); ++ c->c.isC = 1; ++ c->c.env = e; ++ c->c.nupvalues = cast_byte(nelems); ++ return c; ++} ++ ++ ++Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { ++ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); ++ luaC_link(L, obj2gco(c), LUA_TFUNCTION); ++ c->l.isC = 0; ++ c->l.env = e; ++ c->l.nupvalues = cast_byte(nelems); ++ while (nelems--) c->l.upvals[nelems] = NULL; ++ return c; ++} ++ ++ ++UpVal *luaF_newupval (lua_State *L) { ++ UpVal *uv = luaM_new(L, UpVal); ++ luaC_link(L, obj2gco(uv), LUA_TUPVAL); ++ uv->v = &uv->u.value; ++ setnilvalue(uv->v); ++ return uv; ++} ++ ++ ++UpVal *luaF_findupval (lua_State *L, StkId level) { ++ global_State *g = G(L); ++ GCObject **pp = &L->openupval; ++ UpVal *p; ++ UpVal *uv; ++ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { ++ lua_assert(p->v != &p->u.value); ++ if (p->v == level) { /* found a corresponding upvalue? */ ++ if (isdead(g, obj2gco(p))) /* is it dead? */ ++ changewhite(obj2gco(p)); /* ressurect it */ ++ return p; ++ } ++ pp = &p->next; ++ } ++ uv = luaM_new(L, UpVal); /* not found: create a new one */ ++ uv->tt = LUA_TUPVAL; ++ uv->marked = luaC_white(g); ++ uv->v = level; /* current value lives in the stack */ ++ uv->next = *pp; /* chain it in the proper position */ ++ *pp = obj2gco(uv); ++ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ ++ uv->u.l.next = g->uvhead.u.l.next; ++ uv->u.l.next->u.l.prev = uv; ++ g->uvhead.u.l.next = uv; ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ return uv; ++} ++ ++ ++static void unlinkupval (UpVal *uv) { ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ ++ uv->u.l.prev->u.l.next = uv->u.l.next; ++} ++ ++ ++void luaF_freeupval (lua_State *L, UpVal *uv) { ++ if (uv->v != &uv->u.value) /* is it open? */ ++ unlinkupval(uv); /* remove from open list */ ++ luaM_free(L, uv); /* free upvalue */ ++} ++ ++ ++void luaF_close (lua_State *L, StkId level) { ++ UpVal *uv; ++ global_State *g = G(L); ++ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { ++ GCObject *o = obj2gco(uv); ++ lua_assert(!isblack(o) && uv->v != &uv->u.value); ++ L->openupval = uv->next; /* remove from `open' list */ ++ if (isdead(g, o)) ++ luaF_freeupval(L, uv); /* free upvalue */ ++ else { ++ unlinkupval(uv); ++ setobj(L, &uv->u.value, uv->v); ++ uv->v = &uv->u.value; /* now current value lives here */ ++ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ ++ } ++ } ++} ++ ++ ++Proto *luaF_newproto (lua_State *L) { ++ Proto *f = luaM_new(L, Proto); ++ luaC_link(L, obj2gco(f), LUA_TPROTO); ++ f->k = NULL; ++ f->sizek = 0; ++ f->p = NULL; ++ f->sizep = 0; ++ f->code = NULL; ++ f->sizecode = 0; ++ f->sizelineinfo = 0; ++ f->sizeupvalues = 0; ++ f->nups = 0; ++ f->upvalues = NULL; ++ f->numparams = 0; ++ f->is_vararg = 0; ++ f->maxstacksize = 0; ++ f->lineinfo = NULL; ++ f->sizelocvars = 0; ++ f->locvars = NULL; ++ f->linedefined = 0; ++ f->lastlinedefined = 0; ++ f->source = NULL; ++ return f; ++} ++ ++ ++void luaF_freeproto (lua_State *L, Proto *f) { ++ luaM_freearray(L, f->code, f->sizecode, Instruction); ++ luaM_freearray(L, f->p, f->sizep, Proto *); ++ luaM_freearray(L, f->k, f->sizek, TValue); ++ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); ++ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); ++ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); ++ luaM_free(L, f); ++} ++ ++ ++void luaF_freeclosure (lua_State *L, Closure *c) { ++ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : ++ sizeLclosure(c->l.nupvalues); ++ luaM_freemem(L, c, size); ++} ++ ++ ++/* ++** Look for n-th local variable at line `line' in function `func'. ++** Returns NULL if not found. ++*/ ++const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { ++ int i; ++ for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) { ++ if (pc < f->locvars[i].endpc) { /* is variable active? */ ++ local_number--; ++ if (local_number == 0) ++ return getstr(f->locvars[i].varname); ++ } ++ } ++ return NULL; /* not found */ ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lfunc.h +@@ -0,0 +1,34 @@ ++/* ++** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Auxiliary functions to manipulate prototypes and closures ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lfunc_h ++#define lfunc_h ++ ++ ++#include "lobject.h" ++ ++ ++#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ ++ cast(int, sizeof(TValue)*((n)-1))) ++ ++#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ ++ cast(int, sizeof(TValue *)*((n)-1))) ++ ++ ++LUAI_FUNC Proto *luaF_newproto (lua_State *L); ++LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); ++LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); ++LUAI_FUNC UpVal *luaF_newupval (lua_State *L); ++LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); ++LUAI_FUNC void luaF_close (lua_State *L, StkId level); ++LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); ++LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); ++LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); ++LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, ++ int pc); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lgc.c +@@ -0,0 +1,711 @@ ++/* ++** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Garbage Collector ++** See Copyright Notice in lua.h ++*/ ++ ++#include <string.h> ++ ++#define lgc_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++#define GCSTEPSIZE 1024u ++#define GCSWEEPMAX 40 ++#define GCSWEEPCOST 10 ++#define GCFINALIZECOST 100 ++ ++ ++#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) ++ ++#define makewhite(g,x) \ ++ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) ++ ++#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) ++#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) ++ ++#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) ++ ++ ++#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) ++#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) ++ ++ ++#define KEYWEAK bitmask(KEYWEAKBIT) ++#define VALUEWEAK bitmask(VALUEWEAKBIT) ++ ++ ++ ++#define markvalue(g,o) { checkconsistency(o); \ ++ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } ++ ++#define markobject(g,t) { if (iswhite(obj2gco(t))) \ ++ reallymarkobject(g, obj2gco(t)); } ++ ++ ++#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) ++ ++ ++static void removeentry (Node *n) { ++ lua_assert(ttisnil(gval(n))); ++ if (iscollectable(gkey(n))) ++ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ ++} ++ ++ ++static void reallymarkobject (global_State *g, GCObject *o) { ++ lua_assert(iswhite(o) && !isdead(g, o)); ++ white2gray(o); ++ switch (o->gch.tt) { ++ case LUA_TSTRING: { ++ return; ++ } ++ case LUA_TUSERDATA: { ++ Table *mt = gco2u(o)->metatable; ++ gray2black(o); /* udata are never gray */ ++ if (mt) markobject(g, mt); ++ markobject(g, gco2u(o)->env); ++ return; ++ } ++ case LUA_TUPVAL: { ++ UpVal *uv = gco2uv(o); ++ markvalue(g, uv->v); ++ if (uv->v == &uv->u.value) /* closed? */ ++ gray2black(o); /* open upvalues are never black */ ++ return; ++ } ++ case LUA_TFUNCTION: { ++ gco2cl(o)->c.gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TTABLE: { ++ gco2h(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TTHREAD: { ++ gco2th(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ case LUA_TPROTO: { ++ gco2p(o)->gclist = g->gray; ++ g->gray = o; ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++static void marktmu (global_State *g) { ++ GCObject *u = g->tmudata; ++ if (u) { ++ do { ++ u = u->gch.next; ++ makewhite(g, u); /* may be marked, if left from previous GC */ ++ reallymarkobject(g, u); ++ } while (u != g->tmudata); ++ } ++} ++ ++ ++/* move `dead' udata that need finalization to list `tmudata' */ ++size_t luaC_separateudata (lua_State *L, int all) { ++ global_State *g = G(L); ++ size_t deadmem = 0; ++ GCObject **p = &g->mainthread->next; ++ GCObject *curr; ++ while ((curr = *p) != NULL) { ++ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) ++ p = &curr->gch.next; /* don't bother with them */ ++ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { ++ markfinalized(gco2u(curr)); /* don't need finalization */ ++ p = &curr->gch.next; ++ } ++ else { /* must call its gc method */ ++ deadmem += sizeudata(gco2u(curr)); ++ markfinalized(gco2u(curr)); ++ *p = curr->gch.next; ++ /* link `curr' at the end of `tmudata' list */ ++ if (g->tmudata == NULL) /* list is empty? */ ++ g->tmudata = curr->gch.next = curr; /* creates a circular list */ ++ else { ++ curr->gch.next = g->tmudata->gch.next; ++ g->tmudata->gch.next = curr; ++ g->tmudata = curr; ++ } ++ } ++ } ++ return deadmem; ++} ++ ++ ++static int traversetable (global_State *g, Table *h) { ++ int i; ++ int weakkey = 0; ++ int weakvalue = 0; ++ const TValue *mode; ++ if (h->metatable) ++ markobject(g, h->metatable); ++ mode = gfasttm(g, h->metatable, TM_MODE); ++ if (mode && ttisstring(mode)) { /* is there a weak mode? */ ++ weakkey = (strchr(svalue(mode), 'k') != NULL); ++ weakvalue = (strchr(svalue(mode), 'v') != NULL); ++ if (weakkey || weakvalue) { /* is really weak? */ ++ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ ++ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | ++ (weakvalue << VALUEWEAKBIT)); ++ h->gclist = g->weak; /* must be cleared after GC, ... */ ++ g->weak = obj2gco(h); /* ... so put in the appropriate list */ ++ } ++ } ++ if (weakkey && weakvalue) return 1; ++ if (!weakvalue) { ++ i = h->sizearray; ++ while (i--) ++ markvalue(g, &h->array[i]); ++ } ++ i = sizenode(h); ++ while (i--) { ++ Node *n = gnode(h, i); ++ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); ++ if (ttisnil(gval(n))) ++ removeentry(n); /* remove empty entries */ ++ else { ++ lua_assert(!ttisnil(gkey(n))); ++ if (!weakkey) markvalue(g, gkey(n)); ++ if (!weakvalue) markvalue(g, gval(n)); ++ } ++ } ++ return weakkey || weakvalue; ++} ++ ++ ++/* ++** All marks are conditional because a GC may happen while the ++** prototype is still being created ++*/ ++static void traverseproto (global_State *g, Proto *f) { ++ int i; ++ if (f->source) stringmark(f->source); ++ for (i=0; i<f->sizek; i++) /* mark literals */ ++ markvalue(g, &f->k[i]); ++ for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ ++ if (f->upvalues[i]) ++ stringmark(f->upvalues[i]); ++ } ++ for (i=0; i<f->sizep; i++) { /* mark nested protos */ ++ if (f->p[i]) ++ markobject(g, f->p[i]); ++ } ++ for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */ ++ if (f->locvars[i].varname) ++ stringmark(f->locvars[i].varname); ++ } ++} ++ ++ ++ ++static void traverseclosure (global_State *g, Closure *cl) { ++ markobject(g, cl->c.env); ++ if (cl->c.isC) { ++ int i; ++ for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ ++ markvalue(g, &cl->c.upvalue[i]); ++ } ++ else { ++ int i; ++ lua_assert(cl->l.nupvalues == cl->l.p->nups); ++ markobject(g, cl->l.p); ++ for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */ ++ markobject(g, cl->l.upvals[i]); ++ } ++} ++ ++ ++static void checkstacksizes (lua_State *L, StkId max) { ++ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ ++ int s_used = cast_int(max - L->stack); /* part of stack in use */ ++ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ ++ return; /* do not touch the stacks */ ++ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) ++ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ ++ condhardstacktests(luaD_reallocCI(L, ci_used + 1)); ++ if (4*s_used < L->stacksize && ++ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) ++ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ ++ condhardstacktests(luaD_reallocstack(L, s_used)); ++} ++ ++ ++static void traversestack (global_State *g, lua_State *l) { ++ StkId o, lim; ++ CallInfo *ci; ++ markvalue(g, gt(l)); ++ lim = l->top; ++ for (ci = l->base_ci; ci <= l->ci; ci++) { ++ lua_assert(ci->top <= l->stack_last); ++ if (lim < ci->top) lim = ci->top; ++ } ++ for (o = l->stack; o < l->top; o++) ++ markvalue(g, o); ++ for (; o <= lim; o++) ++ setnilvalue(o); ++ checkstacksizes(l, lim); ++} ++ ++ ++/* ++** traverse one gray object, turning it to black. ++** Returns `quantity' traversed. ++*/ ++static l_mem propagatemark (global_State *g) { ++ GCObject *o = g->gray; ++ lua_assert(isgray(o)); ++ gray2black(o); ++ switch (o->gch.tt) { ++ case LUA_TTABLE: { ++ Table *h = gco2h(o); ++ g->gray = h->gclist; ++ if (traversetable(g, h)) /* table is weak? */ ++ black2gray(o); /* keep it gray */ ++ return sizeof(Table) + sizeof(TValue) * h->sizearray + ++ sizeof(Node) * sizenode(h); ++ } ++ case LUA_TFUNCTION: { ++ Closure *cl = gco2cl(o); ++ g->gray = cl->c.gclist; ++ traverseclosure(g, cl); ++ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : ++ sizeLclosure(cl->l.nupvalues); ++ } ++ case LUA_TTHREAD: { ++ lua_State *th = gco2th(o); ++ g->gray = th->gclist; ++ th->gclist = g->grayagain; ++ g->grayagain = o; ++ black2gray(o); ++ traversestack(g, th); ++ return sizeof(lua_State) + sizeof(TValue) * th->stacksize + ++ sizeof(CallInfo) * th->size_ci; ++ } ++ case LUA_TPROTO: { ++ Proto *p = gco2p(o); ++ g->gray = p->gclist; ++ traverseproto(g, p); ++ return sizeof(Proto) + sizeof(Instruction) * p->sizecode + ++ sizeof(Proto *) * p->sizep + ++ sizeof(TValue) * p->sizek + ++ sizeof(int) * p->sizelineinfo + ++ sizeof(LocVar) * p->sizelocvars + ++ sizeof(TString *) * p->sizeupvalues; ++ } ++ default: lua_assert(0); return 0; ++ } ++} ++ ++ ++static size_t propagateall (global_State *g) { ++ size_t m = 0; ++ while (g->gray) m += propagatemark(g); ++ return m; ++} ++ ++ ++/* ++** The next function tells whether a key or value can be cleared from ++** a weak table. Non-collectable objects are never removed from weak ++** tables. Strings behave as `values', so are never removed too. for ++** other objects: if really collected, cannot keep them; for userdata ++** being finalized, keep them in keys, but not in values ++*/ ++static int iscleared (const TValue *o, int iskey) { ++ if (!iscollectable(o)) return 0; ++ if (ttisstring(o)) { ++ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ ++ return 0; ++ } ++ return iswhite(gcvalue(o)) || ++ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); ++} ++ ++ ++/* ++** clear collected entries from weaktables ++*/ ++static void cleartable (GCObject *l) { ++ while (l) { ++ Table *h = gco2h(l); ++ int i = h->sizearray; ++ lua_assert(testbit(h->marked, VALUEWEAKBIT) || ++ testbit(h->marked, KEYWEAKBIT)); ++ if (testbit(h->marked, VALUEWEAKBIT)) { ++ while (i--) { ++ TValue *o = &h->array[i]; ++ if (iscleared(o, 0)) /* value was collected? */ ++ setnilvalue(o); /* remove value */ ++ } ++ } ++ i = sizenode(h); ++ while (i--) { ++ Node *n = gnode(h, i); ++ if (!ttisnil(gval(n)) && /* non-empty entry? */ ++ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { ++ setnilvalue(gval(n)); /* remove value ... */ ++ removeentry(n); /* remove entry from table */ ++ } ++ } ++ l = h->gclist; ++ } ++} ++ ++ ++static void freeobj (lua_State *L, GCObject *o) { ++ switch (o->gch.tt) { ++ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; ++ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; ++ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; ++ case LUA_TTABLE: luaH_free(L, gco2h(o)); break; ++ case LUA_TTHREAD: { ++ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); ++ luaE_freethread(L, gco2th(o)); ++ break; ++ } ++ case LUA_TSTRING: { ++ G(L)->strt.nuse--; ++ luaM_freemem(L, o, sizestring(gco2ts(o))); ++ break; ++ } ++ case LUA_TUSERDATA: { ++ luaM_freemem(L, o, sizeudata(gco2u(o))); ++ break; ++ } ++ default: lua_assert(0); ++ } ++} ++ ++ ++ ++#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) ++ ++ ++static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { ++ GCObject *curr; ++ global_State *g = G(L); ++ int deadmask = otherwhite(g); ++ while ((curr = *p) != NULL && count-- > 0) { ++ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ ++ sweepwholelist(L, &gco2th(curr)->openupval); ++ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ ++ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); ++ makewhite(g, curr); /* make it white (for next cycle) */ ++ p = &curr->gch.next; ++ } ++ else { /* must erase `curr' */ ++ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); ++ *p = curr->gch.next; ++ if (curr == g->rootgc) /* is the first element of the list? */ ++ g->rootgc = curr->gch.next; /* adjust first */ ++ freeobj(L, curr); ++ } ++ } ++ return p; ++} ++ ++ ++static void checkSizes (lua_State *L) { ++ global_State *g = G(L); ++ /* check size of string hash */ ++ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && ++ g->strt.size > MINSTRTABSIZE*2) ++ luaS_resize(L, g->strt.size/2); /* table is too big */ ++ /* check size of buffer */ ++ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ ++ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; ++ luaZ_resizebuffer(L, &g->buff, newsize); ++ } ++} ++ ++ ++static void GCTM (lua_State *L) { ++ global_State *g = G(L); ++ GCObject *o = g->tmudata->gch.next; /* get first element */ ++ Udata *udata = rawgco2u(o); ++ const TValue *tm; ++ /* remove udata from `tmudata' */ ++ if (o == g->tmudata) /* last element? */ ++ g->tmudata = NULL; ++ else ++ g->tmudata->gch.next = udata->uv.next; ++ udata->uv.next = g->mainthread->next; /* return it to `root' list */ ++ g->mainthread->next = o; ++ makewhite(g, o); ++ tm = fasttm(L, udata->uv.metatable, TM_GC); ++ if (tm != NULL) { ++ lu_byte oldah = L->allowhook; ++ lu_mem oldt = g->GCthreshold; ++ L->allowhook = 0; /* stop debug hooks during GC tag method */ ++ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ ++ setobj2s(L, L->top, tm); ++ setuvalue(L, L->top+1, udata); ++ L->top += 2; ++ luaD_call(L, L->top - 2, 0); ++ L->allowhook = oldah; /* restore hooks */ ++ g->GCthreshold = oldt; /* restore threshold */ ++ } ++} ++ ++ ++/* ++** Call all GC tag methods ++*/ ++void luaC_callGCTM (lua_State *L) { ++ while (G(L)->tmudata) ++ GCTM(L); ++} ++ ++ ++void luaC_freeall (lua_State *L) { ++ global_State *g = G(L); ++ int i; ++ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ ++ sweepwholelist(L, &g->rootgc); ++ for (i = 0; i < g->strt.size; i++) /* free all string lists */ ++ sweepwholelist(L, &g->strt.hash[i]); ++} ++ ++ ++static void markmt (global_State *g) { ++ int i; ++ for (i=0; i<NUM_TAGS; i++) ++ if (g->mt[i]) markobject(g, g->mt[i]); ++} ++ ++ ++/* mark root set */ ++static void markroot (lua_State *L) { ++ global_State *g = G(L); ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ markobject(g, g->mainthread); ++ /* make global table be traversed before main stack */ ++ markvalue(g, gt(g->mainthread)); ++ markvalue(g, registry(L)); ++ markmt(g); ++ g->gcstate = GCSpropagate; ++} ++ ++ ++static void remarkupvals (global_State *g) { ++ UpVal *uv; ++ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { ++ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); ++ if (isgray(obj2gco(uv))) ++ markvalue(g, uv->v); ++ } ++} ++ ++ ++static void atomic (lua_State *L) { ++ global_State *g = G(L); ++ size_t udsize; /* total size of userdata to be finalized */ ++ /* remark occasional upvalues of (maybe) dead threads */ ++ remarkupvals(g); ++ /* traverse objects cautch by write barrier and by 'remarkupvals' */ ++ propagateall(g); ++ /* remark weak tables */ ++ g->gray = g->weak; ++ g->weak = NULL; ++ lua_assert(!iswhite(obj2gco(g->mainthread))); ++ markobject(g, L); /* mark running thread */ ++ markmt(g); /* mark basic metatables (again) */ ++ propagateall(g); ++ /* remark gray again */ ++ g->gray = g->grayagain; ++ g->grayagain = NULL; ++ propagateall(g); ++ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ ++ marktmu(g); /* mark `preserved' userdata */ ++ udsize += propagateall(g); /* remark, to propagate `preserveness' */ ++ cleartable(g->weak); /* remove collected objects from weak tables */ ++ /* flip current white */ ++ g->currentwhite = cast_byte(otherwhite(g)); ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ g->gcstate = GCSsweepstring; ++ g->estimate = g->totalbytes - udsize; /* first estimate */ ++} ++ ++ ++static l_mem singlestep (lua_State *L) { ++ global_State *g = G(L); ++ /*lua_checkmemory(L);*/ ++ switch (g->gcstate) { ++ case GCSpause: { ++ markroot(L); /* start a new collection */ ++ return 0; ++ } ++ case GCSpropagate: { ++ if (g->gray) ++ return propagatemark(g); ++ else { /* no more `gray' objects */ ++ atomic(L); /* finish mark phase */ ++ return 0; ++ } ++ } ++ case GCSsweepstring: { ++ lu_mem old = g->totalbytes; ++ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); ++ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ ++ g->gcstate = GCSsweep; /* end sweep-string phase */ ++ lua_assert(old >= g->totalbytes); ++ g->estimate -= old - g->totalbytes; ++ return GCSWEEPCOST; ++ } ++ case GCSsweep: { ++ lu_mem old = g->totalbytes; ++ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); ++ if (*g->sweepgc == NULL) { /* nothing more to sweep? */ ++ checkSizes(L); ++ g->gcstate = GCSfinalize; /* end sweep phase */ ++ } ++ lua_assert(old >= g->totalbytes); ++ g->estimate -= old - g->totalbytes; ++ return GCSWEEPMAX*GCSWEEPCOST; ++ } ++ case GCSfinalize: { ++ if (g->tmudata) { ++ GCTM(L); ++ if (g->estimate > GCFINALIZECOST) ++ g->estimate -= GCFINALIZECOST; ++ return GCFINALIZECOST; ++ } ++ else { ++ g->gcstate = GCSpause; /* end collection */ ++ g->gcdept = 0; ++ return 0; ++ } ++ } ++ default: lua_assert(0); return 0; ++ } ++} ++ ++ ++void luaC_step (lua_State *L) { ++ global_State *g = G(L); ++ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; ++ if (lim == 0) ++ lim = (MAX_LUMEM-1)/2; /* no limit */ ++ g->gcdept += g->totalbytes - g->GCthreshold; ++ do { ++ lim -= singlestep(L); ++ if (g->gcstate == GCSpause) ++ break; ++ } while (lim > 0); ++ if (g->gcstate != GCSpause) { ++ if (g->gcdept < GCSTEPSIZE) ++ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ ++ else { ++ g->gcdept -= GCSTEPSIZE; ++ g->GCthreshold = g->totalbytes; ++ } ++ } ++ else { ++ lua_assert(g->totalbytes >= g->estimate); ++ setthreshold(g); ++ } ++} ++ ++ ++void luaC_fullgc (lua_State *L) { ++ global_State *g = G(L); ++ if (g->gcstate <= GCSpropagate) { ++ /* reset sweep marks to sweep all elements (returning them to white) */ ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ /* reset other collector lists */ ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ g->gcstate = GCSsweepstring; ++ } ++ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); ++ /* finish any pending sweep phase */ ++ while (g->gcstate != GCSfinalize) { ++ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); ++ singlestep(L); ++ } ++ markroot(L); ++ while (g->gcstate != GCSpause) { ++ singlestep(L); ++ } ++ setthreshold(g); ++} ++ ++ ++void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { ++ global_State *g = G(L); ++ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ lua_assert(ttype(&o->gch) != LUA_TTABLE); ++ /* must keep invariant? */ ++ if (g->gcstate == GCSpropagate) ++ reallymarkobject(g, v); /* restore invariant */ ++ else /* don't mind */ ++ makewhite(g, o); /* mark as white just to avoid other barriers */ ++} ++ ++ ++void luaC_barrierback (lua_State *L, Table *t) { ++ global_State *g = G(L); ++ GCObject *o = obj2gco(t); ++ lua_assert(isblack(o) && !isdead(g, o)); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ black2gray(o); /* make table gray (again) */ ++ t->gclist = g->grayagain; ++ g->grayagain = o; ++} ++ ++ ++void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { ++ global_State *g = G(L); ++ o->gch.next = g->rootgc; ++ g->rootgc = o; ++ o->gch.marked = luaC_white(g); ++ o->gch.tt = tt; ++} ++ ++ ++void luaC_linkupval (lua_State *L, UpVal *uv) { ++ global_State *g = G(L); ++ GCObject *o = obj2gco(uv); ++ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ ++ g->rootgc = o; ++ if (isgray(o)) { ++ if (g->gcstate == GCSpropagate) { ++ gray2black(o); /* closed upvalues need barrier */ ++ luaC_barrier(L, uv, uv->v); ++ } ++ else { /* sweep phase: sweep it (turning it into white) */ ++ makewhite(g, o); ++ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); ++ } ++ } ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lgc.h +@@ -0,0 +1,110 @@ ++/* ++** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Garbage Collector ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lgc_h ++#define lgc_h ++ ++ ++#include "lobject.h" ++ ++ ++/* ++** Possible states of the Garbage Collector ++*/ ++#define GCSpause 0 ++#define GCSpropagate 1 ++#define GCSsweepstring 2 ++#define GCSsweep 3 ++#define GCSfinalize 4 ++ ++ ++/* ++** some userful bit tricks ++*/ ++#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) ++#define setbits(x,m) ((x) |= (m)) ++#define testbits(x,m) ((x) & (m)) ++#define bitmask(b) (1<<(b)) ++#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) ++#define l_setbit(x,b) setbits(x, bitmask(b)) ++#define resetbit(x,b) resetbits(x, bitmask(b)) ++#define testbit(x,b) testbits(x, bitmask(b)) ++#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) ++#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) ++#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) ++ ++ ++ ++/* ++** Layout for bit use in `marked' field: ++** bit 0 - object is white (type 0) ++** bit 1 - object is white (type 1) ++** bit 2 - object is black ++** bit 3 - for userdata: has been finalized ++** bit 3 - for tables: has weak keys ++** bit 4 - for tables: has weak values ++** bit 5 - object is fixed (should not be collected) ++** bit 6 - object is "super" fixed (only the main thread) ++*/ ++ ++ ++#define WHITE0BIT 0 ++#define WHITE1BIT 1 ++#define BLACKBIT 2 ++#define FINALIZEDBIT 3 ++#define KEYWEAKBIT 3 ++#define VALUEWEAKBIT 4 ++#define FIXEDBIT 5 ++#define SFIXEDBIT 6 ++#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) ++ ++ ++#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) ++#define isblack(x) testbit((x)->gch.marked, BLACKBIT) ++#define isgray(x) (!isblack(x) && !iswhite(x)) ++ ++#define otherwhite(g) (g->currentwhite ^ WHITEBITS) ++#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) ++ ++#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) ++#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) ++ ++#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) ++ ++#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) ++ ++ ++#define luaC_checkGC(L) { \ ++ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ ++ if (G(L)->totalbytes >= G(L)->GCthreshold) \ ++ luaC_step(L); } ++ ++ ++#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ ++ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } ++ ++#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ ++ luaC_barrierback(L,t); } ++ ++#define luaC_objbarrier(L,p,o) \ ++ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ ++ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } ++ ++#define luaC_objbarriert(L,t,o) \ ++ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } ++ ++LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); ++LUAI_FUNC void luaC_callGCTM (lua_State *L); ++LUAI_FUNC void luaC_freeall (lua_State *L); ++LUAI_FUNC void luaC_step (lua_State *L); ++LUAI_FUNC void luaC_fullgc (lua_State *L); ++LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); ++LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); ++LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); ++LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/llex.c +@@ -0,0 +1,460 @@ ++/* ++** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lexical Analyzer ++** See Copyright Notice in lua.h ++*/ ++ ++#include <ctype.h> ++#include <locale.h> ++#include <string.h> ++ ++#define llex_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldo.h" ++#include "llex.h" ++#include "lobject.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "lzio.h" ++ ++ ++ ++#define next(ls) (ls->current = zgetc(ls->z)) ++ ++ ++ ++ ++#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') ++ ++ ++/* ORDER RESERVED */ ++const char *const luaX_tokens [] = { ++ "and", "break", "do", "else", "elseif", ++ "end", "false", "for", "function", "if", ++ "in", "local", "nil", "not", "or", "repeat", ++ "return", "then", "true", "until", "while", ++ "..", "...", "==", ">=", "<=", "~=", ++ "<number>", "<name>", "<string>", "<eof>", ++ NULL ++}; ++ ++ ++#define save_and_next(ls) (save(ls, ls->current), next(ls)) ++ ++ ++static void save (LexState *ls, int c) { ++ Mbuffer *b = ls->buff; ++ if (b->n + 1 > b->buffsize) { ++ size_t newsize; ++ if (b->buffsize >= MAX_SIZET/2) ++ luaX_lexerror(ls, "lexical element too long", 0); ++ newsize = b->buffsize * 2; ++ luaZ_resizebuffer(ls->L, b, newsize); ++ } ++ b->buffer[b->n++] = cast(char, c); ++} ++ ++ ++void luaX_init (lua_State *L) { ++ int i; ++ for (i=0; i<NUM_RESERVED; i++) { ++ TString *ts = luaS_new(L, luaX_tokens[i]); ++ luaS_fix(ts); /* reserved words are never collected */ ++ lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN); ++ ts->tsv.reserved = cast_byte(i+1); /* reserved word */ ++ } ++} ++ ++ ++#define MAXSRC 80 ++ ++ ++const char *luaX_token2str (LexState *ls, int token) { ++ if (token < FIRST_RESERVED) { ++ lua_assert(token == cast(unsigned char, token)); ++ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : ++ luaO_pushfstring(ls->L, "%c", token); ++ } ++ else ++ return luaX_tokens[token-FIRST_RESERVED]; ++} ++ ++ ++static const char *txtToken (LexState *ls, int token) { ++ switch (token) { ++ case TK_NAME: ++ case TK_STRING: ++ case TK_NUMBER: ++ save(ls, '\0'); ++ return luaZ_buffer(ls->buff); ++ default: ++ return luaX_token2str(ls, token); ++ } ++} ++ ++ ++void luaX_lexerror (LexState *ls, const char *msg, int token) { ++ char buff[MAXSRC]; ++ luaO_chunkid(buff, getstr(ls->source), MAXSRC); ++ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); ++ if (token) ++ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); ++ luaD_throw(ls->L, LUA_ERRSYNTAX); ++} ++ ++ ++void luaX_syntaxerror (LexState *ls, const char *msg) { ++ luaX_lexerror(ls, msg, ls->t.token); ++} ++ ++ ++TString *luaX_newstring (LexState *ls, const char *str, size_t l) { ++ lua_State *L = ls->L; ++ TString *ts = luaS_newlstr(L, str, l); ++ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ ++ if (ttisnil(o)) ++ setbvalue(o, 1); /* make sure `str' will not be collected */ ++ return ts; ++} ++ ++ ++static void inclinenumber (LexState *ls) { ++ int old = ls->current; ++ lua_assert(currIsNewline(ls)); ++ next(ls); /* skip `\n' or `\r' */ ++ if (currIsNewline(ls) && ls->current != old) ++ next(ls); /* skip `\n\r' or `\r\n' */ ++ if (++ls->linenumber >= MAX_INT) ++ luaX_syntaxerror(ls, "chunk has too many lines"); ++} ++ ++ ++void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { ++ ls->decpoint = '.'; ++ ls->L = L; ++ ls->lookahead.token = TK_EOS; /* no look-ahead token */ ++ ls->z = z; ++ ls->fs = NULL; ++ ls->linenumber = 1; ++ ls->lastline = 1; ++ ls->source = source; ++ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ ++ next(ls); /* read first char */ ++} ++ ++ ++ ++/* ++** ======================================================= ++** LEXICAL ANALYZER ++** ======================================================= ++*/ ++ ++ ++ ++static int check_next (LexState *ls, const char *set) { ++ if (!strchr(set, ls->current)) ++ return 0; ++ save_and_next(ls); ++ return 1; ++} ++ ++ ++static void buffreplace (LexState *ls, char from, char to) { ++ size_t n = luaZ_bufflen(ls->buff); ++ char *p = luaZ_buffer(ls->buff); ++ while (n--) ++ if (p[n] == from) p[n] = to; ++} ++ ++ ++static void trydecpoint (LexState *ls, SemInfo *seminfo) { ++ /* format error: try to update decimal point separator */ ++ char old = ls->decpoint; ++ struct lconv *cv = localeconv(); ++ ls->decpoint = (cv ? cv->decimal_point[0] : '.'); ++ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ ++ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { ++ /* format error with correct decimal point: no more options */ ++ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ ++ luaX_lexerror(ls, "malformed number", TK_NUMBER); ++ } ++} ++ ++ ++/* LUA_NUMBER */ ++static void read_numeral (LexState *ls, SemInfo *seminfo) { ++ lua_assert(isdigit(ls->current)); ++ do { ++ save_and_next(ls); ++ } while (isdigit(ls->current) || ls->current == '.'); ++ if (check_next(ls, "Ee")) /* `E'? */ ++ check_next(ls, "+-"); /* optional exponent sign */ ++ while (isalnum(ls->current) || ls->current == '_') ++ save_and_next(ls); ++ save(ls, '\0'); ++ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ ++ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ ++ trydecpoint(ls, seminfo); /* try to update decimal point separator */ ++} ++ ++ ++static int skip_sep (LexState *ls) { ++ int count = 0; ++ int s = ls->current; ++ lua_assert(s == '[' || s == ']'); ++ save_and_next(ls); ++ while (ls->current == '=') { ++ save_and_next(ls); ++ count++; ++ } ++ return (ls->current == s) ? count : (-count) - 1; ++} ++ ++ ++static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { ++ int cont = 0; ++ (void)(cont); /* avoid warnings when `cont' is not used */ ++ save_and_next(ls); /* skip 2nd `[' */ ++ if (currIsNewline(ls)) /* string starts with a newline? */ ++ inclinenumber(ls); /* skip it */ ++ for (;;) { ++ switch (ls->current) { ++ case EOZ: ++ luaX_lexerror(ls, (seminfo) ? "unfinished long string" : ++ "unfinished long comment", TK_EOS); ++ break; /* to avoid warnings */ ++#if defined(LUA_COMPAT_LSTR) ++ case '[': { ++ if (skip_sep(ls) == sep) { ++ save_and_next(ls); /* skip 2nd `[' */ ++ cont++; ++#if LUA_COMPAT_LSTR == 1 ++ if (sep == 0) ++ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); ++#endif ++ } ++ break; ++ } ++#endif ++ case ']': { ++ if (skip_sep(ls) == sep) { ++ save_and_next(ls); /* skip 2nd `]' */ ++#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 ++ cont--; ++ if (sep == 0 && cont >= 0) break; ++#endif ++ goto endloop; ++ } ++ break; ++ } ++ case '\n': ++ case '\r': { ++ save(ls, '\n'); ++ inclinenumber(ls); ++ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ ++ break; ++ } ++ default: { ++ if (seminfo) save_and_next(ls); ++ else next(ls); ++ } ++ } ++ } endloop: ++ if (seminfo) ++ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), ++ luaZ_bufflen(ls->buff) - 2*(2 + sep)); ++} ++ ++ ++static void read_string (LexState *ls, int del, SemInfo *seminfo) { ++ save_and_next(ls); ++ while (ls->current != del) { ++ switch (ls->current) { ++ case EOZ: ++ luaX_lexerror(ls, "unfinished string", TK_EOS); ++ continue; /* to avoid warnings */ ++ case '\n': ++ case '\r': ++ luaX_lexerror(ls, "unfinished string", TK_STRING); ++ continue; /* to avoid warnings */ ++ case '\\': { ++ int c; ++ next(ls); /* do not save the `\' */ ++ switch (ls->current) { ++ case 'a': c = '\a'; break; ++ case 'b': c = '\b'; break; ++ case 'f': c = '\f'; break; ++ case 'n': c = '\n'; break; ++ case 'r': c = '\r'; break; ++ case 't': c = '\t'; break; ++ case 'v': c = '\v'; break; ++ case '\n': /* go through */ ++ case '\r': save(ls, '\n'); inclinenumber(ls); continue; ++ case EOZ: continue; /* will raise an error next loop */ ++ default: { ++ if (!isdigit(ls->current)) ++ save_and_next(ls); /* handles \\, \", \', and \? */ ++ else { /* \xxx */ ++ int i = 0; ++ c = 0; ++ do { ++ c = 10*c + (ls->current-'0'); ++ next(ls); ++ } while (++i<3 && isdigit(ls->current)); ++ if (c > UCHAR_MAX) ++ luaX_lexerror(ls, "escape sequence too large", TK_STRING); ++ save(ls, c); ++ } ++ continue; ++ } ++ } ++ save(ls, c); ++ next(ls); ++ continue; ++ } ++ default: ++ save_and_next(ls); ++ } ++ } ++ save_and_next(ls); /* skip delimiter */ ++ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, ++ luaZ_bufflen(ls->buff) - 2); ++} ++ ++ ++static int llex (LexState *ls, SemInfo *seminfo) { ++ luaZ_resetbuffer(ls->buff); ++ for (;;) { ++ switch (ls->current) { ++ case '\n': ++ case '\r': { ++ inclinenumber(ls); ++ continue; ++ } ++ case '-': { ++ next(ls); ++ if (ls->current != '-') return '-'; ++ /* else is a comment */ ++ next(ls); ++ if (ls->current == '[') { ++ int sep = skip_sep(ls); ++ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ ++ if (sep >= 0) { ++ read_long_string(ls, NULL, sep); /* long comment */ ++ luaZ_resetbuffer(ls->buff); ++ continue; ++ } ++ } ++ /* else short comment */ ++ while (!currIsNewline(ls) && ls->current != EOZ) ++ next(ls); ++ continue; ++ } ++ case '[': { ++ int sep = skip_sep(ls); ++ if (sep >= 0) { ++ read_long_string(ls, seminfo, sep); ++ return TK_STRING; ++ } ++ else if (sep == -1) return '['; ++ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); ++ } ++ case '=': { ++ next(ls); ++ if (ls->current != '=') return '='; ++ else { next(ls); return TK_EQ; } ++ } ++ case '<': { ++ next(ls); ++ if (ls->current != '=') return '<'; ++ else { next(ls); return TK_LE; } ++ } ++ case '>': { ++ next(ls); ++ if (ls->current != '=') return '>'; ++ else { next(ls); return TK_GE; } ++ } ++ case '~': { ++ next(ls); ++ if (ls->current != '=') return '~'; ++ else { next(ls); return TK_NE; } ++ } ++ case '"': ++ case '\'': { ++ read_string(ls, ls->current, seminfo); ++ return TK_STRING; ++ } ++ case '.': { ++ save_and_next(ls); ++ if (check_next(ls, ".")) { ++ if (check_next(ls, ".")) ++ return TK_DOTS; /* ... */ ++ else return TK_CONCAT; /* .. */ ++ } ++ else if (!isdigit(ls->current)) return '.'; ++ else { ++ read_numeral(ls, seminfo); ++ return TK_NUMBER; ++ } ++ } ++ case EOZ: { ++ return TK_EOS; ++ } ++ default: { ++ if (isspace(ls->current)) { ++ lua_assert(!currIsNewline(ls)); ++ next(ls); ++ continue; ++ } ++ else if (isdigit(ls->current)) { ++ read_numeral(ls, seminfo); ++ return TK_NUMBER; ++ } ++ else if (isalpha(ls->current) || ls->current == '_') { ++ /* identifier or reserved word */ ++ TString *ts; ++ do { ++ save_and_next(ls); ++ } while (isalnum(ls->current) || ls->current == '_'); ++ ts = luaX_newstring(ls, luaZ_buffer(ls->buff), ++ luaZ_bufflen(ls->buff)); ++ if (ts->tsv.reserved > 0) /* reserved word? */ ++ return ts->tsv.reserved - 1 + FIRST_RESERVED; ++ else { ++ seminfo->ts = ts; ++ return TK_NAME; ++ } ++ } ++ else { ++ int c = ls->current; ++ next(ls); ++ return c; /* single-char tokens (+ - / ...) */ ++ } ++ } ++ } ++ } ++} ++ ++ ++void luaX_next (LexState *ls) { ++ ls->lastline = ls->linenumber; ++ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ ++ ls->t = ls->lookahead; /* use this one */ ++ ls->lookahead.token = TK_EOS; /* and discharge it */ ++ } ++ else ++ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ ++} ++ ++ ++void luaX_lookahead (LexState *ls) { ++ lua_assert(ls->lookahead.token == TK_EOS); ++ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/llex.h +@@ -0,0 +1,81 @@ ++/* ++** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lexical Analyzer ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef llex_h ++#define llex_h ++ ++#include "lobject.h" ++#include "lzio.h" ++ ++ ++#define FIRST_RESERVED 257 ++ ++/* maximum length of a reserved word */ ++#define TOKEN_LEN (sizeof("function")/sizeof(char)) ++ ++ ++/* ++* WARNING: if you change the order of this enumeration, ++* grep "ORDER RESERVED" ++*/ ++enum RESERVED { ++ /* terminal symbols denoted by reserved words */ ++ TK_AND = FIRST_RESERVED, TK_BREAK, ++ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, ++ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, ++ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, ++ /* other terminal symbols */ ++ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, ++ TK_NAME, TK_STRING, TK_EOS ++}; ++ ++/* number of reserved words */ ++#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) ++ ++ ++/* array with token `names' */ ++LUAI_DATA const char *const luaX_tokens []; ++ ++ ++typedef union { ++ lua_Number r; ++ TString *ts; ++} SemInfo; /* semantics information */ ++ ++ ++typedef struct Token { ++ int token; ++ SemInfo seminfo; ++} Token; ++ ++ ++typedef struct LexState { ++ int current; /* current character (charint) */ ++ int linenumber; /* input line counter */ ++ int lastline; /* line of last token `consumed' */ ++ Token t; /* current token */ ++ Token lookahead; /* look ahead token */ ++ struct FuncState *fs; /* `FuncState' is private to the parser */ ++ struct lua_State *L; ++ ZIO *z; /* input stream */ ++ Mbuffer *buff; /* buffer for tokens */ ++ TString *source; /* current source name */ ++ char decpoint; /* locale decimal point */ ++} LexState; ++ ++ ++LUAI_FUNC void luaX_init (lua_State *L); ++LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, ++ TString *source); ++LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); ++LUAI_FUNC void luaX_next (LexState *ls); ++LUAI_FUNC void luaX_lookahead (LexState *ls); ++LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); ++LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); ++LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/llimits.h +@@ -0,0 +1,125 @@ ++/* ++** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Limits, basic types, and some other `installation-dependent' definitions ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef llimits_h ++#define llimits_h ++ ++#include <stddef.h> ++#include <limits.h> ++ ++#include "lua.h" ++ ++typedef LUAI_UINT32 lu_int32; ++ ++typedef LUAI_UMEM lu_mem; ++ ++typedef LUAI_MEM l_mem; ++ ++ ++ ++/* chars used as small naturals (so that `char' is reserved for characters) */ ++typedef unsigned char lu_byte; ++ ++ ++#define MAX_SIZET ((size_t)(~(size_t)0)-2) ++ ++#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) ++ ++ ++#define MAX_INT (LUA_INT_MAX-2) /* maximum value of an int (-2 for safety) */ ++ ++/* ++** conversion of pointer to integer ++** this is for hashing only; there is no problem if the integer ++** cannot hold the whole pointer value ++*/ ++#define IntPoint(p) ((unsigned int)(lu_mem)(p)) ++ ++ ++ ++/* type to ensure maximum alignment */ ++typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; ++ ++ ++/* result of a `usual argument conversion' over lua_Number */ ++typedef LUAI_UACNUMBER l_uacNumber; ++ ++ ++/* internal assertions for in-house debugging */ ++#ifdef lua_assert ++ ++#define check_exp(c,e) (lua_assert(c), (e)) ++#define api_check(l,e) lua_assert(e) ++ ++#else ++ ++#define lua_assert(c) ((void)0) ++#define check_exp(c,e) (e) ++#define api_check luai_apicheck ++ ++#endif ++ ++ ++#ifndef UNUSED ++#define UNUSED(x) ((void)(x)) /* to avoid warnings */ ++#endif ++ ++ ++#ifndef cast ++#define cast(t, exp) ((t)(exp)) ++#endif ++ ++#define cast_byte(i) cast(lu_byte, (i)) ++#define cast_num(i) cast(lua_Number, (i)) ++#define cast_int(i) cast(int, (i)) ++ ++ ++ ++/* ++** type for virtual-machine instructions ++** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) ++*/ ++typedef lu_int32 Instruction; ++ ++ ++ ++/* maximum stack for a Lua function */ ++#define MAXSTACK 250 ++ ++ ++ ++/* minimum size for the string table (must be power of 2) */ ++#ifndef MINSTRTABSIZE ++#define MINSTRTABSIZE 32 ++#endif ++ ++ ++/* minimum size for string buffer */ ++#ifndef LUA_MINBUFFER ++#define LUA_MINBUFFER 32 ++#endif ++ ++ ++#ifndef lua_lock ++#define lua_lock(L) ((void) 0) ++#define lua_unlock(L) ((void) 0) ++#endif ++ ++#ifndef luai_threadyield ++#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} ++#endif ++ ++ ++/* ++** macro to control inclusion of some hard tests on stack reallocation ++*/ ++#ifndef HARDSTACKTESTS ++#define condhardstacktests(x) ((void)0) ++#else ++#define condhardstacktests(x) x ++#endif ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lmem.c +@@ -0,0 +1,86 @@ ++/* ++** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Interface to Memory Manager ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <stddef.h> ++ ++#define lmem_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++ ++/* ++** About the realloc function: ++** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ++** (`osize' is the old size, `nsize' is the new size) ++** ++** Lua ensures that (ptr == NULL) iff (osize == 0). ++** ++** * frealloc(ud, NULL, 0, x) creates a new block of size `x' ++** ++** * frealloc(ud, p, x, 0) frees the block `p' ++** (in this specific case, frealloc must return NULL). ++** particularly, frealloc(ud, NULL, 0, 0) does nothing ++** (which is equivalent to free(NULL) in ANSI C) ++** ++** frealloc returns NULL if it cannot create or reallocate the area ++** (any reallocation to an equal or smaller size cannot fail!) ++*/ ++ ++ ++ ++#define MINSIZEARRAY 4 ++ ++ ++void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, ++ int limit, const char *errormsg) { ++ void *newblock; ++ int newsize; ++ if (*size >= limit/2) { /* cannot double it? */ ++ if (*size >= limit) /* cannot grow even a little? */ ++ luaG_runerror(L, errormsg); ++ newsize = limit; /* still have at least one free place */ ++ } ++ else { ++ newsize = (*size)*2; ++ if (newsize < MINSIZEARRAY) ++ newsize = MINSIZEARRAY; /* minimum size */ ++ } ++ newblock = luaM_reallocv(L, block, *size, newsize, size_elems); ++ *size = newsize; /* update only when everything else is OK */ ++ return newblock; ++} ++ ++ ++void *luaM_toobig (lua_State *L) { ++ luaG_runerror(L, "memory allocation error: block too big"); ++ return NULL; /* to avoid warnings */ ++} ++ ++ ++ ++/* ++** generic allocation routine. ++*/ ++void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { ++ global_State *g = G(L); ++ lua_assert((osize == 0) == (block == NULL)); ++ block = (*g->frealloc)(g->ud, block, osize, nsize); ++ if (block == NULL && nsize > 0) ++ luaD_throw(L, LUA_ERRMEM); ++ lua_assert((nsize == 0) == (block == NULL)); ++ g->totalbytes = (g->totalbytes - osize) + nsize; ++ return block; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lmem.h +@@ -0,0 +1,49 @@ ++/* ++** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Interface to Memory Manager ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lmem_h ++#define lmem_h ++ ++ ++#include <stddef.h> ++ ++#include "llimits.h" ++#include "lua.h" ++ ++#define MEMERRMSG "not enough memory" ++ ++ ++#define luaM_reallocv(L,b,on,n,e) \ ++ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ ++ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ ++ luaM_toobig(L)) ++ ++#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) ++#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) ++#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) ++ ++#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) ++#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) ++#define luaM_newvector(L,n,t) \ ++ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) ++ ++#define luaM_growvector(L,v,nelems,size,t,limit,e) \ ++ if ((nelems)+1 > (size)) \ ++ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) ++ ++#define luaM_reallocvector(L, v,oldn,n,t) \ ++ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) ++ ++ ++LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, ++ size_t size); ++LUAI_FUNC void *luaM_toobig (lua_State *L); ++LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, ++ size_t size_elem, int limit, ++ const char *errormsg); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lobject.c +@@ -0,0 +1,215 @@ ++/* ++** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Some generic functions over Lua objects ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdarg.h> ++ ++#include <ctype.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#define lobject_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldo.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "lvm.h" ++ ++ ++ ++const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; ++ ++ ++/* ++** converts an integer to a "floating point byte", represented as ++** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ++** eeeee != 0 and (xxx) otherwise. ++*/ ++int luaO_int2fb (unsigned int x) { ++ int e = 0; /* expoent */ ++ while (x >= 16) { ++ x = (x+1) >> 1; ++ e++; ++ } ++ if (x < 8) return x; ++ else return ((e+1) << 3) | (cast_int(x) - 8); ++} ++ ++ ++/* converts back */ ++int luaO_fb2int (int x) { ++ int e = (x >> 3) & 31; ++ if (e == 0) return x; ++ else return ((x & 7)+8) << (e - 1); ++} ++ ++ ++int luaO_log2 (unsigned int x) { ++ static const lu_byte log_2[256] = { ++ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, ++ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, ++ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 ++ }; ++ int l = -1; ++ while (x >= 256) { l += 8; x >>= 8; } ++ return l + log_2[x]; ++ ++} ++ ++ ++int luaO_rawequalObj (const TValue *t1, const TValue *t2) { ++ if (ttype(t1) != ttype(t2)) return 0; ++ else switch (ttype(t1)) { ++ case LUA_TNIL: ++ return 1; ++ case LUA_TNUMBER: ++ return luai_numeq(nvalue(t1), nvalue(t2)); ++ case LUA_TBOOLEAN: ++ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: ++ return pvalue(t1) == pvalue(t2); ++ default: ++ lua_assert(iscollectable(t1)); ++ return gcvalue(t1) == gcvalue(t2); ++ } ++} ++ ++ ++int luaO_str2d (const char *s, lua_Number *result) { ++ char *endptr; ++ *result = lua_str2number(s, &endptr); ++ if (endptr == s) return 0; /* conversion failed */ ++ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ ++ *result = cast_num(strtoul(s, &endptr, 16)); ++ if (*endptr == '\0') return 1; /* most common case */ ++ while (isspace(cast(unsigned char, *endptr))) endptr++; ++ if (*endptr != '\0') return 0; /* invalid trailing characters? */ ++ return 1; ++} ++ ++ ++ ++static void pushstr (lua_State *L, const char *str) { ++ setsvalue2s(L, L->top, luaS_new(L, str)); ++ incr_top(L); ++} ++ ++ ++/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ ++const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { ++ int n = 1; ++ pushstr(L, ""); ++ for (;;) { ++ const char *e = strchr(fmt, '%'); ++ if (e == NULL) break; ++ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); ++ incr_top(L); ++ switch (*(e+1)) { ++ case 's': { ++ const char *s = va_arg(argp, char *); ++ if (s == NULL) s = "(null)"; ++ pushstr(L, s); ++ break; ++ } ++ case 'c': { ++ char buff[2]; ++ buff[0] = cast(char, va_arg(argp, int)); ++ buff[1] = '\0'; ++ pushstr(L, buff); ++ break; ++ } ++ case 'd': { ++ setnvalue(L->top, cast_num(va_arg(argp, int))); ++ incr_top(L); ++ break; ++ } ++ case 'f': { ++ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); ++ incr_top(L); ++ break; ++ } ++ case 'p': { ++ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ ++ sprintf(buff, "%p", va_arg(argp, void *)); ++ pushstr(L, buff); ++ break; ++ } ++ case '%': { ++ pushstr(L, "%"); ++ break; ++ } ++ default: { ++ char buff[3]; ++ buff[0] = '%'; ++ buff[1] = *(e+1); ++ buff[2] = '\0'; ++ pushstr(L, buff); ++ break; ++ } ++ } ++ n += 2; ++ fmt = e+2; ++ } ++ pushstr(L, fmt); ++ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); ++ L->top -= n; ++ return svalue(L->top - 1); ++} ++ ++ ++const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { ++ const char *msg; ++ va_list argp; ++ va_start(argp, fmt); ++ msg = luaO_pushvfstring(L, fmt, argp); ++ va_end(argp); ++ return msg; ++} ++ ++ ++void luaO_chunkid (char *out, const char *source, size_t bufflen) { ++ if (*source == '=') { ++ strncpy(out, source+1, bufflen); /* remove first char */ ++ out[bufflen-1] = '\0'; /* ensures null termination */ ++ } ++ else { /* out = "source", or "...source" */ ++ if (*source == '@') { ++ size_t l; ++ source++; /* skip the `@' */ ++ bufflen -= sizeof(" '...' "); ++ l = strlen(source); ++ strcpy(out, ""); ++ if (l > bufflen) { ++ source += (l-bufflen); /* get last part of file name */ ++ strcat(out, "..."); ++ } ++ strcat(out, source); ++ } ++ else { /* out = [string "string"] */ ++ size_t len = strcspn(source, "\n\r"); /* stop at first newline */ ++ bufflen -= sizeof(" [string \"...\"] "); ++ if (len > bufflen) len = bufflen; ++ strcpy(out, "[string \""); ++ if (source[len] != '\0') { /* must truncate? */ ++ strncat(out, source, len); ++ strcat(out, "..."); ++ } ++ else ++ strcat(out, source); ++ strcat(out, "\"]"); ++ } ++ } ++} +--- /dev/null ++++ b/extensions/LUA/lua/lobject.h +@@ -0,0 +1,381 @@ ++/* ++** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ ++** Type definitions for Lua objects ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lobject_h ++#define lobject_h ++ ++ ++#include <stdarg.h> ++ ++ ++#include "llimits.h" ++#include "lua.h" ++ ++ ++/* tags for values visible from Lua */ ++#define LAST_TAG LUA_TTHREAD ++ ++#define NUM_TAGS (LAST_TAG+1) ++ ++ ++/* ++** Extra tags for non-values ++*/ ++#define LUA_TPROTO (LAST_TAG+1) ++#define LUA_TUPVAL (LAST_TAG+2) ++#define LUA_TDEADKEY (LAST_TAG+3) ++ ++ ++/* ++** Union of all collectable objects ++*/ ++typedef union GCObject GCObject; ++ ++ ++/* ++** Common Header for all collectable objects (in macro form, to be ++** included in other objects) ++*/ ++#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked ++ ++ ++/* ++** Common header in struct form ++*/ ++typedef struct GCheader { ++ CommonHeader; ++} GCheader; ++ ++ ++ ++ ++/* ++** Union of all Lua values ++*/ ++typedef union { ++ GCObject *gc; ++ void *p; ++ lua_Number n; ++ int b; ++} Value; ++ ++ ++/* ++** Tagged Values ++*/ ++ ++#define TValuefields Value value; int tt ++ ++typedef struct lua_TValue { ++ TValuefields; ++} TValue; ++ ++ ++/* Macros to test type */ ++#define ttisnil(o) (ttype(o) == LUA_TNIL) ++#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) ++#define ttisstring(o) (ttype(o) == LUA_TSTRING) ++#define ttistable(o) (ttype(o) == LUA_TTABLE) ++#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) ++#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) ++#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) ++#define ttisthread(o) (ttype(o) == LUA_TTHREAD) ++#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) ++ ++/* Macros to access values */ ++#define ttype(o) ((o)->tt) ++#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) ++#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) ++#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) ++#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) ++#define tsvalue(o) (&rawtsvalue(o)->tsv) ++#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) ++#define uvalue(o) (&rawuvalue(o)->uv) ++#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) ++#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) ++#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) ++#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) ++ ++#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) ++ ++/* ++** for internal debug only ++*/ ++#define checkconsistency(obj) \ ++ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) ++ ++#define checkliveness(g,obj) \ ++ lua_assert(!iscollectable(obj) || \ ++ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) ++ ++ ++/* Macros to set values */ ++#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) ++ ++#define setnvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } ++ ++#define setpvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } ++ ++#define setbvalue(obj,x) \ ++ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } ++ ++#define setsvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ ++ checkliveness(G(L),i_o); } ++ ++#define setuvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ ++ checkliveness(G(L),i_o); } ++ ++#define setthvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ ++ checkliveness(G(L),i_o); } ++ ++#define setclvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ ++ checkliveness(G(L),i_o); } ++ ++#define sethvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ ++ checkliveness(G(L),i_o); } ++ ++#define setptvalue(L,obj,x) \ ++ { TValue *i_o=(obj); \ ++ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ ++ checkliveness(G(L),i_o); } ++ ++ ++ ++ ++#define setobj(L,obj1,obj2) \ ++ { const TValue *o2=(obj2); TValue *o1=(obj1); \ ++ o1->value = o2->value; o1->tt=o2->tt; \ ++ checkliveness(G(L),o1); } ++ ++ ++/* ++** different types of sets, according to destination ++*/ ++ ++/* from stack to (same) stack */ ++#define setobjs2s setobj ++/* to stack (not from same stack) */ ++#define setobj2s setobj ++#define setsvalue2s setsvalue ++#define sethvalue2s sethvalue ++#define setptvalue2s setptvalue ++/* from table to same table */ ++#define setobjt2t setobj ++/* to table */ ++#define setobj2t setobj ++/* to new object */ ++#define setobj2n setobj ++#define setsvalue2n setsvalue ++ ++#define setttype(obj, tt) (ttype(obj) = (tt)) ++ ++ ++#define iscollectable(o) (ttype(o) >= LUA_TSTRING) ++ ++ ++ ++typedef TValue *StkId; /* index to stack elements */ ++ ++ ++/* ++** String headers for string table ++*/ ++typedef union TString { ++ L_Umaxalign dummy; /* ensures maximum alignment for strings */ ++ struct { ++ CommonHeader; ++ lu_byte reserved; ++ unsigned int hash; ++ size_t len; ++ } tsv; ++} TString; ++ ++ ++#define getstr(ts) cast(const char *, (ts) + 1) ++#define svalue(o) getstr(rawtsvalue(o)) ++ ++ ++ ++typedef union Udata { ++ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ ++ struct { ++ CommonHeader; ++ struct Table *metatable; ++ struct Table *env; ++ size_t len; ++ } uv; ++} Udata; ++ ++ ++ ++ ++/* ++** Function Prototypes ++*/ ++typedef struct Proto { ++ CommonHeader; ++ TValue *k; /* constants used by the function */ ++ Instruction *code; ++ struct Proto **p; /* functions defined inside the function */ ++ int *lineinfo; /* map from opcodes to source lines */ ++ struct LocVar *locvars; /* information about local variables */ ++ TString **upvalues; /* upvalue names */ ++ TString *source; ++ int sizeupvalues; ++ int sizek; /* size of `k' */ ++ int sizecode; ++ int sizelineinfo; ++ int sizep; /* size of `p' */ ++ int sizelocvars; ++ int linedefined; ++ int lastlinedefined; ++ GCObject *gclist; ++ lu_byte nups; /* number of upvalues */ ++ lu_byte numparams; ++ lu_byte is_vararg; ++ lu_byte maxstacksize; ++} Proto; ++ ++ ++/* masks for new-style vararg */ ++#define VARARG_HASARG 1 ++#define VARARG_ISVARARG 2 ++#define VARARG_NEEDSARG 4 ++ ++ ++typedef struct LocVar { ++ TString *varname; ++ int startpc; /* first point where variable is active */ ++ int endpc; /* first point where variable is dead */ ++} LocVar; ++ ++ ++ ++/* ++** Upvalues ++*/ ++ ++typedef struct UpVal { ++ CommonHeader; ++ TValue *v; /* points to stack or to its own value */ ++ union { ++ TValue value; /* the value (when closed) */ ++ struct { /* double linked list (when open) */ ++ struct UpVal *prev; ++ struct UpVal *next; ++ } l; ++ } u; ++} UpVal; ++ ++ ++/* ++** Closures ++*/ ++ ++#define ClosureHeader \ ++ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ ++ struct Table *env ++ ++typedef struct CClosure { ++ ClosureHeader; ++ lua_CFunction f; ++ TValue upvalue[1]; ++} CClosure; ++ ++ ++typedef struct LClosure { ++ ClosureHeader; ++ struct Proto *p; ++ UpVal *upvals[1]; ++} LClosure; ++ ++ ++typedef union Closure { ++ CClosure c; ++ LClosure l; ++} Closure; ++ ++ ++#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) ++#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) ++ ++ ++/* ++** Tables ++*/ ++ ++typedef union TKey { ++ struct { ++ TValuefields; ++ struct Node *next; /* for chaining */ ++ } nk; ++ TValue tvk; ++} TKey; ++ ++ ++typedef struct Node { ++ TValue i_val; ++ TKey i_key; ++} Node; ++ ++ ++typedef struct Table { ++ CommonHeader; ++ lu_byte flags; /* 1<<p means tagmethod(p) is not present */ ++ lu_byte lsizenode; /* log2 of size of `node' array */ ++ struct Table *metatable; ++ TValue *array; /* array part */ ++ Node *node; ++ Node *lastfree; /* any free position is before this position */ ++ GCObject *gclist; ++ int sizearray; /* size of `array' array */ ++} Table; ++ ++ ++ ++/* ++** `module' operation for hashing (size is always a power of 2) ++*/ ++#define lmod(s,size) \ ++ (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) ++ ++ ++#define twoto(x) (1<<(x)) ++#define sizenode(t) (twoto((t)->lsizenode)) ++ ++ ++#define luaO_nilobject (&luaO_nilobject_) ++ ++LUAI_DATA const TValue luaO_nilobject_; ++ ++#define ceillog2(x) (luaO_log2((x)-1) + 1) ++ ++LUAI_FUNC int luaO_log2 (unsigned int x); ++LUAI_FUNC int luaO_int2fb (unsigned int x); ++LUAI_FUNC int luaO_fb2int (int x); ++LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); ++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); ++LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, ++ va_list argp); ++LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); ++LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); ++ ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lopcodes.c +@@ -0,0 +1,102 @@ ++/* ++** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#define lopcodes_c ++#define LUA_CORE ++ ++ ++#include "lopcodes.h" ++ ++ ++/* ORDER OP */ ++ ++const char *const luaP_opnames[NUM_OPCODES+1] = { ++ "MOVE", ++ "LOADK", ++ "LOADBOOL", ++ "LOADNIL", ++ "GETUPVAL", ++ "GETGLOBAL", ++ "GETTABLE", ++ "SETGLOBAL", ++ "SETUPVAL", ++ "SETTABLE", ++ "NEWTABLE", ++ "SELF", ++ "ADD", ++ "SUB", ++ "MUL", ++ "DIV", ++ "MOD", ++ "POW", ++ "UNM", ++ "NOT", ++ "LEN", ++ "CONCAT", ++ "JMP", ++ "EQ", ++ "LT", ++ "LE", ++ "TEST", ++ "TESTSET", ++ "CALL", ++ "TAILCALL", ++ "RETURN", ++ "FORLOOP", ++ "FORPREP", ++ "TFORLOOP", ++ "SETLIST", ++ "CLOSE", ++ "CLOSURE", ++ "VARARG", ++ NULL ++}; ++ ++ ++#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) ++ ++const lu_byte luaP_opmodes[NUM_OPCODES] = { ++/* T A B C mode opcode */ ++ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ ++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ++ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ ++ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ++ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ++ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ++ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ ++ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ ++ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ ++ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ++ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ ++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ ++ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ++ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ++ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ ++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ ++ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ ++ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ ++ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ ++ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ ++ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ ++}; ++ +--- /dev/null ++++ b/extensions/LUA/lua/lopcodes.h +@@ -0,0 +1,268 @@ ++/* ++** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Opcodes for Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lopcodes_h ++#define lopcodes_h ++ ++#include "llimits.h" ++ ++ ++/*=========================================================================== ++ We assume that instructions are unsigned numbers. ++ All instructions have an opcode in the first 6 bits. ++ Instructions can have the following fields: ++ `A' : 8 bits ++ `B' : 9 bits ++ `C' : 9 bits ++ `Bx' : 18 bits (`B' and `C' together) ++ `sBx' : signed Bx ++ ++ A signed argument is represented in excess K; that is, the number ++ value is the unsigned value minus K. K is exactly the maximum value ++ for that argument (so that -max is represented by 0, and +max is ++ represented by 2*max), which is half the maximum for the corresponding ++ unsigned argument. ++===========================================================================*/ ++ ++ ++enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ ++ ++ ++/* ++** size and position of opcode arguments. ++*/ ++#define SIZE_C 9 ++#define SIZE_B 9 ++#define SIZE_Bx (SIZE_C + SIZE_B) ++#define SIZE_A 8 ++ ++#define SIZE_OP 6 ++ ++#define POS_OP 0 ++#define POS_A (POS_OP + SIZE_OP) ++#define POS_C (POS_A + SIZE_A) ++#define POS_B (POS_C + SIZE_C) ++#define POS_Bx POS_C ++ ++ ++/* ++** limits for opcode arguments. ++** we use (signed) int to manipulate most arguments, ++** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) ++*/ ++#if SIZE_Bx < LUAI_BITSINT-1 ++#define MAXARG_Bx ((1<<SIZE_Bx)-1) ++#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ ++#else ++#define MAXARG_Bx MAX_INT ++#define MAXARG_sBx MAX_INT ++#endif ++ ++ ++#define MAXARG_A ((1<<SIZE_A)-1) ++#define MAXARG_B ((1<<SIZE_B)-1) ++#define MAXARG_C ((1<<SIZE_C)-1) ++ ++ ++/* creates a mask with `n' 1 bits at position `p' */ ++#define MASK1(n,p) ((~((~(Instruction)0)<<n))<<p) ++ ++/* creates a mask with `n' 0 bits at position `p' */ ++#define MASK0(n,p) (~MASK1(n,p)) ++ ++/* ++** the following macros help to manipulate instructions ++*/ ++ ++#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) ++#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ ++ ((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) ++ ++#define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0))) ++#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ ++ ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) ++ ++#define GETARG_B(i) (cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0))) ++#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ ++ ((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B)))) ++ ++#define GETARG_C(i) (cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0))) ++#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ ++ ((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C)))) ++ ++#define GETARG_Bx(i) (cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0))) ++#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ ++ ((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx)))) ++ ++#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) ++#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) ++ ++ ++#define CREATE_ABC(o,a,b,c) ((cast(Instruction, o)<<POS_OP) \ ++ | (cast(Instruction, a)<<POS_A) \ ++ | (cast(Instruction, b)<<POS_B) \ ++ | (cast(Instruction, c)<<POS_C)) ++ ++#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ ++ | (cast(Instruction, a)<<POS_A) \ ++ | (cast(Instruction, bc)<<POS_Bx)) ++ ++ ++/* ++** Macros to operate RK indices ++*/ ++ ++/* this bit 1 means constant (0 means register) */ ++#define BITRK (1 << (SIZE_B - 1)) ++ ++/* test whether value is a constant */ ++#define ISK(x) ((x) & BITRK) ++ ++/* gets the index of the constant */ ++#define INDEXK(r) ((int)(r) & ~BITRK) ++ ++#define MAXINDEXRK (BITRK - 1) ++ ++/* code a constant index as a RK value */ ++#define RKASK(x) ((x) | BITRK) ++ ++ ++/* ++** invalid register that fits in 8 bits ++*/ ++#define NO_REG MAXARG_A ++ ++ ++/* ++** R(x) - register ++** Kst(x) - constant (in constant table) ++** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) ++*/ ++ ++ ++/* ++** grep "ORDER OP" if you change these enums ++*/ ++ ++typedef enum { ++/*---------------------------------------------------------------------- ++name args description ++------------------------------------------------------------------------*/ ++OP_MOVE,/* A B R(A) := R(B) */ ++OP_LOADK,/* A Bx R(A) := Kst(Bx) */ ++OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ ++OP_LOADNIL,/* A B R(A) := ... := R(B) := nil */ ++OP_GETUPVAL,/* A B R(A) := UpValue[B] */ ++ ++OP_GETGLOBAL,/* A Bx R(A) := Gbl[Kst(Bx)] */ ++OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ ++ ++OP_SETGLOBAL,/* A Bx Gbl[Kst(Bx)] := R(A) */ ++OP_SETUPVAL,/* A B UpValue[B] := R(A) */ ++OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ ++ ++OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ ++ ++OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ ++ ++OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ ++OP_SUB,/* A B C R(A) := RK(B) - RK(C) */ ++OP_MUL,/* A B C R(A) := RK(B) * RK(C) */ ++OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ ++OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ ++OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ ++OP_UNM,/* A B R(A) := -R(B) */ ++OP_NOT,/* A B R(A) := not R(B) */ ++OP_LEN,/* A B R(A) := length of R(B) */ ++ ++OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ ++ ++OP_JMP,/* sBx pc+=sBx */ ++ ++OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ ++OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ ++OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ ++ ++OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ ++OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ ++ ++OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ ++OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ ++OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ ++ ++OP_FORLOOP,/* A sBx R(A)+=R(A+2); ++ if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ ++OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ ++ ++OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); ++ if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */ ++OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ ++ ++OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ ++OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ ++ ++OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ ++} OpCode; ++ ++ ++#define NUM_OPCODES (cast(int, OP_VARARG) + 1) ++ ++ ++ ++/*=========================================================================== ++ Notes: ++ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, ++ and can be 0: OP_CALL then sets `top' to last_result+1, so ++ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. ++ ++ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and ++ set top (like in OP_CALL with C == 0). ++ ++ (*) In OP_RETURN, if (B == 0) then return up to `top' ++ ++ (*) In OP_SETLIST, if (B == 0) then B = `top'; ++ if (C == 0) then next `instruction' is real C ++ ++ (*) For comparisons, A specifies what condition the test should accept ++ (true or false). ++ ++ (*) All `skips' (pc++) assume that next instruction is a jump ++===========================================================================*/ ++ ++ ++/* ++** masks for instruction properties. The format is: ++** bits 0-1: op mode ++** bits 2-3: C arg mode ++** bits 4-5: B arg mode ++** bit 6: instruction set register A ++** bit 7: operator is a test ++*/ ++ ++enum OpArgMask { ++ OpArgN, /* argument is not used */ ++ OpArgU, /* argument is used */ ++ OpArgR, /* argument is a register or a jump offset */ ++ OpArgK /* argument is a constant or register/constant */ ++}; ++ ++LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; ++ ++#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) ++#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) ++#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) ++#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) ++#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) ++ ++ ++LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ ++ ++ ++/* number of list items to accumulate before a SETLIST instruction */ ++#define LFIELDS_PER_FLUSH 50 ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lparser.c +@@ -0,0 +1,1339 @@ ++/* ++** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Lua Parser ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <string.h> ++ ++#define lparser_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lcode.h" ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lparser.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++ ++ ++ ++#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) ++ ++#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) ++ ++#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) ++ ++ ++/* ++** nodes for block list (list of active blocks) ++*/ ++typedef struct BlockCnt { ++ struct BlockCnt *previous; /* chain */ ++ int breaklist; /* list of jumps out of this loop */ ++ lu_byte nactvar; /* # active locals outside the breakable structure */ ++ lu_byte upval; /* true if some variable in the block is an upvalue */ ++ lu_byte isbreakable; /* true if `block' is a loop */ ++} BlockCnt; ++ ++ ++ ++/* ++** prototypes for recursive non-terminal functions ++*/ ++static void chunk (LexState *ls); ++static void expr (LexState *ls, expdesc *v); ++ ++ ++static void anchor_token (LexState *ls) { ++ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { ++ TString *ts = ls->t.seminfo.ts; ++ luaX_newstring(ls, getstr(ts), ts->tsv.len); ++ } ++} ++ ++ ++static void error_expected (LexState *ls, int token) { ++ luaX_syntaxerror(ls, ++ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); ++} ++ ++ ++static void errorlimit (FuncState *fs, int limit, const char *what) { ++ const char *msg = (fs->f->linedefined == 0) ? ++ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : ++ luaO_pushfstring(fs->L, "function at line %d has more than %d %s", ++ fs->f->linedefined, limit, what); ++ luaX_lexerror(fs->ls, msg, 0); ++} ++ ++ ++static int testnext (LexState *ls, int c) { ++ if (ls->t.token == c) { ++ luaX_next(ls); ++ return 1; ++ } ++ else return 0; ++} ++ ++ ++static void check (LexState *ls, int c) { ++ if (ls->t.token != c) ++ error_expected(ls, c); ++} ++ ++static void checknext (LexState *ls, int c) { ++ check(ls, c); ++ luaX_next(ls); ++} ++ ++ ++#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } ++ ++ ++ ++static void check_match (LexState *ls, int what, int who, int where) { ++ if (!testnext(ls, what)) { ++ if (where == ls->linenumber) ++ error_expected(ls, what); ++ else { ++ luaX_syntaxerror(ls, luaO_pushfstring(ls->L, ++ LUA_QS " expected (to close " LUA_QS " at line %d)", ++ luaX_token2str(ls, what), luaX_token2str(ls, who), where)); ++ } ++ } ++} ++ ++ ++static TString *str_checkname (LexState *ls) { ++ TString *ts; ++ check(ls, TK_NAME); ++ ts = ls->t.seminfo.ts; ++ luaX_next(ls); ++ return ts; ++} ++ ++ ++static void init_exp (expdesc *e, expkind k, int i) { ++ e->f = e->t = NO_JUMP; ++ e->k = k; ++ e->u.s.info = i; ++} ++ ++ ++static void codestring (LexState *ls, expdesc *e, TString *s) { ++ init_exp(e, VK, luaK_stringK(ls->fs, s)); ++} ++ ++ ++static void checkname(LexState *ls, expdesc *e) { ++ codestring(ls, e, str_checkname(ls)); ++} ++ ++ ++static int registerlocalvar (LexState *ls, TString *varname) { ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int oldsize = f->sizelocvars; ++ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, ++ LocVar, SHRT_MAX, "too many local variables"); ++ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; ++ f->locvars[fs->nlocvars].varname = varname; ++ luaC_objbarrier(ls->L, f, varname); ++ return fs->nlocvars++; ++} ++ ++ ++#define new_localvarliteral(ls,v,n) \ ++ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) ++ ++ ++static void new_localvar (LexState *ls, TString *name, int n) { ++ FuncState *fs = ls->fs; ++ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); ++ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); ++} ++ ++ ++static void adjustlocalvars (LexState *ls, int nvars) { ++ FuncState *fs = ls->fs; ++ fs->nactvar = cast_byte(fs->nactvar + nvars); ++ for (; nvars; nvars--) { ++ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; ++ } ++} ++ ++ ++static void removevars (LexState *ls, int tolevel) { ++ FuncState *fs = ls->fs; ++ while (fs->nactvar > tolevel) ++ getlocvar(fs, --fs->nactvar).endpc = fs->pc; ++} ++ ++ ++static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { ++ int i; ++ Proto *f = fs->f; ++ int oldsize = f->sizeupvalues; ++ for (i=0; i<f->nups; i++) { ++ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { ++ lua_assert(f->upvalues[i] == name); ++ return i; ++ } ++ } ++ /* new one */ ++ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); ++ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, ++ TString *, MAX_INT, ""); ++ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; ++ f->upvalues[f->nups] = name; ++ luaC_objbarrier(fs->L, f, name); ++ lua_assert(v->k == VLOCAL || v->k == VUPVAL); ++ fs->upvalues[f->nups].k = cast_byte(v->k); ++ fs->upvalues[f->nups].info = cast_byte(v->u.s.info); ++ return f->nups++; ++} ++ ++ ++static int searchvar (FuncState *fs, TString *n) { ++ int i; ++ for (i=fs->nactvar-1; i >= 0; i--) { ++ if (n == getlocvar(fs, i).varname) ++ return i; ++ } ++ return -1; /* not found */ ++} ++ ++ ++static void markupval (FuncState *fs, int level) { ++ BlockCnt *bl = fs->bl; ++ while (bl && bl->nactvar > level) bl = bl->previous; ++ if (bl) bl->upval = 1; ++} ++ ++ ++static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { ++ if (fs == NULL) { /* no more levels? */ ++ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ ++ return VGLOBAL; ++ } ++ else { ++ int v = searchvar(fs, n); /* look up at current level */ ++ if (v >= 0) { ++ init_exp(var, VLOCAL, v); ++ if (!base) ++ markupval(fs, v); /* local will be used as an upval */ ++ return VLOCAL; ++ } ++ else { /* not found at current level; try upper one */ ++ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) ++ return VGLOBAL; ++ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ ++ var->k = VUPVAL; /* upvalue in this level */ ++ return VUPVAL; ++ } ++ } ++} ++ ++ ++static void singlevar (LexState *ls, expdesc *var) { ++ TString *varname = str_checkname(ls); ++ FuncState *fs = ls->fs; ++ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) ++ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ ++} ++ ++ ++static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { ++ FuncState *fs = ls->fs; ++ int extra = nvars - nexps; ++ if (hasmultret(e->k)) { ++ extra++; /* includes call itself */ ++ if (extra < 0) extra = 0; ++ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ ++ if (extra > 1) luaK_reserveregs(fs, extra-1); ++ } ++ else { ++ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ ++ if (extra > 0) { ++ int reg = fs->freereg; ++ luaK_reserveregs(fs, extra); ++ luaK_nil(fs, reg, extra); ++ } ++ } ++} ++ ++ ++static void enterlevel (LexState *ls) { ++ if (++ls->L->nCcalls > LUAI_MAXCCALLS) ++ luaX_lexerror(ls, "chunk has too many syntax levels", 0); ++} ++ ++ ++#define leavelevel(ls) ((ls)->L->nCcalls--) ++ ++ ++static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { ++ bl->breaklist = NO_JUMP; ++ bl->isbreakable = isbreakable; ++ bl->nactvar = fs->nactvar; ++ bl->upval = 0; ++ bl->previous = fs->bl; ++ fs->bl = bl; ++ lua_assert(fs->freereg == fs->nactvar); ++} ++ ++ ++static void leaveblock (FuncState *fs) { ++ BlockCnt *bl = fs->bl; ++ fs->bl = bl->previous; ++ removevars(fs->ls, bl->nactvar); ++ if (bl->upval) ++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); ++ /* a block either controls scope or breaks (never both) */ ++ lua_assert(!bl->isbreakable || !bl->upval); ++ lua_assert(bl->nactvar == fs->nactvar); ++ fs->freereg = fs->nactvar; /* free registers */ ++ luaK_patchtohere(fs, bl->breaklist); ++} ++ ++ ++static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int oldsize = f->sizep; ++ int i; ++ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, ++ MAXARG_Bx, "constant table overflow"); ++ while (oldsize < f->sizep) f->p[oldsize++] = NULL; ++ f->p[fs->np++] = func->f; ++ luaC_objbarrier(ls->L, f, func->f); ++ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); ++ for (i=0; i<func->f->nups; i++) { ++ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; ++ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); ++ } ++} ++ ++ ++static void open_func (LexState *ls, FuncState *fs) { ++ lua_State *L = ls->L; ++ Proto *f = luaF_newproto(L); ++ fs->f = f; ++ fs->prev = ls->fs; /* linked list of funcstates */ ++ fs->ls = ls; ++ fs->L = L; ++ ls->fs = fs; ++ fs->pc = 0; ++ fs->lasttarget = -1; ++ fs->jpc = NO_JUMP; ++ fs->freereg = 0; ++ fs->nk = 0; ++ fs->np = 0; ++ fs->nlocvars = 0; ++ fs->nactvar = 0; ++ fs->bl = NULL; ++ f->source = ls->source; ++ f->maxstacksize = 2; /* registers 0/1 are always valid */ ++ fs->h = luaH_new(L, 0, 0); ++ /* anchor table of constants and prototype (to avoid being collected) */ ++ sethvalue2s(L, L->top, fs->h); ++ incr_top(L); ++ setptvalue2s(L, L->top, f); ++ incr_top(L); ++} ++ ++ ++static void close_func (LexState *ls) { ++ lua_State *L = ls->L; ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ removevars(ls, 0); ++ luaK_ret(fs, 0, 0); /* final return */ ++ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); ++ f->sizecode = fs->pc; ++ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); ++ f->sizelineinfo = fs->pc; ++ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); ++ f->sizek = fs->nk; ++ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); ++ f->sizep = fs->np; ++ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); ++ f->sizelocvars = fs->nlocvars; ++ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); ++ f->sizeupvalues = f->nups; ++ lua_assert(luaG_checkcode(f)); ++ lua_assert(fs->bl == NULL); ++ ls->fs = fs->prev; ++ L->top -= 2; /* remove table and prototype from the stack */ ++ /* last token read was anchored in defunct function; must reanchor it */ ++ if (fs) anchor_token(ls); ++} ++ ++ ++Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { ++ struct LexState lexstate; ++ struct FuncState funcstate; ++ lexstate.buff = buff; ++ luaX_setinput(L, &lexstate, z, luaS_new(L, name)); ++ open_func(&lexstate, &funcstate); ++ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ ++ luaX_next(&lexstate); /* read first token */ ++ chunk(&lexstate); ++ check(&lexstate, TK_EOS); ++ close_func(&lexstate); ++ lua_assert(funcstate.prev == NULL); ++ lua_assert(funcstate.f->nups == 0); ++ lua_assert(lexstate.fs == NULL); ++ return funcstate.f; ++} ++ ++ ++ ++/*============================================================*/ ++/* GRAMMAR RULES */ ++/*============================================================*/ ++ ++ ++static void field (LexState *ls, expdesc *v) { ++ /* field -> ['.' | ':'] NAME */ ++ FuncState *fs = ls->fs; ++ expdesc key; ++ luaK_exp2anyreg(fs, v); ++ luaX_next(ls); /* skip the dot or colon */ ++ checkname(ls, &key); ++ luaK_indexed(fs, v, &key); ++} ++ ++ ++static void yindex (LexState *ls, expdesc *v) { ++ /* index -> '[' expr ']' */ ++ luaX_next(ls); /* skip the '[' */ ++ expr(ls, v); ++ luaK_exp2val(ls->fs, v); ++ checknext(ls, ']'); ++} ++ ++ ++/* ++** {====================================================================== ++** Rules for Constructors ++** ======================================================================= ++*/ ++ ++ ++struct ConsControl { ++ expdesc v; /* last list item read */ ++ expdesc *t; /* table descriptor */ ++ int nh; /* total number of `record' elements */ ++ int na; /* total number of array elements */ ++ int tostore; /* number of array elements pending to be stored */ ++}; ++ ++ ++static void recfield (LexState *ls, struct ConsControl *cc) { ++ /* recfield -> (NAME | `['exp1`]') = exp1 */ ++ FuncState *fs = ls->fs; ++ int reg = ls->fs->freereg; ++ expdesc key, val; ++ int rkkey; ++ if (ls->t.token == TK_NAME) { ++ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); ++ checkname(ls, &key); ++ } ++ else /* ls->t.token == '[' */ ++ yindex(ls, &key); ++ cc->nh++; ++ checknext(ls, '='); ++ rkkey = luaK_exp2RK(fs, &key); ++ expr(ls, &val); ++ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); ++ fs->freereg = reg; /* free registers */ ++} ++ ++ ++static void closelistfield (FuncState *fs, struct ConsControl *cc) { ++ if (cc->v.k == VVOID) return; /* there is no list item */ ++ luaK_exp2nextreg(fs, &cc->v); ++ cc->v.k = VVOID; ++ if (cc->tostore == LFIELDS_PER_FLUSH) { ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ ++ cc->tostore = 0; /* no more items pending */ ++ } ++} ++ ++ ++static void lastlistfield (FuncState *fs, struct ConsControl *cc) { ++ if (cc->tostore == 0) return; ++ if (hasmultret(cc->v.k)) { ++ luaK_setmultret(fs, &cc->v); ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); ++ cc->na--; /* do not count last expression (unknown number of elements) */ ++ } ++ else { ++ if (cc->v.k != VVOID) ++ luaK_exp2nextreg(fs, &cc->v); ++ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); ++ } ++} ++ ++ ++static void listfield (LexState *ls, struct ConsControl *cc) { ++ expr(ls, &cc->v); ++ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); ++ cc->na++; ++ cc->tostore++; ++} ++ ++ ++static void constructor (LexState *ls, expdesc *t) { ++ /* constructor -> ?? */ ++ FuncState *fs = ls->fs; ++ int line = ls->linenumber; ++ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); ++ struct ConsControl cc; ++ cc.na = cc.nh = cc.tostore = 0; ++ cc.t = t; ++ init_exp(t, VRELOCABLE, pc); ++ init_exp(&cc.v, VVOID, 0); /* no value (yet) */ ++ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ ++ checknext(ls, '{'); ++ do { ++ lua_assert(cc.v.k == VVOID || cc.tostore > 0); ++ if (ls->t.token == '}') break; ++ closelistfield(fs, &cc); ++ switch(ls->t.token) { ++ case TK_NAME: { /* may be listfields or recfields */ ++ luaX_lookahead(ls); ++ if (ls->lookahead.token != '=') /* expression? */ ++ listfield(ls, &cc); ++ else ++ recfield(ls, &cc); ++ break; ++ } ++ case '[': { /* constructor_item -> recfield */ ++ recfield(ls, &cc); ++ break; ++ } ++ default: { /* constructor_part -> listfield */ ++ listfield(ls, &cc); ++ break; ++ } ++ } ++ } while (testnext(ls, ',') || testnext(ls, ';')); ++ check_match(ls, '}', '{', line); ++ lastlistfield(fs, &cc); ++ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ ++ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ ++} ++ ++/* }====================================================================== */ ++ ++ ++ ++static void parlist (LexState *ls) { ++ /* parlist -> [ param { `,' param } ] */ ++ FuncState *fs = ls->fs; ++ Proto *f = fs->f; ++ int nparams = 0; ++ f->is_vararg = 0; ++ if (ls->t.token != ')') { /* is `parlist' not empty? */ ++ do { ++ switch (ls->t.token) { ++ case TK_NAME: { /* param -> NAME */ ++ new_localvar(ls, str_checkname(ls), nparams++); ++ break; ++ } ++ case TK_DOTS: { /* param -> `...' */ ++ luaX_next(ls); ++#if defined(LUA_COMPAT_VARARG) ++ /* use `arg' as default name */ ++ new_localvarliteral(ls, "arg", nparams++); ++ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; ++#endif ++ f->is_vararg |= VARARG_ISVARARG; ++ break; ++ } ++ default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected"); ++ } ++ } while (!f->is_vararg && testnext(ls, ',')); ++ } ++ adjustlocalvars(ls, nparams); ++ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); ++ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ ++} ++ ++ ++static void body (LexState *ls, expdesc *e, int needself, int line) { ++ /* body -> `(' parlist `)' chunk END */ ++ FuncState new_fs; ++ open_func(ls, &new_fs); ++ new_fs.f->linedefined = line; ++ checknext(ls, '('); ++ if (needself) { ++ new_localvarliteral(ls, "self", 0); ++ adjustlocalvars(ls, 1); ++ } ++ parlist(ls); ++ checknext(ls, ')'); ++ chunk(ls); ++ new_fs.f->lastlinedefined = ls->linenumber; ++ check_match(ls, TK_END, TK_FUNCTION, line); ++ close_func(ls); ++ pushclosure(ls, &new_fs, e); ++} ++ ++ ++static int explist1 (LexState *ls, expdesc *v) { ++ /* explist1 -> expr { `,' expr } */ ++ int n = 1; /* at least one expression */ ++ expr(ls, v); ++ while (testnext(ls, ',')) { ++ luaK_exp2nextreg(ls->fs, v); ++ expr(ls, v); ++ n++; ++ } ++ return n; ++} ++ ++ ++static void funcargs (LexState *ls, expdesc *f) { ++ FuncState *fs = ls->fs; ++ expdesc args; ++ int base, nparams; ++ int line = ls->linenumber; ++ switch (ls->t.token) { ++ case '(': { /* funcargs -> `(' [ explist1 ] `)' */ ++ if (line != ls->lastline) ++ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); ++ luaX_next(ls); ++ if (ls->t.token == ')') /* arg list is empty? */ ++ args.k = VVOID; ++ else { ++ explist1(ls, &args); ++ luaK_setmultret(fs, &args); ++ } ++ check_match(ls, ')', '(', line); ++ break; ++ } ++ case '{': { /* funcargs -> constructor */ ++ constructor(ls, &args); ++ break; ++ } ++ case TK_STRING: { /* funcargs -> STRING */ ++ codestring(ls, &args, ls->t.seminfo.ts); ++ luaX_next(ls); /* must use `seminfo' before `next' */ ++ break; ++ } ++ default: { ++ luaX_syntaxerror(ls, "function arguments expected"); ++ return; ++ } ++ } ++ lua_assert(f->k == VNONRELOC); ++ base = f->u.s.info; /* base register for call */ ++ if (hasmultret(args.k)) ++ nparams = LUA_MULTRET; /* open call */ ++ else { ++ if (args.k != VVOID) ++ luaK_exp2nextreg(fs, &args); /* close last argument */ ++ nparams = fs->freereg - (base+1); ++ } ++ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); ++ luaK_fixline(fs, line); ++ fs->freereg = base+1; /* call remove function and arguments and leaves ++ (unless changed) one result */ ++} ++ ++ ++ ++ ++/* ++** {====================================================================== ++** Expression parsing ++** ======================================================================= ++*/ ++ ++ ++static void prefixexp (LexState *ls, expdesc *v) { ++ /* prefixexp -> NAME | '(' expr ')' */ ++ switch (ls->t.token) { ++ case '(': { ++ int line = ls->linenumber; ++ luaX_next(ls); ++ expr(ls, v); ++ check_match(ls, ')', '(', line); ++ luaK_dischargevars(ls->fs, v); ++ return; ++ } ++ case TK_NAME: { ++ singlevar(ls, v); ++ return; ++ } ++ default: { ++ luaX_syntaxerror(ls, "unexpected symbol"); ++ return; ++ } ++ } ++} ++ ++ ++static void primaryexp (LexState *ls, expdesc *v) { ++ /* primaryexp -> ++ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ ++ FuncState *fs = ls->fs; ++ prefixexp(ls, v); ++ for (;;) { ++ switch (ls->t.token) { ++ case '.': { /* field */ ++ field(ls, v); ++ break; ++ } ++ case '[': { /* `[' exp1 `]' */ ++ expdesc key; ++ luaK_exp2anyreg(fs, v); ++ yindex(ls, &key); ++ luaK_indexed(fs, v, &key); ++ break; ++ } ++ case ':': { /* `:' NAME funcargs */ ++ expdesc key; ++ luaX_next(ls); ++ checkname(ls, &key); ++ luaK_self(fs, v, &key); ++ funcargs(ls, v); ++ break; ++ } ++ case '(': case TK_STRING: case '{': { /* funcargs */ ++ luaK_exp2nextreg(fs, v); ++ funcargs(ls, v); ++ break; ++ } ++ default: return; ++ } ++ } ++} ++ ++ ++static void simpleexp (LexState *ls, expdesc *v) { ++ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | ++ constructor | FUNCTION body | primaryexp */ ++ switch (ls->t.token) { ++ case TK_NUMBER: { ++ init_exp(v, VKNUM, 0); ++ v->u.nval = ls->t.seminfo.r; ++ break; ++ } ++ case TK_STRING: { ++ codestring(ls, v, ls->t.seminfo.ts); ++ break; ++ } ++ case TK_NIL: { ++ init_exp(v, VNIL, 0); ++ break; ++ } ++ case TK_TRUE: { ++ init_exp(v, VTRUE, 0); ++ break; ++ } ++ case TK_FALSE: { ++ init_exp(v, VFALSE, 0); ++ break; ++ } ++ case TK_DOTS: { /* vararg */ ++ FuncState *fs = ls->fs; ++ check_condition(ls, fs->f->is_vararg, ++ "cannot use " LUA_QL("...") " outside a vararg function"); ++ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ ++ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); ++ break; ++ } ++ case '{': { /* constructor */ ++ constructor(ls, v); ++ return; ++ } ++ case TK_FUNCTION: { ++ luaX_next(ls); ++ body(ls, v, 0, ls->linenumber); ++ return; ++ } ++ default: { ++ primaryexp(ls, v); ++ return; ++ } ++ } ++ luaX_next(ls); ++} ++ ++ ++static UnOpr getunopr (int op) { ++ switch (op) { ++ case TK_NOT: return OPR_NOT; ++ case '-': return OPR_MINUS; ++ case '#': return OPR_LEN; ++ default: return OPR_NOUNOPR; ++ } ++} ++ ++ ++static BinOpr getbinopr (int op) { ++ switch (op) { ++ case '+': return OPR_ADD; ++ case '-': return OPR_SUB; ++ case '*': return OPR_MUL; ++ case '/': return OPR_DIV; ++ case '%': return OPR_MOD; ++ case '^': return OPR_POW; ++ case TK_CONCAT: return OPR_CONCAT; ++ case TK_NE: return OPR_NE; ++ case TK_EQ: return OPR_EQ; ++ case '<': return OPR_LT; ++ case TK_LE: return OPR_LE; ++ case '>': return OPR_GT; ++ case TK_GE: return OPR_GE; ++ case TK_AND: return OPR_AND; ++ case TK_OR: return OPR_OR; ++ default: return OPR_NOBINOPR; ++ } ++} ++ ++ ++static const struct { ++ lu_byte left; /* left priority for each binary operator */ ++ lu_byte right; /* right priority */ ++} priority[] = { /* ORDER OPR */ ++ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ ++ {10, 9}, {5, 4}, /* power and concat (right associative) */ ++ {3, 3}, {3, 3}, /* equality and inequality */ ++ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ ++ {2, 2}, {1, 1} /* logical (and/or) */ ++}; ++ ++#define UNARY_PRIORITY 8 /* priority for unary operators */ ++ ++ ++/* ++** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ++** where `binop' is any binary operator with a priority higher than `limit' ++*/ ++static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { ++ BinOpr op; ++ UnOpr uop; ++ enterlevel(ls); ++ uop = getunopr(ls->t.token); ++ if (uop != OPR_NOUNOPR) { ++ luaX_next(ls); ++ subexpr(ls, v, UNARY_PRIORITY); ++ luaK_prefix(ls->fs, uop, v); ++ } ++ else simpleexp(ls, v); ++ /* expand while operators have priorities higher than `limit' */ ++ op = getbinopr(ls->t.token); ++ while (op != OPR_NOBINOPR && priority[op].left > limit) { ++ expdesc v2; ++ BinOpr nextop; ++ luaX_next(ls); ++ luaK_infix(ls->fs, op, v); ++ /* read sub-expression with higher priority */ ++ nextop = subexpr(ls, &v2, priority[op].right); ++ luaK_posfix(ls->fs, op, v, &v2); ++ op = nextop; ++ } ++ leavelevel(ls); ++ return op; /* return first untreated operator */ ++} ++ ++ ++static void expr (LexState *ls, expdesc *v) { ++ subexpr(ls, v, 0); ++} ++ ++/* }==================================================================== */ ++ ++ ++ ++/* ++** {====================================================================== ++** Rules for Statements ++** ======================================================================= ++*/ ++ ++ ++static int block_follow (int token) { ++ switch (token) { ++ case TK_ELSE: case TK_ELSEIF: case TK_END: ++ case TK_UNTIL: case TK_EOS: ++ return 1; ++ default: return 0; ++ } ++} ++ ++ ++static void block (LexState *ls) { ++ /* block -> chunk */ ++ FuncState *fs = ls->fs; ++ BlockCnt bl; ++ enterblock(fs, &bl, 0); ++ chunk(ls); ++ lua_assert(bl.breaklist == NO_JUMP); ++ leaveblock(fs); ++} ++ ++ ++/* ++** structure to chain all variables in the left-hand side of an ++** assignment ++*/ ++struct LHS_assign { ++ struct LHS_assign *prev; ++ expdesc v; /* variable (global, local, upvalue, or indexed) */ ++}; ++ ++ ++/* ++** check whether, in an assignment to a local variable, the local variable ++** is needed in a previous assignment (to a table). If so, save original ++** local value in a safe place and use this safe copy in the previous ++** assignment. ++*/ ++static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { ++ FuncState *fs = ls->fs; ++ int extra = fs->freereg; /* eventual position to save local variable */ ++ int conflict = 0; ++ for (; lh; lh = lh->prev) { ++ if (lh->v.k == VINDEXED) { ++ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ ++ conflict = 1; ++ lh->v.u.s.info = extra; /* previous assignment will use safe copy */ ++ } ++ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ ++ conflict = 1; ++ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ ++ } ++ } ++ } ++ if (conflict) { ++ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ ++ luaK_reserveregs(fs, 1); ++ } ++} ++ ++ ++static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { ++ expdesc e; ++ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, ++ "syntax error"); ++ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ ++ struct LHS_assign nv; ++ nv.prev = lh; ++ primaryexp(ls, &nv.v); ++ if (nv.v.k == VLOCAL) ++ check_conflict(ls, lh, &nv.v); ++ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, ++ "variables in assignment"); ++ assignment(ls, &nv, nvars+1); ++ } ++ else { /* assignment -> `=' explist1 */ ++ int nexps; ++ checknext(ls, '='); ++ nexps = explist1(ls, &e); ++ if (nexps != nvars) { ++ adjust_assign(ls, nvars, nexps, &e); ++ if (nexps > nvars) ++ ls->fs->freereg -= nexps - nvars; /* remove extra values */ ++ } ++ else { ++ luaK_setoneret(ls->fs, &e); /* close last expression */ ++ luaK_storevar(ls->fs, &lh->v, &e); ++ return; /* avoid default */ ++ } ++ } ++ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ ++ luaK_storevar(ls->fs, &lh->v, &e); ++} ++ ++ ++static int cond (LexState *ls) { ++ /* cond -> exp */ ++ expdesc v; ++ expr(ls, &v); /* read condition */ ++ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ ++ luaK_goiftrue(ls->fs, &v); ++ return v.f; ++} ++ ++ ++static void breakstat (LexState *ls) { ++ FuncState *fs = ls->fs; ++ BlockCnt *bl = fs->bl; ++ int upval = 0; ++ while (bl && !bl->isbreakable) { ++ upval |= bl->upval; ++ bl = bl->previous; ++ } ++ if (!bl) ++ luaX_syntaxerror(ls, "no loop to break"); ++ if (upval) ++ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); ++ luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); ++} ++ ++ ++static void whilestat (LexState *ls, int line) { ++ /* whilestat -> WHILE cond DO block END */ ++ FuncState *fs = ls->fs; ++ int whileinit; ++ int condexit; ++ BlockCnt bl; ++ luaX_next(ls); /* skip WHILE */ ++ whileinit = luaK_getlabel(fs); ++ condexit = cond(ls); ++ enterblock(fs, &bl, 1); ++ checknext(ls, TK_DO); ++ block(ls); ++ luaK_patchlist(fs, luaK_jump(fs), whileinit); ++ check_match(ls, TK_END, TK_WHILE, line); ++ leaveblock(fs); ++ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ ++} ++ ++ ++static void repeatstat (LexState *ls, int line) { ++ /* repeatstat -> REPEAT block UNTIL cond */ ++ int condexit; ++ FuncState *fs = ls->fs; ++ int repeat_init = luaK_getlabel(fs); ++ BlockCnt bl1, bl2; ++ enterblock(fs, &bl1, 1); /* loop block */ ++ enterblock(fs, &bl2, 0); /* scope block */ ++ luaX_next(ls); /* skip REPEAT */ ++ chunk(ls); ++ check_match(ls, TK_UNTIL, TK_REPEAT, line); ++ condexit = cond(ls); /* read condition (inside scope block) */ ++ if (!bl2.upval) { /* no upvalues? */ ++ leaveblock(fs); /* finish scope */ ++ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ ++ } ++ else { /* complete semantics when there are upvalues */ ++ breakstat(ls); /* if condition then break */ ++ luaK_patchtohere(ls->fs, condexit); /* else... */ ++ leaveblock(fs); /* finish scope... */ ++ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ ++ } ++ leaveblock(fs); /* finish loop */ ++} ++ ++ ++static int exp1 (LexState *ls) { ++ expdesc e; ++ int k; ++ expr(ls, &e); ++ k = e.k; ++ luaK_exp2nextreg(ls->fs, &e); ++ return k; ++} ++ ++ ++static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { ++ /* forbody -> DO block */ ++ BlockCnt bl; ++ FuncState *fs = ls->fs; ++ int prep, endfor; ++ adjustlocalvars(ls, 3); /* control variables */ ++ checknext(ls, TK_DO); ++ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); ++ enterblock(fs, &bl, 0); /* scope for declared variables */ ++ adjustlocalvars(ls, nvars); ++ luaK_reserveregs(fs, nvars); ++ block(ls); ++ leaveblock(fs); /* end of scope for declared variables */ ++ luaK_patchtohere(fs, prep); ++ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : ++ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); ++ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ ++ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); ++} ++ ++ ++static void fornum (LexState *ls, TString *varname, int line) { ++ /* fornum -> NAME = exp1,exp1[,exp1] forbody */ ++ FuncState *fs = ls->fs; ++ int base = fs->freereg; ++ new_localvarliteral(ls, "(for index)", 0); ++ new_localvarliteral(ls, "(for limit)", 1); ++ new_localvarliteral(ls, "(for step)", 2); ++ new_localvar(ls, varname, 3); ++ checknext(ls, '='); ++ exp1(ls); /* initial value */ ++ checknext(ls, ','); ++ exp1(ls); /* limit */ ++ if (testnext(ls, ',')) ++ exp1(ls); /* optional step */ ++ else { /* default step = 1 */ ++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); ++ luaK_reserveregs(fs, 1); ++ } ++ forbody(ls, base, line, 1, 1); ++} ++ ++ ++static void forlist (LexState *ls, TString *indexname) { ++ /* forlist -> NAME {,NAME} IN explist1 forbody */ ++ FuncState *fs = ls->fs; ++ expdesc e; ++ int nvars = 0; ++ int line; ++ int base = fs->freereg; ++ /* create control variables */ ++ new_localvarliteral(ls, "(for generator)", nvars++); ++ new_localvarliteral(ls, "(for state)", nvars++); ++ new_localvarliteral(ls, "(for control)", nvars++); ++ /* create declared variables */ ++ new_localvar(ls, indexname, nvars++); ++ while (testnext(ls, ',')) ++ new_localvar(ls, str_checkname(ls), nvars++); ++ checknext(ls, TK_IN); ++ line = ls->linenumber; ++ adjust_assign(ls, 3, explist1(ls, &e), &e); ++ luaK_checkstack(fs, 3); /* extra space to call generator */ ++ forbody(ls, base, line, nvars - 3, 0); ++} ++ ++ ++static void forstat (LexState *ls, int line) { ++ /* forstat -> FOR (fornum | forlist) END */ ++ FuncState *fs = ls->fs; ++ TString *varname; ++ BlockCnt bl; ++ enterblock(fs, &bl, 1); /* scope for loop and control variables */ ++ luaX_next(ls); /* skip `for' */ ++ varname = str_checkname(ls); /* first variable name */ ++ switch (ls->t.token) { ++ case '=': fornum(ls, varname, line); break; ++ case ',': case TK_IN: forlist(ls, varname); break; ++ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); ++ } ++ check_match(ls, TK_END, TK_FOR, line); ++ leaveblock(fs); /* loop scope (`break' jumps to this point) */ ++} ++ ++ ++static int test_then_block (LexState *ls) { ++ /* test_then_block -> [IF | ELSEIF] cond THEN block */ ++ int condexit; ++ luaX_next(ls); /* skip IF or ELSEIF */ ++ condexit = cond(ls); ++ checknext(ls, TK_THEN); ++ block(ls); /* `then' part */ ++ return condexit; ++} ++ ++ ++static void ifstat (LexState *ls, int line) { ++ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ ++ FuncState *fs = ls->fs; ++ int flist; ++ int escapelist = NO_JUMP; ++ flist = test_then_block(ls); /* IF cond THEN block */ ++ while (ls->t.token == TK_ELSEIF) { ++ luaK_concat(fs, &escapelist, luaK_jump(fs)); ++ luaK_patchtohere(fs, flist); ++ flist = test_then_block(ls); /* ELSEIF cond THEN block */ ++ } ++ if (ls->t.token == TK_ELSE) { ++ luaK_concat(fs, &escapelist, luaK_jump(fs)); ++ luaK_patchtohere(fs, flist); ++ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ ++ block(ls); /* `else' part */ ++ } ++ else ++ luaK_concat(fs, &escapelist, flist); ++ luaK_patchtohere(fs, escapelist); ++ check_match(ls, TK_END, TK_IF, line); ++} ++ ++ ++static void localfunc (LexState *ls) { ++ expdesc v, b; ++ FuncState *fs = ls->fs; ++ new_localvar(ls, str_checkname(ls), 0); ++ init_exp(&v, VLOCAL, fs->freereg); ++ luaK_reserveregs(fs, 1); ++ adjustlocalvars(ls, 1); ++ body(ls, &b, 0, ls->linenumber); ++ luaK_storevar(fs, &v, &b); ++ /* debug information will only see the variable after this point! */ ++ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; ++} ++ ++ ++static void localstat (LexState *ls) { ++ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ ++ int nvars = 0; ++ int nexps; ++ expdesc e; ++ do { ++ new_localvar(ls, str_checkname(ls), nvars++); ++ } while (testnext(ls, ',')); ++ if (testnext(ls, '=')) ++ nexps = explist1(ls, &e); ++ else { ++ e.k = VVOID; ++ nexps = 0; ++ } ++ adjust_assign(ls, nvars, nexps, &e); ++ adjustlocalvars(ls, nvars); ++} ++ ++ ++static int funcname (LexState *ls, expdesc *v) { ++ /* funcname -> NAME {field} [`:' NAME] */ ++ int needself = 0; ++ singlevar(ls, v); ++ while (ls->t.token == '.') ++ field(ls, v); ++ if (ls->t.token == ':') { ++ needself = 1; ++ field(ls, v); ++ } ++ return needself; ++} ++ ++ ++static void funcstat (LexState *ls, int line) { ++ /* funcstat -> FUNCTION funcname body */ ++ int needself; ++ expdesc v, b; ++ luaX_next(ls); /* skip FUNCTION */ ++ needself = funcname(ls, &v); ++ body(ls, &b, needself, line); ++ luaK_storevar(ls->fs, &v, &b); ++ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ ++} ++ ++ ++static void exprstat (LexState *ls) { ++ /* stat -> func | assignment */ ++ FuncState *fs = ls->fs; ++ struct LHS_assign v; ++ primaryexp(ls, &v.v); ++ if (v.v.k == VCALL) /* stat -> func */ ++ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ ++ else { /* stat -> assignment */ ++ v.prev = NULL; ++ assignment(ls, &v, 1); ++ } ++} ++ ++ ++static void retstat (LexState *ls) { ++ /* stat -> RETURN explist */ ++ FuncState *fs = ls->fs; ++ expdesc e; ++ int first, nret; /* registers with returned values */ ++ luaX_next(ls); /* skip RETURN */ ++ if (block_follow(ls->t.token) || ls->t.token == ';') ++ first = nret = 0; /* return no values */ ++ else { ++ nret = explist1(ls, &e); /* optional return values */ ++ if (hasmultret(e.k)) { ++ luaK_setmultret(fs, &e); ++ if (e.k == VCALL && nret == 1) { /* tail call? */ ++ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); ++ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); ++ } ++ first = fs->nactvar; ++ nret = LUA_MULTRET; /* return all values */ ++ } ++ else { ++ if (nret == 1) /* only one single value? */ ++ first = luaK_exp2anyreg(fs, &e); ++ else { ++ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ ++ first = fs->nactvar; /* return all `active' values */ ++ lua_assert(nret == fs->freereg - first); ++ } ++ } ++ } ++ luaK_ret(fs, first, nret); ++} ++ ++ ++static int statement (LexState *ls) { ++ int line = ls->linenumber; /* may be needed for error messages */ ++ switch (ls->t.token) { ++ case TK_IF: { /* stat -> ifstat */ ++ ifstat(ls, line); ++ return 0; ++ } ++ case TK_WHILE: { /* stat -> whilestat */ ++ whilestat(ls, line); ++ return 0; ++ } ++ case TK_DO: { /* stat -> DO block END */ ++ luaX_next(ls); /* skip DO */ ++ block(ls); ++ check_match(ls, TK_END, TK_DO, line); ++ return 0; ++ } ++ case TK_FOR: { /* stat -> forstat */ ++ forstat(ls, line); ++ return 0; ++ } ++ case TK_REPEAT: { /* stat -> repeatstat */ ++ repeatstat(ls, line); ++ return 0; ++ } ++ case TK_FUNCTION: { ++ funcstat(ls, line); /* stat -> funcstat */ ++ return 0; ++ } ++ case TK_LOCAL: { /* stat -> localstat */ ++ luaX_next(ls); /* skip LOCAL */ ++ if (testnext(ls, TK_FUNCTION)) /* local function? */ ++ localfunc(ls); ++ else ++ localstat(ls); ++ return 0; ++ } ++ case TK_RETURN: { /* stat -> retstat */ ++ retstat(ls); ++ return 1; /* must be last statement */ ++ } ++ case TK_BREAK: { /* stat -> breakstat */ ++ luaX_next(ls); /* skip BREAK */ ++ breakstat(ls); ++ return 1; /* must be last statement */ ++ } ++ default: { ++ exprstat(ls); ++ return 0; /* to avoid warnings */ ++ } ++ } ++} ++ ++ ++static void chunk (LexState *ls) { ++ /* chunk -> { stat [`;'] } */ ++ int islast = 0; ++ enterlevel(ls); ++ while (!islast && !block_follow(ls->t.token)) { ++ islast = statement(ls); ++ testnext(ls, ';'); ++ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && ++ ls->fs->freereg >= ls->fs->nactvar); ++ ls->fs->freereg = ls->fs->nactvar; /* free registers */ ++ } ++ leavelevel(ls); ++} ++ ++/* }====================================================================== */ +--- /dev/null ++++ b/extensions/LUA/lua/lparser.h +@@ -0,0 +1,82 @@ ++/* ++** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua Parser ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lparser_h ++#define lparser_h ++ ++#include "llimits.h" ++#include "lobject.h" ++#include "lzio.h" ++ ++ ++/* ++** Expression descriptor ++*/ ++ ++typedef enum { ++ VVOID, /* no value */ ++ VNIL, ++ VTRUE, ++ VFALSE, ++ VK, /* info = index of constant in `k' */ ++ VKNUM, /* nval = numerical value */ ++ VLOCAL, /* info = local register */ ++ VUPVAL, /* info = index of upvalue in `upvalues' */ ++ VGLOBAL, /* info = index of table; aux = index of global name in `k' */ ++ VINDEXED, /* info = table register; aux = index register (or `k') */ ++ VJMP, /* info = instruction pc */ ++ VRELOCABLE, /* info = instruction pc */ ++ VNONRELOC, /* info = result register */ ++ VCALL, /* info = instruction pc */ ++ VVARARG /* info = instruction pc */ ++} expkind; ++ ++typedef struct expdesc { ++ expkind k; ++ union { ++ struct { int info, aux; } s; ++ lua_Number nval; ++ } u; ++ int t; /* patch list of `exit when true' */ ++ int f; /* patch list of `exit when false' */ ++} expdesc; ++ ++ ++typedef struct upvaldesc { ++ lu_byte k; ++ lu_byte info; ++} upvaldesc; ++ ++ ++struct BlockCnt; /* defined in lparser.c */ ++ ++ ++/* state needed to generate code for a given function */ ++typedef struct FuncState { ++ Proto *f; /* current function header */ ++ Table *h; /* table to find (and reuse) elements in `k' */ ++ struct FuncState *prev; /* enclosing function */ ++ struct LexState *ls; /* lexical state */ ++ struct lua_State *L; /* copy of the Lua state */ ++ struct BlockCnt *bl; /* chain of current blocks */ ++ int pc; /* next position to code (equivalent to `ncode') */ ++ int lasttarget; /* `pc' of last `jump target' */ ++ int jpc; /* list of pending jumps to `pc' */ ++ int freereg; /* first free register */ ++ int nk; /* number of elements in `k' */ ++ int np; /* number of elements in `p' */ ++ short nlocvars; /* number of elements in `locvars' */ ++ lu_byte nactvar; /* number of active local variables */ ++ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ ++ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ ++} FuncState; ++ ++ ++LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, ++ const char *name); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lstate.c +@@ -0,0 +1,214 @@ ++/* ++** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ ++** Global State ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <stddef.h> ++ ++#define lstate_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "llex.h" ++#include "lmem.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) ++#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) ++#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) ++ ++ ++/* ++** Main thread combines a thread state and the global state ++*/ ++typedef struct LG { ++ lua_State l; ++ global_State g; ++} LG; ++ ++ ++ ++static void stack_init (lua_State *L1, lua_State *L) { ++ /* initialize CallInfo array */ ++ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); ++ L1->ci = L1->base_ci; ++ L1->size_ci = BASIC_CI_SIZE; ++ L1->end_ci = L1->base_ci + L1->size_ci - 1; ++ /* initialize stack array */ ++ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); ++ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; ++ L1->top = L1->stack; ++ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; ++ /* initialize first ci */ ++ L1->ci->func = L1->top; ++ setnilvalue(L1->top++); /* `function' entry for this `ci' */ ++ L1->base = L1->ci->base = L1->top; ++ L1->ci->top = L1->top + LUA_MINSTACK; ++} ++ ++ ++static void freestack (lua_State *L, lua_State *L1) { ++ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); ++ luaM_freearray(L, L1->stack, L1->stacksize, TValue); ++} ++ ++ ++/* ++** open parts that may cause memory-allocation errors ++*/ ++static void f_luaopen (lua_State *L, void *ud) { ++ global_State *g = G(L); ++ UNUSED(ud); ++ stack_init(L, L); /* init stack */ ++ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ ++ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ ++ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ ++ luaT_init(L); ++ luaX_init(L); ++ luaS_fix(luaS_newliteral(L, MEMERRMSG)); ++ g->GCthreshold = 4*g->totalbytes; ++} ++ ++ ++static void preinit_state (lua_State *L, global_State *g) { ++ G(L) = g; ++ L->stack = NULL; ++ L->stacksize = 0; ++ L->errorJmp = NULL; ++ L->hook = NULL; ++ L->hookmask = 0; ++ L->basehookcount = 0; ++ L->allowhook = 1; ++ resethookcount(L); ++ L->openupval = NULL; ++ L->size_ci = 0; ++ L->nCcalls = L->baseCcalls = 0; ++ L->status = 0; ++ L->base_ci = L->ci = NULL; ++ L->savedpc = NULL; ++ L->errfunc = 0; ++ setnilvalue(gt(L)); ++} ++ ++ ++static void close_state (lua_State *L) { ++ global_State *g = G(L); ++ luaF_close(L, L->stack); /* close all upvalues for this thread */ ++ luaC_freeall(L); /* collect all objects */ ++ lua_assert(g->rootgc == obj2gco(L)); ++ lua_assert(g->strt.nuse == 0); ++ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); ++ luaZ_freebuffer(L, &g->buff); ++ freestack(L, L); ++ lua_assert(g->totalbytes == sizeof(LG)); ++ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); ++} ++ ++ ++lua_State *luaE_newthread (lua_State *L) { ++ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); ++ luaC_link(L, obj2gco(L1), LUA_TTHREAD); ++ preinit_state(L1, G(L)); ++ stack_init(L1, L); /* init stack */ ++ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ ++ L1->hookmask = L->hookmask; ++ L1->basehookcount = L->basehookcount; ++ L1->hook = L->hook; ++ resethookcount(L1); ++ lua_assert(iswhite(obj2gco(L1))); ++ return L1; ++} ++ ++ ++void luaE_freethread (lua_State *L, lua_State *L1) { ++ luaF_close(L1, L1->stack); /* close all upvalues for this thread */ ++ lua_assert(L1->openupval == NULL); ++ luai_userstatefree(L1); ++ freestack(L, L1); ++ luaM_freemem(L, fromstate(L1), state_size(lua_State)); ++} ++ ++ ++LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { ++ int i; ++ lua_State *L; ++ global_State *g; ++ void *l = (*f)(ud, NULL, 0, state_size(LG)); ++ if (l == NULL) return NULL; ++ L = tostate(l); ++ g = &((LG *)L)->g; ++ L->next = NULL; ++ L->tt = LUA_TTHREAD; ++ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); ++ L->marked = luaC_white(g); ++ set2bits(L->marked, FIXEDBIT, SFIXEDBIT); ++ preinit_state(L, g); ++ g->frealloc = f; ++ g->ud = ud; ++ g->mainthread = L; ++ g->uvhead.u.l.prev = &g->uvhead; ++ g->uvhead.u.l.next = &g->uvhead; ++ g->GCthreshold = 0; /* mark it as unfinished state */ ++ g->strt.size = 0; ++ g->strt.nuse = 0; ++ g->strt.hash = NULL; ++ setnilvalue(registry(L)); ++ luaZ_initbuffer(L, &g->buff); ++ g->panic = NULL; ++ g->gcstate = GCSpause; ++ g->rootgc = obj2gco(L); ++ g->sweepstrgc = 0; ++ g->sweepgc = &g->rootgc; ++ g->gray = NULL; ++ g->grayagain = NULL; ++ g->weak = NULL; ++ g->tmudata = NULL; ++ g->totalbytes = sizeof(LG); ++ g->gcpause = LUAI_GCPAUSE; ++ g->gcstepmul = LUAI_GCMUL; ++ g->gcdept = 0; ++ for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; ++ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { ++ /* memory allocation error: free partial state */ ++ close_state(L); ++ L = NULL; ++ } ++ else ++ luai_userstateopen(L); ++ return L; ++} ++ ++ ++static void callallgcTM (lua_State *L, void *ud) { ++ UNUSED(ud); ++ luaC_callGCTM(L); /* call GC metamethods for all udata */ ++} ++ ++ ++LUA_API void lua_close (lua_State *L) { ++ L = G(L)->mainthread; /* only the main thread can be closed */ ++ lua_lock(L); ++ luaF_close(L, L->stack); /* close all upvalues for this thread */ ++ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ ++ L->errfunc = 0; /* no error function during GC metamethods */ ++ do { /* repeat until no more errors */ ++ L->ci = L->base_ci; ++ L->base = L->top = L->ci->base; ++ L->nCcalls = L->baseCcalls = 0; ++ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); ++ lua_assert(G(L)->tmudata == NULL); ++ luai_userstateclose(L); ++ close_state(L); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstate.h +@@ -0,0 +1,169 @@ ++/* ++** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ ++** Global State ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lstate_h ++#define lstate_h ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "ltm.h" ++#include "lzio.h" ++ ++ ++ ++struct lua_longjmp; /* defined in ldo.c */ ++ ++ ++/* table of globals */ ++#define gt(L) (&L->l_gt) ++ ++/* registry */ ++#define registry(L) (&G(L)->l_registry) ++ ++ ++/* extra stack space to handle TM calls and some other extras */ ++#define EXTRA_STACK 5 ++ ++ ++#define BASIC_CI_SIZE 8 ++ ++#define BASIC_STACK_SIZE (2*LUA_MINSTACK) ++ ++ ++ ++typedef struct stringtable { ++ GCObject **hash; ++ lu_int32 nuse; /* number of elements */ ++ int size; ++} stringtable; ++ ++ ++/* ++** informations about a call ++*/ ++typedef struct CallInfo { ++ StkId base; /* base for this function */ ++ StkId func; /* function index in the stack */ ++ StkId top; /* top for this function */ ++ const Instruction *savedpc; ++ int nresults; /* expected number of results from this function */ ++ int tailcalls; /* number of tail calls lost under this entry */ ++} CallInfo; ++ ++ ++ ++#define curr_func(L) (clvalue(L->ci->func)) ++#define ci_func(ci) (clvalue((ci)->func)) ++#define f_isLua(ci) (!ci_func(ci)->c.isC) ++#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) ++ ++ ++/* ++** `global state', shared by all threads of this state ++*/ ++typedef struct global_State { ++ stringtable strt; /* hash table for strings */ ++ lua_Alloc frealloc; /* function to reallocate memory */ ++ void *ud; /* auxiliary data to `frealloc' */ ++ lu_byte currentwhite; ++ lu_byte gcstate; /* state of garbage collector */ ++ int sweepstrgc; /* position of sweep in `strt' */ ++ GCObject *rootgc; /* list of all collectable objects */ ++ GCObject **sweepgc; /* position of sweep in `rootgc' */ ++ GCObject *gray; /* list of gray objects */ ++ GCObject *grayagain; /* list of objects to be traversed atomically */ ++ GCObject *weak; /* list of weak tables (to be cleared) */ ++ GCObject *tmudata; /* last element of list of userdata to be GC */ ++ Mbuffer buff; /* temporary buffer for string concatentation */ ++ lu_mem GCthreshold; ++ lu_mem totalbytes; /* number of bytes currently allocated */ ++ lu_mem estimate; /* an estimate of number of bytes actually in use */ ++ lu_mem gcdept; /* how much GC is `behind schedule' */ ++ int gcpause; /* size of pause between successive GCs */ ++ int gcstepmul; /* GC `granularity' */ ++ lua_CFunction panic; /* to be called in unprotected errors */ ++ TValue l_registry; ++ struct lua_State *mainthread; ++ UpVal uvhead; /* head of double-linked list of all open upvalues */ ++ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ ++ TString *tmname[TM_N]; /* array with tag-method names */ ++} global_State; ++ ++ ++/* ++** `per thread' state ++*/ ++struct lua_State { ++ CommonHeader; ++ lu_byte status; ++ StkId top; /* first free slot in the stack */ ++ StkId base; /* base of current function */ ++ global_State *l_G; ++ CallInfo *ci; /* call info for current function */ ++ const Instruction *savedpc; /* `savedpc' of current function */ ++ StkId stack_last; /* last free slot in the stack */ ++ StkId stack; /* stack base */ ++ CallInfo *end_ci; /* points after end of ci array*/ ++ CallInfo *base_ci; /* array of CallInfo's */ ++ int stacksize; ++ int size_ci; /* size of array `base_ci' */ ++ unsigned short nCcalls; /* number of nested C calls */ ++ unsigned short baseCcalls; /* nested C calls when resuming coroutine */ ++ lu_byte hookmask; ++ lu_byte allowhook; ++ int basehookcount; ++ int hookcount; ++ lua_Hook hook; ++ TValue l_gt; /* table of globals */ ++ TValue env; /* temporary place for environments */ ++ GCObject *openupval; /* list of open upvalues in this stack */ ++ GCObject *gclist; ++ struct lua_longjmp *errorJmp; /* current error recover point */ ++ ptrdiff_t errfunc; /* current error handling function (stack index) */ ++}; ++ ++ ++#define G(L) (L->l_G) ++ ++ ++/* ++** Union of all collectable objects ++*/ ++union GCObject { ++ GCheader gch; ++ union TString ts; ++ union Udata u; ++ union Closure cl; ++ struct Table h; ++ struct Proto p; ++ struct UpVal uv; ++ struct lua_State th; /* thread */ ++}; ++ ++ ++/* macros to convert a GCObject into a specific value */ ++#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) ++#define gco2ts(o) (&rawgco2ts(o)->tsv) ++#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) ++#define gco2u(o) (&rawgco2u(o)->uv) ++#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) ++#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) ++#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) ++#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) ++#define ngcotouv(o) \ ++ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) ++#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) ++ ++/* macro to convert any Lua object into a GCObject */ ++#define obj2gco(v) (cast(GCObject *, (v))) ++ ++ ++LUAI_FUNC lua_State *luaE_newthread (lua_State *L); ++LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstring.c +@@ -0,0 +1,110 @@ ++/* ++** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** String table (keeps all strings handled by Lua) ++** See Copyright Notice in lua.h ++*/ ++ ++#include <string.h> ++ ++#define lstring_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++ ++ ++ ++void luaS_resize (lua_State *L, int newsize) { ++ GCObject **newhash; ++ stringtable *tb; ++ int i; ++ if (G(L)->gcstate == GCSsweepstring) ++ return; /* cannot resize during GC traverse */ ++ newhash = luaM_newvector(L, newsize, GCObject *); ++ tb = &G(L)->strt; ++ for (i=0; i<newsize; i++) newhash[i] = NULL; ++ /* rehash */ ++ for (i=0; i<tb->size; i++) { ++ GCObject *p = tb->hash[i]; ++ while (p) { /* for each node in the list */ ++ GCObject *next = p->gch.next; /* save next */ ++ unsigned int h = gco2ts(p)->hash; ++ int h1 = lmod(h, newsize); /* new position */ ++ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); ++ p->gch.next = newhash[h1]; /* chain it */ ++ newhash[h1] = p; ++ p = next; ++ } ++ } ++ luaM_freearray(L, tb->hash, tb->size, TString *); ++ tb->size = newsize; ++ tb->hash = newhash; ++} ++ ++ ++static TString *newlstr (lua_State *L, const char *str, size_t l, ++ unsigned int h) { ++ TString *ts; ++ stringtable *tb; ++ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) ++ luaM_toobig(L); ++ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); ++ ts->tsv.len = l; ++ ts->tsv.hash = h; ++ ts->tsv.marked = luaC_white(G(L)); ++ ts->tsv.tt = LUA_TSTRING; ++ ts->tsv.reserved = 0; ++ memcpy(ts+1, str, l*sizeof(char)); ++ ((char *)(ts+1))[l] = '\0'; /* ending 0 */ ++ tb = &G(L)->strt; ++ h = lmod(h, tb->size); ++ ts->tsv.next = tb->hash[h]; /* chain new entry */ ++ tb->hash[h] = obj2gco(ts); ++ tb->nuse++; ++ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) ++ luaS_resize(L, tb->size*2); /* too crowded */ ++ return ts; ++} ++ ++ ++TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { ++ GCObject *o; ++ unsigned int h = cast(unsigned int, l); /* seed */ ++ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ ++ size_t l1; ++ for (l1=l; l1>=step; l1-=step) /* compute hash */ ++ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); ++ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; ++ o != NULL; ++ o = o->gch.next) { ++ TString *ts = rawgco2ts(o); ++ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { ++ /* string may be dead */ ++ if (isdead(G(L), o)) changewhite(o); ++ return ts; ++ } ++ } ++ return newlstr(L, str, l, h); /* not found */ ++} ++ ++ ++Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { ++ Udata *u; ++ if (s > MAX_SIZET - sizeof(Udata)) ++ luaM_toobig(L); ++ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); ++ u->uv.marked = luaC_white(G(L)); /* is not finalized */ ++ u->uv.tt = LUA_TUSERDATA; ++ u->uv.len = s; ++ u->uv.metatable = NULL; ++ u->uv.env = e; ++ /* chain it on udata list (after main thread) */ ++ u->uv.next = G(L)->mainthread->next; ++ G(L)->mainthread->next = obj2gco(u); ++ return u; ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lstring.h +@@ -0,0 +1,31 @@ ++/* ++** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ ++** String table (keep all strings handled by Lua) ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lstring_h ++#define lstring_h ++ ++ ++#include "lgc.h" ++#include "lobject.h" ++#include "lstate.h" ++ ++ ++#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) ++ ++#define sizeudata(u) (sizeof(union Udata)+(u)->len) ++ ++#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) ++#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ ++ (sizeof(s)/sizeof(char))-1)) ++ ++#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) ++ ++LUAI_FUNC void luaS_resize (lua_State *L, int newsize); ++LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); ++LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lstrlib.c +@@ -0,0 +1,883 @@ ++/* ++** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ++** Standard library for string operations and pattern-matching ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <ctype.h> ++#include <stddef.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#define lstrlib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++/* macro to `unsign' a character */ ++#define uchar(c) ((unsigned char)(c)) ++ ++ ++ ++static int str_len (lua_State *L) { ++ size_t l; ++ luaL_checklstring(L, 1, &l); ++ lua_pushinteger(L, l); ++ return 1; ++} ++ ++ ++static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { ++ /* relative string position: negative means back from end */ ++ if (pos < 0) pos += (ptrdiff_t)len + 1; ++ return (pos >= 0) ? pos : 0; ++} ++ ++ ++static int str_sub (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); ++ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); ++ if (start < 1) start = 1; ++ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; ++ if (start <= end) ++ lua_pushlstring(L, s+start-1, end-start+1); ++ else lua_pushliteral(L, ""); ++ return 1; ++} ++ ++ ++static int str_reverse (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_reverse: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (l--) luaL_addchar(b, s[l]); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_lower (lua_State *L) { ++ size_t l; ++ size_t i; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_lower: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ for (i=0; i<l; i++) ++ luaL_addchar(b, tolower(uchar(s[i]))); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_upper (lua_State *L) { ++ size_t l; ++ size_t i; ++ const char *s = luaL_checklstring(L, 1, &l); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_upper: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ for (i=0; i<l; i++) ++ luaL_addchar(b, toupper(uchar(s[i]))); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++static int str_rep (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ int n = luaL_checkint(L, 2); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_rep: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (n-- > 0) ++ luaL_addlstring(b, s, l); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int str_byte (lua_State *L) { ++ size_t l; ++ const char *s = luaL_checklstring(L, 1, &l); ++ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); ++ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); ++ int n, i; ++ if (posi <= 0) posi = 1; ++ if ((size_t)pose > l) pose = l; ++ if (posi > pose) return 0; /* empty interval; return no values */ ++ n = (int)(pose - posi + 1); ++ if (posi + n <= pose) /* overflow? */ ++ luaL_error(L, "string slice too long"); ++ luaL_checkstack(L, n, "string slice too long"); ++ for (i=0; i<n; i++) ++ lua_pushinteger(L, uchar(s[posi+i-1])); ++ return n; ++} ++ ++ ++static int str_char (lua_State *L) { ++ int n = lua_gettop(L); /* number of arguments */ ++ int i; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_char: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ for (i=1; i<=n; i++) { ++ int c = luaL_checkint(L, i); ++ luaL_argcheck(L, uchar(c) == c, i, "invalid value"); ++ luaL_addchar(b, uchar(c)); ++ } ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static int writer (lua_State *L, const void* b, size_t size, void* B) { ++ (void)L; ++ luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); ++ return 0; ++} ++ ++ ++static int str_dump (lua_State *L) { ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_dump: cannot allocate memory"); ++ luaL_checktype(L, 1, LUA_TFUNCTION); ++ lua_settop(L, 1); ++ luaL_buffinit(L,b); ++ if (lua_dump(L, writer, b) != 0){ ++ kfree(b); ++ luaL_error(L, "unable to dump given function"); ++ } ++ ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++ ++/* ++** {====================================================== ++** PATTERN MATCHING ++** ======================================================= ++*/ ++ ++ ++#define CAP_UNFINISHED (-1) ++#define CAP_POSITION (-2) ++ ++typedef struct MatchState { ++ const char *src_init; /* init of source string */ ++ const char *src_end; /* end (`\0') of source string */ ++ lua_State *L; ++ int level; /* total number of captures (finished or unfinished) */ ++ struct { ++ const char *init; ++ ptrdiff_t len; ++ } capture[LUA_MAXCAPTURES]; ++} MatchState; ++ ++ ++#define L_ESC '%' ++#define SPECIALS "^$*+?.([%-" ++ ++ ++static int check_capture (MatchState *ms, int l) { ++ l -= '1'; ++ if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) ++ return luaL_error(ms->L, "invalid capture index"); ++ return l; ++} ++ ++ ++static int capture_to_close (MatchState *ms) { ++ int level = ms->level; ++ for (level--; level>=0; level--) ++ if (ms->capture[level].len == CAP_UNFINISHED) return level; ++ return luaL_error(ms->L, "invalid pattern capture"); ++} ++ ++ ++static const char *classend (MatchState *ms, const char *p) { ++ switch (*p++) { ++ case L_ESC: { ++ if (*p == '\0') ++ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); ++ return p+1; ++ } ++ case '[': { ++ if (*p == '^') p++; ++ do { /* look for a `]' */ ++ if (*p == '\0') ++ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); ++ if (*(p++) == L_ESC && *p != '\0') ++ p++; /* skip escapes (e.g. `%]') */ ++ } while (*p != ']'); ++ return p+1; ++ } ++ default: { ++ return p; ++ } ++ } ++} ++ ++ ++static int match_class (int c, int cl) { ++ int res; ++ switch (tolower(cl)) { ++ case 'a' : res = isalpha(c); break; ++ case 'c' : res = iscntrl(c); break; ++ case 'd' : res = isdigit(c); break; ++ case 'l' : res = islower(c); break; ++ case 'p' : res = ispunct(c); break; ++ case 's' : res = isspace(c); break; ++ case 'u' : res = isupper(c); break; ++ case 'w' : res = isalnum(c); break; ++ case 'x' : res = isxdigit(c); break; ++ case 'z' : res = (c == 0); break; ++ default: return (cl == c); ++ } ++ return (islower(cl) ? res : !res); ++} ++ ++ ++static int matchbracketclass (int c, const char *p, const char *ec) { ++ int sig = 1; ++ if (*(p+1) == '^') { ++ sig = 0; ++ p++; /* skip the `^' */ ++ } ++ while (++p < ec) { ++ if (*p == L_ESC) { ++ p++; ++ if (match_class(c, uchar(*p))) ++ return sig; ++ } ++ else if ((*(p+1) == '-') && (p+2 < ec)) { ++ p+=2; ++ if (uchar(*(p-2)) <= c && c <= uchar(*p)) ++ return sig; ++ } ++ else if (uchar(*p) == c) return sig; ++ } ++ return !sig; ++} ++ ++ ++static int singlematch (int c, const char *p, const char *ep) { ++ switch (*p) { ++ case '.': return 1; /* matches any char */ ++ case L_ESC: return match_class(c, uchar(*(p+1))); ++ case '[': return matchbracketclass(c, p, ep-1); ++ default: return (uchar(*p) == c); ++ } ++} ++ ++ ++static const char *match (MatchState *ms, const char *s, const char *p); ++ ++ ++static const char *matchbalance (MatchState *ms, const char *s, ++ const char *p) { ++ if (*p == 0 || *(p+1) == 0) ++ luaL_error(ms->L, "unbalanced pattern"); ++ if (*s != *p) return NULL; ++ else { ++ int b = *p; ++ int e = *(p+1); ++ int cont = 1; ++ while (++s < ms->src_end) { ++ if (*s == e) { ++ if (--cont == 0) return s+1; ++ } ++ else if (*s == b) cont++; ++ } ++ } ++ return NULL; /* string ends out of balance */ ++} ++ ++ ++static const char *max_expand (MatchState *ms, const char *s, ++ const char *p, const char *ep) { ++ ptrdiff_t i = 0; /* counts maximum expand for item */ ++ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep)) ++ i++; ++ /* keeps trying to match with the maximum repetitions */ ++ while (i>=0) { ++ const char *res = match(ms, (s+i), ep+1); ++ if (res) return res; ++ i--; /* else didn't match; reduce 1 repetition to try again */ ++ } ++ return NULL; ++} ++ ++ ++static const char *min_expand (MatchState *ms, const char *s, ++ const char *p, const char *ep) { ++ for (;;) { ++ const char *res = match(ms, s, ep+1); ++ if (res != NULL) ++ return res; ++ else if (s<ms->src_end && singlematch(uchar(*s), p, ep)) ++ s++; /* try with one more repetition */ ++ else return NULL; ++ } ++} ++ ++ ++static const char *start_capture (MatchState *ms, const char *s, ++ const char *p, int what) { ++ const char *res; ++ int level = ms->level; ++ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); ++ ms->capture[level].init = s; ++ ms->capture[level].len = what; ++ ms->level = level+1; ++ if ((res=match(ms, s, p)) == NULL) /* match failed? */ ++ ms->level--; /* undo capture */ ++ return res; ++} ++ ++ ++static const char *end_capture (MatchState *ms, const char *s, ++ const char *p) { ++ int l = capture_to_close(ms); ++ const char *res; ++ ms->capture[l].len = s - ms->capture[l].init; /* close capture */ ++ if ((res = match(ms, s, p)) == NULL) /* match failed? */ ++ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ ++ return res; ++} ++ ++ ++static const char *match_capture (MatchState *ms, const char *s, int l) { ++ size_t len; ++ l = check_capture(ms, l); ++ len = ms->capture[l].len; ++ if ((size_t)(ms->src_end-s) >= len && ++ memcmp(ms->capture[l].init, s, len) == 0) ++ return s+len; ++ else return NULL; ++} ++ ++ ++static const char *match (MatchState *ms, const char *s, const char *p) { ++ init: /* using goto's to optimize tail recursion */ ++ switch (*p) { ++ case '(': { /* start capture */ ++ if (*(p+1) == ')') /* position capture? */ ++ return start_capture(ms, s, p+2, CAP_POSITION); ++ else ++ return start_capture(ms, s, p+1, CAP_UNFINISHED); ++ } ++ case ')': { /* end capture */ ++ return end_capture(ms, s, p+1); ++ } ++ case L_ESC: { ++ switch (*(p+1)) { ++ case 'b': { /* balanced string? */ ++ s = matchbalance(ms, s, p+2); ++ if (s == NULL) return NULL; ++ p+=4; goto init; /* else return match(ms, s, p+4); */ ++ } ++ case 'f': { /* frontier? */ ++ const char *ep; char previous; ++ p += 2; ++ if (*p != '[') ++ luaL_error(ms->L, "missing " LUA_QL("[") " after " ++ LUA_QL("%%f") " in pattern"); ++ ep = classend(ms, p); /* points to what is next */ ++ previous = (s == ms->src_init) ? '\0' : *(s-1); ++ if (matchbracketclass(uchar(previous), p, ep-1) || ++ !matchbracketclass(uchar(*s), p, ep-1)) return NULL; ++ p=ep; goto init; /* else return match(ms, s, ep); */ ++ } ++ default: { ++ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ ++ s = match_capture(ms, s, uchar(*(p+1))); ++ if (s == NULL) return NULL; ++ p+=2; goto init; /* else return match(ms, s, p+2) */ ++ } ++ goto dflt; /* case default */ ++ } ++ } ++ } ++ case '\0': { /* end of pattern */ ++ return s; /* match succeeded */ ++ } ++ case '$': { ++ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ ++ return (s == ms->src_end) ? s : NULL; /* check end of string */ ++ else goto dflt; ++ } ++ default: dflt: { /* it is a pattern item */ ++ const char *ep = classend(ms, p); /* points to what is next */ ++ int m = s<ms->src_end && singlematch(uchar(*s), p, ep); ++ switch (*ep) { ++ case '?': { /* optional */ ++ const char *res; ++ if (m && ((res=match(ms, s+1, ep+1)) != NULL)) ++ return res; ++ p=ep+1; goto init; /* else return match(ms, s, ep+1); */ ++ } ++ case '*': { /* 0 or more repetitions */ ++ return max_expand(ms, s, p, ep); ++ } ++ case '+': { /* 1 or more repetitions */ ++ return (m ? max_expand(ms, s+1, p, ep) : NULL); ++ } ++ case '-': { /* 0 or more repetitions (minimum) */ ++ return min_expand(ms, s, p, ep); ++ } ++ default: { ++ if (!m) return NULL; ++ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ ++ } ++ } ++ } ++ } ++} ++ ++ ++ ++static const char *lmemfind (const char *s1, size_t l1, ++ const char *s2, size_t l2) { ++ if (l2 == 0) return s1; /* empty strings are everywhere */ ++ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ ++ else { ++ const char *init; /* to search for a `*s2' inside `s1' */ ++ l2--; /* 1st char will be checked by `memchr' */ ++ l1 = l1-l2; /* `s2' cannot be found after that */ ++ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { ++ init++; /* 1st char is already checked */ ++ if (memcmp(init, s2+1, l2) == 0) ++ return init-1; ++ else { /* correct `l1' and `s1' to try again */ ++ l1 -= init-s1; ++ s1 = init; ++ } ++ } ++ return NULL; /* not found */ ++ } ++} ++ ++ ++static void push_onecapture (MatchState *ms, int i, const char *s, ++ const char *e) { ++ if (i >= ms->level) { ++ if (i == 0) /* ms->level == 0, too */ ++ lua_pushlstring(ms->L, s, e - s); /* add whole match */ ++ else ++ luaL_error(ms->L, "invalid capture index"); ++ } ++ else { ++ ptrdiff_t l = ms->capture[i].len; ++ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); ++ if (l == CAP_POSITION) ++ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); ++ else ++ lua_pushlstring(ms->L, ms->capture[i].init, l); ++ } ++} ++ ++ ++static int push_captures (MatchState *ms, const char *s, const char *e) { ++ int i; ++ int nlevels = (ms->level == 0 && s) ? 1 : ms->level; ++ luaL_checkstack(ms->L, nlevels, "too many captures"); ++ for (i = 0; i < nlevels; i++) ++ push_onecapture(ms, i, s, e); ++ return nlevels; /* number of strings pushed */ ++} ++ ++ ++static int str_find_aux (lua_State *L, int find) { ++ size_t l1, l2; ++ const char *s = luaL_checklstring(L, 1, &l1); ++ const char *p = luaL_checklstring(L, 2, &l2); ++ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; ++ if (init < 0) init = 0; ++ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; ++ if (find && (lua_toboolean(L, 4) || /* explicit request? */ ++ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ ++ /* do a plain search */ ++ const char *s2 = lmemfind(s+init, l1-init, p, l2); ++ if (s2) { ++ lua_pushinteger(L, s2-s+1); ++ lua_pushinteger(L, s2-s+l2); ++ return 2; ++ } ++ } ++ else { ++ MatchState ms; ++ int anchor = (*p == '^') ? (p++, 1) : 0; ++ const char *s1=s+init; ++ ms.L = L; ++ ms.src_init = s; ++ ms.src_end = s+l1; ++ do { ++ const char *res; ++ ms.level = 0; ++ if ((res=match(&ms, s1, p)) != NULL) { ++ if (find) { ++ lua_pushinteger(L, s1-s+1); /* start */ ++ lua_pushinteger(L, res-s); /* end */ ++ return push_captures(&ms, NULL, 0) + 2; ++ } ++ else ++ return push_captures(&ms, s1, res); ++ } ++ } while (s1++ < ms.src_end && !anchor); ++ } ++ lua_pushnil(L); /* not found */ ++ return 1; ++} ++ ++ ++static int str_find (lua_State *L) { ++ return str_find_aux(L, 1); ++} ++ ++ ++static int str_match (lua_State *L) { ++ return str_find_aux(L, 0); ++} ++ ++ ++static int gmatch_aux (lua_State *L) { ++ MatchState ms; ++ size_t ls; ++ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); ++ const char *p = lua_tostring(L, lua_upvalueindex(2)); ++ const char *src; ++ ms.L = L; ++ ms.src_init = s; ++ ms.src_end = s+ls; ++ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); ++ src <= ms.src_end; ++ src++) { ++ const char *e; ++ ms.level = 0; ++ if ((e = match(&ms, src, p)) != NULL) { ++ lua_Integer newstart = e-s; ++ if (e == src) newstart++; /* empty match? go at least one position */ ++ lua_pushinteger(L, newstart); ++ lua_replace(L, lua_upvalueindex(3)); ++ return push_captures(&ms, src, e); ++ } ++ } ++ return 0; /* not found */ ++} ++ ++ ++static int gmatch (lua_State *L) { ++ luaL_checkstring(L, 1); ++ luaL_checkstring(L, 2); ++ lua_settop(L, 2); ++ lua_pushinteger(L, 0); ++ lua_pushcclosure(L, gmatch_aux, 3); ++ return 1; ++} ++ ++ ++static int gfind_nodef (lua_State *L) { ++ return luaL_error(L, LUA_QL("string.gfind") " was renamed to " ++ LUA_QL("string.gmatch")); ++} ++ ++ ++static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, ++ const char *e) { ++ size_t l, i; ++ const char *news = lua_tolstring(ms->L, 3, &l); ++ for (i = 0; i < l; i++) { ++ if (news[i] != L_ESC) ++ luaL_addchar(b, news[i]); ++ else { ++ i++; /* skip ESC */ ++ if (!isdigit(uchar(news[i]))) ++ luaL_addchar(b, news[i]); ++ else if (news[i] == '0') ++ luaL_addlstring(b, s, e - s); ++ else { ++ push_onecapture(ms, news[i] - '1', s, e); ++ luaL_addvalue(b); /* add capture to accumulated result */ ++ } ++ } ++ } ++} ++ ++ ++static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, ++ const char *e) { ++ lua_State *L = ms->L; ++ switch (lua_type(L, 3)) { ++ case LUA_TNUMBER: ++ case LUA_TSTRING: { ++ add_s(ms, b, s, e); ++ return; ++ } ++ case LUA_TFUNCTION: { ++ int n; ++ lua_pushvalue(L, 3); ++ n = push_captures(ms, s, e); ++ lua_call(L, n, 1); ++ break; ++ } ++ case LUA_TTABLE: { ++ push_onecapture(ms, 0, s, e); ++ lua_gettable(L, 3); ++ break; ++ } ++ } ++ if (!lua_toboolean(L, -1)) { /* nil or false? */ ++ lua_pop(L, 1); ++ lua_pushlstring(L, s, e - s); /* keep original text */ ++ } ++ else if (!lua_isstring(L, -1)) ++ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); ++ luaL_addvalue(b); /* add result to accumulator */ ++} ++ ++ ++static int str_gsub (lua_State *L) { ++ size_t srcl; ++ const char *src = luaL_checklstring(L, 1, &srcl); ++ const char *p = luaL_checkstring(L, 2); ++ int tr = lua_type(L, 3); ++ int max_s = luaL_optint(L, 4, srcl+1); ++ int anchor = (*p == '^') ? (p++, 1) : 0; ++ int n = 0; ++ MatchState ms; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_gsub: cannot allocate memory"); ++ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || ++ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, ++ "string/function/table expected"); ++ luaL_buffinit(L, b); ++ ms.L = L; ++ ms.src_init = src; ++ ms.src_end = src+srcl; ++ while (n < max_s) { ++ const char *e; ++ ms.level = 0; ++ e = match(&ms, src, p); ++ if (e) { ++ n++; ++ add_value(&ms, b, src, e); ++ } ++ if (e && e>src) /* non empty match? */ ++ src = e; /* skip it */ ++ else if (src < ms.src_end) ++ luaL_addchar(b, *src++); ++ else break; ++ if (anchor) break; ++ } ++ luaL_addlstring(b, src, ms.src_end-src); ++ luaL_pushresult(b); ++ lua_pushinteger(L, n); /* number of substitutions */ ++ kfree(b); ++ return 2; ++} ++ ++/* }====================================================== */ ++ ++ ++/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ ++#define MAX_ITEM 512 ++/* valid flags in a format specification */ ++#define FLAGS "-+ #0" ++/* ++** maximum size of each format specification (such as '%-099.99d') ++** (+10 accounts for %99.99x plus margin of error) ++*/ ++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) ++ ++ ++static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { ++ size_t l; ++ const char *s = luaL_checklstring(L, arg, &l); ++ luaL_addchar(b, '"'); ++ while (l--) { ++ switch (*s) { ++ case '"': case '\\': case '\n': { ++ luaL_addchar(b, '\\'); ++ luaL_addchar(b, *s); ++ break; ++ } ++ case '\r': { ++ luaL_addlstring(b, "\\r", 2); ++ break; ++ } ++ case '\0': { ++ luaL_addlstring(b, "\\000", 4); ++ break; ++ } ++ default: { ++ luaL_addchar(b, *s); ++ break; ++ } ++ } ++ s++; ++ } ++ luaL_addchar(b, '"'); ++} ++ ++static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { ++ const char *p = strfrmt; ++ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ ++ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) ++ luaL_error(L, "invalid format (repeated flags)"); ++ if (isdigit(uchar(*p))) p++; /* skip width */ ++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ ++ if (*p == '.') { ++ p++; ++ if (isdigit(uchar(*p))) p++; /* skip precision */ ++ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ ++ } ++ if (isdigit(uchar(*p))) ++ luaL_error(L, "invalid format (width or precision too long)"); ++ *(form++) = '%'; ++ strncpy(form, strfrmt, p - strfrmt + 1); ++ form += p - strfrmt + 1; ++ *form = '\0'; ++ return p; ++} ++ ++ ++static void addintlen (char *form) { ++ size_t l = strlen(form); ++ char spec = form[l - 1]; ++ strcpy(form + l - 1, LUA_INTFRMLEN); ++ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; ++ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; ++} ++ ++ ++static int str_format (lua_State *L) { ++ int arg = 1; ++ size_t sfl; ++ const char *strfrmt = luaL_checklstring(L, arg, &sfl); ++ const char *strfrmt_end = strfrmt+sfl; ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "str_format: cannot allocate memory"); ++ luaL_buffinit(L, b); ++ while (strfrmt < strfrmt_end) { ++ if (*strfrmt != L_ESC) ++ luaL_addchar(b, *strfrmt++); ++ else if (*++strfrmt == L_ESC) ++ luaL_addchar(b, *strfrmt++); /* %% */ ++ else { /* format item */ ++ char form[MAX_FORMAT]; /* to store the format (`%...') */ ++ char buff[MAX_ITEM]; /* to store the formatted item */ ++ arg++; ++ strfrmt = scanformat(L, strfrmt, form); ++ switch (*strfrmt++) { ++ case 'c': { ++ sprintf(buff, form, (int)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'd': case 'i': { ++ addintlen(form); ++ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'o': case 'u': case 'x': case 'X': { ++ addintlen(form); ++ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); ++ break; ++ } ++ case 'q': { ++ addquoted(L, b, arg); ++ continue; /* skip the 'addsize' at the end */ ++ } ++ case 's': { ++ size_t l; ++ const char *s = luaL_checklstring(L, arg, &l); ++ if (!strchr(form, '.') && l >= 100) { ++ /* no precision and string is too long to be formatted; ++ keep original string */ ++ lua_pushvalue(L, arg); ++ luaL_addvalue(b); ++ continue; /* skip the `addsize' at the end */ ++ } ++ else { ++ sprintf(buff, form, s); ++ break; ++ } ++ } ++ default: { /* also treat cases `pnLlh' */ ++ kfree(b); ++ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " ++ LUA_QL("format"), *(strfrmt - 1)); ++ } ++ } ++ luaL_addlstring(b, buff, strlen(buff)); ++ } ++ } ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++static const luaL_Reg strlib[] = { ++ {"byte", str_byte}, ++ {"char", str_char}, ++ {"dump", str_dump}, ++ {"find", str_find}, ++ {"format", str_format}, ++ {"gfind", gfind_nodef}, ++ {"gmatch", gmatch}, ++ {"gsub", str_gsub}, ++ {"len", str_len}, ++ {"lower", str_lower}, ++ {"match", str_match}, ++ {"rep", str_rep}, ++ {"reverse", str_reverse}, ++ {"sub", str_sub}, ++ {"upper", str_upper}, ++ {NULL, NULL} ++}; ++ ++ ++static void createmetatable (lua_State *L) { ++ lua_createtable(L, 0, 1); /* create metatable for strings */ ++ lua_pushliteral(L, ""); /* dummy string */ ++ lua_pushvalue(L, -2); ++ lua_setmetatable(L, -2); /* set string metatable */ ++ lua_pop(L, 1); /* pop dummy string */ ++ lua_pushvalue(L, -2); /* string library... */ ++ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ ++ lua_pop(L, 1); /* pop metatable */ ++} ++ ++ ++/* ++** Open string library ++*/ ++LUALIB_API int luaopen_string (lua_State *L) { ++ luaL_register(L, LUA_STRLIBNAME, strlib); ++#if defined(LUA_COMPAT_GFIND) ++ lua_getfield(L, -1, "gmatch"); ++ lua_setfield(L, -2, "gfind"); ++#endif ++ createmetatable(L); ++ return 1; ++} +--- /dev/null ++++ b/extensions/LUA/lua/ltable.c +@@ -0,0 +1,588 @@ ++/* ++** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ ++** Lua tables (hash) ++** See Copyright Notice in lua.h ++*/ ++ ++ ++/* ++** Implementation of tables (aka arrays, objects, or hash tables). ++** Tables keep its elements in two parts: an array part and a hash part. ++** Non-negative integer keys are all candidates to be kept in the array ++** part. The actual size of the array is the largest `n' such that at ++** least half the slots between 0 and n are in use. ++** Hash uses a mix of chained scatter table with Brent's variation. ++** A main invariant of these tables is that, if an element is not ++** in its main position (i.e. the `original' position that its hash gives ++** to it), then the colliding element is in its own main position. ++** Hence even when the load factor reaches 100%, performance remains good. ++*/ ++ ++#include <math.h> ++#include <string.h> ++ ++#define ltable_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lgc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstate.h" ++#include "ltable.h" ++ ++ ++/* ++** max size of array part is 2^MAXBITS ++*/ ++#if LUAI_BITSINT > 26 ++#define MAXBITS 26 ++#else ++#define MAXBITS (LUAI_BITSINT-2) ++#endif ++ ++#define MAXASIZE (1 << MAXBITS) ++ ++ ++#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) ++ ++#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) ++#define hashboolean(t,p) hashpow2(t, p) ++ ++ ++/* ++** for some types, it is better to avoid modulus by power of 2, as ++** they tend to have many 2 factors. ++*/ ++#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) ++ ++ ++#define hashpointer(t,p) hashmod(t, IntPoint(p)) ++ ++ ++/* ++** number of ints inside a lua_Number ++*/ ++#define numints cast_int(sizeof(lua_Number)/sizeof(int)) ++ ++ ++ ++#define dummynode (&dummynode_) ++ ++static const Node dummynode_ = { ++ {{NULL}, LUA_TNIL}, /* value */ ++ {{{NULL}, LUA_TNIL, NULL}} /* key */ ++}; ++ ++ ++/* ++** hash for lua_Numbers ++*/ ++static Node *hashnum (const Table *t, lua_Number n) { ++ unsigned int a[numints]; ++ int i; ++ if (luai_numeq(n, 0)) /* avoid problems with -0 */ ++ return gnode(t, 0); ++ memcpy(a, &n, sizeof(a)); ++ for (i = 1; i < numints; i++) a[0] += a[i]; ++ return hashmod(t, a[0]); ++} ++ ++ ++ ++/* ++** returns the `main' position of an element in a table (that is, the index ++** of its hash value) ++*/ ++static Node *mainposition (const Table *t, const TValue *key) { ++ switch (ttype(key)) { ++ case LUA_TNUMBER: ++ return hashnum(t, nvalue(key)); ++ case LUA_TSTRING: ++ return hashstr(t, rawtsvalue(key)); ++ case LUA_TBOOLEAN: ++ return hashboolean(t, bvalue(key)); ++ case LUA_TLIGHTUSERDATA: ++ return hashpointer(t, pvalue(key)); ++ default: ++ return hashpointer(t, gcvalue(key)); ++ } ++} ++ ++ ++/* ++** returns the index for `key' if `key' is an appropriate key to live in ++** the array part of the table, -1 otherwise. ++*/ ++static int arrayindex (const TValue *key) { ++ if (ttisnumber(key)) { ++ lua_Number n = nvalue(key); ++ int k; ++ lua_number2int(k, n); ++ if (luai_numeq(cast_num(k), n)) ++ return k; ++ } ++ return -1; /* `key' did not match some condition */ ++} ++ ++ ++/* ++** returns the index of a `key' for table traversals. First goes all ++** elements in the array part, then elements in the hash part. The ++** beginning of a traversal is signalled by -1. ++*/ ++static int findindex (lua_State *L, Table *t, StkId key) { ++ int i; ++ if (ttisnil(key)) return -1; /* first iteration */ ++ i = arrayindex(key); ++ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ ++ return i-1; /* yes; that's the index (corrected to C) */ ++ else { ++ Node *n = mainposition(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ /* key may be dead already, but it is ok to use it in `next' */ ++ if (luaO_rawequalObj(key2tval(n), key) || ++ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && ++ gcvalue(gkey(n)) == gcvalue(key))) { ++ i = cast_int(n - gnode(t, 0)); /* key index in hash table */ ++ /* hash elements are numbered after array ones */ ++ return i + t->sizearray; ++ } ++ else n = gnext(n); ++ } while (n); ++ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ ++ return 0; /* to avoid warnings */ ++ } ++} ++ ++ ++int luaH_next (lua_State *L, Table *t, StkId key) { ++ int i = findindex(L, t, key); /* find original element */ ++ for (i++; i < t->sizearray; i++) { /* try first array part */ ++ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ ++ setnvalue(key, cast_num(i+1)); ++ setobj2s(L, key+1, &t->array[i]); ++ return 1; ++ } ++ } ++ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ ++ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ ++ setobj2s(L, key, key2tval(gnode(t, i))); ++ setobj2s(L, key+1, gval(gnode(t, i))); ++ return 1; ++ } ++ } ++ return 0; /* no more elements */ ++} ++ ++ ++/* ++** {============================================================= ++** Rehash ++** ============================================================== ++*/ ++ ++ ++static int computesizes (int nums[], int *narray) { ++ int i; ++ int twotoi; /* 2^i */ ++ int a = 0; /* number of elements smaller than 2^i */ ++ int na = 0; /* number of elements to go to array part */ ++ int n = 0; /* optimal size for array part */ ++ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { ++ if (nums[i] > 0) { ++ a += nums[i]; ++ if (a > twotoi/2) { /* more than half elements present? */ ++ n = twotoi; /* optimal size (till now) */ ++ na = a; /* all elements smaller than n will go to array part */ ++ } ++ } ++ if (a == *narray) break; /* all elements already counted */ ++ } ++ *narray = n; ++ lua_assert(*narray/2 <= na && na <= *narray); ++ return na; ++} ++ ++ ++static int countint (const TValue *key, int *nums) { ++ int k = arrayindex(key); ++ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ ++ nums[ceillog2(k)]++; /* count as such */ ++ return 1; ++ } ++ else ++ return 0; ++} ++ ++ ++static int numusearray (const Table *t, int *nums) { ++ int lg; ++ int ttlg; /* 2^lg */ ++ int ause = 0; /* summation of `nums' */ ++ int i = 1; /* count to traverse all array keys */ ++ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ ++ int lc = 0; /* counter */ ++ int lim = ttlg; ++ if (lim > t->sizearray) { ++ lim = t->sizearray; /* adjust upper limit */ ++ if (i > lim) ++ break; /* no more elements to count */ ++ } ++ /* count elements in range (2^(lg-1), 2^lg] */ ++ for (; i <= lim; i++) { ++ if (!ttisnil(&t->array[i-1])) ++ lc++; ++ } ++ nums[lg] += lc; ++ ause += lc; ++ } ++ return ause; ++} ++ ++ ++static int numusehash (const Table *t, int *nums, int *pnasize) { ++ int totaluse = 0; /* total number of elements */ ++ int ause = 0; /* summation of `nums' */ ++ int i = sizenode(t); ++ while (i--) { ++ Node *n = &t->node[i]; ++ if (!ttisnil(gval(n))) { ++ ause += countint(key2tval(n), nums); ++ totaluse++; ++ } ++ } ++ *pnasize += ause; ++ return totaluse; ++} ++ ++ ++static void setarrayvector (lua_State *L, Table *t, int size) { ++ int i; ++ luaM_reallocvector(L, t->array, t->sizearray, size, TValue); ++ for (i=t->sizearray; i<size; i++) ++ setnilvalue(&t->array[i]); ++ t->sizearray = size; ++} ++ ++ ++static void setnodevector (lua_State *L, Table *t, int size) { ++ int lsize; ++ if (size == 0) { /* no elements to hash part? */ ++ t->node = cast(Node *, dummynode); /* use common `dummynode' */ ++ lsize = 0; ++ } ++ else { ++ int i; ++ lsize = ceillog2(size); ++ if (lsize > MAXBITS) ++ luaG_runerror(L, "table overflow"); ++ size = twoto(lsize); ++ t->node = luaM_newvector(L, size, Node); ++ for (i=0; i<size; i++) { ++ Node *n = gnode(t, i); ++ gnext(n) = NULL; ++ setnilvalue(gkey(n)); ++ setnilvalue(gval(n)); ++ } ++ } ++ t->lsizenode = cast_byte(lsize); ++ t->lastfree = gnode(t, size); /* all positions are free */ ++} ++ ++ ++static void resize (lua_State *L, Table *t, int nasize, int nhsize) { ++ int i; ++ int oldasize = t->sizearray; ++ int oldhsize = t->lsizenode; ++ Node *nold = t->node; /* save old hash ... */ ++ if (nasize > oldasize) /* array part must grow? */ ++ setarrayvector(L, t, nasize); ++ /* create new hash part with appropriate size */ ++ setnodevector(L, t, nhsize); ++ if (nasize < oldasize) { /* array part must shrink? */ ++ t->sizearray = nasize; ++ /* re-insert elements from vanishing slice */ ++ for (i=nasize; i<oldasize; i++) { ++ if (!ttisnil(&t->array[i])) ++ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); ++ } ++ /* shrink array */ ++ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); ++ } ++ /* re-insert elements from hash part */ ++ for (i = twoto(oldhsize) - 1; i >= 0; i--) { ++ Node *old = nold+i; ++ if (!ttisnil(gval(old))) ++ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); ++ } ++ if (nold != dummynode) ++ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ ++} ++ ++ ++void luaH_resizearray (lua_State *L, Table *t, int nasize) { ++ int nsize = (t->node == dummynode) ? 0 : sizenode(t); ++ resize(L, t, nasize, nsize); ++} ++ ++ ++static void rehash (lua_State *L, Table *t, const TValue *ek) { ++ int nasize, na; ++ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ ++ int i; ++ int totaluse; ++ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ ++ nasize = numusearray(t, nums); /* count keys in array part */ ++ totaluse = nasize; /* all those keys are integer keys */ ++ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ ++ /* count extra key */ ++ nasize += countint(ek, nums); ++ totaluse++; ++ /* compute new size for array part */ ++ na = computesizes(nums, &nasize); ++ /* resize the table to new computed sizes */ ++ resize(L, t, nasize, totaluse - na); ++} ++ ++ ++ ++/* ++** }============================================================= ++*/ ++ ++ ++Table *luaH_new (lua_State *L, int narray, int nhash) { ++ Table *t = luaM_new(L, Table); ++ luaC_link(L, obj2gco(t), LUA_TTABLE); ++ t->metatable = NULL; ++ t->flags = cast_byte(~0); ++ /* temporary values (kept only if some malloc fails) */ ++ t->array = NULL; ++ t->sizearray = 0; ++ t->lsizenode = 0; ++ t->node = cast(Node *, dummynode); ++ setarrayvector(L, t, narray); ++ setnodevector(L, t, nhash); ++ return t; ++} ++ ++ ++void luaH_free (lua_State *L, Table *t) { ++ if (t->node != dummynode) ++ luaM_freearray(L, t->node, sizenode(t), Node); ++ luaM_freearray(L, t->array, t->sizearray, TValue); ++ luaM_free(L, t); ++} ++ ++ ++static Node *getfreepos (Table *t) { ++ while (t->lastfree-- > t->node) { ++ if (ttisnil(gkey(t->lastfree))) ++ return t->lastfree; ++ } ++ return NULL; /* could not find a free place */ ++} ++ ++ ++ ++/* ++** inserts a new key into a hash table; first, check whether key's main ++** position is free. If not, check whether colliding node is in its main ++** position or not: if it is not, move colliding node to an empty place and ++** put new key in its main position; otherwise (colliding node is in its main ++** position), new key goes to an empty position. ++*/ ++static TValue *newkey (lua_State *L, Table *t, const TValue *key) { ++ Node *mp = mainposition(t, key); ++ if (!ttisnil(gval(mp)) || mp == dummynode) { ++ Node *othern; ++ Node *n = getfreepos(t); /* get a free place */ ++ if (n == NULL) { /* cannot find a free place? */ ++ rehash(L, t, key); /* grow table */ ++ return luaH_set(L, t, key); /* re-insert key into grown table */ ++ } ++ lua_assert(n != dummynode); ++ othern = mainposition(t, key2tval(mp)); ++ if (othern != mp) { /* is colliding node out of its main position? */ ++ /* yes; move colliding node into free position */ ++ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ ++ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ ++ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ ++ gnext(mp) = NULL; /* now `mp' is free */ ++ setnilvalue(gval(mp)); ++ } ++ else { /* colliding node is in its own main position */ ++ /* new node will go into free position */ ++ gnext(n) = gnext(mp); /* chain new position */ ++ gnext(mp) = n; ++ mp = n; ++ } ++ } ++ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; ++ luaC_barriert(L, t, key); ++ lua_assert(ttisnil(gval(mp))); ++ return gval(mp); ++} ++ ++ ++/* ++** search function for integers ++*/ ++const TValue *luaH_getnum (Table *t, int key) { ++ /* (1 <= key && key <= t->sizearray) */ ++ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) ++ return &t->array[key-1]; ++ else { ++ lua_Number nk = cast_num(key); ++ Node *n = hashnum(t, nk); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++ } ++} ++ ++ ++/* ++** search function for strings ++*/ ++const TValue *luaH_getstr (Table *t, TString *key) { ++ Node *n = hashstr(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++} ++ ++ ++/* ++** main search function ++*/ ++const TValue *luaH_get (Table *t, const TValue *key) { ++ switch (ttype(key)) { ++ case LUA_TNIL: return luaO_nilobject; ++ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); ++ case LUA_TNUMBER: { ++ int k; ++ lua_Number n = nvalue(key); ++ lua_number2int(k, n); ++ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ ++ return luaH_getnum(t, k); /* use specialized version */ ++ /* else go through */ ++ } ++ default: { ++ Node *n = mainposition(t, key); ++ do { /* check whether `key' is somewhere in the chain */ ++ if (luaO_rawequalObj(key2tval(n), key)) ++ return gval(n); /* that's it */ ++ else n = gnext(n); ++ } while (n); ++ return luaO_nilobject; ++ } ++ } ++} ++ ++ ++TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { ++ const TValue *p = luaH_get(t, key); ++ t->flags = 0; ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ if (ttisnil(key)) luaG_runerror(L, "table index is nil"); ++ else if (ttisnumber(key) && luai_numisnan(nvalue(key))) ++ luaG_runerror(L, "table index is NaN"); ++ return newkey(L, t, key); ++ } ++} ++ ++ ++TValue *luaH_setnum (lua_State *L, Table *t, int key) { ++ const TValue *p = luaH_getnum(t, key); ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ TValue k; ++ setnvalue(&k, cast_num(key)); ++ return newkey(L, t, &k); ++ } ++} ++ ++ ++TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { ++ const TValue *p = luaH_getstr(t, key); ++ if (p != luaO_nilobject) ++ return cast(TValue *, p); ++ else { ++ TValue k; ++ setsvalue(L, &k, key); ++ return newkey(L, t, &k); ++ } ++} ++ ++ ++static int unbound_search (Table *t, unsigned int j) { ++ unsigned int i = j; /* i is zero or a present index */ ++ j++; ++ /* find `i' and `j' such that i is present and j is not */ ++ while (!ttisnil(luaH_getnum(t, j))) { ++ i = j; ++ j *= 2; ++ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ ++ /* table was built with bad purposes: resort to linear search */ ++ i = 1; ++ while (!ttisnil(luaH_getnum(t, i))) i++; ++ return i - 1; ++ } ++ } ++ /* now do a binary search between them */ ++ while (j - i > 1) { ++ unsigned int m = (i+j)/2; ++ if (ttisnil(luaH_getnum(t, m))) j = m; ++ else i = m; ++ } ++ return i; ++} ++ ++ ++/* ++** Try to find a boundary in table `t'. A `boundary' is an integer index ++** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). ++*/ ++int luaH_getn (Table *t) { ++ unsigned int j = t->sizearray; ++ if (j > 0 && ttisnil(&t->array[j - 1])) { ++ /* there is a boundary in the array part: (binary) search for it */ ++ unsigned int i = 0; ++ while (j - i > 1) { ++ unsigned int m = (i+j)/2; ++ if (ttisnil(&t->array[m - 1])) j = m; ++ else i = m; ++ } ++ return i; ++ } ++ /* else must find a boundary in hash part */ ++ else if (t->node == dummynode) /* hash part is empty? */ ++ return j; /* that is easy... */ ++ else return unbound_search(t, j); ++} ++ ++ ++ ++#if defined(LUA_DEBUG) ++ ++Node *luaH_mainposition (const Table *t, const TValue *key) { ++ return mainposition(t, key); ++} ++ ++int luaH_isdummy (Node *n) { return n == dummynode; } ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ltable.h +@@ -0,0 +1,40 @@ ++/* ++** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua tables (hash) ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ltable_h ++#define ltable_h ++ ++#include "lobject.h" ++ ++ ++#define gnode(t,i) (&(t)->node[i]) ++#define gkey(n) (&(n)->i_key.nk) ++#define gval(n) (&(n)->i_val) ++#define gnext(n) ((n)->i_key.nk.next) ++ ++#define key2tval(n) (&(n)->i_key.tvk) ++ ++ ++LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); ++LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); ++LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); ++LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); ++LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); ++LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); ++LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); ++LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); ++LUAI_FUNC void luaH_free (lua_State *L, Table *t); ++LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); ++LUAI_FUNC int luaH_getn (Table *t); ++ ++ ++#if defined(LUA_DEBUG) ++LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); ++LUAI_FUNC int luaH_isdummy (Node *n); ++#endif ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/ltablib.c +@@ -0,0 +1,288 @@ ++/* ++** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ ++** Library for Table Manipulation ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#include <stddef.h> ++ ++#define ltablib_c ++#define LUA_LIB ++ ++#include "lua.h" ++ ++#include "lauxlib.h" ++#include "lualib.h" ++ ++ ++#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) ++ ++ ++static int foreachi (lua_State *L) { ++ int i; ++ int n = aux_getn(L, 1); ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ for (i=1; i <= n; i++) { ++ lua_pushvalue(L, 2); /* function */ ++ lua_pushinteger(L, i); /* 1st argument */ ++ lua_rawgeti(L, 1, i); /* 2nd argument */ ++ lua_call(L, 2, 1); ++ if (!lua_isnil(L, -1)) ++ return 1; ++ lua_pop(L, 1); /* remove nil result */ ++ } ++ return 0; ++} ++ ++ ++static int foreach (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ lua_pushnil(L); /* first key */ ++ while (lua_next(L, 1)) { ++ lua_pushvalue(L, 2); /* function */ ++ lua_pushvalue(L, -3); /* key */ ++ lua_pushvalue(L, -3); /* value */ ++ lua_call(L, 2, 1); ++ if (!lua_isnil(L, -1)) ++ return 1; ++ lua_pop(L, 2); /* remove value and result */ ++ } ++ return 0; ++} ++ ++ ++static int maxn (lua_State *L) { ++ lua_Number max = 0; ++ luaL_checktype(L, 1, LUA_TTABLE); ++ lua_pushnil(L); /* first key */ ++ while (lua_next(L, 1)) { ++ lua_pop(L, 1); /* remove value */ ++ if (lua_type(L, -1) == LUA_TNUMBER) { ++ lua_Number v = lua_tonumber(L, -1); ++ if (v > max) max = v; ++ } ++ } ++ lua_pushnumber(L, max); ++ return 1; ++} ++ ++ ++static int getn (lua_State *L) { ++ lua_pushinteger(L, aux_getn(L, 1)); ++ return 1; ++} ++ ++ ++static int setn (lua_State *L) { ++ luaL_checktype(L, 1, LUA_TTABLE); ++#ifndef luaL_setn ++ luaL_setn(L, 1, luaL_checkint(L, 2)); ++#else ++ luaL_error(L, LUA_QL("setn") " is obsolete"); ++#endif ++ lua_pushvalue(L, 1); ++ return 1; ++} ++ ++ ++static int tinsert (lua_State *L) { ++ int e = aux_getn(L, 1) + 1; /* first empty element */ ++ int pos; /* where to insert new element */ ++ switch (lua_gettop(L)) { ++ case 2: { /* called with only 2 arguments */ ++ pos = e; /* insert new element at the end */ ++ break; ++ } ++ case 3: { ++ int i; ++ pos = luaL_checkint(L, 2); /* 2nd argument is the position */ ++ if (pos > e) e = pos; /* `grow' array if necessary */ ++ for (i = e; i > pos; i--) { /* move up elements */ ++ lua_rawgeti(L, 1, i-1); ++ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ ++ } ++ break; ++ } ++ default: { ++ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); ++ } ++ } ++ luaL_setn(L, 1, e); /* new size */ ++ lua_rawseti(L, 1, pos); /* t[pos] = v */ ++ return 0; ++} ++ ++ ++static int tremove (lua_State *L) { ++ int e = aux_getn(L, 1); ++ int pos = luaL_optint(L, 2, e); ++ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ ++ return 0; /* nothing to remove */ ++ luaL_setn(L, 1, e - 1); /* t.n = n-1 */ ++ lua_rawgeti(L, 1, pos); /* result = t[pos] */ ++ for ( ;pos<e; pos++) { ++ lua_rawgeti(L, 1, pos+1); ++ lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ ++ } ++ lua_pushnil(L); ++ lua_rawseti(L, 1, e); /* t[e] = nil */ ++ return 1; ++} ++ ++ ++static void addfield (lua_State *L, luaL_Buffer *b, int i) { ++ lua_rawgeti(L, 1, i); ++ if (!lua_isstring(L, -1)) ++ luaL_error(L, "invalid value (%s) at index %d in table for " ++ LUA_QL("concat"), luaL_typename(L, -1), i); ++ luaL_addvalue(b); ++} ++ ++ ++static int tconcat (lua_State *L) { ++ size_t lsep; ++ int i, last; ++ const char *sep = luaL_optlstring(L, 2, "", &lsep); ++ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); ++ if(!b) luaL_error(L, "tconcat: cannot allocate memory"); ++ luaL_checktype(L, 1, LUA_TTABLE); ++ i = luaL_optint(L, 3, 1); ++ last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1)); ++ luaL_buffinit(L, b); ++ for (; i < last; i++) { ++ addfield(L, b, i); ++ luaL_addlstring(b, sep, lsep); ++ } ++ if (i == last) /* add last value (if interval was not empty) */ ++ addfield(L, b, i); ++ luaL_pushresult(b); ++ kfree(b); ++ return 1; ++} ++ ++ ++ ++/* ++** {====================================================== ++** Quicksort ++** (based on `Algorithms in MODULA-3', Robert Sedgewick; ++** Addison-Wesley, 1993.) ++*/ ++ ++ ++static void set2 (lua_State *L, int i, int j) { ++ lua_rawseti(L, 1, i); ++ lua_rawseti(L, 1, j); ++} ++ ++static int sort_comp (lua_State *L, int a, int b) { ++ if (!lua_isnil(L, 2)) { /* function? */ ++ int res; ++ lua_pushvalue(L, 2); ++ lua_pushvalue(L, a-1); /* -1 to compensate function */ ++ lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ ++ lua_call(L, 2, 1); ++ res = lua_toboolean(L, -1); ++ lua_pop(L, 1); ++ return res; ++ } ++ else /* a < b? */ ++ return lua_lessthan(L, a, b); ++} ++ ++static void auxsort (lua_State *L, int l, int u) { ++ while (l < u) { /* for tail recursion */ ++ int i, j; ++ /* sort elements a[l], a[(l+u)/2] and a[u] */ ++ lua_rawgeti(L, 1, l); ++ lua_rawgeti(L, 1, u); ++ if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ ++ set2(L, l, u); /* swap a[l] - a[u] */ ++ else ++ lua_pop(L, 2); ++ if (u-l == 1) break; /* only 2 elements */ ++ i = (l+u)/2; ++ lua_rawgeti(L, 1, i); ++ lua_rawgeti(L, 1, l); ++ if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */ ++ set2(L, i, l); ++ else { ++ lua_pop(L, 1); /* remove a[l] */ ++ lua_rawgeti(L, 1, u); ++ if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */ ++ set2(L, i, u); ++ else ++ lua_pop(L, 2); ++ } ++ if (u-l == 2) break; /* only 3 elements */ ++ lua_rawgeti(L, 1, i); /* Pivot */ ++ lua_pushvalue(L, -1); ++ lua_rawgeti(L, 1, u-1); ++ set2(L, i, u-1); ++ /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */ ++ i = l; j = u-1; ++ for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ ++ /* repeat ++i until a[i] >= P */ ++ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { ++ if (i>u) luaL_error(L, "invalid order function for sorting"); ++ lua_pop(L, 1); /* remove a[i] */ ++ } ++ /* repeat --j until a[j] <= P */ ++ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { ++ if (j<l) luaL_error(L, "invalid order function for sorting"); ++ lua_pop(L, 1); /* remove a[j] */ ++ } ++ if (j<i) { ++ lua_pop(L, 3); /* pop pivot, a[i], a[j] */ ++ break; ++ } ++ set2(L, i, j); ++ } ++ lua_rawgeti(L, 1, u-1); ++ lua_rawgeti(L, 1, i); ++ set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */ ++ /* a[l..i-1] <= a[i] == P <= a[i+1..u] */ ++ /* adjust so that smaller half is in [j..i] and larger one in [l..u] */ ++ if (i-l < u-i) { ++ j=l; i=i-1; l=i+2; ++ } ++ else { ++ j=i+1; i=u; u=j-2; ++ } ++ auxsort(L, j, i); /* call recursively the smaller one */ ++ } /* repeat the routine for the larger one */ ++} ++ ++static int sort (lua_State *L) { ++ int n = aux_getn(L, 1); ++ luaL_checkstack(L, 40, ""); /* assume array is smaller than 2^40 */ ++ if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ ++ luaL_checktype(L, 2, LUA_TFUNCTION); ++ lua_settop(L, 2); /* make sure there is two arguments */ ++ auxsort(L, 1, n); ++ return 0; ++} ++ ++/* }====================================================== */ ++ ++ ++static const luaL_Reg tab_funcs[] = { ++ {"concat", tconcat}, ++ {"foreach", foreach}, ++ {"foreachi", foreachi}, ++ {"getn", getn}, ++ {"maxn", maxn}, ++ {"insert", tinsert}, ++ {"remove", tremove}, ++ {"setn", setn}, ++ {"sort", sort}, ++ {NULL, NULL} ++}; ++ ++ ++LUALIB_API int luaopen_table (lua_State *L) { ++ luaL_register(L, LUA_TABLIBNAME, tab_funcs); ++ return 1; ++} +--- /dev/null ++++ b/extensions/LUA/lua/ltm.c +@@ -0,0 +1,74 @@ ++/* ++** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Tag methods ++** See Copyright Notice in lua.h ++*/ ++ ++#include <string.h> ++ ++#define ltm_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "lobject.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++ ++ ++ ++const char *const luaT_typenames[] = { ++ "nil", "boolean", "userdata", "number", ++ "string", "table", "function", "userdata", "thread", ++ "proto", "upval" ++}; ++ ++ ++void luaT_init (lua_State *L) { ++ static const char *const luaT_eventname[] = { /* ORDER TM */ ++ "__index", "__newindex", ++ "__gc", "__mode", "__eq", ++ "__add", "__sub", "__mul", "__div", "__mod", ++ "__pow", "__unm", "__len", "__lt", "__le", ++ "__concat", "__call" ++ }; ++ int i; ++ for (i=0; i<TM_N; i++) { ++ G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]); ++ luaS_fix(G(L)->tmname[i]); /* never collect these names */ ++ } ++} ++ ++ ++/* ++** function to be used with macro "fasttm": optimized for absence of ++** tag methods ++*/ ++const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { ++ const TValue *tm = luaH_getstr(events, ename); ++ lua_assert(event <= TM_EQ); ++ if (ttisnil(tm)) { /* no tag method? */ ++ events->flags |= cast_byte(1u<<event); /* cache this fact */ ++ return NULL; ++ } ++ else return tm; ++} ++ ++ ++const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { ++ Table *mt; ++ switch (ttype(o)) { ++ case LUA_TTABLE: ++ mt = hvalue(o)->metatable; ++ break; ++ case LUA_TUSERDATA: ++ mt = uvalue(o)->metatable; ++ break; ++ default: ++ mt = G(L)->mt[ttype(o)]; ++ } ++ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/ltm.h +@@ -0,0 +1,54 @@ ++/* ++** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Tag methods ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef ltm_h ++#define ltm_h ++ ++ ++#include "lobject.h" ++ ++ ++/* ++* WARNING: if you change the order of this enumeration, ++* grep "ORDER TM" ++*/ ++typedef enum { ++ TM_INDEX, ++ TM_NEWINDEX, ++ TM_GC, ++ TM_MODE, ++ TM_EQ, /* last tag method with `fast' access */ ++ TM_ADD, ++ TM_SUB, ++ TM_MUL, ++ TM_DIV, ++ TM_MOD, ++ TM_POW, ++ TM_UNM, ++ TM_LEN, ++ TM_LT, ++ TM_LE, ++ TM_CONCAT, ++ TM_CALL, ++ TM_N /* number of elements in the enum */ ++} TMS; ++ ++ ++ ++#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ++ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) ++ ++#define fasttm(l,et,e) gfasttm(G(l), et, e) ++ ++LUAI_DATA const char *const luaT_typenames[]; ++ ++ ++LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); ++LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, ++ TMS event); ++LUAI_FUNC void luaT_init (lua_State *L); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/luaconf.h +@@ -0,0 +1,797 @@ ++/* ++** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ ++** Configuration file for Lua ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lconfig_h ++#define lconfig_h ++ ++#include <stddef.h> ++ ++#if !defined(__KERNEL__) ++#include <limits.h> ++#else ++#define UCHAR_MAX 255 ++#define SHRT_MAX 32767 ++#define BUFSIZ 8192 ++#define NO_FPU ++#endif ++ ++/* ++** ================================================================== ++** Search for "@@" to find all configurable definitions. ++** =================================================================== ++*/ ++ ++ ++/* ++@@ LUA_ANSI controls the use of non-ansi features. ++** CHANGE it (define it) if you want Lua to avoid the use of any ++** non-ansi feature or library. ++*/ ++#if defined(__STRICT_ANSI__) ++#define LUA_ANSI ++#endif ++ ++ ++#if !defined(LUA_ANSI) && defined(_WIN32) ++#define LUA_WIN ++#endif ++ ++#if defined(LUA_USE_LINUX) ++#define LUA_USE_POSIX ++#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ ++#define LUA_USE_READLINE /* needs some extra libraries */ ++#endif ++ ++#if defined(LUA_USE_MACOSX) ++#define LUA_USE_POSIX ++#define LUA_DL_DYLD /* does not need extra library */ ++#endif ++ ++ ++ ++/* ++@@ LUA_USE_POSIX includes all functionallity listed as X/Open System ++@* Interfaces Extension (XSI). ++** CHANGE it (define it) if your system is XSI compatible. ++*/ ++#if defined(LUA_USE_POSIX) ++#define LUA_USE_MKSTEMP ++#define LUA_USE_ISATTY ++#define LUA_USE_POPEN ++#define LUA_USE_ULONGJMP ++#endif ++ ++ ++/* ++@@ LUA_PATH and LUA_CPATH are the names of the environment variables that ++@* Lua check to set its paths. ++@@ LUA_INIT is the name of the environment variable that Lua ++@* checks for initialization code. ++** CHANGE them if you want different names. ++*/ ++#define LUA_PATH "LUA_PATH" ++#define LUA_CPATH "LUA_CPATH" ++#define LUA_INIT "LUA_INIT" ++ ++ ++/* ++@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for ++@* Lua libraries. ++@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for ++@* C libraries. ++** CHANGE them if your machine has a non-conventional directory ++** hierarchy or if you want to install your libraries in ++** non-conventional directories. ++*/ ++#if defined(_WIN32) ++/* ++** In Windows, any exclamation mark ('!') in the path is replaced by the ++** path of the directory of the executable file of the current process. ++*/ ++#define LUA_LDIR "!\\lua\\" ++#define LUA_CDIR "!\\" ++#define LUA_PATH_DEFAULT \ ++ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ ++ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" ++#define LUA_CPATH_DEFAULT \ ++ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" ++ ++#else ++#define LUA_ROOT "/usr/local/" ++#define LUA_LDIR LUA_ROOT "share/lua/5.1/" ++#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" ++#define LUA_PATH_DEFAULT \ ++ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ ++ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" ++#define LUA_CPATH_DEFAULT \ ++ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" ++#endif ++ ++ ++/* ++@@ LUA_DIRSEP is the directory separator (for submodules). ++** CHANGE it if your machine does not use "/" as the directory separator ++** and is not Windows. (On Windows Lua automatically uses "\".) ++*/ ++#if defined(_WIN32) ++#define LUA_DIRSEP "\\" ++#else ++#define LUA_DIRSEP "/" ++#endif ++ ++ ++/* ++@@ LUA_PATHSEP is the character that separates templates in a path. ++@@ LUA_PATH_MARK is the string that marks the substitution points in a ++@* template. ++@@ LUA_EXECDIR in a Windows path is replaced by the executable's ++@* directory. ++@@ LUA_IGMARK is a mark to ignore all before it when bulding the ++@* luaopen_ function name. ++** CHANGE them if for some reason your system cannot use those ++** characters. (E.g., if one of those characters is a common character ++** in file/directory names.) Probably you do not need to change them. ++*/ ++#define LUA_PATHSEP ";" ++#define LUA_PATH_MARK "?" ++#define LUA_EXECDIR "!" ++#define LUA_IGMARK "-" ++ ++ ++/* ++@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. ++** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ++** machines, ptrdiff_t gives a good choice between int or long.) ++*/ ++#define LUA_INTEGER ptrdiff_t ++ ++ ++/* ++@@ LUA_API is a mark for all core API functions. ++@@ LUALIB_API is a mark for all standard library functions. ++** CHANGE them if you need to define those functions in some special way. ++** For instance, if you want to create one Windows DLL with the core and ++** the libraries, you may want to use the following definition (define ++** LUA_BUILD_AS_DLL to get it). ++*/ ++#if defined(LUA_BUILD_AS_DLL) ++ ++#if defined(LUA_CORE) || defined(LUA_LIB) ++#define LUA_API __declspec(dllexport) ++#else ++#define LUA_API __declspec(dllimport) ++#endif ++ ++#else ++ ++#define LUA_API extern ++ ++#endif ++ ++/* more often than not the libs go together with the core */ ++#define LUALIB_API LUA_API ++ ++ ++/* ++@@ LUAI_FUNC is a mark for all extern functions that are not to be ++@* exported to outside modules. ++@@ LUAI_DATA is a mark for all extern (const) variables that are not to ++@* be exported to outside modules. ++** CHANGE them if you need to mark them in some special way. Elf/gcc ++** (versions 3.2 and later) mark them as "hidden" to optimize access ++** when Lua is compiled as a shared library. ++*/ ++#if defined(luaall_c) ++#define LUAI_FUNC static ++#define LUAI_DATA /* empty */ ++ ++#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ ++ defined(__ELF__) ++#define LUAI_FUNC __attribute__((visibility("hidden"))) extern ++#define LUAI_DATA LUAI_FUNC ++ ++#else ++#define LUAI_FUNC extern ++#define LUAI_DATA extern ++#endif ++ ++ ++ ++/* ++@@ LUA_QL describes how error messages quote program elements. ++** CHANGE it if you want a different appearance. ++*/ ++#define LUA_QL(x) "'" x "'" ++#define LUA_QS LUA_QL("%s") ++ ++ ++/* ++@@ LUA_IDSIZE gives the maximum size for the description of the source ++@* of a function in debug information. ++** CHANGE it if you want a different size. ++*/ ++#define LUA_IDSIZE 60 ++ ++ ++/* ++** {================================================================== ++** Stand-alone configuration ++** =================================================================== ++*/ ++ ++#if defined(lua_c) || defined(luaall_c) ++ ++/* ++@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that ++@* is, whether we're running lua interactively). ++** CHANGE it if you have a better definition for non-POSIX/non-Windows ++** systems. ++*/ ++#if defined(LUA_USE_ISATTY) ++#include <unistd.h> ++#define lua_stdin_is_tty() isatty(0) ++#elif defined(LUA_WIN) ++#include <io.h> ++#include <stdio.h> ++#define lua_stdin_is_tty() _isatty(_fileno(stdin)) ++#else ++#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ ++#endif ++ ++ ++/* ++@@ LUA_PROMPT is the default prompt used by stand-alone Lua. ++@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. ++** CHANGE them if you want different prompts. (You can also change the ++** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) ++*/ ++#define LUA_PROMPT "> " ++#define LUA_PROMPT2 ">> " ++ ++ ++/* ++@@ LUA_PROGNAME is the default name for the stand-alone Lua program. ++** CHANGE it if your stand-alone interpreter has a different name and ++** your system is not able to detect that name automatically. ++*/ ++#define LUA_PROGNAME "lua" ++ ++ ++/* ++@@ LUA_MAXINPUT is the maximum length for an input line in the ++@* stand-alone interpreter. ++** CHANGE it if you need longer lines. ++*/ ++#define LUA_MAXINPUT 512 ++ ++ ++/* ++@@ lua_readline defines how to show a prompt and then read a line from ++@* the standard input. ++@@ lua_saveline defines how to "save" a read line in a "history". ++@@ lua_freeline defines how to free a line read by lua_readline. ++** CHANGE them if you want to improve this functionality (e.g., by using ++** GNU readline and history facilities). ++*/ ++#if defined(LUA_USE_READLINE) ++#include <stdio.h> ++#include <readline/readline.h> ++#include <readline/history.h> ++#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) ++#define lua_saveline(L,idx) \ ++ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ ++ add_history(lua_tostring(L, idx)); /* add it to history */ ++#define lua_freeline(L,b) ((void)L, free(b)) ++#else ++#define lua_readline(L,b,p) \ ++ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ ++ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ ++#define lua_saveline(L,idx) { (void)L; (void)idx; } ++#define lua_freeline(L,b) { (void)L; (void)b; } ++#endif ++ ++#endif ++ ++/* }================================================================== */ ++ ++ ++/* ++@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles ++@* as a percentage. ++** CHANGE it if you want the GC to run faster or slower (higher values ++** mean larger pauses which mean slower collection.) You can also change ++** this value dynamically. ++*/ ++#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ ++ ++ ++/* ++@@ LUAI_GCMUL defines the default speed of garbage collection relative to ++@* memory allocation as a percentage. ++** CHANGE it if you want to change the granularity of the garbage ++** collection. (Higher values mean coarser collections. 0 represents ++** infinity, where each step performs a full collection.) You can also ++** change this value dynamically. ++*/ ++#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ ++ ++ ++ ++/* ++@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. ++** CHANGE it (define it) if you want exact compatibility with the ++** behavior of setn/getn in Lua 5.0. ++*/ ++#undef LUA_COMPAT_GETN ++ ++/* ++@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. ++** CHANGE it to undefined as soon as you do not need a global 'loadlib' ++** function (the function is still available as 'package.loadlib'). ++*/ ++#undef LUA_COMPAT_LOADLIB ++ ++/* ++@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. ++** CHANGE it to undefined as soon as your programs use only '...' to ++** access vararg parameters (instead of the old 'arg' table). ++*/ ++#define LUA_COMPAT_VARARG ++ ++/* ++@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. ++** CHANGE it to undefined as soon as your programs use 'math.fmod' or ++** the new '%' operator instead of 'math.mod'. ++*/ ++#define LUA_COMPAT_MOD ++ ++/* ++@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting ++@* facility. ++** CHANGE it to 2 if you want the old behaviour, or undefine it to turn ++** off the advisory error when nesting [[...]]. ++*/ ++#define LUA_COMPAT_LSTR 1 ++ ++/* ++@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. ++** CHANGE it to undefined as soon as you rename 'string.gfind' to ++** 'string.gmatch'. ++*/ ++#define LUA_COMPAT_GFIND ++ ++/* ++@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' ++@* behavior. ++** CHANGE it to undefined as soon as you replace to 'luaL_register' ++** your uses of 'luaL_openlib' ++*/ ++#define LUA_COMPAT_OPENLIB ++ ++ ++ ++/* ++@@ luai_apicheck is the assert macro used by the Lua-C API. ++** CHANGE luai_apicheck if you want Lua to perform some checks in the ++** parameters it gets from API calls. This may slow down the interpreter ++** a bit, but may be quite useful when debugging C code that interfaces ++** with Lua. A useful redefinition is to use assert.h. ++*/ ++#if defined(LUA_USE_APICHECK) ++#include <assert.h> ++#define luai_apicheck(L,o) { (void)L; assert(o); } ++#else ++#define luai_apicheck(L,o) { (void)L; } ++#endif ++ ++ ++/* ++@@ LUAI_BITSINT defines the number of bits in an int. ++** CHANGE here if Lua cannot automatically detect the number of bits of ++** your machine. Probably you do not need to change this. ++*/ ++/* avoid overflows in comparison */ ++#if !defined(__KERNEL__) ++#include <limits.h> ++#define LUA_INT_MAX INT_MAX ++#else ++#define LUA_INT_MAX (~0U>>1) ++#endif ++ ++#if LUA_INT_MAX-20 < 32760 ++#define LUAI_BITSINT 16 ++#elif LUA_INT_MAX > 2147483640L ++/* int has at least 32 bits */ ++#define LUAI_BITSINT 32 ++#else ++#error "you must define LUA_BITSINT with number of bits in an integer" ++#endif ++ ++ ++/* ++@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. ++@@ LUAI_INT32 is an signed integer with at least 32 bits. ++@@ LUAI_UMEM is an unsigned integer big enough to count the total ++@* memory used by Lua. ++@@ LUAI_MEM is a signed integer big enough to count the total memory ++@* used by Lua. ++** CHANGE here if for some weird reason the default definitions are not ++** good enough for your machine. (The definitions in the 'else' ++** part always works, but may waste space on machines with 64-bit ++** longs.) Probably you do not need to change this. ++*/ ++#if LUAI_BITSINT >= 32 ++#define LUAI_UINT32 unsigned int ++#define LUAI_INT32 int ++#define LUAI_MAXINT32 INT_MAX ++#define LUAI_UMEM size_t ++#define LUAI_MEM ptrdiff_t ++#else ++/* 16-bit ints */ ++#define LUAI_UINT32 unsigned long ++#define LUAI_INT32 long ++#define LUAI_MAXINT32 LONG_MAX ++#define LUAI_UMEM unsigned long ++#define LUAI_MEM long ++#endif ++ ++ ++/* ++@@ LUAI_MAXCALLS limits the number of nested calls. ++** CHANGE it if you need really deep recursive calls. This limit is ++** arbitrary; its only purpose is to stop infinite recursion before ++** exhausting memory. ++*/ ++#define LUAI_MAXCALLS 20000 ++ ++ ++/* ++@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function ++@* can use. ++** CHANGE it if you need lots of (Lua) stack space for your C ++** functions. This limit is arbitrary; its only purpose is to stop C ++** functions to consume unlimited stack space. (must be smaller than ++** -LUA_REGISTRYINDEX) ++*/ ++#define LUAI_MAXCSTACK 8000 ++ ++ ++ ++/* ++** {================================================================== ++** CHANGE (to smaller values) the following definitions if your system ++** has a small C stack. (Or you may want to change them to larger ++** values if your system has a large C stack and these limits are ++** too rigid for you.) Some of these constants control the size of ++** stack-allocated arrays used by the compiler or the interpreter, while ++** others limit the maximum number of recursive calls that the compiler ++** or the interpreter can perform. Values too large may cause a C stack ++** overflow for some forms of deep constructs. ++** =================================================================== ++*/ ++ ++ ++/* ++@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and ++@* syntactical nested non-terminals in a program. ++*/ ++#define LUAI_MAXCCALLS 200 ++ ++ ++/* ++@@ LUAI_MAXVARS is the maximum number of local variables per function ++@* (must be smaller than 250). ++*/ ++#define LUAI_MAXVARS 200 ++ ++ ++/* ++@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function ++@* (must be smaller than 250). ++*/ ++#define LUAI_MAXUPVALUES 60 ++ ++ ++/* ++@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. ++*/ ++#define LUAL_BUFFERSIZE BUFSIZ ++ ++/* }================================================================== */ ++ ++ ++ ++ ++/* ++** {================================================================== ++@@ LUA_NUMBER is the type of numbers in Lua. ++** CHANGE the following definitions only if you want to build Lua ++** with a number type different from double. You may also need to ++** change lua_number2int & lua_number2integer. ++** =================================================================== ++*/ ++#if !defined(NO_FPU) ++#define LUA_NUMBER_DOUBLE ++#define LUA_NUMBER double ++#else ++#define LUA_NUMBER long ++#endif ++ ++/* ++@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' ++@* over a number. ++*/ ++#define LUAI_UACNUMBER LUA_NUMBER ++ ++ ++/* ++@@ LUA_NUMBER_SCAN is the format for reading numbers. ++@@ LUA_NUMBER_FMT is the format for writing numbers. ++@@ lua_number2str converts a number to a string. ++@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. ++@@ lua_str2number converts a string to a number. ++*/ ++#if !defined(NO_FPU) ++#define LUA_NUMBER_SCAN "%lf" ++#define LUA_NUMBER_FMT "%.14g" ++#define lua_str2number(s,p) strtod((s), (p)) ++#else ++#define LUA_NUMBER_SCAN "%ld" ++#define LUA_NUMBER_FMT "%ld" ++#if !defined(__KERNEL__) ++#define lua_str2number(s,p) strtol((s), (p), 10) ++#else ++#define lua_str2number(s,p) simple_strtol((s), (p), 10) ++#endif ++#endif ++ ++#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ ++#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) ++ ++/* ++@@ The luai_num* macros define the primitive operations over numbers. ++*/ ++#if defined(LUA_CORE) ++#define luai_numadd(a,b) ((a)+(b)) ++#define luai_numsub(a,b) ((a)-(b)) ++#define luai_nummul(a,b) ((a)*(b)) ++#define luai_numdiv(a,b) ((a)/(b)) ++#define luai_numunm(a) (-(a)) ++#define luai_numeq(a,b) ((a)==(b)) ++#define luai_numlt(a,b) ((a)<(b)) ++#define luai_numle(a,b) ((a)<=(b)) ++#define luai_numisnan(a) (!luai_numeq((a), (a))) ++#if !defined(NO_FPU) ++#include <math.h> ++#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) ++#define luai_numpow(a,b) (pow(a,b)) ++#else ++#define luai_nummod(a,b) ((a)%(b)) ++#define luai_numpow(a,b) luai_nummul(a,b) ++#endif ++#endif ++ ++ ++/* ++@@ lua_number2int is a macro to convert lua_Number to int. ++@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ++** CHANGE them if you know a faster way to convert a lua_Number to ++** int (with any rounding method and without throwing errors) in your ++** system. In Pentium machines, a naive typecast from double to int ++** in C is extremely slow, so any alternative is worth trying. ++*/ ++ ++/* On a Pentium, resort to a trick */ ++#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ ++ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) ++ ++/* On a Microsoft compiler, use assembler */ ++#if defined(_MSC_VER) ++ ++#define lua_number2int(i,d) __asm fld d __asm fistp i ++#define lua_number2integer(i,n) lua_number2int(i, n) ++ ++/* the next trick should work on any Pentium, but sometimes clashes ++ with a DirectX idiosyncrasy */ ++#else ++ ++union luai_Cast { double l_d; long l_l; }; ++#define lua_number2int(i,d) \ ++ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } ++#define lua_number2integer(i,n) lua_number2int(i, n) ++ ++#endif ++ ++ ++/* this option always works, but may be slow */ ++#else ++#define lua_number2int(i,d) ((i)=(int)(d)) ++#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) ++ ++#endif ++ ++/* }================================================================== */ ++ ++ ++/* ++@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. ++** CHANGE it if your system requires alignments larger than double. (For ++** instance, if your system supports long doubles and they must be ++** aligned in 16-byte boundaries, then you should add long double in the ++** union.) Probably you do not need to change this. ++*/ ++#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } ++ ++ ++/* ++@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. ++** CHANGE them if you prefer to use longjmp/setjmp even with C++ ++** or if want/don't to use _longjmp/_setjmp instead of regular ++** longjmp/setjmp. By default, Lua handles errors with exceptions when ++** compiling as C++ code, with _longjmp/_setjmp when asked to use them, ++** and with longjmp/setjmp otherwise. ++*/ ++#if defined(__KERNEL__) ++#undef LUA_USE_ULONGJMP ++#endif ++ ++#if defined(__cplusplus) ++/* C++ exceptions */ ++#define LUAI_THROW(L,c) throw(c) ++#define LUAI_TRY(L,c,a) try { a } catch(...) \ ++ { if ((c)->status == 0) (c)->status = -1; } ++#define luai_jmpbuf int /* dummy variable */ ++ ++#elif defined(LUA_USE_ULONGJMP) ++/* in Unix, try _longjmp/_setjmp (more efficient) */ ++#define LUAI_THROW(L,c) _longjmp((c)->b, 1) ++#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } ++#define luai_jmpbuf jmp_buf ++ ++#else ++/* default handling with long jumps */ ++#define LUAI_THROW(L,c) longjmp((c)->b, 1) ++#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } ++#define luai_jmpbuf jmp_buf ++ ++#endif ++ ++ ++/* ++@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern ++@* can do during pattern-matching. ++** CHANGE it if you need more captures. This limit is arbitrary. ++*/ ++#define LUA_MAXCAPTURES 32 ++ ++ ++/* ++@@ lua_tmpnam is the function that the OS library uses to create a ++@* temporary name. ++@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. ++** CHANGE them if you have an alternative to tmpnam (which is considered ++** insecure) or if you want the original tmpnam anyway. By default, Lua ++** uses tmpnam except when POSIX is available, where it uses mkstemp. ++*/ ++#if defined(loslib_c) || defined(luaall_c) ++ ++#if defined(LUA_USE_MKSTEMP) ++#include <unistd.h> ++#define LUA_TMPNAMBUFSIZE 32 ++#define lua_tmpnam(b,e) { \ ++ strcpy(b, "/tmp/lua_XXXXXX"); \ ++ e = mkstemp(b); \ ++ if (e != -1) close(e); \ ++ e = (e == -1); } ++ ++#else ++#define LUA_TMPNAMBUFSIZE L_tmpnam ++#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } ++#endif ++ ++#endif ++ ++ ++/* ++@@ lua_popen spawns a new process connected to the current one through ++@* the file streams. ++** CHANGE it if you have a way to implement it in your system. ++*/ ++#if defined(LUA_USE_POPEN) ++ ++#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) ++#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) ++ ++#elif defined(LUA_WIN) ++ ++#define lua_popen(L,c,m) ((void)L, _popen(c,m)) ++#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) ++ ++#else ++ ++#define lua_popen(L,c,m) ((void)((void)c, m), \ ++ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) ++#define lua_pclose(L,file) ((void)((void)L, file), 0) ++ ++#endif ++ ++/* ++@@ LUA_DL_* define which dynamic-library system Lua should use. ++** CHANGE here if Lua has problems choosing the appropriate ++** dynamic-library system for your platform (either Windows' DLL, Mac's ++** dyld, or Unix's dlopen). If your system is some kind of Unix, there ++** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for ++** it. To use dlopen you also need to adapt the src/Makefile (probably ++** adding -ldl to the linker options), so Lua does not select it ++** automatically. (When you change the makefile to add -ldl, you must ++** also add -DLUA_USE_DLOPEN.) ++** If you do not want any kind of dynamic library, undefine all these ++** options. ++** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. ++*/ ++#if defined(LUA_USE_DLOPEN) ++#define LUA_DL_DLOPEN ++#endif ++ ++#if defined(LUA_WIN) ++#define LUA_DL_DLL ++#endif ++ ++ ++/* ++@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State ++@* (the data goes just *before* the lua_State pointer). ++** CHANGE (define) this if you really need that. This value must be ++** a multiple of the maximum alignment required for your machine. ++*/ ++#define LUAI_EXTRASPACE 0 ++ ++ ++/* ++@@ luai_userstate* allow user-specific actions on threads. ++** CHANGE them if you defined LUAI_EXTRASPACE and need to do something ++** extra when a thread is created/deleted/resumed/yielded. ++*/ ++#define luai_userstateopen(L) ((void)L) ++#define luai_userstateclose(L) ((void)L) ++#define luai_userstatethread(L,L1) ((void)L) ++#define luai_userstatefree(L) ((void)L) ++#define luai_userstateresume(L,n) ((void)L) ++#define luai_userstateyield(L,n) ((void)L) ++ ++ ++/* ++@@ LUA_INTFRMLEN is the length modifier for integer conversions ++@* in 'string.format'. ++@@ LUA_INTFRM_T is the integer type correspoding to the previous length ++@* modifier. ++** CHANGE them if your system supports long long or does not support long. ++*/ ++ ++#if defined(LUA_USELONGLONG) ++ ++#define LUA_INTFRMLEN "ll" ++#define LUA_INTFRM_T long long ++ ++#else ++ ++#define LUA_INTFRMLEN "l" ++#define LUA_INTFRM_T long ++ ++#endif ++ ++/* =================================================================== */ ++ ++/* ++** Local configuration. You can use this space to add your redefinitions ++** without modifying the main part of the file. ++*/ ++ ++ ++ ++#endif ++ +--- /dev/null ++++ b/extensions/LUA/lua/lua.h +@@ -0,0 +1,387 @@ ++/* ++** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ++** Lua - An Extensible Extension Language ++** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ++** See Copyright Notice at the end of this file ++*/ ++ ++ ++#ifndef lua_h ++#define lua_h ++ ++#include <stdarg.h> ++#include <stddef.h> ++ ++#include "luaconf.h" ++ ++ ++#define LUA_VERSION "Lua 5.1" ++#define LUA_RELEASE "Lua 5.1.4" ++#define LUA_VERSION_NUM 501 ++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" ++#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" ++ ++ ++/* mark for precompiled code (`<esc>Lua') */ ++#define LUA_SIGNATURE "\033Lua" ++ ++/* option for multiple returns in `lua_pcall' and `lua_call' */ ++#define LUA_MULTRET (-1) ++ ++ ++/* ++** pseudo-indices ++*/ ++#define LUA_REGISTRYINDEX (-10000) ++#define LUA_ENVIRONINDEX (-10001) ++#define LUA_GLOBALSINDEX (-10002) ++#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) ++ ++ ++/* thread status; 0 is OK */ ++#define LUA_YIELD 1 ++#define LUA_ERRRUN 2 ++#define LUA_ERRSYNTAX 3 ++#define LUA_ERRMEM 4 ++#define LUA_ERRERR 5 ++ ++ ++typedef struct lua_State lua_State; ++ ++typedef int (*lua_CFunction) (lua_State *L); ++ ++ ++/* ++** functions that read/write blocks when loading/dumping Lua chunks ++*/ ++typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); ++ ++typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); ++ ++ ++/* ++** prototype for memory-allocation functions ++*/ ++typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); ++ ++ ++/* ++** basic types ++*/ ++#define LUA_TNONE (-1) ++ ++#define LUA_TNIL 0 ++#define LUA_TBOOLEAN 1 ++#define LUA_TLIGHTUSERDATA 2 ++#define LUA_TNUMBER 3 ++#define LUA_TSTRING 4 ++#define LUA_TTABLE 5 ++#define LUA_TFUNCTION 6 ++#define LUA_TUSERDATA 7 ++#define LUA_TTHREAD 8 ++ ++ ++ ++/* minimum Lua stack available to a C function */ ++#define LUA_MINSTACK 20 ++ ++ ++/* ++** generic extra include file ++*/ ++#if defined(LUA_USER_H) ++#include LUA_USER_H ++#endif ++ ++ ++/* type of numbers in Lua */ ++typedef LUA_NUMBER lua_Number; ++ ++ ++/* type for integer functions */ ++typedef LUA_INTEGER lua_Integer; ++ ++ ++ ++/* ++** state manipulation ++*/ ++LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); ++LUA_API void (lua_close) (lua_State *L); ++LUA_API lua_State *(lua_newthread) (lua_State *L); ++ ++LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); ++ ++ ++/* ++** basic stack manipulation ++*/ ++LUA_API int (lua_gettop) (lua_State *L); ++LUA_API void (lua_settop) (lua_State *L, int idx); ++LUA_API void (lua_pushvalue) (lua_State *L, int idx); ++LUA_API void (lua_remove) (lua_State *L, int idx); ++LUA_API void (lua_insert) (lua_State *L, int idx); ++LUA_API void (lua_replace) (lua_State *L, int idx); ++LUA_API int (lua_checkstack) (lua_State *L, int sz); ++ ++LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); ++ ++ ++/* ++** access functions (stack -> C) ++*/ ++ ++LUA_API int (lua_isnumber) (lua_State *L, int idx); ++LUA_API int (lua_isstring) (lua_State *L, int idx); ++LUA_API int (lua_iscfunction) (lua_State *L, int idx); ++LUA_API int (lua_isuserdata) (lua_State *L, int idx); ++LUA_API int (lua_type) (lua_State *L, int idx); ++LUA_API const char *(lua_typename) (lua_State *L, int tp); ++ ++LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); ++LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); ++LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); ++ ++LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); ++LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); ++LUA_API int (lua_toboolean) (lua_State *L, int idx); ++LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); ++LUA_API size_t (lua_objlen) (lua_State *L, int idx); ++LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); ++LUA_API void *(lua_touserdata) (lua_State *L, int idx); ++LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); ++LUA_API const void *(lua_topointer) (lua_State *L, int idx); ++ ++ ++/* ++** push functions (C -> stack) ++*/ ++LUA_API void (lua_pushnil) (lua_State *L); ++LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); ++LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); ++LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); ++LUA_API void (lua_pushstring) (lua_State *L, const char *s); ++LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, ++ va_list argp); ++LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); ++LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); ++LUA_API void (lua_pushboolean) (lua_State *L, int b); ++LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); ++LUA_API int (lua_pushthread) (lua_State *L); ++ ++ ++/* ++** get functions (Lua -> stack) ++*/ ++LUA_API void (lua_gettable) (lua_State *L, int idx); ++LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); ++LUA_API void (lua_rawget) (lua_State *L, int idx); ++LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); ++LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); ++LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); ++LUA_API int (lua_getmetatable) (lua_State *L, int objindex); ++LUA_API void (lua_getfenv) (lua_State *L, int idx); ++ ++ ++/* ++** set functions (stack -> Lua) ++*/ ++LUA_API void (lua_settable) (lua_State *L, int idx); ++LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); ++LUA_API void (lua_rawset) (lua_State *L, int idx); ++LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); ++LUA_API int (lua_setmetatable) (lua_State *L, int objindex); ++LUA_API int (lua_setfenv) (lua_State *L, int idx); ++ ++ ++/* ++** `load' and `call' functions (load and run Lua code) ++*/ ++LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); ++LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); ++LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); ++LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, ++ const char *chunkname); ++ ++LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); ++ ++ ++/* ++** coroutine functions ++*/ ++LUA_API int (lua_yield) (lua_State *L, int nresults); ++LUA_API int (lua_resume) (lua_State *L, int narg); ++LUA_API int (lua_status) (lua_State *L); ++ ++/* ++** garbage-collection function and options ++*/ ++ ++#define LUA_GCSTOP 0 ++#define LUA_GCRESTART 1 ++#define LUA_GCCOLLECT 2 ++#define LUA_GCCOUNT 3 ++#define LUA_GCCOUNTB 4 ++#define LUA_GCSTEP 5 ++#define LUA_GCSETPAUSE 6 ++#define LUA_GCSETSTEPMUL 7 ++ ++LUA_API int (lua_gc) (lua_State *L, int what, int data); ++ ++ ++/* ++** miscellaneous functions ++*/ ++ ++LUA_API int (lua_error) (lua_State *L); ++ ++LUA_API int (lua_next) (lua_State *L, int idx); ++ ++LUA_API void (lua_concat) (lua_State *L, int n); ++ ++LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); ++LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); ++ ++ ++ ++/* ++** =============================================================== ++** some useful macros ++** =============================================================== ++*/ ++ ++#define lua_pop(L,n) lua_settop(L, -(n)-1) ++ ++#define lua_newtable(L) lua_createtable(L, 0, 0) ++ ++#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) ++ ++#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) ++ ++#define lua_strlen(L,i) lua_objlen(L, (i)) ++ ++#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) ++#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) ++#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) ++#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) ++#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) ++#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) ++#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) ++#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) ++ ++#define lua_pushliteral(L, s) \ ++ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) ++ ++#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) ++#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) ++ ++#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) ++ ++ ++ ++/* ++** compatibility macros and functions ++*/ ++ ++#define lua_open() luaL_newstate() ++ ++#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) ++ ++#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) ++ ++#define lua_Chunkreader lua_Reader ++#define lua_Chunkwriter lua_Writer ++ ++ ++/* hack */ ++LUA_API void lua_setlevel (lua_State *from, lua_State *to); ++ ++ ++/* ++** {====================================================================== ++** Debug API ++** ======================================================================= ++*/ ++ ++ ++/* ++** Event codes ++*/ ++#define LUA_HOOKCALL 0 ++#define LUA_HOOKRET 1 ++#define LUA_HOOKLINE 2 ++#define LUA_HOOKCOUNT 3 ++#define LUA_HOOKTAILRET 4 ++ ++ ++/* ++** Event masks ++*/ ++#define LUA_MASKCALL (1 << LUA_HOOKCALL) ++#define LUA_MASKRET (1 << LUA_HOOKRET) ++#define LUA_MASKLINE (1 << LUA_HOOKLINE) ++#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) ++ ++typedef struct lua_Debug lua_Debug; /* activation record */ ++ ++ ++/* Functions to be called by the debuger in specific events */ ++typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); ++ ++ ++LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); ++LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); ++LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); ++LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); ++LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); ++LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); ++ ++LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); ++LUA_API lua_Hook lua_gethook (lua_State *L); ++LUA_API int lua_gethookmask (lua_State *L); ++LUA_API int lua_gethookcount (lua_State *L); ++ ++ ++struct lua_Debug { ++ int event; ++ const char *name; /* (n) */ ++ const char *namewhat; /* (n) `global', `local', `field', `method' */ ++ const char *what; /* (S) `Lua', `C', `main', `tail' */ ++ const char *source; /* (S) */ ++ int currentline; /* (l) */ ++ int nups; /* (u) number of upvalues */ ++ int linedefined; /* (S) */ ++ int lastlinedefined; /* (S) */ ++ char short_src[LUA_IDSIZE]; /* (S) */ ++ /* private part */ ++ int i_ci; /* active function */ ++}; ++ ++/* }====================================================================== */ ++ ++ ++/****************************************************************************** ++* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. ++* ++* Permission is hereby granted, free of charge, to any person obtaining ++* a copy of this software and associated documentation files (the ++* "Software"), to deal in the Software without restriction, including ++* without limitation the rights to use, copy, modify, merge, publish, ++* distribute, sublicense, and/or sell copies of the Software, and to ++* permit persons to whom the Software is furnished to do so, subject to ++* the following conditions: ++* ++* The above copyright notice and this permission notice shall be ++* included in all copies or substantial portions of the Software. ++* ++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY ++* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, ++* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ++* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++******************************************************************************/ ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lualib.h +@@ -0,0 +1,55 @@ ++/* ++** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua standard libraries ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lualib_h ++#define lualib_h ++ ++#include "lua.h" ++ ++ ++/* Key to file-handle type */ ++#define LUA_FILEHANDLE "FILE*" ++ ++ ++#define LUA_COLIBNAME "coroutine" ++LUALIB_API int (luaopen_base) (lua_State *L); ++ ++#define LUA_TABLIBNAME "table" ++LUALIB_API int (luaopen_table) (lua_State *L); ++/* ++#define LUA_IOLIBNAME "io" ++LUALIB_API int (luaopen_io) (lua_State *L); ++ ++#define LUA_OSLIBNAME "os" ++LUALIB_API int (luaopen_os) (lua_State *L); ++*/ ++ ++#define LUA_STRLIBNAME "string" ++LUALIB_API int (luaopen_string) (lua_State *L); ++ ++/* ++#define LUA_MATHLIBNAME "math" ++LUALIB_API int (luaopen_math) (lua_State *L); ++ ++#define LUA_DBLIBNAME "debug" ++LUALIB_API int (luaopen_debug) (lua_State *L); ++ ++#define LUA_LOADLIBNAME "package" ++LUALIB_API int (luaopen_package) (lua_State *L); ++*/ ++ ++/* open all previous libraries */ ++LUALIB_API void (luaL_openlibs) (lua_State *L); ++ ++ ++ ++#ifndef lua_assert ++#define lua_assert(x) ((void)0) ++#endif ++ ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lundump.c +@@ -0,0 +1,227 @@ ++/* ++** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ ++** load precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#include <string.h> ++ ++#define lundump_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lmem.h" ++#include "lobject.h" ++#include "lstring.h" ++#include "lundump.h" ++#include "lzio.h" ++ ++typedef struct { ++ lua_State* L; ++ ZIO* Z; ++ Mbuffer* b; ++ const char* name; ++} LoadState; ++ ++#ifdef LUAC_TRUST_BINARIES ++#define IF(c,s) ++#define error(S,s) ++#else ++#define IF(c,s) if (c) error(S,s) ++ ++static void error(LoadState* S, const char* why) ++{ ++ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); ++ luaD_throw(S->L,LUA_ERRSYNTAX); ++} ++#endif ++ ++#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) ++#define LoadByte(S) (lu_byte)LoadChar(S) ++#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) ++#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) ++ ++static void LoadBlock(LoadState* S, void* b, size_t size) ++{ ++ size_t r=luaZ_read(S->Z,b,size); ++ IF (r!=0, "unexpected end"); ++} ++ ++static int LoadChar(LoadState* S) ++{ ++ char x; ++ LoadVar(S,x); ++ return x; ++} ++ ++static int LoadInt(LoadState* S) ++{ ++ int x; ++ LoadVar(S,x); ++ IF (x<0, "bad integer"); ++ return x; ++} ++ ++static lua_Number LoadNumber(LoadState* S) ++{ ++ lua_Number x; ++ LoadVar(S,x); ++ return x; ++} ++ ++static TString* LoadString(LoadState* S) ++{ ++ size_t size; ++ LoadVar(S,size); ++ if (size==0) ++ return NULL; ++ else ++ { ++ char* s=luaZ_openspace(S->L,S->b,size); ++ LoadBlock(S,s,size); ++ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ ++ } ++} ++ ++static void LoadCode(LoadState* S, Proto* f) ++{ ++ int n=LoadInt(S); ++ f->code=luaM_newvector(S->L,n,Instruction); ++ f->sizecode=n; ++ LoadVector(S,f->code,n,sizeof(Instruction)); ++} ++ ++static Proto* LoadFunction(LoadState* S, TString* p); ++ ++static void LoadConstants(LoadState* S, Proto* f) ++{ ++ int i,n; ++ n=LoadInt(S); ++ f->k=luaM_newvector(S->L,n,TValue); ++ f->sizek=n; ++ for (i=0; i<n; i++) setnilvalue(&f->k[i]); ++ for (i=0; i<n; i++) ++ { ++ TValue* o=&f->k[i]; ++ int t=LoadChar(S); ++ switch (t) ++ { ++ case LUA_TNIL: ++ setnilvalue(o); ++ break; ++ case LUA_TBOOLEAN: ++ setbvalue(o,LoadChar(S)!=0); ++ break; ++ case LUA_TNUMBER: ++ setnvalue(o,LoadNumber(S)); ++ break; ++ case LUA_TSTRING: ++ setsvalue2n(S->L,o,LoadString(S)); ++ break; ++ default: ++ error(S,"bad constant"); ++ break; ++ } ++ } ++ n=LoadInt(S); ++ f->p=luaM_newvector(S->L,n,Proto*); ++ f->sizep=n; ++ for (i=0; i<n; i++) f->p[i]=NULL; ++ for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source); ++} ++ ++static void LoadDebug(LoadState* S, Proto* f) ++{ ++ int i,n; ++ n=LoadInt(S); ++ f->lineinfo=luaM_newvector(S->L,n,int); ++ f->sizelineinfo=n; ++ LoadVector(S,f->lineinfo,n,sizeof(int)); ++ n=LoadInt(S); ++ f->locvars=luaM_newvector(S->L,n,LocVar); ++ f->sizelocvars=n; ++ for (i=0; i<n; i++) f->locvars[i].varname=NULL; ++ for (i=0; i<n; i++) ++ { ++ f->locvars[i].varname=LoadString(S); ++ f->locvars[i].startpc=LoadInt(S); ++ f->locvars[i].endpc=LoadInt(S); ++ } ++ n=LoadInt(S); ++ f->upvalues=luaM_newvector(S->L,n,TString*); ++ f->sizeupvalues=n; ++ for (i=0; i<n; i++) f->upvalues[i]=NULL; ++ for (i=0; i<n; i++) f->upvalues[i]=LoadString(S); ++} ++ ++static Proto* LoadFunction(LoadState* S, TString* p) ++{ ++ Proto* f; ++ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); ++ f=luaF_newproto(S->L); ++ setptvalue2s(S->L,S->L->top,f); incr_top(S->L); ++ f->source=LoadString(S); if (f->source==NULL) f->source=p; ++ f->linedefined=LoadInt(S); ++ f->lastlinedefined=LoadInt(S); ++ f->nups=LoadByte(S); ++ f->numparams=LoadByte(S); ++ f->is_vararg=LoadByte(S); ++ f->maxstacksize=LoadByte(S); ++ LoadCode(S,f); ++ LoadConstants(S,f); ++ LoadDebug(S,f); ++ IF (!luaG_checkcode(f), "bad code"); ++ S->L->top--; ++ S->L->nCcalls--; ++ return f; ++} ++ ++static void LoadHeader(LoadState* S) ++{ ++ char h[LUAC_HEADERSIZE]; ++ char s[LUAC_HEADERSIZE]; ++ luaU_header(h); ++ LoadBlock(S,s,LUAC_HEADERSIZE); ++ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); ++} ++ ++/* ++** load precompiled chunk ++*/ ++Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) ++{ ++ LoadState S; ++ if (*name=='@' || *name=='=') ++ S.name=name+1; ++ else if (*name==LUA_SIGNATURE[0]) ++ S.name="binary string"; ++ else ++ S.name=name; ++ S.L=L; ++ S.Z=Z; ++ S.b=buff; ++ LoadHeader(&S); ++ return LoadFunction(&S,luaS_newliteral(L,"=?")); ++} ++ ++/* ++* make header ++*/ ++void luaU_header (char* h) ++{ ++ int x=1; ++ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); ++ h+=sizeof(LUA_SIGNATURE)-1; ++ *h++=(char)LUAC_VERSION; ++ *h++=(char)LUAC_FORMAT; ++ *h++=(char)*(char*)&x; /* endianness */ ++ *h++=(char)sizeof(int); ++ *h++=(char)sizeof(size_t); ++ *h++=(char)sizeof(Instruction); ++ *h++=(char)sizeof(lua_Number); ++ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ ++} +--- /dev/null ++++ b/extensions/LUA/lua/lundump.h +@@ -0,0 +1,36 @@ ++/* ++** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ++** load precompiled Lua chunks ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lundump_h ++#define lundump_h ++ ++#include "lobject.h" ++#include "lzio.h" ++ ++/* load one chunk; from lundump.c */ ++LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); ++ ++/* make header; from lundump.c */ ++LUAI_FUNC void luaU_header (char* h); ++ ++/* dump one chunk; from ldump.c */ ++LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); ++ ++#ifdef luac_c ++/* print one chunk; from print.c */ ++LUAI_FUNC void luaU_print (const Proto* f, int full); ++#endif ++ ++/* for header of binary files -- this is Lua 5.1 */ ++#define LUAC_VERSION 0x51 ++ ++/* for header of binary files -- this is the official format */ ++#define LUAC_FORMAT 0 ++ ++/* size of header of binary files */ ++#define LUAC_HEADERSIZE 12 ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lvm.c +@@ -0,0 +1,762 @@ ++/* ++** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ ++** Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#define lvm_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "ldebug.h" ++#include "ldo.h" ++#include "lfunc.h" ++#include "lgc.h" ++#include "lobject.h" ++#include "lopcodes.h" ++#include "lstate.h" ++#include "lstring.h" ++#include "ltable.h" ++#include "ltm.h" ++#include "lvm.h" ++ ++ ++ ++/* limit for table tag-method chains (to avoid loops) */ ++#define MAXTAGLOOP 100 ++ ++ ++const TValue *luaV_tonumber (const TValue *obj, TValue *n) { ++ lua_Number num; ++ if (ttisnumber(obj)) return obj; ++ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { ++ setnvalue(n, num); ++ return n; ++ } ++ else ++ return NULL; ++} ++ ++ ++int luaV_tostring (lua_State *L, StkId obj) { ++ if (!ttisnumber(obj)) ++ return 0; ++ else { ++ char s[LUAI_MAXNUMBER2STR]; ++ lua_Number n = nvalue(obj); ++ lua_number2str(s, n); ++ setsvalue2s(L, obj, luaS_new(L, s)); ++ return 1; ++ } ++} ++ ++ ++static void traceexec (lua_State *L, const Instruction *pc) { ++ lu_byte mask = L->hookmask; ++ const Instruction *oldpc = L->savedpc; ++ L->savedpc = pc; ++ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { ++ resethookcount(L); ++ luaD_callhook(L, LUA_HOOKCOUNT, -1); ++ } ++ if (mask & LUA_MASKLINE) { ++ Proto *p = ci_func(L->ci)->l.p; ++ int npc = pcRel(pc, p); ++ int newline = getline(p, npc); ++ /* call linehook when enter a new function, when jump back (loop), ++ or when enter a new line */ ++ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) ++ luaD_callhook(L, LUA_HOOKLINE, newline); ++ } ++} ++ ++ ++static void callTMres (lua_State *L, StkId res, const TValue *f, ++ const TValue *p1, const TValue *p2) { ++ ptrdiff_t result = savestack(L, res); ++ setobj2s(L, L->top, f); /* push function */ ++ setobj2s(L, L->top+1, p1); /* 1st argument */ ++ setobj2s(L, L->top+2, p2); /* 2nd argument */ ++ luaD_checkstack(L, 3); ++ L->top += 3; ++ luaD_call(L, L->top - 3, 1); ++ res = restorestack(L, result); ++ L->top--; ++ setobjs2s(L, res, L->top); ++} ++ ++ ++ ++static void callTM (lua_State *L, const TValue *f, const TValue *p1, ++ const TValue *p2, const TValue *p3) { ++ setobj2s(L, L->top, f); /* push function */ ++ setobj2s(L, L->top+1, p1); /* 1st argument */ ++ setobj2s(L, L->top+2, p2); /* 2nd argument */ ++ setobj2s(L, L->top+3, p3); /* 3th argument */ ++ luaD_checkstack(L, 4); ++ L->top += 4; ++ luaD_call(L, L->top - 4, 0); ++} ++ ++ ++void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { ++ int loop; ++ for (loop = 0; loop < MAXTAGLOOP; loop++) { ++ const TValue *tm; ++ if (ttistable(t)) { /* `t' is a table? */ ++ Table *h = hvalue(t); ++ const TValue *res = luaH_get(h, key); /* do a primitive get */ ++ if (!ttisnil(res) || /* result is no nil? */ ++ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ ++ setobj2s(L, val, res); ++ return; ++ } ++ /* else will try the tag method */ ++ } ++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) ++ luaG_typeerror(L, t, "index"); ++ if (ttisfunction(tm)) { ++ callTMres(L, val, tm, t, key); ++ return; ++ } ++ t = tm; /* else repeat with `tm' */ ++ } ++ luaG_runerror(L, "loop in gettable"); ++} ++ ++ ++void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { ++ int loop; ++ for (loop = 0; loop < MAXTAGLOOP; loop++) { ++ const TValue *tm; ++ if (ttistable(t)) { /* `t' is a table? */ ++ Table *h = hvalue(t); ++ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ ++ if (!ttisnil(oldval) || /* result is no nil? */ ++ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ ++ setobj2t(L, oldval, val); ++ luaC_barriert(L, h, val); ++ return; ++ } ++ /* else will try the tag method */ ++ } ++ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) ++ luaG_typeerror(L, t, "index"); ++ if (ttisfunction(tm)) { ++ callTM(L, tm, t, key, val); ++ return; ++ } ++ t = tm; /* else repeat with `tm' */ ++ } ++ luaG_runerror(L, "loop in settable"); ++} ++ ++ ++static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, ++ StkId res, TMS event) { ++ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ ++ if (ttisnil(tm)) ++ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ ++ if (ttisnil(tm)) return 0; ++ callTMres(L, res, tm, p1, p2); ++ return 1; ++} ++ ++ ++static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, ++ TMS event) { ++ const TValue *tm1 = fasttm(L, mt1, event); ++ const TValue *tm2; ++ if (tm1 == NULL) return NULL; /* no metamethod */ ++ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ ++ tm2 = fasttm(L, mt2, event); ++ if (tm2 == NULL) return NULL; /* no metamethod */ ++ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ ++ return tm1; ++ return NULL; ++} ++ ++ ++static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, ++ TMS event) { ++ const TValue *tm1 = luaT_gettmbyobj(L, p1, event); ++ const TValue *tm2; ++ if (ttisnil(tm1)) return -1; /* no metamethod? */ ++ tm2 = luaT_gettmbyobj(L, p2, event); ++ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ ++ return -1; ++ callTMres(L, L->top, tm1, p1, p2); ++ return !l_isfalse(L->top); ++} ++ ++ ++static int l_strcmp (const TString *ls, const TString *rs) { ++ const char *l = getstr(ls); ++ size_t ll = ls->tsv.len; ++ const char *r = getstr(rs); ++ size_t lr = rs->tsv.len; ++ for (;;) { ++ int temp = strcoll(l, r); ++ if (temp != 0) return temp; ++ else { /* strings are equal up to a `\0' */ ++ size_t len = strlen(l); /* index of first `\0' in both strings */ ++ if (len == lr) /* r is finished? */ ++ return (len == ll) ? 0 : 1; ++ else if (len == ll) /* l is finished? */ ++ return -1; /* l is smaller than r (because r is not finished) */ ++ /* both strings longer than `len'; go on comparing (after the `\0') */ ++ len++; ++ l += len; ll -= len; r += len; lr -= len; ++ } ++ } ++} ++ ++ ++int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { ++ int res; ++ if (ttype(l) != ttype(r)) ++ return luaG_ordererror(L, l, r); ++ else if (ttisnumber(l)) ++ return luai_numlt(nvalue(l), nvalue(r)); ++ else if (ttisstring(l)) ++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; ++ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) ++ return res; ++ return luaG_ordererror(L, l, r); ++} ++ ++ ++static int lessequal (lua_State *L, const TValue *l, const TValue *r) { ++ int res; ++ if (ttype(l) != ttype(r)) ++ return luaG_ordererror(L, l, r); ++ else if (ttisnumber(l)) ++ return luai_numle(nvalue(l), nvalue(r)); ++ else if (ttisstring(l)) ++ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; ++ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ ++ return res; ++ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ ++ return !res; ++ return luaG_ordererror(L, l, r); ++} ++ ++ ++int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { ++ const TValue *tm; ++ lua_assert(ttype(t1) == ttype(t2)); ++ switch (ttype(t1)) { ++ case LUA_TNIL: return 1; ++ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); ++ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ ++ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); ++ case LUA_TUSERDATA: { ++ if (uvalue(t1) == uvalue(t2)) return 1; ++ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, ++ TM_EQ); ++ break; /* will try TM */ ++ } ++ case LUA_TTABLE: { ++ if (hvalue(t1) == hvalue(t2)) return 1; ++ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); ++ break; /* will try TM */ ++ } ++ default: return gcvalue(t1) == gcvalue(t2); ++ } ++ if (tm == NULL) return 0; /* no TM? */ ++ callTMres(L, L->top, tm, t1, t2); /* call TM */ ++ return !l_isfalse(L->top); ++} ++ ++ ++void luaV_concat (lua_State *L, int total, int last) { ++ do { ++ StkId top = L->base + last + 1; ++ int n = 2; /* number of elements handled in this pass (at least 2) */ ++ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { ++ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) ++ luaG_concaterror(L, top-2, top-1); ++ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ ++ (void)tostring(L, top - 2); /* result is first op (as string) */ ++ else { ++ /* at least two string values; get as many as possible */ ++ size_t tl = tsvalue(top-1)->len; ++ char *buffer; ++ int i; ++ /* collect total length */ ++ for (n = 1; n < total && tostring(L, top-n-1); n++) { ++ size_t l = tsvalue(top-n-1)->len; ++ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); ++ tl += l; ++ } ++ buffer = luaZ_openspace(L, &G(L)->buff, tl); ++ tl = 0; ++ for (i=n; i>0; i--) { /* concat all strings */ ++ size_t l = tsvalue(top-i)->len; ++ memcpy(buffer+tl, svalue(top-i), l); ++ tl += l; ++ } ++ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); ++ } ++ total -= n-1; /* got `n' strings to create 1 new */ ++ last -= n-1; ++ } while (total > 1); /* repeat until only 1 result left */ ++} ++ ++ ++static void Arith (lua_State *L, StkId ra, const TValue *rb, ++ const TValue *rc, TMS op) { ++ TValue tempb, tempc; ++ const TValue *b, *c; ++ if ((b = luaV_tonumber(rb, &tempb)) != NULL && ++ (c = luaV_tonumber(rc, &tempc)) != NULL) { ++ lua_Number nb = nvalue(b), nc = nvalue(c); ++ switch (op) { ++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; ++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; ++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; ++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; ++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; ++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; ++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; ++ default: lua_assert(0); break; ++ } ++ } ++ else if (!call_binTM(L, rb, rc, ra, op)) ++ luaG_aritherror(L, rb, rc); ++} ++ ++ ++ ++/* ++** some macros for common tasks in `luaV_execute' ++*/ ++ ++#define runtime_check(L, c) { if (!(c)) break; } ++ ++#define RA(i) (base+GETARG_A(i)) ++/* to be used after possible stack reallocation */ ++#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) ++#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) ++#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ++ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) ++#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ++ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) ++#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) ++ ++ ++#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} ++ ++ ++#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } ++ ++ ++#define arith_op(op,tm) { \ ++ TValue *rb = RKB(i); \ ++ TValue *rc = RKC(i); \ ++ if (ttisnumber(rb) && ttisnumber(rc)) { \ ++ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ ++ setnvalue(ra, op(nb, nc)); \ ++ } \ ++ else \ ++ Protect(Arith(L, ra, rb, rc, tm)); \ ++ } ++ ++ ++ ++void luaV_execute (lua_State *L, int nexeccalls) { ++ LClosure *cl; ++ StkId base; ++ TValue *k; ++ const Instruction *pc; ++ reentry: /* entry point */ ++ lua_assert(isLua(L->ci)); ++ pc = L->savedpc; ++ cl = &clvalue(L->ci->func)->l; ++ base = L->base; ++ k = cl->p->k; ++ /* main loop of interpreter */ ++ for (;;) { ++ const Instruction i = *pc++; ++ StkId ra; ++ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && ++ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { ++ traceexec(L, pc); ++ if (L->status == LUA_YIELD) { /* did hook yield? */ ++ L->savedpc = pc - 1; ++ return; ++ } ++ base = L->base; ++ } ++ /* warning!! several calls may realloc the stack and invalidate `ra' */ ++ ra = RA(i); ++ lua_assert(base == L->base && L->base == L->ci->base); ++ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); ++ lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); ++ switch (GET_OPCODE(i)) { ++ case OP_MOVE: { ++ setobjs2s(L, ra, RB(i)); ++ continue; ++ } ++ case OP_LOADK: { ++ setobj2s(L, ra, KBx(i)); ++ continue; ++ } ++ case OP_LOADBOOL: { ++ setbvalue(ra, GETARG_B(i)); ++ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ ++ continue; ++ } ++ case OP_LOADNIL: { ++ TValue *rb = RB(i); ++ do { ++ setnilvalue(rb--); ++ } while (rb >= ra); ++ continue; ++ } ++ case OP_GETUPVAL: { ++ int b = GETARG_B(i); ++ setobj2s(L, ra, cl->upvals[b]->v); ++ continue; ++ } ++ case OP_GETGLOBAL: { ++ TValue g; ++ TValue *rb = KBx(i); ++ sethvalue(L, &g, cl->env); ++ lua_assert(ttisstring(rb)); ++ Protect(luaV_gettable(L, &g, rb, ra)); ++ continue; ++ } ++ case OP_GETTABLE: { ++ Protect(luaV_gettable(L, RB(i), RKC(i), ra)); ++ continue; ++ } ++ case OP_SETGLOBAL: { ++ TValue g; ++ sethvalue(L, &g, cl->env); ++ lua_assert(ttisstring(KBx(i))); ++ Protect(luaV_settable(L, &g, KBx(i), ra)); ++ continue; ++ } ++ case OP_SETUPVAL: { ++ UpVal *uv = cl->upvals[GETARG_B(i)]; ++ setobj(L, uv->v, ra); ++ luaC_barrier(L, uv, ra); ++ continue; ++ } ++ case OP_SETTABLE: { ++ Protect(luaV_settable(L, ra, RKB(i), RKC(i))); ++ continue; ++ } ++ case OP_NEWTABLE: { ++ int b = GETARG_B(i); ++ int c = GETARG_C(i); ++ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); ++ Protect(luaC_checkGC(L)); ++ continue; ++ } ++ case OP_SELF: { ++ StkId rb = RB(i); ++ setobjs2s(L, ra+1, rb); ++ Protect(luaV_gettable(L, rb, RKC(i), ra)); ++ continue; ++ } ++ case OP_ADD: { ++ arith_op(luai_numadd, TM_ADD); ++ continue; ++ } ++ case OP_SUB: { ++ arith_op(luai_numsub, TM_SUB); ++ continue; ++ } ++ case OP_MUL: { ++ arith_op(luai_nummul, TM_MUL); ++ continue; ++ } ++ case OP_DIV: { ++ arith_op(luai_numdiv, TM_DIV); ++ continue; ++ } ++ case OP_MOD: { ++ arith_op(luai_nummod, TM_MOD); ++ continue; ++ } ++ case OP_POW: { ++ arith_op(luai_numpow, TM_POW); ++ continue; ++ } ++ case OP_UNM: { ++ TValue *rb = RB(i); ++ if (ttisnumber(rb)) { ++ lua_Number nb = nvalue(rb); ++ setnvalue(ra, luai_numunm(nb)); ++ } ++ else { ++ Protect(Arith(L, ra, rb, rb, TM_UNM)); ++ } ++ continue; ++ } ++ case OP_NOT: { ++ int res = l_isfalse(RB(i)); /* next assignment may change this value */ ++ setbvalue(ra, res); ++ continue; ++ } ++ case OP_LEN: { ++ const TValue *rb = RB(i); ++ switch (ttype(rb)) { ++ case LUA_TTABLE: { ++ setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); ++ break; ++ } ++ case LUA_TSTRING: { ++ setnvalue(ra, cast_num(tsvalue(rb)->len)); ++ break; ++ } ++ default: { /* try metamethod */ ++ Protect( ++ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) ++ luaG_typeerror(L, rb, "get length of"); ++ ) ++ } ++ } ++ continue; ++ } ++ case OP_CONCAT: { ++ int b = GETARG_B(i); ++ int c = GETARG_C(i); ++ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); ++ setobjs2s(L, RA(i), base+b); ++ continue; ++ } ++ case OP_JMP: { ++ dojump(L, pc, GETARG_sBx(i)); ++ continue; ++ } ++ case OP_EQ: { ++ TValue *rb = RKB(i); ++ TValue *rc = RKC(i); ++ Protect( ++ if (equalobj(L, rb, rc) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_LT: { ++ Protect( ++ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_LE: { ++ Protect( ++ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ ) ++ pc++; ++ continue; ++ } ++ case OP_TEST: { ++ if (l_isfalse(ra) != GETARG_C(i)) ++ dojump(L, pc, GETARG_sBx(*pc)); ++ pc++; ++ continue; ++ } ++ case OP_TESTSET: { ++ TValue *rb = RB(i); ++ if (l_isfalse(rb) != GETARG_C(i)) { ++ setobjs2s(L, ra, rb); ++ dojump(L, pc, GETARG_sBx(*pc)); ++ } ++ pc++; ++ continue; ++ } ++ case OP_CALL: { ++ int b = GETARG_B(i); ++ int nresults = GETARG_C(i) - 1; ++ if (b != 0) L->top = ra+b; /* else previous instruction set top */ ++ L->savedpc = pc; ++ switch (luaD_precall(L, ra, nresults)) { ++ case PCRLUA: { ++ nexeccalls++; ++ goto reentry; /* restart luaV_execute over new Lua function */ ++ } ++ case PCRC: { ++ /* it was a C function (`precall' called it); adjust results */ ++ if (nresults >= 0) L->top = L->ci->top; ++ base = L->base; ++ continue; ++ } ++ default: { ++ return; /* yield */ ++ } ++ } ++ } ++ case OP_TAILCALL: { ++ int b = GETARG_B(i); ++ if (b != 0) L->top = ra+b; /* else previous instruction set top */ ++ L->savedpc = pc; ++ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); ++ switch (luaD_precall(L, ra, LUA_MULTRET)) { ++ case PCRLUA: { ++ /* tail call: put new frame in place of previous one */ ++ CallInfo *ci = L->ci - 1; /* previous frame */ ++ int aux; ++ StkId func = ci->func; ++ StkId pfunc = (ci+1)->func; /* previous function index */ ++ if (L->openupval) luaF_close(L, ci->base); ++ L->base = ci->base = ci->func + ((ci+1)->base - pfunc); ++ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ ++ setobjs2s(L, func+aux, pfunc+aux); ++ ci->top = L->top = func+aux; /* correct top */ ++ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); ++ ci->savedpc = L->savedpc; ++ ci->tailcalls++; /* one more call lost */ ++ L->ci--; /* remove new frame */ ++ goto reentry; ++ } ++ case PCRC: { /* it was a C function (`precall' called it) */ ++ base = L->base; ++ continue; ++ } ++ default: { ++ return; /* yield */ ++ } ++ } ++ } ++ case OP_RETURN: { ++ int b = GETARG_B(i); ++ if (b != 0) L->top = ra+b-1; ++ if (L->openupval) luaF_close(L, base); ++ L->savedpc = pc; ++ b = luaD_poscall(L, ra); ++ if (--nexeccalls == 0) /* was previous function running `here'? */ ++ return; /* no: return */ ++ else { /* yes: continue its execution */ ++ if (b) L->top = L->ci->top; ++ lua_assert(isLua(L->ci)); ++ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); ++ goto reentry; ++ } ++ } ++ case OP_FORLOOP: { ++ lua_Number step = nvalue(ra+2); ++ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ ++ lua_Number limit = nvalue(ra+1); ++ if (luai_numlt(0, step) ? luai_numle(idx, limit) ++ : luai_numle(limit, idx)) { ++ dojump(L, pc, GETARG_sBx(i)); /* jump back */ ++ setnvalue(ra, idx); /* update internal index... */ ++ setnvalue(ra+3, idx); /* ...and external index */ ++ } ++ continue; ++ } ++ case OP_FORPREP: { ++ const TValue *init = ra; ++ const TValue *plimit = ra+1; ++ const TValue *pstep = ra+2; ++ L->savedpc = pc; /* next steps may throw errors */ ++ if (!tonumber(init, ra)) ++ luaG_runerror(L, LUA_QL("for") " initial value must be a number"); ++ else if (!tonumber(plimit, ra+1)) ++ luaG_runerror(L, LUA_QL("for") " limit must be a number"); ++ else if (!tonumber(pstep, ra+2)) ++ luaG_runerror(L, LUA_QL("for") " step must be a number"); ++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); ++ dojump(L, pc, GETARG_sBx(i)); ++ continue; ++ } ++ case OP_TFORLOOP: { ++ StkId cb = ra + 3; /* call base */ ++ setobjs2s(L, cb+2, ra+2); ++ setobjs2s(L, cb+1, ra+1); ++ setobjs2s(L, cb, ra); ++ L->top = cb+3; /* func. + 2 args (state and index) */ ++ Protect(luaD_call(L, cb, GETARG_C(i))); ++ L->top = L->ci->top; ++ cb = RA(i) + 3; /* previous call may change the stack */ ++ if (!ttisnil(cb)) { /* continue loop? */ ++ setobjs2s(L, cb-1, cb); /* save control variable */ ++ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ ++ } ++ pc++; ++ continue; ++ } ++ case OP_SETLIST: { ++ int n = GETARG_B(i); ++ int c = GETARG_C(i); ++ int last; ++ Table *h; ++ if (n == 0) { ++ n = cast_int(L->top - ra) - 1; ++ L->top = L->ci->top; ++ } ++ if (c == 0) c = cast_int(*pc++); ++ runtime_check(L, ttistable(ra)); ++ h = hvalue(ra); ++ last = ((c-1)*LFIELDS_PER_FLUSH) + n; ++ if (last > h->sizearray) /* needs more space? */ ++ luaH_resizearray(L, h, last); /* pre-alloc it at once */ ++ for (; n > 0; n--) { ++ TValue *val = ra+n; ++ setobj2t(L, luaH_setnum(L, h, last--), val); ++ luaC_barriert(L, h, val); ++ } ++ continue; ++ } ++ case OP_CLOSE: { ++ luaF_close(L, ra); ++ continue; ++ } ++ case OP_CLOSURE: { ++ Proto *p; ++ Closure *ncl; ++ int nup, j; ++ p = cl->p->p[GETARG_Bx(i)]; ++ nup = p->nups; ++ ncl = luaF_newLclosure(L, nup, cl->env); ++ ncl->l.p = p; ++ for (j=0; j<nup; j++, pc++) { ++ if (GET_OPCODE(*pc) == OP_GETUPVAL) ++ ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; ++ else { ++ lua_assert(GET_OPCODE(*pc) == OP_MOVE); ++ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); ++ } ++ } ++ setclvalue(L, ra, ncl); ++ Protect(luaC_checkGC(L)); ++ continue; ++ } ++ case OP_VARARG: { ++ int b = GETARG_B(i) - 1; ++ int j; ++ CallInfo *ci = L->ci; ++ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; ++ if (b == LUA_MULTRET) { ++ Protect(luaD_checkstack(L, n)); ++ ra = RA(i); /* previous call may change the stack */ ++ b = n; ++ L->top = ra + n; ++ } ++ for (j = 0; j < b; j++) { ++ if (j < n) { ++ setobjs2s(L, ra + j, ci->base - n + j); ++ } ++ else { ++ setnilvalue(ra + j); ++ } ++ } ++ continue; ++ } ++ } ++ } ++} ++ +--- /dev/null ++++ b/extensions/LUA/lua/lvm.h +@@ -0,0 +1,36 @@ ++/* ++** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Lua virtual machine ++** See Copyright Notice in lua.h ++*/ ++ ++#ifndef lvm_h ++#define lvm_h ++ ++ ++#include "ldo.h" ++#include "lobject.h" ++#include "ltm.h" ++ ++ ++#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) ++ ++#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ ++ (((o) = luaV_tonumber(o,n)) != NULL)) ++ ++#define equalobj(L,o1,o2) \ ++ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) ++ ++ ++LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); ++LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); ++LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); ++LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); ++LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, ++ StkId val); ++LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, ++ StkId val); ++LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); ++LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/lua/lzio.c +@@ -0,0 +1,81 @@ ++/* ++** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ++** a generic input stream interface ++** See Copyright Notice in lua.h ++*/ ++ ++#include <string.h> ++ ++#define lzio_c ++#define LUA_CORE ++ ++#include "lua.h" ++ ++#include "llimits.h" ++#include "lmem.h" ++#include "lstate.h" ++#include "lzio.h" ++ ++ ++int luaZ_fill (ZIO *z) { ++ size_t size; ++ lua_State *L = z->L; ++ const char *buff; ++ lua_unlock(L); ++ buff = z->reader(L, z->data, &size); ++ lua_lock(L); ++ if (buff == NULL || size == 0) return EOZ; ++ z->n = size - 1; ++ z->p = buff; ++ return char2int(*(z->p++)); ++} ++ ++ ++int luaZ_lookahead (ZIO *z) { ++ if (z->n == 0) { ++ if (luaZ_fill(z) == EOZ) ++ return EOZ; ++ else { ++ z->n++; /* luaZ_fill removed first byte; put back it */ ++ z->p--; ++ } ++ } ++ return char2int(*z->p); ++} ++ ++ ++void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { ++ z->L = L; ++ z->reader = reader; ++ z->data = data; ++ z->n = 0; ++ z->p = NULL; ++} ++ ++ ++/* --------------------------------------------------------------- read --- */ ++size_t luaZ_read (ZIO *z, void *b, size_t n) { ++ while (n) { ++ size_t m; ++ if (luaZ_lookahead(z) == EOZ) ++ return n; /* return number of missing bytes */ ++ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ ++ memcpy(b, z->p, m); ++ z->n -= m; ++ z->p += m; ++ b = (char *)b + m; ++ n -= m; ++ } ++ return 0; ++} ++ ++/* ------------------------------------------------------------------------ */ ++char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { ++ if (n > buff->buffsize) { ++ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; ++ luaZ_resizebuffer(L, buff, n); ++ } ++ return buff->buffer; ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/lua/lzio.h +@@ -0,0 +1,67 @@ ++/* ++** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ ++** Buffered streams ++** See Copyright Notice in lua.h ++*/ ++ ++ ++#ifndef lzio_h ++#define lzio_h ++ ++#include "lua.h" ++ ++#include "lmem.h" ++ ++ ++#define EOZ (-1) /* end of stream */ ++ ++typedef struct Zio ZIO; ++ ++#define char2int(c) cast(int, cast(unsigned char, (c))) ++ ++#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) ++ ++typedef struct Mbuffer { ++ char *buffer; ++ size_t n; ++ size_t buffsize; ++} Mbuffer; ++ ++#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) ++ ++#define luaZ_buffer(buff) ((buff)->buffer) ++#define luaZ_sizebuffer(buff) ((buff)->buffsize) ++#define luaZ_bufflen(buff) ((buff)->n) ++ ++#define luaZ_resetbuffer(buff) ((buff)->n = 0) ++ ++ ++#define luaZ_resizebuffer(L, buff, size) \ ++ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ ++ (buff)->buffsize = size) ++ ++#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) ++ ++ ++LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); ++LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, ++ void *data); ++LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ ++LUAI_FUNC int luaZ_lookahead (ZIO *z); ++ ++ ++ ++/* --------- Private Part ------------------ */ ++ ++struct Zio { ++ size_t n; /* bytes still unread */ ++ const char *p; /* current position in buffer */ ++ lua_Reader reader; ++ void* data; /* additional data */ ++ lua_State *L; /* Lua state (for reader) */ ++}; ++ ++ ++LUAI_FUNC int luaZ_fill (ZIO *z); ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/Makefile +@@ -0,0 +1,389 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# extensions/LUA/Makefile. Generated from Makefile.in by configure. ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++ ++ ++# -*- Makefile -*- ++# AUTOMAKE ++ ++pkgdatadir = $(datadir)/xtables-addons ++pkgincludedir = $(includedir)/xtables-addons ++pkglibdir = $(libdir)/xtables-addons ++pkglibexecdir = $(libexecdir)/xtables-addons ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = i686-pc-linux-gnu ++host_triplet = i686-pc-linux-gnu ++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in ++subdir = extensions/LUA ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++SOURCES = ++DIST_SOURCES = ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run aclocal-1.11 ++AMTAR = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run tar ++AR = ar ++AUTOCONF = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoconf ++AUTOHEADER = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoheader ++AUTOMAKE = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run automake-1.11 ++AWK = mawk ++CC = gcc ++CCDEPMODE = depmode=gcc3 ++CFLAGS = -g -O2 ++CPP = gcc -E ++CPPFLAGS = ++CYGPATH_W = echo ++DEFS = -DHAVE_CONFIG_H ++DEPDIR = .deps ++DSYMUTIL = ++DUMPBIN = ++ECHO_C = ++ECHO_N = -n ++ECHO_T = ++EGREP = /bin/grep -E ++EXEEXT = ++FGREP = /bin/grep -F ++GREP = /bin/grep ++INSTALL = /usr/bin/install -c ++INSTALL_DATA = ${INSTALL} -m 644 ++INSTALL_PROGRAM = ${INSTALL} ++INSTALL_SCRIPT = ${INSTALL} ++INSTALL_STRIP_PROGRAM = $(install_sh) -c -s ++LD = /usr/bin/ld ++LDFLAGS = ++LIBOBJS = ++LIBS = ++LIBTOOL = $(SHELL) $(top_builddir)/libtool ++LIPO = ++LN_S = ln -s ++LTLIBOBJS = ++MAKEINFO = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run makeinfo ++MKDIR_P = /bin/mkdir -p ++NM = /usr/bin/nm -B ++NMEDIT = ++OBJDUMP = objdump ++OBJEXT = o ++OTOOL = ++OTOOL64 = ++PACKAGE = xtables-addons ++PACKAGE_BUGREPORT = ++PACKAGE_NAME = xtables-addons ++PACKAGE_STRING = xtables-addons 1.21 ++PACKAGE_TARNAME = xtables-addons ++PACKAGE_URL = ++PACKAGE_VERSION = 1.21 ++PATH_SEPARATOR = : ++PKG_CONFIG = /usr/bin/pkg-config ++RANLIB = ranlib ++SED = /bin/sed ++SET_MAKE = ++SHELL = /bin/bash ++STRIP = strip ++VERSION = 1.21 ++abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA ++abs_srcdir = /home/andre/Dropbox/xtables-addons/extensions/LUA ++abs_top_builddir = /home/andre/Dropbox/xtables-addons ++abs_top_srcdir = /home/andre/Dropbox/xtables-addons ++ac_ct_CC = gcc ++ac_ct_DUMPBIN = ++am__include = include ++am__leading_dot = . ++am__quote = ++am__tar = ${AMTAR} chof - "$$tardir" ++am__untar = ${AMTAR} xf - ++bindir = ${exec_prefix}/bin ++build = i686-pc-linux-gnu ++build_alias = ++build_cpu = i686 ++build_os = linux-gnu ++build_vendor = pc ++builddir = . ++datadir = ${datarootdir} ++datarootdir = ${prefix}/share ++docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} ++dvidir = ${docdir} ++exec_prefix = ${prefix} ++host = i686-pc-linux-gnu ++host_alias = ++host_cpu = i686 ++host_os = linux-gnu ++host_vendor = pc ++htmldir = ${docdir} ++includedir = ${prefix}/include ++infodir = ${datarootdir}/info ++install_sh = ${SHELL} /home/andre/Dropbox/xtables-addons/install-sh ++kbuilddir = /lib/modules/2.6.33-020633-generic/build ++kinclude_CFLAGS = -I /lib/modules/2.6.33-020633-generic/build/include ++ksourcedir = ++libdir = ${exec_prefix}/lib ++libexecdir = ${exec_prefix}/libexec ++libxtables_CFLAGS = ++libxtables_LIBS = -L/lib -lxtables ++localedir = ${datarootdir}/locale ++localstatedir = ${prefix}/var ++lt_ECHO = echo ++mandir = ${datarootdir}/man ++mkdir_p = /bin/mkdir -p ++oldincludedir = /usr/include ++pdfdir = ${docdir} ++prefix = /usr/local ++program_transform_name = s,x,x, ++psdir = ${docdir} ++regular_CFLAGS = -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Winline -pipe -DXTABLES_LIBDIR=\"${xtlibdir}\" ++sbindir = ${exec_prefix}/sbin ++sharedstatedir = ${prefix}/com ++srcdir = . ++sysconfdir = ${prefix}/etc ++target_alias = ++top_build_prefix = ../../ ++top_builddir = ../.. ++top_srcdir = ../.. ++xtlibdir = ${libexecdir}/xtables ++XA_SRCDIR = ${srcdir} ++XA_TOPSRCDIR = ${top_srcdir} ++XA_ABSTOPSRCDIR = ${abs_top_srcdir} ++_mcall = -f ${top_builddir}/Makefile.iptrules ++all: all-am ++ ++.SUFFIXES: ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign extensions/LUA/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++tags: TAGS ++TAGS: ++ ++ctags: CTAGS ++CTAGS: ++ ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile all-local ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-local mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f Makefile ++distclean-am: clean-am distclean-generic ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-exec-local ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-generic mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: all all-am all-local check check-am clean clean-generic \ ++ clean-libtool clean-local distclean distclean-generic \ ++ distclean-libtool distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am install-dvi \ ++ install-dvi-am install-exec install-exec-am install-exec-local \ ++ install-html install-html-am install-info install-info-am \ ++ install-man install-pdf install-pdf-am install-ps \ ++ install-ps-am install-strip installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ++ ps ps-am uninstall uninstall-am ++ ++export XA_SRCDIR ++export XA_TOPSRCDIR ++export XA_ABSTOPSRCDIR ++ ++all-local: user-all-local ++ ++install-exec-local: user-install-local ++ ++clean-local: user-clean-local ++ ++user-all-local: ++ ${MAKE} ${_mcall} all; ++ ++# Have no user-install-data-local ATM ++user-install-local: user-install-exec-local ++ ++user-install-exec-local: ++ ${MAKE} ${_mcall} install; ++ ++user-clean-local: ++ ${MAKE} ${_mcall} clean; ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: ++ +--- /dev/null ++++ b/extensions/LUA/Makefile.am +@@ -0,0 +1 @@ ++include ../../Makefile.extra +--- /dev/null ++++ b/extensions/LUA/Makefile.in +@@ -0,0 +1,389 @@ ++# Makefile.in generated by automake 1.11.1 from Makefile.am. ++# @configure_input@ ++ ++# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, ++# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, ++# Inc. ++# This Makefile.in is free software; the Free Software Foundation ++# gives unlimited permission to copy and/or distribute it, ++# with or without modifications, as long as this notice is preserved. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY, to the extent permitted by law; without ++# even the implied warranty of MERCHANTABILITY or FITNESS FOR A ++# PARTICULAR PURPOSE. ++ ++@SET_MAKE@ ++ ++# -*- Makefile -*- ++# AUTOMAKE ++VPATH = @srcdir@ ++pkgdatadir = $(datadir)/@PACKAGE@ ++pkgincludedir = $(includedir)/@PACKAGE@ ++pkglibdir = $(libdir)/@PACKAGE@ ++pkglibexecdir = $(libexecdir)/@PACKAGE@ ++am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd ++install_sh_DATA = $(install_sh) -c -m 644 ++install_sh_PROGRAM = $(install_sh) -c ++install_sh_SCRIPT = $(install_sh) -c ++INSTALL_HEADER = $(INSTALL_DATA) ++transform = $(program_transform_name) ++NORMAL_INSTALL = : ++PRE_INSTALL = : ++POST_INSTALL = : ++NORMAL_UNINSTALL = : ++PRE_UNINSTALL = : ++POST_UNINSTALL = : ++build_triplet = @build@ ++host_triplet = @host@ ++DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ ++ $(srcdir)/Makefile.in ++subdir = extensions/LUA ++ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ++am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ ++ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ ++ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ ++ $(top_srcdir)/configure.ac ++am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ ++ $(ACLOCAL_M4) ++mkinstalldirs = $(install_sh) -d ++CONFIG_HEADER = $(top_builddir)/config.h ++CONFIG_CLEAN_FILES = ++CONFIG_CLEAN_VPATH_FILES = ++SOURCES = ++DIST_SOURCES = ++DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ++ACLOCAL = @ACLOCAL@ ++AMTAR = @AMTAR@ ++AR = @AR@ ++AUTOCONF = @AUTOCONF@ ++AUTOHEADER = @AUTOHEADER@ ++AUTOMAKE = @AUTOMAKE@ ++AWK = @AWK@ ++CC = @CC@ ++CCDEPMODE = @CCDEPMODE@ ++CFLAGS = @CFLAGS@ ++CPP = @CPP@ ++CPPFLAGS = @CPPFLAGS@ ++CYGPATH_W = @CYGPATH_W@ ++DEFS = @DEFS@ ++DEPDIR = @DEPDIR@ ++DSYMUTIL = @DSYMUTIL@ ++DUMPBIN = @DUMPBIN@ ++ECHO_C = @ECHO_C@ ++ECHO_N = @ECHO_N@ ++ECHO_T = @ECHO_T@ ++EGREP = @EGREP@ ++EXEEXT = @EXEEXT@ ++FGREP = @FGREP@ ++GREP = @GREP@ ++INSTALL = @INSTALL@ ++INSTALL_DATA = @INSTALL_DATA@ ++INSTALL_PROGRAM = @INSTALL_PROGRAM@ ++INSTALL_SCRIPT = @INSTALL_SCRIPT@ ++INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ ++LD = @LD@ ++LDFLAGS = @LDFLAGS@ ++LIBOBJS = @LIBOBJS@ ++LIBS = @LIBS@ ++LIBTOOL = @LIBTOOL@ ++LIPO = @LIPO@ ++LN_S = @LN_S@ ++LTLIBOBJS = @LTLIBOBJS@ ++MAKEINFO = @MAKEINFO@ ++MKDIR_P = @MKDIR_P@ ++NM = @NM@ ++NMEDIT = @NMEDIT@ ++OBJDUMP = @OBJDUMP@ ++OBJEXT = @OBJEXT@ ++OTOOL = @OTOOL@ ++OTOOL64 = @OTOOL64@ ++PACKAGE = @PACKAGE@ ++PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ ++PACKAGE_NAME = @PACKAGE_NAME@ ++PACKAGE_STRING = @PACKAGE_STRING@ ++PACKAGE_TARNAME = @PACKAGE_TARNAME@ ++PACKAGE_URL = @PACKAGE_URL@ ++PACKAGE_VERSION = @PACKAGE_VERSION@ ++PATH_SEPARATOR = @PATH_SEPARATOR@ ++PKG_CONFIG = @PKG_CONFIG@ ++RANLIB = @RANLIB@ ++SED = @SED@ ++SET_MAKE = @SET_MAKE@ ++SHELL = @SHELL@ ++STRIP = @STRIP@ ++VERSION = @VERSION@ ++abs_builddir = @abs_builddir@ ++abs_srcdir = @abs_srcdir@ ++abs_top_builddir = @abs_top_builddir@ ++abs_top_srcdir = @abs_top_srcdir@ ++ac_ct_CC = @ac_ct_CC@ ++ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ++am__include = @am__include@ ++am__leading_dot = @am__leading_dot@ ++am__quote = @am__quote@ ++am__tar = @am__tar@ ++am__untar = @am__untar@ ++bindir = @bindir@ ++build = @build@ ++build_alias = @build_alias@ ++build_cpu = @build_cpu@ ++build_os = @build_os@ ++build_vendor = @build_vendor@ ++builddir = @builddir@ ++datadir = @datadir@ ++datarootdir = @datarootdir@ ++docdir = @docdir@ ++dvidir = @dvidir@ ++exec_prefix = @exec_prefix@ ++host = @host@ ++host_alias = @host_alias@ ++host_cpu = @host_cpu@ ++host_os = @host_os@ ++host_vendor = @host_vendor@ ++htmldir = @htmldir@ ++includedir = @includedir@ ++infodir = @infodir@ ++install_sh = @install_sh@ ++kbuilddir = @kbuilddir@ ++kinclude_CFLAGS = @kinclude_CFLAGS@ ++ksourcedir = @ksourcedir@ ++libdir = @libdir@ ++libexecdir = @libexecdir@ ++libxtables_CFLAGS = @libxtables_CFLAGS@ ++libxtables_LIBS = @libxtables_LIBS@ ++localedir = @localedir@ ++localstatedir = @localstatedir@ ++lt_ECHO = @lt_ECHO@ ++mandir = @mandir@ ++mkdir_p = @mkdir_p@ ++oldincludedir = @oldincludedir@ ++pdfdir = @pdfdir@ ++prefix = @prefix@ ++program_transform_name = @program_transform_name@ ++psdir = @psdir@ ++regular_CFLAGS = @regular_CFLAGS@ ++sbindir = @sbindir@ ++sharedstatedir = @sharedstatedir@ ++srcdir = @srcdir@ ++sysconfdir = @sysconfdir@ ++target_alias = @target_alias@ ++top_build_prefix = @top_build_prefix@ ++top_builddir = @top_builddir@ ++top_srcdir = @top_srcdir@ ++xtlibdir = @xtlibdir@ ++XA_SRCDIR = ${srcdir} ++XA_TOPSRCDIR = ${top_srcdir} ++XA_ABSTOPSRCDIR = ${abs_top_srcdir} ++_mcall = -f ${top_builddir}/Makefile.iptrules ++all: all-am ++ ++.SUFFIXES: ++$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) ++ @for dep in $?; do \ ++ case '$(am__configure_deps)' in \ ++ *$$dep*) \ ++ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ ++ && { if test -f $@; then exit 0; else break; fi; }; \ ++ exit 1;; \ ++ esac; \ ++ done; \ ++ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ ++ $(am__cd) $(top_srcdir) && \ ++ $(AUTOMAKE) --foreign extensions/LUA/Makefile ++.PRECIOUS: Makefile ++Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status ++ @case '$?' in \ ++ *config.status*) \ ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ ++ *) \ ++ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ ++ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ ++ esac; ++ ++$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++ ++$(top_srcdir)/configure: $(am__configure_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(ACLOCAL_M4): $(am__aclocal_m4_deps) ++ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ++$(am__aclocal_m4_deps): ++ ++mostlyclean-libtool: ++ -rm -f *.lo ++ ++clean-libtool: ++ -rm -rf .libs _libs ++tags: TAGS ++TAGS: ++ ++ctags: CTAGS ++CTAGS: ++ ++ ++distdir: $(DISTFILES) ++ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ ++ list='$(DISTFILES)'; \ ++ dist_files=`for file in $$list; do echo $$file; done | \ ++ sed -e "s|^$$srcdirstrip/||;t" \ ++ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ ++ case $$dist_files in \ ++ */*) $(MKDIR_P) `echo "$$dist_files" | \ ++ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ ++ sort -u` ;; \ ++ esac; \ ++ for file in $$dist_files; do \ ++ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ ++ if test -d $$d/$$file; then \ ++ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ ++ if test -d "$(distdir)/$$file"; then \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ ++ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ ++ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ ++ fi; \ ++ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ ++ else \ ++ test -f "$(distdir)/$$file" \ ++ || cp -p $$d/$$file "$(distdir)/$$file" \ ++ || exit 1; \ ++ fi; \ ++ done ++check-am: all-am ++check: check-am ++all-am: Makefile all-local ++installdirs: ++install: install-am ++install-exec: install-exec-am ++install-data: install-data-am ++uninstall: uninstall-am ++ ++install-am: all-am ++ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am ++ ++installcheck: installcheck-am ++install-strip: ++ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ ++ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ ++ `test -z '$(STRIP)' || \ ++ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install ++mostlyclean-generic: ++ ++clean-generic: ++ ++distclean-generic: ++ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) ++ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) ++ ++maintainer-clean-generic: ++ @echo "This command is intended for maintainers to use" ++ @echo "it deletes files that may require special tools to rebuild." ++clean: clean-am ++ ++clean-am: clean-generic clean-libtool clean-local mostlyclean-am ++ ++distclean: distclean-am ++ -rm -f Makefile ++distclean-am: clean-am distclean-generic ++ ++dvi: dvi-am ++ ++dvi-am: ++ ++html: html-am ++ ++html-am: ++ ++info: info-am ++ ++info-am: ++ ++install-data-am: ++ ++install-dvi: install-dvi-am ++ ++install-dvi-am: ++ ++install-exec-am: install-exec-local ++ ++install-html: install-html-am ++ ++install-html-am: ++ ++install-info: install-info-am ++ ++install-info-am: ++ ++install-man: ++ ++install-pdf: install-pdf-am ++ ++install-pdf-am: ++ ++install-ps: install-ps-am ++ ++install-ps-am: ++ ++installcheck-am: ++ ++maintainer-clean: maintainer-clean-am ++ -rm -f Makefile ++maintainer-clean-am: distclean-am maintainer-clean-generic ++ ++mostlyclean: mostlyclean-am ++ ++mostlyclean-am: mostlyclean-generic mostlyclean-libtool ++ ++pdf: pdf-am ++ ++pdf-am: ++ ++ps: ps-am ++ ++ps-am: ++ ++uninstall-am: ++ ++.MAKE: install-am install-strip ++ ++.PHONY: all all-am all-local check check-am clean clean-generic \ ++ clean-libtool clean-local distclean distclean-generic \ ++ distclean-libtool distdir dvi dvi-am html html-am info info-am \ ++ install install-am install-data install-data-am install-dvi \ ++ install-dvi-am install-exec install-exec-am install-exec-local \ ++ install-html install-html-am install-info install-info-am \ ++ install-man install-pdf install-pdf-am install-ps \ ++ install-ps-am install-strip installcheck installcheck-am \ ++ installdirs maintainer-clean maintainer-clean-generic \ ++ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ++ ps ps-am uninstall uninstall-am ++ ++export XA_SRCDIR ++export XA_TOPSRCDIR ++export XA_ABSTOPSRCDIR ++ ++all-local: user-all-local ++ ++install-exec-local: user-install-local ++ ++clean-local: user-clean-local ++ ++user-all-local: ++ ${MAKE} ${_mcall} all; ++ ++# Have no user-install-data-local ATM ++user-install-local: user-install-exec-local ++ ++user-install-exec-local: ++ ${MAKE} ${_mcall} install; ++ ++user-clean-local: ++ ${MAKE} ${_mcall} clean; ++ ++# Tell versions [3.59,3.63) of GNU make to not export all variables. ++# Otherwise a system limit (for SysV at least) may be exceeded. ++.NOEXPORT: ++ +--- /dev/null ++++ b/extensions/LUA/Mbuild +@@ -0,0 +1,3 @@ ++# -*- Makefile -*- ++ ++obj-${build_LUA} += libxt_LUA.so +--- /dev/null ++++ b/extensions/LUA/nf_lua.c +@@ -0,0 +1,64 @@ ++#if defined(__KERNEL__) ++ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++#include <linux/timer.h> ++#include <linux/random.h> ++#include <linux/netfilter/x_tables.h> ++ ++#endif ++ ++#include "lua.h" ++#include "lobject.h" /*sizeof(udata) */ ++#include "lauxlib.h" ++#include "controller.h" ++ ++#if defined(__KERNEL__) /* reachs until luaopen_nflib */ ++ ++ ++static int32_t nf_get_random(lua_State *L) ++{ ++ uint32_t rand = 0; ++ ++ get_random_bytes(&rand, sizeof(uint32_t )); ++ lua_pushnumber(L, rand); ++ return 1; ++} ++ ++static int32_t nf_get_time(lua_State *L) ++{ ++ lua_pushnumber(L, jiffies_to_msecs(jiffies_64)); ++ return 1; ++} ++ ++static const struct luaL_Reg nf_lua_lib_f [] = { ++ { "get_random", nf_get_random }, ++ { "get_time", nf_get_time }, ++ { NULL, NULL } ++}; ++ ++void luaopen_nflib(lua_State *L) ++{ ++ int32_t top; ++ ++ luaL_register(L, NETFILTER_LIB, nf_lua_lib_f); ++ lua_pop(L, 1); ++ ++ /* registering verdicts inside the _G */ ++ lua_getglobal(L, "_G"); ++ top = lua_gettop(L); ++ ++ lua_pushinteger(L, XT_CONTINUE); ++ lua_setfield(L, top, "XT_CONTINUE"); /* continiue with next rule */ ++ ++ lua_pushinteger(L, NF_DROP); ++ lua_setfield(L, top, "NF_DROP"); /* stop traversal in the current table hook and drop packet */ ++ ++ lua_pushinteger(L, NF_ACCEPT); ++ lua_setfield(L, top, "NF_ACCEPT"); /* stop traversal in the current table hook and accept packet */ ++ ++ lua_pop(L, 1); /* pop _G */ ++} ++ ++#endif +--- /dev/null ++++ b/extensions/LUA/prot_buf_dynamic.c +@@ -0,0 +1,486 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "controller.h" ++ ++ ++ ++struct protocol_buf * dyn_prot_buf_array[MAX_NR_OF_DYN_PROT_BUFS] = { NULL }; ++ ++ ++/* LUA_API: the function 'field_dynamic_setter' acts as a wrapper around ++ * a given Lua field setter function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'set' ++ * member of the protocol_field. We call this function passing the actual ++ * segment as byte array and the set value. ++ * ++ * Paramters: ++ * 1. lua_packet_segment (implicit) ++ * 2. some lua value ++ * ++ * Upvalues: ++ * 1. pointer to the protocol buffer ++ * 2. field index ++ * ++ * Returns: ++ * 1. true or false if the 'set' was successful ++ */ ++int32_t field_dynamic_setter(lua_State *L) ++{ ++ size_t nbytes; ++ lua_packet_segment * array; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].set); ++ if (!lua_isfunction(L, -1)) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); ++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); ++ array->length = seg->length; ++ array->start = seg->start + seg->offset; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ lua_pushvalue(L, 2); /* push value to set */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ pr_debug("Error: %s \n", lua_tostring(L, -1)); ++ lua_pop(L, 1); ++ lua_pushboolean(L, 0); ++ } ++ return 1; ++} ++ ++/* LUA_API: the function 'field_dynamic_getter' acts as a wrapper around ++ * a given Lua field getter function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'get' ++ * member of the protocol_field. We call this function passing the actual ++ * segment as byte array. ++ * ++ * Paramters: ++ * 1. lua_packet_segment (implicit) ++ * ++ * Upvalues: ++ * 1. pointer to the protocol buffer ++ * 2. field index ++ * ++ * Returns: ++ * 1. true or false if the 'get' was successful ++ */ ++int32_t field_dynamic_getter(lua_State *L) ++{ ++ size_t nbytes; ++ lua_packet_segment * array; ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].get); ++ if (!lua_isfunction(L, -1)) { ++ lua_pushboolean(L, 0); ++ return 1; ++ } ++ ++ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); ++ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); ++ array->length = seg->length; ++ array->start = seg->start + seg->offset; ++ array->changes = NULL; ++ ++ luaL_getmetatable(L, LUA_BYTE_ARRAY); ++ lua_setmetatable(L, -2); ++ if (lua_pcall(L, 1, 1, 0) != 0) { ++ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); ++ lua_pop(L, 1); ++ lua_pushboolean(L, 0); ++ } ++ return 1; ++} ++ ++/* LUA_API: the function 'has_protocol_dynamic' acts as a wrapper around ++ * a given lua has_protocol function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'has_protocol' ++ * member of the protocol_buffer. We call this function passing the actual ++ * segment. ++ * ++ * Paramters: ++ * 1. lua_packet_segment ++ * 2. protocol type ++ * ++ * Returns: ++ * 1. true or false if the payload field contains the given protocol ++ */ ++int32_t has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t type) ++{ ++ lua_packet_segment *seg_new; ++ int32_t res = 0; ++ ++ /* the function name is piggybacked as a string */ ++ lua_getglobal(L, (char *)prot_buf->has_protocol); ++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ seg_new->start = seg->start; ++ seg_new->offset = seg->offset; ++ seg_new->length = seg->length; ++ seg_new->changes = NULL; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ lua_pushinteger(L, type); /* push the protocol type */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); ++ lua_pop(L, 1); ++ return 0; ++ } ++ res = lua_toboolean(L, -1); ++ lua_pop(L, 1); ++ ++ return res; ++} ++ ++/* LUA_API: the function 'get_field_changes_dynamic' acts as a wrapper around ++ * a given lua get_field_changes function of a dynamic protocol buffer. The ++ * string containing the lua function name was piggybacked in the 'get_field_changes' ++ * member of the protocol_buffer. We call this function passing the actual ++ * segment. The lua function must return two lua table containing the offset ++ * and length changes (in bits). ++ * ++ * Paramters: ++ * 1. lua_packet_segment ++ * ++ * Returns: ++ * 1. new allocated field_changes struct ++ */ ++struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) ++{ ++ lua_packet_segment *seg_new; ++ struct field_changes * changes; ++ int32_t nr_of_changes, i; ++ ++ lua_getglobal(L, (char *)prot_buf->get_field_changes); ++ ++ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ seg_new->start = seg->start; ++ seg_new->offset = seg->offset; ++ seg_new->length = seg->length; ++ seg_new->changes = NULL; ++ luaL_getmetatable(L, prot_buf->name); ++ lua_setmetatable(L, -2); ++ ++ if (lua_pcall(L, 1, 2, 0) != 0) ++ luaL_error(L, "inside get_field_changes_dynamic. %s\n", lua_tostring(L, -1)); ++ ++ /* the function call must return a table containing length changes */ ++ luaL_checktype(L, -1, LUA_TTABLE); ++ /* the function call must return a table containing offset changes */ ++ luaL_checktype(L, -2, LUA_TTABLE); ++ /* both tables have to be of same size */ ++ if (lua_objlen(L, -1) != lua_objlen(L, -2)) ++ luaL_error(L, "the provided tables are not of equal size"); ++ ++ nr_of_changes = lua_objlen(L, -1); ++ changes = get_allocated_field_changes(L, nr_of_changes); ++ ++ /* loop over the tables */ ++ for (i = 1; i < nr_of_changes; i++) { ++ lua_rawgeti(L, -1, i); /* push length value of field at index i */ ++ changes->field_length_changes[i - 1] = luaL_checkinteger(L, -1); ++ lua_pop(L, 1); /* pop offset value */ ++ ++ lua_rawgeti(L, -2, i); /* push offset value of field at index i */ ++ changes->field_offset_changes[i - 1] = luaL_checkinteger(L, -1); ++ lua_pop(L, 1); /* pop length value */ ++ } ++ ++ /* pop both tables */ ++ lua_pop(L, 2); ++ ++ return changes; ++} ++ ++/* C_INT: 'get_free_protocol_index' is only used internally. This function ++ * gets a free slot inside the array holding all the protocol buffers. ++ * There are several ways to get to this information. In this case I take ++ * the way over the reflected array SUPPORTED_PROTOCOL_TABLE inside the ++ * Lua state. Since this function is called at laodtime, we do not have ++ * to care about performance. ++ */ ++static int32_t get_free_protocol_index(lua_State *L) ++{ ++ int32_t protocol_index; ++ ++ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); ++ protocol_index = lua_objlen(L, -1) + 1; ++ lua_pop(L, 1); ++ return protocol_index; ++} ++ ++/* C_API: 'free_dynamic_prot_buf' frees the allocated memory of a given ++ * dynamic protocol buffer. this function is normally called inside a ++ * cleanup routine. Be aware, before running this function you must be ++ * sure that no references to the dynamic protocol buffers were available. ++ * It's recomended to close the Lua state before calling the function. */ ++void free_dynamic_prot_buf(struct protocol_buf * prot_buf) ++{ ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ for (; field->name != NULL; field++) { ++ if (field->get) kfree(field->get); ++ if (field->set) kfree(field->set); ++ if (field->name) kfree((char *)field->name); ++ } ++ ++ if (prot_buf->payload_field) kfree(prot_buf->payload_field); ++ if (prot_buf->has_protocol) kfree(prot_buf->has_protocol); ++ ++ if (prot_buf->get_field_changes) kfree(prot_buf->get_field_changes); ++ kfree((char *)prot_buf->name); ++ kfree(prot_buf); ++ return; ++} ++ ++void cleanup_dynamic_prot_bufs(void) ++{ ++ int32_t i; ++ ++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { ++ if (dyn_prot_buf_array[i]) { ++ free_dynamic_prot_buf(dyn_prot_buf_array[i]); ++ dyn_prot_buf_array[i] = NULL; ++ } ++ } ++ return; ++} ++ ++ ++/* C_INT: 'free_protocol_fields' is used internally as a helper function for ++ * 'register_dynamic_protbuf'. It is used when durin registration an error ++ * occurs and the afore allocated fields needed to be freed. */ ++static inline void free_protocol_fields(struct protocol_field * prot_fields, int32_t i) ++{ ++ struct protocol_field * f; ++ ++ while (i >= 0) { ++ f = &prot_fields[i]; ++ if (f->name) kfree((void *)f->name); ++ if (f->get) kfree((void *)f->get); ++ if (f->set) kfree((void *)f->set); ++ kfree((void *)f); ++ i--; ++ } ++} ++ ++/* LUA_API: 'register_dynamic_protbuf' is called from within the Lua script. ++ * it takes a Lua table representing the dynamic protocol buffer as parameter. ++ * e.g.: ++ * eth_prot_buf = { ++ * name = "packet_eth_dyn", ++ * payload_field = "data", ++ * protocol_fields = { ++ * {"dmac", 0, 48, nil, nil }, ++ * {"smac", 48, 48, nil, nil }, ++ * {"type", 96, 16, nil, nil }, ++ * {"data", 112, 0, nil, nil }, ++ * }, ++ * has_protocol = "eth_dyn_has_protocol", ++ * get_field_changes = "eth_dyn_get_field_changes" ++ * } ++ * register_dynamic_protbuf(eth_prot_buf) ++ * ++ * the table gets parsed and a new protocol_buf struct is allocated and ++ * initialized using 'register_protbuf', which is also used for the static ++ * protocol buffers. This enables an identical behavior like the static ++ * protocol buffers. The dynamic protocol buffers are not garbage collected, ++ * use 'free_dynamic_protbuf' to free them after closing the Lua state. ++ */ ++static int32_t register_dynamic_protbuf(lua_State *L) ++{ ++ struct protocol_buf *prot_buf; ++ struct protocol_field *field, sentinel = PROT_FIELD_SENTINEL; ++ int32_t nr_of_fields, i; ++ ++ prot_buf = (struct protocol_buf *)kmalloc(sizeof(struct protocol_buf), GFP_KERNEL); ++ prot_buf->is_dynamic = 1; ++ ++ /* check if parameter is a table */ ++ luaL_checktype(L, 1, LUA_TTABLE); ++ ++ /* initialize prot_buf.name */ ++ lua_getfield(L, 1, "name"); ++ prot_buf->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->name, luaL_checkstring(L, -1)); ++ lua_pop(L, 1); /* pop res from lua_getfield */ ++ ++ /* check if protocol buffer is already registered */ ++ lua_getglobal(L, prot_buf->name); ++ if (!lua_isnil(L, -1)) { ++ lua_pop(L, 1); /* pop res from lua_getglobal */ ++ pr_debug("protocol_buf '%s' already registered.\n", prot_buf->name); ++ goto free_prot_buf; ++ } ++ lua_pop(L, 1); /* pop res from lua_getglobal */ ++ ++ /* initialize payload field */ ++ lua_getfield(L, 1, "payload_field"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->payload_field = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy(prot_buf->payload_field, lua_tostring(L, -1)); ++ }else ++ prot_buf->payload_field = NULL; ++ lua_pop(L, 1); /* pop res from lua_getfield */ ++ ++ /* initialize protocol_fields field*/ ++ lua_getfield(L, 1, "protocol_fields"); ++ if (!lua_istable(L, -1)) { ++ pr_debug("invalid protocol_fields table.\n"); ++ goto err2; ++ ++ } ++ ++ nr_of_fields = lua_objlen(L, -1); ++ prot_buf->protocol_fields = (struct protocol_field *)kmalloc((nr_of_fields + 1) * sizeof(struct protocol_field), GFP_KERNEL); ++ ++ for (i = 1; i <= nr_of_fields; i++) { ++ field = &prot_buf->protocol_fields[i - 1]; ++ /* initialize protocol field */ ++ lua_rawgeti(L, -1, i); /* push field-table */ ++ if (!lua_istable(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field at %i.\n", i); ++ goto err; ++ } ++ ++ /* initialize protocol field name */ ++ lua_rawgeti(L, -1, 1); ++ if (!lua_isstring(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field name at %i.\n", i); ++ goto err; ++ } ++ ++ field->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char*)field->name, lua_tostring(L, -1)); ++ lua_pop(L, 1); /* pop field name */ ++ ++ /* initialize protocol field offset */ ++ lua_rawgeti(L, -1, 2); ++ if (!lua_isnumber(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field offset at %i.\n", i); ++ goto err; ++ } ++ field->offset = lua_tointeger(L, -1); ++ lua_pop(L, 1); /* pop field offset */ ++ ++ /* initialize protocol field length */ ++ lua_rawgeti(L, -1, 3); ++ if (!lua_isnumber(L, -1)) { ++ free_protocol_fields(prot_buf->protocol_fields, i); ++ pr_debug("invalid protocol_field length at %i.\n", i); ++ goto err; ++ } ++ field->length = lua_tointeger(L, -1); ++ lua_pop(L, 1); /* pop field length */ ++ ++ /* initialize protocol field getter */ ++ lua_rawgeti(L, -1, 4); ++ if (lua_isstring(L, -1)) { ++ field->get = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)field->get, lua_tostring(L, -1)); /* the get-wrapper knows about the piggybacked string */ ++ }else ++ field->get = NULL; ++ lua_pop(L, 1); /* pop field getter */ ++ ++ /* initialize protocol field setter */ ++ lua_rawgeti(L, -1, 5); ++ if (lua_isstring(L, -1)) { ++ field->set = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)field->set, lua_tostring(L, -1)); /* the set-wrapper knows about the piggybacked string */ ++ }else ++ field->set = NULL; ++ lua_pop(L, 1); /* pop field setter */ ++ ++ /* field initialization completed */ ++ lua_pop(L, 1); /* pop field-table */ ++ } ++ ++ /* put sentinel at the end of protocol_fields */ ++ memcpy(&prot_buf->protocol_fields[nr_of_fields], &sentinel, sizeof(sentinel)); ++ lua_pop(L, 1); /* pop protocol-fields-table */ ++ ++ /* initialize has_protocol field */ ++ lua_getfield(L, 1, "has_protocol"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->has_protocol = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->has_protocol, lua_tostring(L, -1)); /* the has_protocol-wrapper knows about the piggybacked string */ ++ }else ++ prot_buf->has_protocol = NULL; ++ lua_pop(L, 1); /* pop has_protocol */ ++ ++ /* initialize get_field_changes field */ ++ lua_getfield(L, 1, "get_field_changes"); ++ if (lua_isstring(L, -1)) { ++ prot_buf->get_field_changes = kmalloc(lua_objlen(L, -1), GFP_KERNEL); ++ strcpy((char *)prot_buf->get_field_changes, lua_tostring(L, -1)); /* the get_field_changes-wrapper knows about the piggybacked string */ ++ }else ++ prot_buf->get_field_changes = NULL; ++ lua_pop(L, 1); /* pop get_field_changes */ ++ ++ /* Storing the pointer to the DYNAMIC protbuf within dyn_prot_buf_array, in order to free it at cleanup */ ++ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { ++ if (!dyn_prot_buf_array[i]) { ++ dyn_prot_buf_array[i] = prot_buf; ++ break; ++ }else ++ goto err; ++ } ++ ++ /* call the "common" register_protbuf */ ++ register_protbuf(L, prot_buf, get_free_protocol_index(L)); /* register prot_buf as it is done with the static ones */ ++ ++ return 0; ++ ++err: ++ kfree(prot_buf->protocol_fields); ++err2: ++ if (prot_buf->payload_field) kfree(prot_buf->payload_field); ++free_prot_buf: ++ kfree((void *)prot_buf->name); ++ kfree(prot_buf); ++ ++ luaL_error(L, "one or more error happend while registering a dynamic protocol buffer, please consult the debug log"); ++ ++ return 0; ++ ++} ++ ++void luaopen_protbuf_dynamic(lua_State *L) ++{ ++ lua_getglobal(L, "_G"); ++ lua_pushcclosure(L, register_dynamic_protbuf, 0); ++ lua_setfield(L, -2, "register_dynamic_protbuf"); ++ lua_pop(L, 1); /* pop _G */ ++ return; ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_ethernet.c +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "controller.h" ++ ++ ++static int32_t eth_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ uint8_t *embedded_protocol = seg->start + seg->offset + 12 /*bytes*/; ++ unsigned short res = (unsigned short)((embedded_protocol[1] << CHAR_BIT) | (embedded_protocol[0] << CHAR_BIT)); ++ ++ switch (res) { ++ case 0x0800: /* 1: Internet Protocol (IP) */ ++ if (protocol_type == PACKET_IP) return 1; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static const struct protocol_field eth_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "dmac", 0, 48, NULL, NULL }, ++ { "smac", 48, 48, NULL, NULL }, ++ { "type", 96, 16, NULL, NULL }, ++ { "data", 112, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf eth_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_ETH, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)ð_protocol_fields, ++ .has_protocol = ð_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++ ++void luaopen_protbuf_eth(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)ð_protocol_buf, PACKET_ETH); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_helpers.c +@@ -0,0 +1,216 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#if defined(__KERNEL__) ++#include <linux/netfilter_ipv4.h> ++#include <linux/slab.h> /* kmalloc */ ++#endif ++ ++#include "controller.h" ++ ++int32_t get_header_size(struct protocol_buf * prot_buf) ++{ ++ int32_t bit_counter = 0; ++ struct protocol_field * field = prot_buf->protocol_fields; ++ ++ for (; field->name; field++) ++ bit_counter += field->length; ++ ++ return bit_counter >> 3; ++} ++ ++ ++int32_t set_32_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint32_t *)(seg->start + seg->offset) = (uint32_t )htonl(luaL_checkinteger(L, 2)); ++ return 0; ++} ++int32_t get_32_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, ntohl(*((uint32_t *)(seg->start + seg->offset)))); ++ return 1; ++} ++ ++int32_t set_16_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint16_t *)(seg->start + seg->offset) = (uint16_t)htons(luaL_checkinteger(L, 2)); ++ return 0; ++} ++int32_t get_16_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, ntohs(*((uint16_t *)(seg->start + seg->offset)))); ++ return 1; ++} ++ ++int32_t set_lower_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; ++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); ++ ++ *pos &= 0x0F; /* reset lower 4 bits*/ ++ *pos |= b; ++ ++ return 0; ++} ++ ++int32_t get_lower_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) >> 4); ++ return 1; ++} ++ ++int32_t set_upper_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; ++ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); ++ ++ *pos &= 0xF0; /* reset upper 4 bits*/ ++ *pos |= (b >> 4); ++ ++ return 0; ++} ++ ++int32_t get_upper_4_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) & 0x0F); ++ return 1; ++} ++ ++ ++int32_t set_8_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ *(uint8_t *)(seg->start + seg->offset) = (uint8_t)luaL_checkinteger(L, 2); ++ return 0; ++} ++ ++int32_t get_8_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ lua_pushinteger(L, *(uint8_t *)(seg->start + seg->offset)); ++ return 1; ++} ++ ++int32_t set_1_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ unsigned long l = 0; ++ ++ memcpy(&l, (seg->start + seg->offset), seg->length); ++ l |= (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); ++ memcpy((seg->start + seg->offset), &l, seg->length); ++ ++ return 0; ++} ++ ++int32_t get_1_bit_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ unsigned long l = 0; ++ uint32_t bit = 0; ++ ++ memcpy(&l, (seg->start + seg->offset), seg->length); ++ bit = l & (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); ++ ++ lua_pushboolean(L, bit); ++ return 1; ++} ++ ++int32_t get_string_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++ /* Warning we cast from uchar to char */ ++ lua_pushlstring(L, (char *)seg->start + seg->offset, seg->length); ++ return 1; ++} ++ ++int32_t set_data_generic(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ lua_packet_segment * data = checkbytearray(L, 2); ++ ++ pr_debug("seg->length %u, data->length %u\n", seg->length, data->length); ++ ++ if (seg->length >= data->length) ++ memcpy((seg->start + seg->offset), data->start, data->length); ++ else ++ luaL_error(L, "provided byte array too big for given packet segment"); ++ return 0; ++} ++ ++struct field_changes * get_allocated_field_changes(lua_State *L, int32_t nr_of_fields) ++{ ++ struct field_changes * changes; ++ ++ changes = kmalloc(sizeof(struct field_changes), GFP_ATOMIC); ++ ++ if (!changes) ++ goto failure; ++ ++ changes->field_length_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); ++ if (!changes->field_length_changes) ++ goto free1; ++ ++ changes->field_offset_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); ++ if (!changes->field_offset_changes) ++ goto free2; ++ ++ memset(changes->field_length_changes, 0, nr_of_fields * sizeof(int)); ++ memset(changes->field_offset_changes, 0, nr_of_fields * sizeof(int)); ++ ++ changes->ref_count = 1; ++ ++ return changes; ++ ++free2: kfree(changes->field_length_changes); ++free1: kfree(changes); ++failure: ++ if (!changes) luaL_error(L, "couldnt allocate memory inside 'get_allocated_field_changes'"); ++ return NULL; /* only to omit warnings */ ++} +\ No newline at end of file +--- /dev/null ++++ b/extensions/LUA/prot_buf_icmp.c +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "controller.h" ++ ++static int32_t icmp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 0; ++} ++ ++static const struct protocol_field icmp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "type", 0, 8, NULL, NULL }, ++ { "code", 8, 8, NULL, NULL }, ++ { "checksum", 16, 16, NULL, NULL }, ++ { "id", 32, 16, NULL, NULL }, ++ { "sequence", 48, 16, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf icmp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_ICMP, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&icmp_protocol_fields, ++ .has_protocol = &icmp_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_icmp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&icmp_protocol_buf, PACKET_ICMP); ++} ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_ip.c +@@ -0,0 +1,209 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#if defined(__KERNEL__) ++ #include <net/checksum.h> ++ #include <net/tcp.h> ++#endif ++ ++#include "controller.h" ++ ++ ++#define IP_FMT "%u.%u.%u.%u" ++#define IP_ACC(buf) buf[0], buf[1], buf[2], buf[3] ++ ++ ++static int32_t ip_version_set(lua_State *L) ++{ ++ uint8_t version_checked; ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *version_seg = seg->start + seg->offset; ++ int32_t version = luaL_checkinteger(L, 2); ++ ++ luaL_argcheck(L, version >= 0 && version <= 15, 1, "version number invalid"); ++ ++ version_checked = (uint8_t)version; ++ ++ version_seg[0] &= (uint8_t)0x0F; /* reset version bits */ ++ version_seg[0] |= version_checked << 4; ++ ++ return 0; ++} ++static int32_t ip_version_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *version_seg = seg->start + seg->offset; ++ uint8_t v = version_seg[0] & 0xF0; ++ ++ v >>= 4; ++ ++ lua_pushinteger(L, v); ++ return 1; ++} ++ ++static int32_t ip_ihl_set(lua_State *L) ++{ ++ uint8_t ihl_checked; ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *ihl_seg = seg->start + seg->offset; ++ int32_t ihl = luaL_checkinteger(L, 2); ++ ++ luaL_argcheck(L, ihl >= 5 && ihl <= 15, 1, "ip header length invalid"); // RFC 791 5x32 = 160 bits ++ ++ ihl_checked = (uint8_t)ihl; ++ ++ ihl_seg[0] &= (uint8_t)0xF0; /* reset ihl bits */ ++ ihl_seg[0] |= ihl_checked; ++ ++ return 0; ++} ++static int32_t ip_ihl_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *ihl_seg = seg->start + seg->offset; ++ uint8_t v = ihl_seg[0] & 0x0F; ++ ++ lua_pushinteger(L, v); ++ return 1; ++} ++ ++static int32_t ip_addr_set(lua_State *L) ++{ ++ int32_t field_id = lua_tointeger(L, lua_upvalueindex(2)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *addr_seg = seg->start + seg->offset; ++ uint32_t old_addr; ++ char *ip = (char *)luaL_checkstring(L, 2); ++ uint32_t a, b, c, d; ++ struct sk_buff * skb = (struct sk_buff *)lua_touserdata(L, 3); ++ ++ /* for tcp / udp checksumming*/ ++ uint32_t prot_offset; ++ uint8_t *check, *protocol_seg; ++ ++ /* end */ ++ ++ sscanf(ip, IP_FMT, &a, &b, &c, &d); ++ ++ luaL_argcheck(L, a < 256 && b < 256 && c < 256 && d < 256, 1, "invalid ip addr"); ++ ++ old_addr = *((uint32_t *)addr_seg); ++ addr_seg[0] = (uint8_t)a; ++ addr_seg[1] = (uint8_t)b; ++ addr_seg[2] = (uint8_t)c; ++ addr_seg[3] = (uint8_t)d; ++ ++#if defined(__KERNEL__) ++ if (old_addr != *(uint32_t *)addr_seg) { ++ int32_t offset = (field_id == 10) ? -2 : -6; /* offset from saddr or daddr */ ++ ++ csum_replace4((uint16_t *)(addr_seg + offset), old_addr, *(uint32_t *)addr_seg); ++ ++ prot_offset = (field_id == 10) ? -3 : -7; /* offset from saddr or daddr */ ++ protocol_seg = seg->start + seg->offset + prot_offset; ++ ++ if (skb && (protocol_seg[0] == 0x06 || protocol_seg[0] == 0x11)) { /* is payload TCP or UDP ? */ ++ ++ check = seg->start + seg->offset; /* tmp res */ ++ check += (field_id == 10) ? 8 : 16; /* the start of the payload, depending saddr or daddr */ ++ check += (protocol_seg[0] == 0x06) ? 16 : 6; /* the start of the checksum, depending on TCP or UDP */ ++ ++ inet_proto_csum_replace4((__sum16 *)check, skb, old_addr, *(uint32_t *)addr_seg, 1); ++ ++ lua_pop(L, 1); ++ } ++ } ++#endif ++ return 0; ++} ++ ++ ++ ++ ++ ++static int32_t ip_addr_get(lua_State *L) ++{ ++ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); ++ uint8_t *addr_seg = seg->start + seg->offset; ++ ++ char buf[16]; /*max: 255.255.255.255\0 --> 16 chars */ ++ ++ sprintf(buf, IP_FMT, IP_ACC(addr_seg)); ++ lua_pushstring(L, buf); ++ return 1; ++} ++ ++static int32_t ip_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ uint8_t * embedded_protocol = seg->start + seg->offset + 9 /*bytes*/; ++ ++ switch (embedded_protocol[0]) { ++ case 0x01: /* 1: Internet Control Message Protocol (ICMP) */ ++ if (protocol_type == PACKET_ICMP) return 1; ++ break; ++ case 0x02: /* 2: Internet Group Management Protocol (IGMP) */ ++ break; ++ case 0x06: /* 6: Transmission Control Protocol (TCP) */ ++ if (protocol_type == PACKET_TCP) return 1; ++ break; ++ case 0x11: /* 17: User Datagram Protocol (UDP) */ ++ if (protocol_type == PACKET_UDP) return 1; ++ break; ++ case 0x59: /* 89: Open Shortest Path First (OSPF) */ ++ break; ++ case 0x84: /* 132: Stream Control Transmission Protocol (SCTP) */ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const struct protocol_field ip_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "version", 0, 4, ip_version_get, ip_version_set }, ++ { "ihl", 4, 4, ip_ihl_get, ip_ihl_set }, ++ { "tos", 8, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "tot_len", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "id", 32, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "flags", 48, 3, get_1_bit_generic, set_1_bit_generic }, ++ { "frag_off", 51, 13, NULL, NULL }, ++ { "ttl", 64, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "protocol", 72, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "check", 80, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "saddr", 96, 32, ip_addr_get, ip_addr_set }, ++ { "daddr", 128, 32, ip_addr_get, ip_addr_set }, ++ { "data", 160, 0, NULL, set_data_generic }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf ip_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_IP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&ip_protocol_fields, ++ .has_protocol = &ip_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_ip(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&ip_protocol_buf, PACKET_IP); ++} ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_raw.c +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include "controller.h" ++static int32_t raw_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static const struct protocol_field raw_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "data", 0, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf raw_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_RAW, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&raw_protocol_fields, ++ .has_protocol = &raw_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_raw(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&raw_protocol_buf, PACKET_RAW); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_tcp.c +@@ -0,0 +1,188 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#if defined(__KERNEL__) ++ #include <net/checksum.h> ++ #include <net/tcp.h> ++#endif ++#include "controller.h" ++ ++ ++static int32_t tcp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static int32_t tcp_set_checksum(lua_State *L) ++{ ++ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); ++ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); ++ ++#if defined(__KERNEL__) ++ uint8_t * check_seg = seg->start + seg->offset; ++ uint8_t * tcp_hdr = check_seg - 16; ++ uint8_t * saddr = tcp_hdr - 8; ++ uint8_t * daddr = saddr + 4; ++ uint32_t len = 20 + (seg->changes->field_length_changes[11] / 8) + (seg->changes->field_length_changes[10] / 8); ++ unsigned short checksum = tcp_v4_check(len, *(uint32_t *)saddr, *(uint32_t *)daddr, ++ csum_partial(tcp_hdr, len, 0)); ++ ++ memcpy(check_seg, &checksum, sizeof(unsigned short)); ++#endif ++ return 0; ++} ++ ++ ++static const struct protocol_field tcp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "seq", 32, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "ack", 64, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "data_off", 96, 4, get_lower_4_bit_generic, set_lower_4_bit_generic }, ++ { "reserved", 100, 4, get_upper_4_bit_generic, set_upper_4_bit_generic }, ++ { "flags", 104, 8, get_1_bit_generic, set_1_bit_generic }, ++ { "window_size", 112, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "check", 128, 16, get_16_bit_generic, tcp_set_checksum }, ++ { "urgent", 144, 16, NULL, NULL }, ++ { "options", 160, 0, NULL, set_data_generic }, ++ { "data", 160, 0, NULL, set_data_generic }, /* begin of data depends on options */ ++ PROT_FIELD_SENTINEL, ++}; ++ ++ ++static const struct protocol_field tcp_options_and_data[] = { ++ /* field name offset length getter setter */ ++ { "MSS", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "WS", 0, 8, get_8_bit_generic, set_8_bit_generic }, ++ { "SACK", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "TSVAL", 0, 32, get_32_bit_generic, set_32_bit_generic }, ++ { "TSER", 0, 32, get_32_bit_generic, set_32_bit_generic }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++ ++static struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg); ++ ++static const struct protocol_buf tcp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TCP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&tcp_protocol_fields, ++ .has_protocol = &tcp_has_protocol, ++ .get_field_changes = &tcp_get_field_changes, ++}; ++ ++ ++static struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg); ++ ++static const struct protocol_buf tcp_options_and_data_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TCP_OPT, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&tcp_options_and_data, ++ .has_protocol = NULL, ++ .get_field_changes = &tcp_options_get_field_changes, ++}; ++ ++struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'data_off'-field, the length of ++ * the 'options' field has to be changed, as well as the length and offset ++ * of the 'data' field */ ++ uint8_t *tcp_hdr = seg->start + seg->offset; ++ ++ /* get the pointer to the 'data_off' field */ ++ uint8_t * data_off_field = tcp_hdr + 12; /* 12 bytes offset */ ++ /* extract the stored header length in bits */ ++ uint32_t tcp_hdr_len = ((*(uint8_t *)data_off_field) >> 4) * 32; ++ ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 12); ++ ++ /* depending on the tcp header length, change the length of the options*/ ++ changes->field_length_changes[10] = tcp_hdr_len - 160; ++ /* depending on the options length, change the offset of the data */ ++ changes->field_offset_changes[11] = changes->field_length_changes[10]; ++ changes->field_length_changes[11] = (seg->length * 8) - tcp_hdr_len; ++ ++ return changes; ++ ++} ++ ++struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'data_off'-field, the length of ++ * the 'options' field has to be changed, as well as the length and offset ++ * of the 'data' field */ ++ uint8_t *tcp_opt_hdr = seg->start + seg->offset; ++ ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 5); ++ ++ int32_t MSS = 0, WS = 0, SACK = 0, TS = 0, i; ++ ++ uint8_t b1, b2; ++ ++ for (i = 0; i < seg->length; i++) { ++ b1 = tcp_opt_hdr[i]; ++ b2 = tcp_opt_hdr[i + 1]; ++ ++ if (b1 == 0x00) ++ break; ++ ++ /* test for MSS */ ++ if (!MSS && (b1 == 0x02 && b2 == 0x04)) { ++ changes->field_offset_changes[0] = (i + 2) * CHAR_BIT; ++ MSS = 1; ++ } ++ ++ /* test for WS --- yet buggy somehow */ ++ if (!WS && (b1 == 0x03 && b2 == 0x03)) { ++ changes->field_offset_changes[1] = (i + 2) * CHAR_BIT; ++ WS = 1; ++ } ++ ++ /* test for SACK*/ ++ if (!SACK && (b1 == 0x04 && b2 == 0x02)) { ++ changes->field_offset_changes[2] = i * CHAR_BIT; /* has no value */ ++ SACK = 1; ++ } ++ ++ /* test for TS */ ++ if (!TS && (b1 == 0x08 && b2 == 0x0A)) { ++ changes->field_offset_changes[3] = (i + 2) * CHAR_BIT; ++ changes->field_offset_changes[4] = (i + 2 + 4) * CHAR_BIT; ++ TS = 1; ++ } ++ } ++ ++ return changes; ++ ++} ++ ++void luaopen_protbuf_tcp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tcp_protocol_buf, PACKET_TCP); ++} ++void luaopen_protbuf_tcp_options(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tcp_options_and_data_buf, PACKET_TCP_OPTIONS); ++} ++ ++ +--- /dev/null ++++ b/extensions/LUA/prot_buf_tftp.c +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++#include "controller.h" ++ ++static const struct protocol_field tftp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "opcode", 0, 16, get_16_bit_generic, NULL}, ++ { "filename", 0, 0, get_string_generic, NULL}, ++ { "mode", 0, 0, get_string_generic, NULL}, ++ { "block_nr", 0, 16, get_16_bit_generic, NULL}, ++ { "data", 0, 0, NULL, NULL}, ++ PROT_FIELD_SENTINEL, ++}; ++ ++struct field_changes * tftp_get_field_changes(lua_State *L, lua_packet_segment * seg) ++{ ++ /* depending on the value stored inside the 'opcode'-field we have to change ++ * offsets and lengths */ ++ uint8_t *tftp_hdr = seg->start + seg->offset; ++ short opcode = ntohs(*((uint16_t *)tftp_hdr)); ++ /* get an allocated 'field_changes' structure */ ++ struct field_changes * changes = get_allocated_field_changes(L, 5); ++ switch (opcode) { ++ case 1: /* Read Request (RRQ) */ ++ /* setting offset and length of field 'filename' */ ++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; ++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; ++ /* setting offset and length of field 'mode' */ ++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; ++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); ++ break; ++ case 2: /* Write Request (WRQ) */ ++ /* setting offset and length of field 'filename' */ ++ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; ++ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; ++ /* setting offset and length of field 'mode' */ ++ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; ++ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); ++ break; ++ case 3: /* Data (DATA) */ ++ /* setting offset of field 'block_nr' */ ++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; ++ /* setting offset of field 'data' */ ++ changes->field_offset_changes[4] = changes->field_offset_changes[3] + (sizeof(unsigned short) << 3); ++ break; ++ case 4: /* Acknowledgment (ACK) */ ++ /* setting offset of field 'block_nr' */ ++ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; ++ break; ++ case 5: /* Error (ERROR) */ ++ /* we don't care ... yet */ ++ break; ++ default: ++ break; ++ } ++ ++ return changes; ++} ++ ++static const struct protocol_buf tftp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_TFTP, ++ .payload_field = NULL, ++ .protocol_fields = (struct protocol_field *)&tftp_protocol_fields, ++ .has_protocol = NULL, /* we don't need it, since we don't provide a payload field */ ++ .get_field_changes = tftp_get_field_changes, ++}; ++ ++void luaopen_protbuf_tftp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&tftp_protocol_buf, PACKET_TFTP); ++} +--- /dev/null ++++ b/extensions/LUA/prot_buf_udp.c +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#if defined(__KERNEL__) ++ #include <net/checksum.h> ++#endif ++ ++#include "controller.h" ++ ++ ++static int32_t udp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) ++{ ++ return 1; ++} ++ ++static const struct protocol_field udp_protocol_fields[] = { ++ /* field name offset length getter setter */ ++ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "length", 32, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "check", 48, 16, get_16_bit_generic, set_16_bit_generic }, ++ { "data", 64, 0, NULL, NULL }, ++ PROT_FIELD_SENTINEL, ++}; ++ ++static const struct protocol_buf udp_protocol_buf = { ++ .is_dynamic = 0, ++ .name = LUA_PACKET_SEG_UDP, ++ .payload_field = "data", ++ .protocol_fields = (struct protocol_field *)&udp_protocol_fields, ++ .has_protocol = &udp_has_protocol, ++ .get_field_changes = NULL, ++}; ++ ++void luaopen_protbuf_udp(lua_State *L) ++{ ++ register_protbuf(L, (struct protocol_buf *)&udp_protocol_buf, PACKET_UDP); ++} +--- /dev/null ++++ b/extensions/LUA/xt_LUA.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre.graf@stud.unibas.ch> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#ifndef XT_LUA_H_ ++#define XT_LUA_H_ ++ ++#define MAX_FILENAME_SIZE 256 ++#define MAX_FUNCTION_SIZE 256 ++#define MAX_SCRIPT_SIZE 32768 ++#define LUA_STATE_ARRAY_SIZE 128 ++ ++/* the targetsize is stored in a u16, so max size of the xt_lua_tginfo cannot exceed 64K*/ ++struct xt_lua_tginfo { ++ char buf[MAX_SCRIPT_SIZE]; ++ char filename[MAX_FILENAME_SIZE]; ++ char function[MAX_FUNCTION_SIZE]; ++ __u64 script_size; ++ __u32 state_id; ++}; ++ ++#endif /* XT_LUA_H_ */ +--- /dev/null ++++ b/extensions/LUA/xt_LUA_target.c +@@ -0,0 +1,286 @@ ++/* ++ * Copyright (C) 2010 University of Basel <http://cn.cs.unibas.ch/> ++ * by Andre Graf <andre@dergraf.org> ++ * ++ * 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, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++#include <asm/uaccess.h> ++#include <net/ip.h> ++#include <linux/netfilter/x_tables.h> ++#include "xt_LUA.h" ++ ++#include "controller.h" ++ ++/*::* ++ * lua_envs ++ * ---------- ++ * This array holds a defined number of `lua_envs`_ structures. ++ * The used array index is also used as the Lua state identifier. ++ * The size of the array is defined in `LUA_STATE_ARRAY_SIZE`_. ++ */ ++struct lua_env * lua_envs[LUA_STATE_ARRAY_SIZE]; ++ ++/*::* ++ * lua_state_refs ++ * -------------- ++ * This array holds the reference counts of the several `lua_nf_state`_s ++ * which are stored inside the array `lua_states`_. ++ */ ++uint32_t lua_state_refs[LUA_STATE_ARRAY_SIZE] = { 0 }; ++ ++/*::* ++ * lua_tg ++ * ------ ++ * This function is called whenever a packet matches all matching conditions ++ * inside a rule. It is the target. It extracts the state identifier comming ++ * inside the *xt_target_param* structure and uses it to access the proper ++ * Lua state inside the `lua_states`_ array. ++ * ++ * It then constructs a new Lua userdata of type *lua_packet_segment* and ++ * initializes it with the lowest network header available. This userdata ++ * is annotated with the Lua metatable `LUA_PACKET_SEG_RAW`_ which converts ++ * the userdata to a raw lua packet having all raw functions available. ++ * This raw packet is the single parameter to the Lua function *process_packet* ++ * which must be defined inside the Lua script provided by the user. So far ++ * hardcoded, may be later configured by Lua - subject to change. ++ * ++ * The process_packet function must return an integer value, the verdict. For ++ * convenience reasons xt_LUA exports the verdicts NF_ACCEPT, NF_DROP and ++ * XT_CONTINUE inside the *register_lua_packet_lib* function. ++ */ ++ ++spinlock_t lock = SPIN_LOCK_UNLOCKED; ++ ++static uint32_t ++lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) ++{ ++ uint32_t verdict; ++ lua_packet_segment *p; ++ const struct xt_lua_tginfo *info = par->targinfo; ++ lua_State * L; ++ ++ /* START critical section on SMP, PacketScript is on the sequential trail at the moment TODO*/ ++ spin_lock_irq(&lock); ++ ++ L = lua_envs[info->state_id]->L; ++ ++ if (!skb_make_writable(pskb, pskb->len)) ++ return NF_DROP; ++ ++ /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ ++ lua_getglobal(L, info->function); ++ ++ /* push the lua_packet_segment as a parameter */ ++ p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); ++ if (pskb->mac_header) ++ p->start = pskb->mac_header; ++ else if (pskb->network_header) ++ p->start = pskb->network_header; ++ else if (pskb->transport_header) ++ p->start = pskb->transport_header; ++ p->offset = 0; ++ p->length = (unsigned long)pskb->tail - (unsigned long)p->start; ++ p->changes = NULL; ++ ++ /* marking userdata 'lua_packet_seg' with the corresponding metatable */ ++ luaL_getmetatable(L, LUA_PACKET_SEG_RAW); ++ lua_setmetatable(L, -2); ++ ++ /* push a reference to the skb as a parameter, needed at the moment for calculating TCP checksum, but I am not happy with it*/ ++ lua_pushlightuserdata(L, (void *)skb_get(pskb)); ++ ++ /* do the function call (2 argument, 1 result) */ ++ if (lua_pcall(L, 2, 1, 0) != 0) { ++ printk(KERN_ERR "LUA [%d]: pcall '%s' failed: %s\n", info->state_id, info->function, lua_tostring(L, -1)); ++ lua_pop(L, 1); ++ return NF_DROP; ++ } ++ ++ if (!lua_isnumber(L, -1)) { ++ printk(KERN_ERR "LUA [%d]: function '%s' must return a verdict\n", info->state_id, info->function); ++ lua_pop(L, 1); ++ return NF_DROP; ++ } ++ ++ verdict = lua_tonumber(L, -1); ++ lua_pop(L, 1); ++ ++ kfree_skb(pskb); ++ ++ /* END critical section on SMP */ ++ spin_unlock_irq(&lock); ++ ++ ++ return verdict; ++ ++} ++/* Helper for checkentry */ ++static bool load_script_into_state(uint32_t state_id, unsigned long script_size, char *script_buf) ++{ ++ char *buf = kmalloc(script_size, GFP_KERNEL); ++ int32_t ret; ++ struct lua_env * env = kmalloc(sizeof(struct lua_env), GFP_KERNEL); ++ ++ if (!script_size > 0) { ++ pr_debug("LUA [%d]: script_size %lu < 0\n", state_id, script_size); ++ return false; ++ } ++ ++ env->L = lua_open(); ++ luaopen_base(env->L); ++ luaopen_controller(env->L); ++ ++ lua_getglobal(env->L, "_G"); ++ lua_pushinteger(env->L, state_id); ++ lua_setfield(env->L, -2, "STATE_ID"); ++ lua_pop(env->L, 1); /* pop _G */ ++ ++ strncpy(buf, script_buf, script_size); ++ ret = luaL_loadbuffer(env->L, buf, script_size, "PacketScript, loadbuffer") || ++ lua_pcall(env->L, 0, 1, 0); ++ ++ if (ret != 0) { ++ printk(KERN_ERR "LUA [%d]: failure loading script, error %s \n", state_id, lua_tostring(env->L, -1)); ++ lua_pop(env->L, 1); ++ kfree(buf); ++ kfree(env); ++ return false; ++ } ++ ++ lua_envs[state_id] = env; ++ ++ kfree(buf); ++ ++ return true; ++} ++/*::* ++ * lua_tg_checkentry ++ * ----------------- ++ * This function is used as a kernel-side sanity check of the data comming ++ * from the iptables userspace program. Since this is the function which is ++ * called everytime a new rule (with -j xt_LUA) is injected, this function ++ * is used to do the bookkeeping work, such as counting the reference of ++ * several Lua states and the initialization of new states if needed. As an ++ * extra initialization step it loads the provided Lua script into the Lua ++ * state. ++ * ++ * Lua state initialization ++ * ~~~~~~~~~~~~~~~~~~~~~~~~ ++ * 1. If a new rule is inserted and there is no existing state for the given ++ * state identifier (default state identifier is 0) a new Lua state is ++ * initialized using *lua_open*. ++ * 2. The Lua base library is registered inside the newly initialized state. ++ * Have a look at *lua/lbaselib.c* to see what functions of the Lua base ++ * library are available inside Lua. ++ * 3. The Lua packet library is registered inside the Lua state using the ++ * function *register_lua_packet_lib*. So far this function only registers ++ * the Netfilter verdicts NF_ACCEPT, NF_DROP and XT_CONTINUE inside the ++ * global environment of the given Lua state. ++ * 4. All the protocol Buffers, and the functions for accessing the bytes are ++ * registered using *register_protocols*. ++ * ++ * Lua state reference counting ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * Bookkeeping of the Lua states inside the *lua_state_refs* array. The ++ * state identifier is mapped to the array index, which holds an integer ++ * counting the several initialized states. ++ * ++ * Loading the Lua script ++ * ~~~~~~~~~~~~~~~~~~~~~~ ++ * Copying the buffer which was initialized by the userspace program to a ++ * buffer with the proper size. The script is then loaded by the function ++ * xt_LUA_loadcode, which wrapps the *luaL_loadbuffer* function and does ++ * some workqueue initialization. So far this is done each time this function ++ * is called, subject to change. ++ */ ++static bool ++lua_tg_checkentry(const struct xt_tgchk_param *par) ++{ ++ const struct xt_lua_tginfo *info = par->targinfo; ++ ++ if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { ++ lua_state_refs[info->state_id]++; ++ return true; ++ } ++ return false; ++} ++ ++/*::* ++ * lua_tg_destroy ++ * -------------- ++ * This function is the counterpart of the `lua_tg_checkentry`_ function. It is ++ * responsible to free all the resources alocated inside the checkentry process. ++ * To be more specific it frees the Lua state using *lua_close* and kfree on all ++ * the dynamically allocated pointers to the registered dynamic protocol buffers. ++ * ++ * Additionally the function cares about decrementing the reference counters ++ * inside the array `lua_states`_. ++ */ ++static void ++lua_tg_destroy(const struct xt_tgdtor_param *par) ++{ ++ const struct xt_lua_tginfo *info = par->targinfo; ++ struct lua_env * env = lua_envs[info->state_id]; ++ ++ if (lua_state_refs[info->state_id] == 1) { ++ lua_close(env->L); ++ cleanup_dynamic_prot_bufs(); /* clean memory allocated by protocols defined in Lua */ ++ kfree(env); ++ pr_debug("LUA [%d]: Rule removed, close Lua state\n", info->state_id); ++ } else ++ pr_debug("LUA [%d]: Rule removed, Lua state stays open, referenced %d time(s)\n", ++ info->state_id, lua_state_refs[info->state_id] - 1); ++ ++ lua_state_refs[info->state_id]--; ++} ++ ++static struct xt_target lua_tg_reg __read_mostly = { ++ .name = "LUA", ++ .revision = 0, ++ .family = NFPROTO_UNSPEC, ++ .targetsize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), ++ .target = lua_tg, ++ .checkentry = lua_tg_checkentry, ++ .destroy = lua_tg_destroy, ++ .me = THIS_MODULE, ++}; ++ ++ ++static int32_t lua_tg_init(void) ++{ ++ return xt_register_target(&lua_tg_reg); ++} ++ ++static void lua_tg_exit(void) ++{ ++ xt_unregister_target(&lua_tg_reg); ++} ++ ++module_init(lua_tg_init); ++module_exit(lua_tg_exit); ++ ++MODULE_AUTHOR("Andre Graf <andre@dergraf.org>"); ++MODULE_DESCRIPTION("Xtables: Processing of matched packets using the Lua scripting environment"); ++MODULE_ALIAS("ipt_LUA"); ++MODULE_ALIAS("ipt6t_LUA"); ++MODULE_ALIAS("arpt_LUA"); ++MODULE_ALIAS("ebt_LUA"); ++MODULE_LICENSE("GPL"); ++ ++ ++ +--- a/extensions/Kbuild ++++ b/extensions/Kbuild +@@ -29,6 +29,7 @@ obj-${build_pknock} += pknock/ + obj-${build_psd} += xt_psd.o + obj-${build_quota2} += xt_quota2.o + obj-${build_rtsp} += rtsp/ ++obj-${build_LUA} += LUA/ + + -include ${M}/*.Kbuild + -include ${M}/Kbuild.* +--- a/extensions/Mbuild ++++ b/extensions/Mbuild +@@ -22,3 +22,4 @@ obj-${build_pknock} += pknock/ + obj-${build_psd} += libxt_psd.so + obj-${build_quota2} += libxt_quota2.so + obj-${build_gradm} += libxt_gradm.so ++obj-${build_LUA} += LUA/ +--- a/mconfig ++++ b/mconfig +@@ -23,3 +23,4 @@ build_pknock=m + build_psd=m + build_quota2=m + build_rtsp=m ++build_LUA=m diff --git a/package/network/utils/xtables-addons/patches/201-fix-lua-packetscript.patch b/package/network/utils/xtables-addons/patches/201-fix-lua-packetscript.patch new file mode 100644 index 0000000..966d29d --- /dev/null +++ b/package/network/utils/xtables-addons/patches/201-fix-lua-packetscript.patch @@ -0,0 +1,89 @@ +--- a/extensions/LUA/xt_LUA_target.c ++++ b/extensions/LUA/xt_LUA_target.c +@@ -64,10 +64,10 @@ uint32_t lua_state_refs[LUA_STATE_ARRAY + * XT_CONTINUE inside the *register_lua_packet_lib* function. + */ + +-spinlock_t lock = SPIN_LOCK_UNLOCKED; ++DEFINE_SPINLOCK(lock); + + static uint32_t +-lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) ++lua_tg(struct sk_buff *pskb, const struct xt_action_param *par) + { + uint32_t verdict; + lua_packet_segment *p; +@@ -208,16 +208,16 @@ static bool load_script_into_state(uint3 + * some workqueue initialization. So far this is done each time this function + * is called, subject to change. + */ +-static bool ++static int + lua_tg_checkentry(const struct xt_tgchk_param *par) + { + const struct xt_lua_tginfo *info = par->targinfo; + + if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { + lua_state_refs[info->state_id]++; +- return true; ++ return 0; + } +- return false; ++ return -EINVAL; + } + + /*::* +--- a/extensions/LUA/lua/llimits.h ++++ b/extensions/LUA/lua/llimits.h +@@ -8,7 +8,6 @@ + #define llimits_h + + #include <stddef.h> +-#include <limits.h> + + #include "lua.h" + +--- a/extensions/LUA/lua/lapi.c ++++ b/extensions/LUA/lua/lapi.c +@@ -4,9 +4,6 @@ + ** See Copyright Notice in lua.h + */ + +-#include <stdarg.h> +-#include <math.h> +-#include <assert.h> + #include <string.h> + + #define lapi_c +--- a/extensions/LUA/lua/ltable.c ++++ b/extensions/LUA/lua/ltable.c +@@ -18,7 +18,6 @@ + ** Hence even when the load factor reaches 100%, performance remains good. + */ + +-#include <math.h> + #include <string.h> + + #define ltable_c +--- a/extensions/LUA/lua/luaconf.h ++++ b/extensions/LUA/lua/luaconf.h +@@ -13,6 +13,10 @@ + #if !defined(__KERNEL__) + #include <limits.h> + #else ++#undef UCHAR_MAX ++#undef SHRT_MAX ++#undef BUFSIZ ++#undef NO_FPU + #define UCHAR_MAX 255 + #define SHRT_MAX 32767 + #define BUFSIZ 8192 +@@ -637,6 +641,8 @@ union luai_Cast { double l_d; long l_l; + */ + #if defined(__KERNEL__) + #undef LUA_USE_ULONGJMP ++#define setjmp __builtin_setjmp ++#define longjmp __builtin_longjmp + #endif + + #if defined(__cplusplus) diff --git a/package/network/utils/xtables-addons/patches/300-geoip-endian-detection.patch b/package/network/utils/xtables-addons/patches/300-geoip-endian-detection.patch new file mode 100644 index 0000000..842e7af --- /dev/null +++ b/package/network/utils/xtables-addons/patches/300-geoip-endian-detection.patch @@ -0,0 +1,18 @@ +--- a/extensions/libxt_geoip.c ++++ b/extensions/libxt_geoip.c +@@ -59,13 +59,13 @@ geoip_get_subnets(const char *code, uint + + /* Use simple integer vector files */ + if (nfproto == NFPROTO_IPV6) { +-#if __BYTE_ORDER == _BIG_ENDIAN ++#if BYTE_ORDER == BIG_ENDIAN + snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv6", code); + #else + snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv6", code); + #endif + } else { +-#if __BYTE_ORDER == _BIG_ENDIAN ++#if BYTE_ORDER == BIG_ENDIAN + snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/BE/%s.iv4", code); + #else + snprintf(buf, sizeof(buf), GEOIP_DB_DIR "/LE/%s.iv4", code); |